Annotation of qemu/slirp/slirp.c, revision 1.1.1.4

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

unix.superglobalmegacorp.com

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