Annotation of previous/src/slirp/slirp.c, revision 1.1

1.1     ! root        1: #include "slirp.h"
        !             2: 
        !             3: /* host address */
        !             4: struct in_addr our_addr;
        !             5: /* host dns address */
        !             6: struct in_addr dns_addr;
        !             7: /* host loopback address */
        !             8: struct in_addr loopback_addr;
        !             9: 
        !            10: /* address for slirp virtual addresses */
        !            11: struct in_addr special_addr;
        !            12: /* virtual address alias for host */
        !            13: struct in_addr alias_addr;
        !            14: 
        !            15: const uint8_t special_ethaddr[6] = { 
        !            16:     0x52, 0x54, 0x00, 0x12, 0x35, 0x00
        !            17: };
        !            18: 
        !            19: uint8_t client_ethaddr[6];
        !            20: 
        !            21: int do_slowtimo;
        !            22: int link_up;
        !            23: struct timeval tt;
        !            24: FILE *lfd;
        !            25: struct ex_list *exec_list;
        !            26: 
        !            27: /* XXX: suppress those select globals */
        !            28: fd_set *global_readfds, *global_writefds, *global_xfds;
        !            29: 
        !            30: char slirp_hostname[33];
        !            31: 
        !            32: #ifdef _WIN32
        !            33: 
        !            34: static int get_dns_addr(struct in_addr *pdns_addr)
        !            35: {
        !            36:     FIXED_INFO *FixedInfo=NULL;
        !            37:     ULONG    BufLen;
        !            38:     DWORD    ret;
        !            39:     IP_ADDR_STRING *pIPAddr;
        !            40:     struct in_addr tmp_addr;
        !            41:     
        !            42:     FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
        !            43:     BufLen = sizeof(FIXED_INFO);
        !            44:    
        !            45:     if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
        !            46:         if (FixedInfo) {
        !            47:             GlobalFree(FixedInfo);
        !            48:             FixedInfo = NULL;
        !            49:         }
        !            50:         FixedInfo = GlobalAlloc(GPTR, BufLen);
        !            51:     }
        !            52:        
        !            53:     if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
        !            54:         printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret );
        !            55:         if (FixedInfo) {
        !            56:             GlobalFree(FixedInfo);
        !            57:             FixedInfo = NULL;
        !            58:         }
        !            59:         return -1;
        !            60:     }
        !            61:      
        !            62:     pIPAddr = &(FixedInfo->DnsServerList);
        !            63:     inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
        !            64:     *pdns_addr = tmp_addr;
        !            65: #if 0
        !            66:     printf( "DNS Servers:\n" );
        !            67:     printf( "DNS Addr:%s\n", pIPAddr->IpAddress.String );
        !            68:     
        !            69:     pIPAddr = FixedInfo -> DnsServerList.Next;
        !            70:     while ( pIPAddr ) {
        !            71:             printf( "DNS Addr:%s\n", pIPAddr ->IpAddress.String );
        !            72:             pIPAddr = pIPAddr ->Next;
        !            73:     }
        !            74: #endif
        !            75:     if (FixedInfo) {
        !            76:         GlobalFree(FixedInfo);
        !            77:         FixedInfo = NULL;
        !            78:     }
        !            79:     return 0;
        !            80: }
        !            81: 
        !            82: #else
        !            83: 
        !            84: static int get_dns_addr(struct in_addr *pdns_addr)
        !            85: {
        !            86:     char buff[512];
        !            87:     char buff2[256];
        !            88:     FILE *f;
        !            89:     int found = 0;
        !            90:     struct in_addr tmp_addr;
        !            91:     
        !            92:     f = fopen("/etc/resolv.conf", "r");
        !            93:     if (!f)
        !            94:         return -1;
        !            95: 
        !            96:     lprint("IP address of your DNS(s): ");
        !            97:     while (fgets(buff, 512, f) != NULL) {
        !            98:         if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
        !            99:             if (!inet_aton(buff2, &tmp_addr))
        !           100:                 continue;
        !           101:             if (tmp_addr.s_addr == loopback_addr.s_addr)
        !           102:                 tmp_addr = our_addr;
        !           103:             /* If it's the first one, set it to dns_addr */
        !           104:             if (!found)
        !           105:                 *pdns_addr = tmp_addr;
        !           106:             else
        !           107:                 lprint(", ");
        !           108:             if (++found > 3) {
        !           109:                 lprint("(more)");
        !           110:                 break;
        !           111:             } else
        !           112:                 lprint("%s", inet_ntoa(tmp_addr));
        !           113:         }
        !           114:     }
        !           115:     fclose(f);
        !           116:     if (!found)
        !           117:         return -1;
        !           118:     return 0;
        !           119: }
        !           120: 
        !           121: #endif
        !           122: 
        !           123: #ifdef _WIN32
        !           124: void slirp_cleanup(void)
        !           125: {
        !           126:     WSACleanup();
        !           127: }
        !           128: #endif
        !           129: 
        !           130: int slirp_init(void)
        !           131: {
        !           132:     //    debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
        !           133:     
        !           134: #ifdef _WIN32
        !           135:     {
        !           136:         WSADATA Data;
        !           137:         WSAStartup(MAKEWORD(2,0), &Data);
        !           138:        atexit(slirp_cleanup);
        !           139:     }
        !           140: #endif
        !           141: 
        !           142:     link_up = 1;
        !           143: 
        !           144:     if_init();
        !           145:     ip_init();
        !           146: 
        !           147:     /* Initialise mbufs *after* setting the MTU */
        !           148:     m_init();
        !           149: 
        !           150:     /* set default addresses */
        !           151:     inet_aton("127.0.0.1", &loopback_addr);
        !           152: 
        !           153:     if (get_dns_addr(&dns_addr) < 0)
        !           154:         return -1;
        !           155: 
        !           156:     inet_aton(CTL_SPECIAL, &special_addr);
        !           157:        alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
        !           158:        getouraddr();
        !           159:     return 0;
        !           160: }
        !           161: 
        !           162: #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
        !           163: #define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
        !           164: #define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
        !           165: 
        !           166: /*
        !           167:  * curtime kept to an accuracy of 1ms
        !           168:  */
        !           169: #ifdef _WIN32
        !           170: static void updtime(void)
        !           171: {
        !           172:     struct _timeb tb;
        !           173: 
        !           174:     _ftime(&tb);
        !           175:     curtime = (u_int)tb.time * (u_int)1000;
        !           176:     curtime += (u_int)tb.millitm;
        !           177: }
        !           178: #else
        !           179: static void updtime(void)
        !           180: {
        !           181:        gettimeofday(&tt, 0);
        !           182:        
        !           183:        curtime = (u_int)tt.tv_sec * (u_int)1000;
        !           184:        curtime += (u_int)tt.tv_usec / (u_int)1000;
        !           185:        
        !           186:        if ((tt.tv_usec % 1000) >= 500)
        !           187:           curtime++;
        !           188: }
        !           189: #endif
        !           190: 
        !           191: int slirp_select_fill(int *pnfds, 
        !           192:                                          fd_set *readfds, fd_set *writefds, fd_set *xfds)
        !           193: {
        !           194:     struct socket *so, *so_next;
        !           195:     int nfds;
        !           196:     int timeout, tmp_time;
        !           197: 
        !           198:     /* fail safe */
        !           199:     global_readfds = NULL;
        !           200:     global_writefds = NULL;
        !           201:     global_xfds = NULL;
        !           202:     
        !           203:     nfds = *pnfds;
        !           204:        /*
        !           205:         * First, TCP sockets
        !           206:         */
        !           207:        do_slowtimo = 0;
        !           208:        if (link_up) {
        !           209:                /* 
        !           210:                 * *_slowtimo needs calling if there are IP fragments
        !           211:                 * in the fragment queue, or there are TCP connections active
        !           212:                 */
        !           213:                do_slowtimo = ((tcb.so_next != &tcb) ||
        !           214:                         (&ipq.ip_link != ipq.ip_link.next));
        !           215:        
        !           216:                for (so = tcb.so_next; so != &tcb; so = so_next) {
        !           217:                        so_next = so->so_next;
        !           218:                        
        !           219:                        /*
        !           220:                         * See if we need a tcp_fasttimo
        !           221:                         */
        !           222:                        if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
        !           223:                           time_fasttimo = curtime; /* Flag when we want a fasttimo */
        !           224:                        
        !           225:                        /*
        !           226:                         * NOFDREF can include still connecting to local-host,
        !           227:                         * newly socreated() sockets etc. Don't want to select these.
        !           228:                         */
        !           229:                        if (so->so_state & SS_NOFDREF || so->s == -1)
        !           230:                           continue;
        !           231:                        
        !           232:                        /*
        !           233:                         * Set for reading sockets which are accepting
        !           234:                         */
        !           235:                        if (so->so_state & SS_FACCEPTCONN) {
        !           236:                                 FD_SET(so->s, readfds);
        !           237:                                UPD_NFDS(so->s);
        !           238:                                continue;
        !           239:                        }
        !           240:                        
        !           241:                        /*
        !           242:                         * Set for writing sockets which are connecting
        !           243:                         */
        !           244:                        if (so->so_state & SS_ISFCONNECTING) {
        !           245:                                FD_SET(so->s, writefds);
        !           246:                                UPD_NFDS(so->s);
        !           247:                                continue;
        !           248:                        }
        !           249:                        
        !           250:                        /*
        !           251:                         * Set for writing if we are connected, can send more, and
        !           252:                         * we have something to send
        !           253:                         */
        !           254:                        if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
        !           255:                                FD_SET(so->s, writefds);
        !           256:                                UPD_NFDS(so->s);
        !           257:                        }
        !           258:                        
        !           259:                        /*
        !           260:                         * Set for reading (and urgent data) if we are connected, can
        !           261:                         * receive more, and we have room for it XXX /2 ?
        !           262:                         */
        !           263:                        if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
        !           264:                                FD_SET(so->s, readfds);
        !           265:                                FD_SET(so->s, xfds);
        !           266:                                UPD_NFDS(so->s);
        !           267:                        }
        !           268:                }
        !           269:                
        !           270:                /*
        !           271:                 * UDP sockets
        !           272:                 */
        !           273:                for (so = udb.so_next; so != &udb; so = so_next) {
        !           274:                        so_next = so->so_next;
        !           275:                        
        !           276:                        /*
        !           277:                         * See if it's timed out
        !           278:                         */
        !           279:                        if (so->so_expire) {
        !           280:                                if (so->so_expire <= curtime) {
        !           281:                                        udp_detach(so);
        !           282:                                        continue;
        !           283:                                } else
        !           284:                                        do_slowtimo = 1; /* Let socket expire */
        !           285:                        }
        !           286:                        
        !           287:                        /*
        !           288:                         * When UDP packets are received from over the
        !           289:                         * link, they're sendto()'d straight away, so
        !           290:                         * no need for setting for writing
        !           291:                         * Limit the number of packets queued by this session
        !           292:                         * to 4.  Note that even though we try and limit this
        !           293:                         * to 4 packets, the session could have more queued
        !           294:                         * if the packets needed to be fragmented
        !           295:                         * (XXX <= 4 ?)
        !           296:                         */
        !           297:                        if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
        !           298:                                FD_SET(so->s, readfds);
        !           299:                                UPD_NFDS(so->s);
        !           300:                        }
        !           301:                }
        !           302:        }
        !           303:        
        !           304:        /*
        !           305:         * Setup timeout to use minimum CPU usage, especially when idle
        !           306:         */
        !           307: 
        !           308:        timeout = -1;
        !           309: 
        !           310:        /*
        !           311:         * If a slowtimo is needed, set timeout to 5ms from the last
        !           312:         * slow timeout. If a fast timeout is needed, set timeout within
        !           313:         * 2ms of when it was requested.
        !           314:         */
        !           315: #      define SLOW_TIMO 5
        !           316: #      define FAST_TIMO 2
        !           317:        if (do_slowtimo) {
        !           318:                timeout = (SLOW_TIMO - (curtime - last_slowtimo)) * 1000;
        !           319:                if (timeout < 0)
        !           320:                   timeout = 0;
        !           321:                else if (timeout > (SLOW_TIMO * 1000))
        !           322:                   timeout = SLOW_TIMO * 1000;
        !           323:                
        !           324:                /* Can only fasttimo if we also slowtimo */
        !           325:                if (time_fasttimo) {
        !           326:                        tmp_time = (FAST_TIMO - (curtime - time_fasttimo)) * 1000;
        !           327:                        if (tmp_time < 0)
        !           328:                                tmp_time = 0;
        !           329:                        
        !           330:                        /* Choose the smallest of the 2 */
        !           331:                        if (tmp_time < timeout)
        !           332:                           timeout = tmp_time;
        !           333:                }
        !           334:        }
        !           335:        *pnfds = nfds;
        !           336: 
        !           337:        /*
        !           338:         * Adjust the timeout to make the minimum timeout
        !           339:         * 2ms (XXX?) to lessen the CPU load
        !           340:         */
        !           341:        if (timeout < (FAST_TIMO * 1000))
        !           342:                timeout = FAST_TIMO * 1000;
        !           343: 
        !           344:        return timeout;
        !           345: }      
        !           346: 
        !           347: void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
        !           348: {
        !           349:     struct socket *so, *so_next;
        !           350:     int ret;
        !           351: 
        !           352:     global_readfds = readfds;
        !           353:     global_writefds = writefds;
        !           354:     global_xfds = xfds;
        !           355: 
        !           356:        /* Update time */
        !           357:        updtime();
        !           358:        
        !           359:        /*
        !           360:         * See if anything has timed out 
        !           361:         */
        !           362:        if (link_up) {
        !           363:                if (time_fasttimo && ((curtime - time_fasttimo) >= FAST_TIMO)) {
        !           364:                        tcp_fasttimo();
        !           365:                        time_fasttimo = 0;
        !           366:                }
        !           367:                if (do_slowtimo && ((curtime - last_slowtimo) >= SLOW_TIMO)) {
        !           368:                        ip_slowtimo();
        !           369:                        tcp_slowtimo();
        !           370:                        last_slowtimo = curtime;
        !           371:                }
        !           372:        }
        !           373:        
        !           374:        /*
        !           375:         * Check sockets
        !           376:         */
        !           377:        if (link_up) {
        !           378:                /*
        !           379:                 * Check TCP sockets
        !           380:                 */
        !           381:                for (so = tcb.so_next; so != &tcb; so = so_next) {
        !           382:                        so_next = so->so_next;
        !           383:                        
        !           384:                        /*
        !           385:                         * FD_ISSET is meaningless on these sockets
        !           386:                         * (and they can crash the program)
        !           387:                         */
        !           388:                        if (so->so_state & SS_NOFDREF || so->s == -1)
        !           389:                           continue;
        !           390:                        
        !           391:                        /*
        !           392:                         * Check for URG data
        !           393:                         * This will soread as well, so no need to
        !           394:                         * test for readfds below if this succeeds
        !           395:                         */
        !           396:                        if (FD_ISSET(so->s, xfds))
        !           397:                           sorecvoob(so);
        !           398:                        /*
        !           399:                         * Check sockets for reading
        !           400:                         */
        !           401:                        else if (FD_ISSET(so->s, readfds)) {
        !           402:                                /*
        !           403:                                 * Check for incoming connections
        !           404:                                 */
        !           405:                                if (so->so_state & SS_FACCEPTCONN) {
        !           406:                                        tcp_connect(so);
        !           407:                                        continue;
        !           408:                                } /* else */
        !           409:                                ret = soread(so);
        !           410:                                
        !           411:                                /* Output it if we read something */
        !           412:                                if (ret > 0)
        !           413:                                   tcp_output(sototcpcb(so));
        !           414:                        }
        !           415:                        
        !           416:                        /*
        !           417:                         * Check sockets for writing
        !           418:                         */
        !           419:                        if (FD_ISSET(so->s, writefds)) {
        !           420:                          /*
        !           421:                           * Check for non-blocking, still-connecting sockets
        !           422:                           */
        !           423:                          if (so->so_state & SS_ISFCONNECTING) {
        !           424:                            /* Connected */
        !           425:                            so->so_state &= ~SS_ISFCONNECTING;
        !           426:                            
        !           427:                            ret = send(so->s, &ret, 0, 0);
        !           428:                            if (ret < 0) {
        !           429:                              /* XXXXX Must fix, zero bytes is a NOP */
        !           430:                              if (errno == EAGAIN || errno == EWOULDBLOCK ||
        !           431:                                  errno == EINPROGRESS || errno == ENOTCONN)
        !           432:                                continue;
        !           433:                              
        !           434:                              /* else failed */
        !           435:                              so->so_state = SS_NOFDREF;
        !           436:                            }
        !           437:                            /* else so->so_state &= ~SS_ISFCONNECTING; */
        !           438:                            
        !           439:                            /*
        !           440:                             * Continue tcp_input
        !           441:                             */
        !           442:                            tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
        !           443:                            /* continue; */
        !           444:                          } else
        !           445:                            ret = sowrite(so);
        !           446:                          /*
        !           447:                           * XXXXX If we wrote something (a lot), there 
        !           448:                           * could be a need for a window update.
        !           449:                           * In the worst case, the remote will send
        !           450:                           * a window probe to get things going again
        !           451:                           */
        !           452:                        }
        !           453:                        
        !           454:                        /*
        !           455:                         * Probe a still-connecting, non-blocking socket
        !           456:                         * to check if it's still alive
        !           457:                         */
        !           458: #ifdef PROBE_CONN
        !           459:                        if (so->so_state & SS_ISFCONNECTING) {
        !           460:                          ret = recv(so->s, (char *)&ret, 0,0);
        !           461:                          
        !           462:                          if (ret < 0) {
        !           463:                            /* XXX */
        !           464:                            if (errno == EAGAIN || errno == EWOULDBLOCK ||
        !           465:                                errno == EINPROGRESS || errno == ENOTCONN)
        !           466:                              continue; /* Still connecting, continue */
        !           467:                            
        !           468:                            /* else failed */
        !           469:                            so->so_state = SS_NOFDREF;
        !           470:                            
        !           471:                            /* tcp_input will take care of it */
        !           472:                          } else {
        !           473:                            ret = send(so->s, &ret, 0,0);
        !           474:                            if (ret < 0) {
        !           475:                              /* XXX */
        !           476:                              if (errno == EAGAIN || errno == EWOULDBLOCK ||
        !           477:                                  errno == EINPROGRESS || errno == ENOTCONN)
        !           478:                                continue;
        !           479:                              /* else failed */
        !           480:                              so->so_state = SS_NOFDREF;
        !           481:                            } else
        !           482:                              so->so_state &= ~SS_ISFCONNECTING;
        !           483:                            
        !           484:                          }
        !           485:                          tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
        !           486:                        } /* SS_ISFCONNECTING */
        !           487: #endif
        !           488:                }
        !           489:                
        !           490:                /*
        !           491:                 * Now UDP sockets.
        !           492:                 * Incoming packets are sent straight away, they're not buffered.
        !           493:                 * Incoming UDP data isn't buffered either.
        !           494:                 */
        !           495:                for (so = udb.so_next; so != &udb; so = so_next) {
        !           496:                        so_next = so->so_next;
        !           497:                        
        !           498:                        if (so->s != -1 && FD_ISSET(so->s, readfds)) {
        !           499:                             sorecvfrom(so);
        !           500:                         }
        !           501:                }
        !           502:        }
        !           503:        
        !           504:        /*
        !           505:         * See if we can start outputting
        !           506:         */
        !           507:        if (if_queued && link_up)
        !           508:           if_start();
        !           509: 
        !           510:        /* clear global file descriptor sets.
        !           511:         * these reside on the stack in vl.c
        !           512:         * so they're unusable if we're not in
        !           513:         * slirp_select_fill or slirp_select_poll.
        !           514:         */
        !           515:         global_readfds = NULL;
        !           516:         global_writefds = NULL;
        !           517:         global_xfds = NULL;
        !           518: }
        !           519: 
        !           520: #define ETH_ALEN 6
        !           521: #define ETH_HLEN 14
        !           522: 
        !           523: #define ETH_P_IP       0x0800          /* Internet Protocol packet     */
        !           524: #define ETH_P_ARP      0x0806          /* Address Resolution packet    */
        !           525: 
        !           526: #define        ARPOP_REQUEST   1               /* ARP request                  */
        !           527: #define        ARPOP_REPLY     2               /* ARP reply                    */
        !           528: 
        !           529: struct ethhdr 
        !           530: {
        !           531:        unsigned char   h_dest[ETH_ALEN];       /* destination eth addr */
        !           532:        unsigned char   h_source[ETH_ALEN];     /* source ether addr    */
        !           533:        unsigned short  h_proto;                /* packet type ID field */
        !           534: };
        !           535: 
        !           536: struct arphdr
        !           537: {
        !           538:        unsigned short  ar_hrd;         /* format of hardware address   */
        !           539:        unsigned short  ar_pro;         /* format of protocol address   */
        !           540:        unsigned char   ar_hln;         /* length of hardware address   */
        !           541:        unsigned char   ar_pln;         /* length of protocol address   */
        !           542:        unsigned short  ar_op;          /* ARP opcode (command)         */
        !           543: 
        !           544:         /*
        !           545:          *      Ethernet looks like this : This bit is variable sized however...
        !           546:          */
        !           547:        unsigned char           ar_sha[ETH_ALEN];       /* sender hardware address      */
        !           548:        unsigned char           ar_sip[4];              /* sender IP address            */
        !           549:        unsigned char           ar_tha[ETH_ALEN];       /* target hardware address      */
        !           550:        unsigned char           ar_tip[4];              /* target IP address            */
        !           551: };
        !           552: 
        !           553: void arp_input(const uint8_t *pkt, int pkt_len)
        !           554: {
        !           555:     struct ethhdr *eh = (struct ethhdr *)pkt;
        !           556:     struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
        !           557:     uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)];
        !           558:     struct ethhdr *reh = (struct ethhdr *)arp_reply;
        !           559:     struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);
        !           560:     int ar_op;
        !           561:     struct ex_list *ex_ptr;
        !           562: 
        !           563:     ar_op = ntohs(ah->ar_op);
        !           564:     switch(ar_op) {
        !           565:     case ARPOP_REQUEST:
        !           566:         if (!memcmp(ah->ar_tip, &special_addr, 3)) {
        !           567:             if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS) 
        !           568:                 goto arp_ok;
        !           569:             for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
        !           570:                 if (ex_ptr->ex_addr == ah->ar_tip[3])
        !           571:                     goto arp_ok;
        !           572:             }
        !           573:             return;
        !           574:         arp_ok:
        !           575:             /* XXX: make an ARP request to have the client address */
        !           576:             memcpy(client_ethaddr, eh->h_source, ETH_ALEN);
        !           577: 
        !           578:             /* ARP request for alias/dns mac address */
        !           579:             memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
        !           580:             memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
        !           581:             reh->h_source[5] = ah->ar_tip[3];
        !           582:             reh->h_proto = htons(ETH_P_ARP);
        !           583: 
        !           584:             rah->ar_hrd = htons(1);
        !           585:             rah->ar_pro = htons(ETH_P_IP);
        !           586:             rah->ar_hln = ETH_ALEN;
        !           587:             rah->ar_pln = 4;
        !           588:             rah->ar_op = htons(ARPOP_REPLY);
        !           589:             memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
        !           590:             memcpy(rah->ar_sip, ah->ar_tip, 4);
        !           591:             memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
        !           592:             memcpy(rah->ar_tip, ah->ar_sip, 4);
        !           593:             slirp_output(arp_reply, sizeof(arp_reply));
        !           594:         }
        !           595:         break;
        !           596:     default:
        !           597:         break;
        !           598:     }
        !           599: }
        !           600: 
        !           601: void slirp_input(const uint8_t *pkt, int pkt_len)
        !           602: {
        !           603:     struct mbuf *m;
        !           604:     int proto;
        !           605: 
        !           606:     if (pkt_len < ETH_HLEN)
        !           607:         return;
        !           608:     
        !           609:     proto = (pkt[12] << 8) | pkt[13];
        !           610:     switch(proto) {
        !           611:     case ETH_P_ARP:
        !           612:         arp_input(pkt, pkt_len);
        !           613:         break;
        !           614:     case ETH_P_IP:
        !           615:         m = m_get();
        !           616:         if (!m)
        !           617:             return;
        !           618:         /* Note: we add to align the IP header */
        !           619:         m->m_len = pkt_len + 2;
        !           620:         memcpy(m->m_data + 2, pkt, pkt_len);
        !           621: 
        !           622:         m->m_data += 2 + ETH_HLEN;
        !           623:         m->m_len -= 2 + ETH_HLEN;
        !           624: 
        !           625:         ip_input(m);
        !           626:         break;
        !           627:     default:
        !           628:         break;
        !           629:     }
        !           630: }
        !           631: 
        !           632: /* output the IP packet to the ethernet device */
        !           633: void if_encap(const uint8_t *ip_data, int ip_data_len)
        !           634: {
        !           635:     uint8_t buf[1600];
        !           636:     struct ethhdr *eh = (struct ethhdr *)buf;
        !           637: 
        !           638:     if (ip_data_len + ETH_HLEN > sizeof(buf))
        !           639:         return;
        !           640: 
        !           641:     memcpy(eh->h_dest, client_ethaddr, ETH_ALEN);
        !           642:     memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1);
        !           643:     /* XXX: not correct */
        !           644:     eh->h_source[5] = CTL_ALIAS;
        !           645:     eh->h_proto = htons(ETH_P_IP);
        !           646:     memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
        !           647:     slirp_output(buf, ip_data_len + ETH_HLEN);
        !           648: }
        !           649: 
        !           650: int slirp_redir(int is_udp, int host_port, 
        !           651:                 struct in_addr guest_addr, int guest_port)
        !           652: {
        !           653:     if (is_udp) {
        !           654:         if (!udp_listen(htons(host_port), guest_addr.s_addr, 
        !           655:                         htons(guest_port), 0))
        !           656:             return -1;
        !           657:     } else {
        !           658:         if (!solisten(htons(host_port), guest_addr.s_addr, 
        !           659:                       htons(guest_port), 0))
        !           660:             return -1;
        !           661:     }
        !           662:     return 0;
        !           663: }
        !           664: 
        !           665: int slirp_add_exec(int do_pty, const char *args, int addr_low_byte, 
        !           666:                   int guest_port)
        !           667: {
        !           668:     return add_exec(&exec_list, do_pty, (char *)args, 
        !           669:                     addr_low_byte, htons(guest_port));
        !           670: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.