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

unix.superglobalmegacorp.com

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