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

1.1.1.5   root        1: /*
                      2:  * libslirp glue
                      3:  *
                      4:  * Copyright (c) 2004-2008 Fabrice Bellard
                      5:  *
                      6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      7:  * of this software and associated documentation files (the "Software"), to deal
                      8:  * in the Software without restriction, including without limitation the rights
                      9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     10:  * copies of the Software, and to permit persons to whom the Software is
                     11:  * furnished to do so, subject to the following conditions:
                     12:  *
                     13:  * The above copyright notice and this permission notice shall be included in
                     14:  * all copies or substantial portions of the Software.
                     15:  *
                     16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     22:  * THE SOFTWARE.
                     23:  */
                     24: #include "qemu-common.h"
1.1.1.6 ! root       25: #include "qemu-timer.h"
1.1.1.5   root       26: #include "qemu-char.h"
1.1       root       27: #include "slirp.h"
1.1.1.5   root       28: #include "hw/hw.h"
1.1       root       29: 
                     30: /* host address */
                     31: struct in_addr our_addr;
                     32: /* host dns address */
                     33: struct in_addr dns_addr;
                     34: /* host loopback address */
                     35: struct in_addr loopback_addr;
                     36: 
1.1.1.6 ! root       37: /* emulated hosts use the MAC addr 52:55:IP:IP:IP:IP */
1.1.1.4   root       38: static const uint8_t special_ethaddr[6] = {
1.1.1.6 ! root       39:     0x52, 0x55, 0x00, 0x00, 0x00, 0x00
1.1       root       40: };
                     41: 
1.1.1.5   root       42: static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
1.1       root       43: 
                     44: /* XXX: suppress those select globals */
                     45: fd_set *global_readfds, *global_writefds, *global_xfds;
                     46: 
1.1.1.6 ! root       47: u_int curtime;
        !            48: static u_int time_fasttimo, last_slowtimo;
        !            49: static int do_slowtimo;
        !            50: 
        !            51: static TAILQ_HEAD(slirp_instances, Slirp) slirp_instances =
        !            52:     TAILQ_HEAD_INITIALIZER(slirp_instances);
1.1.1.2   root       53: 
1.1       root       54: #ifdef _WIN32
                     55: 
                     56: static int get_dns_addr(struct in_addr *pdns_addr)
                     57: {
                     58:     FIXED_INFO *FixedInfo=NULL;
                     59:     ULONG    BufLen;
                     60:     DWORD    ret;
                     61:     IP_ADDR_STRING *pIPAddr;
                     62:     struct in_addr tmp_addr;
1.1.1.4   root       63: 
1.1       root       64:     FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
                     65:     BufLen = sizeof(FIXED_INFO);
1.1.1.4   root       66: 
1.1       root       67:     if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
                     68:         if (FixedInfo) {
                     69:             GlobalFree(FixedInfo);
                     70:             FixedInfo = NULL;
                     71:         }
                     72:         FixedInfo = GlobalAlloc(GPTR, BufLen);
                     73:     }
1.1.1.4   root       74: 
1.1       root       75:     if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
                     76:         printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret );
                     77:         if (FixedInfo) {
                     78:             GlobalFree(FixedInfo);
                     79:             FixedInfo = NULL;
                     80:         }
                     81:         return -1;
                     82:     }
1.1.1.4   root       83: 
1.1       root       84:     pIPAddr = &(FixedInfo->DnsServerList);
                     85:     inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
                     86:     *pdns_addr = tmp_addr;
                     87:     if (FixedInfo) {
                     88:         GlobalFree(FixedInfo);
                     89:         FixedInfo = NULL;
                     90:     }
                     91:     return 0;
                     92: }
                     93: 
1.1.1.6 ! root       94: static void winsock_cleanup(void)
        !            95: {
        !            96:     WSACleanup();
        !            97: }
        !            98: 
1.1       root       99: #else
                    100: 
                    101: static int get_dns_addr(struct in_addr *pdns_addr)
                    102: {
                    103:     char buff[512];
1.1.1.5   root      104:     char buff2[257];
1.1       root      105:     FILE *f;
                    106:     int found = 0;
                    107:     struct in_addr tmp_addr;
1.1.1.4   root      108: 
1.1       root      109:     f = fopen("/etc/resolv.conf", "r");
                    110:     if (!f)
                    111:         return -1;
                    112: 
1.1.1.4   root      113: #ifdef DEBUG
1.1       root      114:     lprint("IP address of your DNS(s): ");
1.1.1.4   root      115: #endif
1.1       root      116:     while (fgets(buff, 512, f) != NULL) {
                    117:         if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
                    118:             if (!inet_aton(buff2, &tmp_addr))
                    119:                 continue;
                    120:             if (tmp_addr.s_addr == loopback_addr.s_addr)
                    121:                 tmp_addr = our_addr;
                    122:             /* If it's the first one, set it to dns_addr */
                    123:             if (!found)
                    124:                 *pdns_addr = tmp_addr;
1.1.1.4   root      125: #ifdef DEBUG
1.1       root      126:             else
                    127:                 lprint(", ");
1.1.1.4   root      128: #endif
1.1       root      129:             if (++found > 3) {
1.1.1.4   root      130: #ifdef DEBUG
1.1       root      131:                 lprint("(more)");
1.1.1.4   root      132: #endif
1.1       root      133:                 break;
1.1.1.4   root      134:             }
                    135: #ifdef DEBUG
                    136:             else
1.1       root      137:                 lprint("%s", inet_ntoa(tmp_addr));
1.1.1.4   root      138: #endif
1.1       root      139:         }
                    140:     }
                    141:     fclose(f);
                    142:     if (!found)
                    143:         return -1;
                    144:     return 0;
                    145: }
                    146: 
                    147: #endif
                    148: 
1.1.1.6 ! root      149: static void slirp_init_once(void)
1.1       root      150: {
1.1.1.6 ! root      151:     static int initialized;
        !           152:     struct hostent *he;
        !           153:     char our_name[256];
        !           154: #ifdef _WIN32
        !           155:     WSADATA Data;
1.1       root      156: #endif
                    157: 
1.1.1.6 ! root      158:     if (initialized) {
        !           159:         return;
        !           160:     }
        !           161:     initialized = 1;
        !           162: 
        !           163: #ifdef _WIN32
        !           164:     WSAStartup(MAKEWORD(2,0), &Data);
        !           165:     atexit(winsock_cleanup);
        !           166: #endif
        !           167: 
        !           168:     loopback_addr.s_addr = htonl(INADDR_LOOPBACK);
        !           169: 
        !           170:     /* FIXME: This address may change during runtime */
        !           171:     if (gethostname(our_name, sizeof(our_name)) == 0) {
        !           172:         he = gethostbyname(our_name);
        !           173:         if (he) {
        !           174:             our_addr = *(struct in_addr *)he->h_addr;
        !           175:         }
        !           176:     }
        !           177:     if (our_addr.s_addr == 0) {
        !           178:         our_addr = loopback_addr;
        !           179:     }
        !           180: 
        !           181:     /* FIXME: This address may change during runtime */
        !           182:     if (get_dns_addr(&dns_addr) < 0) {
        !           183:         dns_addr = loopback_addr;
        !           184:     }
        !           185: }
        !           186: 
1.1.1.5   root      187: static void slirp_state_save(QEMUFile *f, void *opaque);
                    188: static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
                    189: 
1.1.1.6 ! root      190: Slirp *slirp_init(int restricted, struct in_addr vnetwork,
        !           191:                   struct in_addr vnetmask, struct in_addr vhost,
        !           192:                   const char *vhostname, const char *tftp_path,
        !           193:                   const char *bootfile, struct in_addr vdhcp_start,
        !           194:                   struct in_addr vnameserver, void *opaque)
1.1       root      195: {
1.1.1.6 ! root      196:     Slirp *slirp = qemu_mallocz(sizeof(Slirp));
1.1.1.4   root      197: 
1.1.1.6 ! root      198:     slirp_init_once();
1.1       root      199: 
1.1.1.6 ! root      200:     slirp->restricted = restricted;
1.1       root      201: 
1.1.1.6 ! root      202:     if_init(slirp);
        !           203:     ip_init(slirp);
1.1       root      204: 
                    205:     /* Initialise mbufs *after* setting the MTU */
1.1.1.6 ! root      206:     m_init(slirp);
1.1       root      207: 
1.1.1.6 ! root      208:     slirp->vnetwork_addr = vnetwork;
        !           209:     slirp->vnetwork_mask = vnetmask;
        !           210:     slirp->vhost_addr = vhost;
        !           211:     if (vhostname) {
        !           212:         pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname),
        !           213:                 vhostname);
        !           214:     }
        !           215:     if (tftp_path) {
        !           216:         slirp->tftp_prefix = qemu_strdup(tftp_path);
1.1       root      217:     }
1.1.1.6 ! root      218:     if (bootfile) {
        !           219:         slirp->bootp_filename = qemu_strdup(bootfile);
        !           220:     }
        !           221:     slirp->vdhcp_startaddr = vdhcp_start;
        !           222:     slirp->vnameserver_addr = vnameserver;
1.1       root      223: 
1.1.1.6 ! root      224:     slirp->opaque = opaque;
1.1.1.5   root      225: 
1.1.1.6 ! root      226:     register_savevm("slirp", 0, 3, slirp_state_save, slirp_state_load, slirp);
1.1       root      227: 
1.1.1.6 ! root      228:     TAILQ_INSERT_TAIL(&slirp_instances, slirp, entry);
1.1       root      229: 
1.1.1.6 ! root      230:     return slirp;
1.1       root      231: }
1.1.1.6 ! root      232: 
        !           233: void slirp_cleanup(Slirp *slirp)
1.1       root      234: {
1.1.1.6 ! root      235:     TAILQ_REMOVE(&slirp_instances, slirp, entry);
1.1.1.4   root      236: 
1.1.1.6 ! root      237:     unregister_savevm("slirp", slirp);
1.1.1.4   root      238: 
1.1.1.6 ! root      239:     qemu_free(slirp->tftp_prefix);
        !           240:     qemu_free(slirp->bootp_filename);
        !           241:     qemu_free(slirp);
1.1       root      242: }
1.1.1.6 ! root      243: 
        !           244: #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
        !           245: #define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
        !           246: #define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
1.1       root      247: 
1.1.1.4   root      248: void slirp_select_fill(int *pnfds,
1.1       root      249:                        fd_set *readfds, fd_set *writefds, fd_set *xfds)
                    250: {
1.1.1.6 ! root      251:     Slirp *slirp;
1.1       root      252:     struct socket *so, *so_next;
                    253:     int nfds;
1.1.1.6 ! root      254: 
        !           255:     if (TAILQ_EMPTY(&slirp_instances)) {
        !           256:         return;
        !           257:     }
1.1       root      258: 
                    259:     /* fail safe */
                    260:     global_readfds = NULL;
                    261:     global_writefds = NULL;
                    262:     global_xfds = NULL;
1.1.1.4   root      263: 
1.1       root      264:     nfds = *pnfds;
                    265:        /*
                    266:         * First, TCP sockets
                    267:         */
                    268:        do_slowtimo = 0;
1.1.1.6 ! root      269: 
        !           270:        TAILQ_FOREACH(slirp, &slirp_instances, entry) {
1.1.1.4   root      271:                /*
1.1       root      272:                 * *_slowtimo needs calling if there are IP fragments
                    273:                 * in the fragment queue, or there are TCP connections active
                    274:                 */
1.1.1.6 ! root      275:                do_slowtimo |= ((slirp->tcb.so_next != &slirp->tcb) ||
        !           276:                    (&slirp->ipq.ip_link != slirp->ipq.ip_link.next));
1.1.1.4   root      277: 
1.1.1.6 ! root      278:                for (so = slirp->tcb.so_next; so != &slirp->tcb;
        !           279:                     so = so_next) {
1.1       root      280:                        so_next = so->so_next;
1.1.1.4   root      281: 
1.1       root      282:                        /*
                    283:                         * See if we need a tcp_fasttimo
                    284:                         */
                    285:                        if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
                    286:                           time_fasttimo = curtime; /* Flag when we want a fasttimo */
1.1.1.4   root      287: 
1.1       root      288:                        /*
                    289:                         * NOFDREF can include still connecting to local-host,
                    290:                         * newly socreated() sockets etc. Don't want to select these.
                    291:                         */
                    292:                        if (so->so_state & SS_NOFDREF || so->s == -1)
                    293:                           continue;
1.1.1.4   root      294: 
1.1       root      295:                        /*
                    296:                         * Set for reading sockets which are accepting
                    297:                         */
                    298:                        if (so->so_state & SS_FACCEPTCONN) {
                    299:                                 FD_SET(so->s, readfds);
                    300:                                UPD_NFDS(so->s);
                    301:                                continue;
                    302:                        }
1.1.1.4   root      303: 
1.1       root      304:                        /*
                    305:                         * Set for writing sockets which are connecting
                    306:                         */
                    307:                        if (so->so_state & SS_ISFCONNECTING) {
                    308:                                FD_SET(so->s, writefds);
                    309:                                UPD_NFDS(so->s);
                    310:                                continue;
                    311:                        }
1.1.1.4   root      312: 
1.1       root      313:                        /*
                    314:                         * Set for writing if we are connected, can send more, and
                    315:                         * we have something to send
                    316:                         */
                    317:                        if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
                    318:                                FD_SET(so->s, writefds);
                    319:                                UPD_NFDS(so->s);
                    320:                        }
1.1.1.4   root      321: 
1.1       root      322:                        /*
                    323:                         * Set for reading (and urgent data) if we are connected, can
                    324:                         * receive more, and we have room for it XXX /2 ?
                    325:                         */
                    326:                        if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
                    327:                                FD_SET(so->s, readfds);
                    328:                                FD_SET(so->s, xfds);
                    329:                                UPD_NFDS(so->s);
                    330:                        }
                    331:                }
1.1.1.4   root      332: 
1.1       root      333:                /*
                    334:                 * UDP sockets
                    335:                 */
1.1.1.6 ! root      336:                for (so = slirp->udb.so_next; so != &slirp->udb;
        !           337:                     so = so_next) {
1.1       root      338:                        so_next = so->so_next;
1.1.1.4   root      339: 
1.1       root      340:                        /*
                    341:                         * See if it's timed out
                    342:                         */
                    343:                        if (so->so_expire) {
                    344:                                if (so->so_expire <= curtime) {
                    345:                                        udp_detach(so);
                    346:                                        continue;
                    347:                                } else
                    348:                                        do_slowtimo = 1; /* Let socket expire */
                    349:                        }
1.1.1.4   root      350: 
1.1       root      351:                        /*
                    352:                         * When UDP packets are received from over the
                    353:                         * link, they're sendto()'d straight away, so
                    354:                         * no need for setting for writing
                    355:                         * Limit the number of packets queued by this session
                    356:                         * to 4.  Note that even though we try and limit this
                    357:                         * to 4 packets, the session could have more queued
                    358:                         * if the packets needed to be fragmented
                    359:                         * (XXX <= 4 ?)
                    360:                         */
                    361:                        if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
                    362:                                FD_SET(so->s, readfds);
                    363:                                UPD_NFDS(so->s);
                    364:                        }
                    365:                }
                    366:        }
1.1.1.4   root      367: 
1.1       root      368:         *pnfds = nfds;
1.1.1.4   root      369: }
1.1       root      370: 
1.1.1.6 ! root      371: void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
        !           372:                        int select_error)
1.1       root      373: {
1.1.1.6 ! root      374:     Slirp *slirp;
1.1       root      375:     struct socket *so, *so_next;
                    376:     int ret;
                    377: 
1.1.1.6 ! root      378:     if (TAILQ_EMPTY(&slirp_instances)) {
        !           379:         return;
        !           380:     }
        !           381: 
1.1       root      382:     global_readfds = readfds;
                    383:     global_writefds = writefds;
                    384:     global_xfds = xfds;
                    385: 
1.1.1.6 ! root      386:     curtime = qemu_get_clock(rt_clock);
1.1.1.4   root      387: 
1.1.1.6 ! root      388:     TAILQ_FOREACH(slirp, &slirp_instances, entry) {
1.1       root      389:        /*
1.1.1.4   root      390:         * See if anything has timed out
1.1       root      391:         */
                    392:                if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
1.1.1.6 ! root      393:                        tcp_fasttimo(slirp);
1.1       root      394:                        time_fasttimo = 0;
                    395:                }
                    396:                if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
1.1.1.6 ! root      397:                        ip_slowtimo(slirp);
        !           398:                        tcp_slowtimo(slirp);
1.1       root      399:                        last_slowtimo = curtime;
                    400:                }
1.1.1.4   root      401: 
1.1       root      402:        /*
                    403:         * Check sockets
                    404:         */
1.1.1.6 ! root      405:        if (!select_error) {
1.1       root      406:                /*
                    407:                 * Check TCP sockets
                    408:                 */
1.1.1.6 ! root      409:                for (so = slirp->tcb.so_next; so != &slirp->tcb;
        !           410:                     so = so_next) {
1.1       root      411:                        so_next = so->so_next;
1.1.1.4   root      412: 
1.1       root      413:                        /*
                    414:                         * FD_ISSET is meaningless on these sockets
                    415:                         * (and they can crash the program)
                    416:                         */
                    417:                        if (so->so_state & SS_NOFDREF || so->s == -1)
                    418:                           continue;
1.1.1.4   root      419: 
1.1       root      420:                        /*
                    421:                         * Check for URG data
                    422:                         * This will soread as well, so no need to
                    423:                         * test for readfds below if this succeeds
                    424:                         */
                    425:                        if (FD_ISSET(so->s, xfds))
                    426:                           sorecvoob(so);
                    427:                        /*
                    428:                         * Check sockets for reading
                    429:                         */
                    430:                        else if (FD_ISSET(so->s, readfds)) {
                    431:                                /*
                    432:                                 * Check for incoming connections
                    433:                                 */
                    434:                                if (so->so_state & SS_FACCEPTCONN) {
                    435:                                        tcp_connect(so);
                    436:                                        continue;
                    437:                                } /* else */
                    438:                                ret = soread(so);
1.1.1.4   root      439: 
1.1       root      440:                                /* Output it if we read something */
                    441:                                if (ret > 0)
                    442:                                   tcp_output(sototcpcb(so));
                    443:                        }
1.1.1.4   root      444: 
1.1       root      445:                        /*
                    446:                         * Check sockets for writing
                    447:                         */
                    448:                        if (FD_ISSET(so->s, writefds)) {
                    449:                          /*
                    450:                           * Check for non-blocking, still-connecting sockets
                    451:                           */
                    452:                          if (so->so_state & SS_ISFCONNECTING) {
                    453:                            /* Connected */
                    454:                            so->so_state &= ~SS_ISFCONNECTING;
1.1.1.4   root      455: 
1.1.1.6 ! root      456:                            ret = send(so->s, (const void *) &ret, 0, 0);
1.1       root      457:                            if (ret < 0) {
                    458:                              /* XXXXX Must fix, zero bytes is a NOP */
                    459:                              if (errno == EAGAIN || errno == EWOULDBLOCK ||
                    460:                                  errno == EINPROGRESS || errno == ENOTCONN)
                    461:                                continue;
1.1.1.4   root      462: 
1.1       root      463:                              /* else failed */
1.1.1.6 ! root      464:                              so->so_state &= SS_PERSISTENT_MASK;
        !           465:                              so->so_state |= SS_NOFDREF;
1.1       root      466:                            }
                    467:                            /* else so->so_state &= ~SS_ISFCONNECTING; */
1.1.1.4   root      468: 
1.1       root      469:                            /*
                    470:                             * Continue tcp_input
                    471:                             */
                    472:                            tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
                    473:                            /* continue; */
                    474:                          } else
                    475:                            ret = sowrite(so);
                    476:                          /*
1.1.1.4   root      477:                           * XXXXX If we wrote something (a lot), there
1.1       root      478:                           * could be a need for a window update.
                    479:                           * In the worst case, the remote will send
                    480:                           * a window probe to get things going again
                    481:                           */
                    482:                        }
1.1.1.4   root      483: 
1.1       root      484:                        /*
                    485:                         * Probe a still-connecting, non-blocking socket
                    486:                         * to check if it's still alive
                    487:                         */
                    488: #ifdef PROBE_CONN
                    489:                        if (so->so_state & SS_ISFCONNECTING) {
                    490:                          ret = recv(so->s, (char *)&ret, 0,0);
1.1.1.4   root      491: 
1.1       root      492:                          if (ret < 0) {
                    493:                            /* XXX */
                    494:                            if (errno == EAGAIN || errno == EWOULDBLOCK ||
                    495:                                errno == EINPROGRESS || errno == ENOTCONN)
                    496:                              continue; /* Still connecting, continue */
1.1.1.4   root      497: 
1.1       root      498:                            /* else failed */
1.1.1.6 ! root      499:                            so->so_state &= SS_PERSISTENT_MASK;
        !           500:                            so->so_state |= SS_NOFDREF;
1.1.1.4   root      501: 
1.1       root      502:                            /* tcp_input will take care of it */
                    503:                          } else {
                    504:                            ret = send(so->s, &ret, 0,0);
                    505:                            if (ret < 0) {
                    506:                              /* XXX */
                    507:                              if (errno == EAGAIN || errno == EWOULDBLOCK ||
                    508:                                  errno == EINPROGRESS || errno == ENOTCONN)
                    509:                                continue;
                    510:                              /* else failed */
1.1.1.6 ! root      511:                              so->so_state &= SS_PERSISTENT_MASK;
        !           512:                              so->so_state |= SS_NOFDREF;
1.1       root      513:                            } else
                    514:                              so->so_state &= ~SS_ISFCONNECTING;
1.1.1.4   root      515: 
1.1       root      516:                          }
                    517:                          tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
                    518:                        } /* SS_ISFCONNECTING */
                    519: #endif
                    520:                }
1.1.1.4   root      521: 
1.1       root      522:                /*
                    523:                 * Now UDP sockets.
                    524:                 * Incoming packets are sent straight away, they're not buffered.
                    525:                 * Incoming UDP data isn't buffered either.
                    526:                 */
1.1.1.6 ! root      527:                for (so = slirp->udb.so_next; so != &slirp->udb;
        !           528:                     so = so_next) {
1.1       root      529:                        so_next = so->so_next;
1.1.1.4   root      530: 
1.1       root      531:                        if (so->s != -1 && FD_ISSET(so->s, readfds)) {
                    532:                             sorecvfrom(so);
                    533:                         }
                    534:                }
                    535:        }
1.1.1.4   root      536: 
1.1       root      537:        /*
                    538:         * See if we can start outputting
                    539:         */
1.1.1.6 ! root      540:        if (slirp->if_queued) {
        !           541:            if_start(slirp);
        !           542:        }
        !           543:     }
1.1       root      544: 
                    545:        /* clear global file descriptor sets.
                    546:         * these reside on the stack in vl.c
                    547:         * so they're unusable if we're not in
                    548:         * slirp_select_fill or slirp_select_poll.
                    549:         */
                    550:         global_readfds = NULL;
                    551:         global_writefds = NULL;
                    552:         global_xfds = NULL;
                    553: }
                    554: 
                    555: #define ETH_ALEN 6
                    556: #define ETH_HLEN 14
                    557: 
                    558: #define ETH_P_IP       0x0800          /* Internet Protocol packet     */
                    559: #define ETH_P_ARP      0x0806          /* Address Resolution packet    */
                    560: 
                    561: #define        ARPOP_REQUEST   1               /* ARP request                  */
                    562: #define        ARPOP_REPLY     2               /* ARP reply                    */
                    563: 
1.1.1.4   root      564: struct ethhdr
1.1       root      565: {
                    566:        unsigned char   h_dest[ETH_ALEN];       /* destination eth addr */
                    567:        unsigned char   h_source[ETH_ALEN];     /* source ether addr    */
                    568:        unsigned short  h_proto;                /* packet type ID field */
                    569: };
                    570: 
                    571: struct arphdr
                    572: {
                    573:        unsigned short  ar_hrd;         /* format of hardware address   */
                    574:        unsigned short  ar_pro;         /* format of protocol address   */
                    575:        unsigned char   ar_hln;         /* length of hardware address   */
                    576:        unsigned char   ar_pln;         /* length of protocol address   */
                    577:        unsigned short  ar_op;          /* ARP opcode (command)         */
                    578: 
                    579:         /*
                    580:          *      Ethernet looks like this : This bit is variable sized however...
                    581:          */
                    582:        unsigned char           ar_sha[ETH_ALEN];       /* sender hardware address      */
1.1.1.6 ! root      583:        uint32_t                ar_sip;                 /* sender IP address            */
1.1       root      584:        unsigned char           ar_tha[ETH_ALEN];       /* target hardware address      */
1.1.1.6 ! root      585:        uint32_t                ar_tip  ;               /* target IP address            */
        !           586: } __attribute__((packed));
1.1       root      587: 
1.1.1.6 ! root      588: static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
1.1       root      589: {
                    590:     struct ethhdr *eh = (struct ethhdr *)pkt;
                    591:     struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
                    592:     uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)];
                    593:     struct ethhdr *reh = (struct ethhdr *)arp_reply;
                    594:     struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);
                    595:     int ar_op;
                    596:     struct ex_list *ex_ptr;
                    597: 
                    598:     ar_op = ntohs(ah->ar_op);
                    599:     switch(ar_op) {
                    600:     case ARPOP_REQUEST:
1.1.1.6 ! root      601:         if ((ah->ar_tip & slirp->vnetwork_mask.s_addr) ==
        !           602:             slirp->vnetwork_addr.s_addr) {
        !           603:             if (ah->ar_tip == slirp->vnameserver_addr.s_addr ||
        !           604:                 ah->ar_tip == slirp->vhost_addr.s_addr)
1.1       root      605:                 goto arp_ok;
1.1.1.6 ! root      606:             for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
        !           607:                 if (ex_ptr->ex_addr.s_addr == ah->ar_tip)
1.1       root      608:                     goto arp_ok;
                    609:             }
                    610:             return;
                    611:         arp_ok:
                    612:             /* XXX: make an ARP request to have the client address */
1.1.1.6 ! root      613:             memcpy(slirp->client_ethaddr, eh->h_source, ETH_ALEN);
1.1       root      614: 
                    615:             /* ARP request for alias/dns mac address */
                    616:             memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
1.1.1.6 ! root      617:             memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
        !           618:             memcpy(&reh->h_source[2], &ah->ar_tip, 4);
1.1       root      619:             reh->h_proto = htons(ETH_P_ARP);
                    620: 
                    621:             rah->ar_hrd = htons(1);
                    622:             rah->ar_pro = htons(ETH_P_IP);
                    623:             rah->ar_hln = ETH_ALEN;
                    624:             rah->ar_pln = 4;
                    625:             rah->ar_op = htons(ARPOP_REPLY);
                    626:             memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
1.1.1.6 ! root      627:             rah->ar_sip = ah->ar_tip;
1.1       root      628:             memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
1.1.1.6 ! root      629:             rah->ar_tip = ah->ar_sip;
        !           630:             slirp_output(slirp->opaque, arp_reply, sizeof(arp_reply));
1.1       root      631:         }
                    632:         break;
1.1.1.5   root      633:     case ARPOP_REPLY:
                    634:         /* reply to request of client mac address ? */
1.1.1.6 ! root      635:         if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN) &&
        !           636:             ah->ar_sip == slirp->client_ipaddr.s_addr) {
        !           637:             memcpy(slirp->client_ethaddr, ah->ar_sha, ETH_ALEN);
1.1.1.5   root      638:         }
                    639:         break;
1.1       root      640:     default:
                    641:         break;
                    642:     }
                    643: }
                    644: 
1.1.1.6 ! root      645: void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
1.1       root      646: {
                    647:     struct mbuf *m;
                    648:     int proto;
                    649: 
                    650:     if (pkt_len < ETH_HLEN)
                    651:         return;
1.1.1.4   root      652: 
1.1       root      653:     proto = ntohs(*(uint16_t *)(pkt + 12));
                    654:     switch(proto) {
                    655:     case ETH_P_ARP:
1.1.1.6 ! root      656:         arp_input(slirp, pkt, pkt_len);
1.1       root      657:         break;
                    658:     case ETH_P_IP:
1.1.1.6 ! root      659:         m = m_get(slirp);
1.1       root      660:         if (!m)
                    661:             return;
1.1.1.3   root      662:         /* Note: we add to align the IP header */
1.1.1.5   root      663:         if (M_FREEROOM(m) < pkt_len + 2) {
                    664:             m_inc(m, pkt_len + 2);
                    665:         }
1.1.1.3   root      666:         m->m_len = pkt_len + 2;
                    667:         memcpy(m->m_data + 2, pkt, pkt_len);
1.1       root      668: 
1.1.1.3   root      669:         m->m_data += 2 + ETH_HLEN;
                    670:         m->m_len -= 2 + ETH_HLEN;
1.1       root      671: 
                    672:         ip_input(m);
                    673:         break;
                    674:     default:
                    675:         break;
                    676:     }
                    677: }
                    678: 
                    679: /* output the IP packet to the ethernet device */
1.1.1.6 ! root      680: void if_encap(Slirp *slirp, const uint8_t *ip_data, int ip_data_len)
1.1       root      681: {
                    682:     uint8_t buf[1600];
                    683:     struct ethhdr *eh = (struct ethhdr *)buf;
                    684: 
                    685:     if (ip_data_len + ETH_HLEN > sizeof(buf))
                    686:         return;
1.1.1.5   root      687:     
1.1.1.6 ! root      688:     if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN)) {
1.1.1.5   root      689:         uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];
                    690:         struct ethhdr *reh = (struct ethhdr *)arp_req;
                    691:         struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN);
                    692:         const struct ip *iph = (const struct ip *)ip_data;
                    693: 
                    694:         /* If the client addr is not known, there is no point in
                    695:            sending the packet to it. Normally the sender should have
                    696:            done an ARP request to get its MAC address. Here we do it
                    697:            in place of sending the packet and we hope that the sender
                    698:            will retry sending its packet. */
                    699:         memset(reh->h_dest, 0xff, ETH_ALEN);
1.1.1.6 ! root      700:         memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
        !           701:         memcpy(&reh->h_source[2], &slirp->vhost_addr, 4);
1.1.1.5   root      702:         reh->h_proto = htons(ETH_P_ARP);
                    703:         rah->ar_hrd = htons(1);
                    704:         rah->ar_pro = htons(ETH_P_IP);
                    705:         rah->ar_hln = ETH_ALEN;
                    706:         rah->ar_pln = 4;
                    707:         rah->ar_op = htons(ARPOP_REQUEST);
                    708:         /* source hw addr */
1.1.1.6 ! root      709:         memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 4);
        !           710:         memcpy(&rah->ar_sha[2], &slirp->vhost_addr, 4);
1.1.1.5   root      711:         /* source IP */
1.1.1.6 ! root      712:         rah->ar_sip = slirp->vhost_addr.s_addr;
1.1.1.5   root      713:         /* target hw addr (none) */
                    714:         memset(rah->ar_tha, 0, ETH_ALEN);
                    715:         /* target IP */
1.1.1.6 ! root      716:         rah->ar_tip = iph->ip_dst.s_addr;
        !           717:         slirp->client_ipaddr = iph->ip_dst;
        !           718:         slirp_output(slirp->opaque, arp_req, sizeof(arp_req));
1.1.1.5   root      719:     } else {
1.1.1.6 ! root      720:         memcpy(eh->h_dest, slirp->client_ethaddr, ETH_ALEN);
        !           721:         memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4);
1.1.1.5   root      722:         /* XXX: not correct */
1.1.1.6 ! root      723:         memcpy(&eh->h_source[2], &slirp->vhost_addr, 4);
1.1.1.5   root      724:         eh->h_proto = htons(ETH_P_IP);
                    725:         memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
1.1.1.6 ! root      726:         slirp_output(slirp->opaque, buf, ip_data_len + ETH_HLEN);
1.1.1.5   root      727:     }
1.1       root      728: }
                    729: 
1.1.1.6 ! root      730: /* Drop host forwarding rule, return 0 if found. */
        !           731: int slirp_remove_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
        !           732:                          int host_port)
        !           733: {
        !           734:     struct socket *so;
        !           735:     struct socket *head = (is_udp ? &slirp->udb : &slirp->tcb);
        !           736:     struct sockaddr_in addr;
        !           737:     int port = htons(host_port);
        !           738:     socklen_t addr_len;
        !           739: 
        !           740:     for (so = head->so_next; so != head; so = so->so_next) {
        !           741:         addr_len = sizeof(addr);
        !           742:         if ((so->so_state & SS_HOSTFWD) &&
        !           743:             getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 &&
        !           744:             addr.sin_addr.s_addr == host_addr.s_addr &&
        !           745:             addr.sin_port == port) {
        !           746:             close(so->s);
        !           747:             sofree(so);
        !           748:             return 0;
        !           749:         }
        !           750:     }
        !           751: 
        !           752:     return -1;
        !           753: }
        !           754: 
        !           755: int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
        !           756:                       int host_port, struct in_addr guest_addr, int guest_port)
1.1       root      757: {
1.1.1.6 ! root      758:     if (!guest_addr.s_addr) {
        !           759:         guest_addr = slirp->vdhcp_startaddr;
        !           760:     }
1.1       root      761:     if (is_udp) {
1.1.1.6 ! root      762:         if (!udp_listen(slirp, host_addr.s_addr, htons(host_port),
        !           763:                         guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))
1.1       root      764:             return -1;
                    765:     } else {
1.1.1.6 ! root      766:         if (!tcp_listen(slirp, host_addr.s_addr, htons(host_port),
        !           767:                         guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))
1.1       root      768:             return -1;
                    769:     }
                    770:     return 0;
                    771: }
                    772: 
1.1.1.6 ! root      773: int slirp_add_exec(Slirp *slirp, int do_pty, const void *args,
        !           774:                    struct in_addr *guest_addr, int guest_port)
1.1       root      775: {
1.1.1.6 ! root      776:     if (!guest_addr->s_addr) {
        !           777:         guest_addr->s_addr = slirp->vnetwork_addr.s_addr |
        !           778:             (htonl(0x0204) & ~slirp->vnetwork_mask.s_addr);
        !           779:     }
        !           780:     if ((guest_addr->s_addr & slirp->vnetwork_mask.s_addr) !=
        !           781:         slirp->vnetwork_addr.s_addr ||
        !           782:         guest_addr->s_addr == slirp->vhost_addr.s_addr ||
        !           783:         guest_addr->s_addr == slirp->vnameserver_addr.s_addr) {
        !           784:         return -1;
        !           785:     }
        !           786:     return add_exec(&slirp->exec_list, do_pty, (char *)args, *guest_addr,
        !           787:                     htons(guest_port));
1.1       root      788: }
1.1.1.5   root      789: 
                    790: ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
                    791: {
                    792:        if (so->s == -1 && so->extra) {
                    793:                qemu_chr_write(so->extra, buf, len);
                    794:                return len;
                    795:        }
                    796: 
                    797:        return send(so->s, buf, len, flags);
                    798: }
                    799: 
1.1.1.6 ! root      800: static struct socket *
        !           801: slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, int guest_port)
1.1.1.5   root      802: {
1.1.1.6 ! root      803:     struct socket *so;
1.1.1.5   root      804: 
1.1.1.6 ! root      805:     for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) {
        !           806:         if (so->so_faddr.s_addr == guest_addr.s_addr &&
        !           807:             htons(so->so_fport) == guest_port) {
        !           808:             return so;
        !           809:         }
        !           810:     }
        !           811:     return NULL;
1.1.1.5   root      812: }
                    813: 
1.1.1.6 ! root      814: size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr,
        !           815:                              int guest_port)
1.1.1.5   root      816: {
                    817:        struct iovec iov[2];
                    818:        struct socket *so;
                    819: 
1.1.1.6 ! root      820:        so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
1.1.1.5   root      821: 
                    822:        if (!so || so->so_state & SS_NOFDREF)
                    823:                return 0;
                    824: 
                    825:        if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen/2))
                    826:                return 0;
                    827: 
                    828:        return sopreprbuf(so, iov, NULL);
                    829: }
                    830: 
1.1.1.6 ! root      831: void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port,
        !           832:                        const uint8_t *buf, int size)
1.1.1.5   root      833: {
                    834:     int ret;
1.1.1.6 ! root      835:     struct socket *so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
        !           836: 
1.1.1.5   root      837:     if (!so)
                    838:         return;
                    839: 
                    840:     ret = soreadbuf(so, (const char *)buf, size);
                    841: 
                    842:     if (ret > 0)
                    843:         tcp_output(sototcpcb(so));
                    844: }
                    845: 
                    846: static void slirp_tcp_save(QEMUFile *f, struct tcpcb *tp)
                    847: {
                    848:     int i;
                    849: 
                    850:     qemu_put_sbe16(f, tp->t_state);
                    851:     for (i = 0; i < TCPT_NTIMERS; i++)
                    852:         qemu_put_sbe16(f, tp->t_timer[i]);
                    853:     qemu_put_sbe16(f, tp->t_rxtshift);
                    854:     qemu_put_sbe16(f, tp->t_rxtcur);
                    855:     qemu_put_sbe16(f, tp->t_dupacks);
                    856:     qemu_put_be16(f, tp->t_maxseg);
                    857:     qemu_put_sbyte(f, tp->t_force);
                    858:     qemu_put_be16(f, tp->t_flags);
                    859:     qemu_put_be32(f, tp->snd_una);
                    860:     qemu_put_be32(f, tp->snd_nxt);
                    861:     qemu_put_be32(f, tp->snd_up);
                    862:     qemu_put_be32(f, tp->snd_wl1);
                    863:     qemu_put_be32(f, tp->snd_wl2);
                    864:     qemu_put_be32(f, tp->iss);
                    865:     qemu_put_be32(f, tp->snd_wnd);
                    866:     qemu_put_be32(f, tp->rcv_wnd);
                    867:     qemu_put_be32(f, tp->rcv_nxt);
                    868:     qemu_put_be32(f, tp->rcv_up);
                    869:     qemu_put_be32(f, tp->irs);
                    870:     qemu_put_be32(f, tp->rcv_adv);
                    871:     qemu_put_be32(f, tp->snd_max);
                    872:     qemu_put_be32(f, tp->snd_cwnd);
                    873:     qemu_put_be32(f, tp->snd_ssthresh);
                    874:     qemu_put_sbe16(f, tp->t_idle);
                    875:     qemu_put_sbe16(f, tp->t_rtt);
                    876:     qemu_put_be32(f, tp->t_rtseq);
                    877:     qemu_put_sbe16(f, tp->t_srtt);
                    878:     qemu_put_sbe16(f, tp->t_rttvar);
                    879:     qemu_put_be16(f, tp->t_rttmin);
                    880:     qemu_put_be32(f, tp->max_sndwnd);
                    881:     qemu_put_byte(f, tp->t_oobflags);
                    882:     qemu_put_byte(f, tp->t_iobc);
                    883:     qemu_put_sbe16(f, tp->t_softerror);
                    884:     qemu_put_byte(f, tp->snd_scale);
                    885:     qemu_put_byte(f, tp->rcv_scale);
                    886:     qemu_put_byte(f, tp->request_r_scale);
                    887:     qemu_put_byte(f, tp->requested_s_scale);
                    888:     qemu_put_be32(f, tp->ts_recent);
                    889:     qemu_put_be32(f, tp->ts_recent_age);
                    890:     qemu_put_be32(f, tp->last_ack_sent);
                    891: }
                    892: 
                    893: static void slirp_sbuf_save(QEMUFile *f, struct sbuf *sbuf)
                    894: {
                    895:     uint32_t off;
                    896: 
                    897:     qemu_put_be32(f, sbuf->sb_cc);
                    898:     qemu_put_be32(f, sbuf->sb_datalen);
                    899:     off = (uint32_t)(sbuf->sb_wptr - sbuf->sb_data);
                    900:     qemu_put_sbe32(f, off);
                    901:     off = (uint32_t)(sbuf->sb_rptr - sbuf->sb_data);
                    902:     qemu_put_sbe32(f, off);
                    903:     qemu_put_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
                    904: }
                    905: 
                    906: static void slirp_socket_save(QEMUFile *f, struct socket *so)
                    907: {
                    908:     qemu_put_be32(f, so->so_urgc);
                    909:     qemu_put_be32(f, so->so_faddr.s_addr);
                    910:     qemu_put_be32(f, so->so_laddr.s_addr);
                    911:     qemu_put_be16(f, so->so_fport);
                    912:     qemu_put_be16(f, so->so_lport);
                    913:     qemu_put_byte(f, so->so_iptos);
                    914:     qemu_put_byte(f, so->so_emu);
                    915:     qemu_put_byte(f, so->so_type);
                    916:     qemu_put_be32(f, so->so_state);
                    917:     slirp_sbuf_save(f, &so->so_rcv);
                    918:     slirp_sbuf_save(f, &so->so_snd);
                    919:     slirp_tcp_save(f, so->so_tcpcb);
                    920: }
                    921: 
1.1.1.6 ! root      922: static void slirp_bootp_save(QEMUFile *f, Slirp *slirp)
        !           923: {
        !           924:     int i;
        !           925: 
        !           926:     for (i = 0; i < NB_BOOTP_CLIENTS; i++) {
        !           927:         qemu_put_be16(f, slirp->bootp_clients[i].allocated);
        !           928:         qemu_put_buffer(f, slirp->bootp_clients[i].macaddr, 6);
        !           929:     }
        !           930: }
        !           931: 
1.1.1.5   root      932: static void slirp_state_save(QEMUFile *f, void *opaque)
                    933: {
1.1.1.6 ! root      934:     Slirp *slirp = opaque;
1.1.1.5   root      935:     struct ex_list *ex_ptr;
                    936: 
1.1.1.6 ! root      937:     for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
1.1.1.5   root      938:         if (ex_ptr->ex_pty == 3) {
                    939:             struct socket *so;
1.1.1.6 ! root      940:             so = slirp_find_ctl_socket(slirp, ex_ptr->ex_addr,
        !           941:                                        ntohs(ex_ptr->ex_fport));
1.1.1.5   root      942:             if (!so)
                    943:                 continue;
                    944: 
                    945:             qemu_put_byte(f, 42);
                    946:             slirp_socket_save(f, so);
                    947:         }
                    948:     qemu_put_byte(f, 0);
1.1.1.6 ! root      949: 
        !           950:     qemu_put_be16(f, slirp->ip_id);
        !           951: 
        !           952:     slirp_bootp_save(f, slirp);
1.1.1.5   root      953: }
                    954: 
                    955: static void slirp_tcp_load(QEMUFile *f, struct tcpcb *tp)
                    956: {
                    957:     int i;
                    958: 
                    959:     tp->t_state = qemu_get_sbe16(f);
                    960:     for (i = 0; i < TCPT_NTIMERS; i++)
                    961:         tp->t_timer[i] = qemu_get_sbe16(f);
                    962:     tp->t_rxtshift = qemu_get_sbe16(f);
                    963:     tp->t_rxtcur = qemu_get_sbe16(f);
                    964:     tp->t_dupacks = qemu_get_sbe16(f);
                    965:     tp->t_maxseg = qemu_get_be16(f);
                    966:     tp->t_force = qemu_get_sbyte(f);
                    967:     tp->t_flags = qemu_get_be16(f);
                    968:     tp->snd_una = qemu_get_be32(f);
                    969:     tp->snd_nxt = qemu_get_be32(f);
                    970:     tp->snd_up = qemu_get_be32(f);
                    971:     tp->snd_wl1 = qemu_get_be32(f);
                    972:     tp->snd_wl2 = qemu_get_be32(f);
                    973:     tp->iss = qemu_get_be32(f);
                    974:     tp->snd_wnd = qemu_get_be32(f);
                    975:     tp->rcv_wnd = qemu_get_be32(f);
                    976:     tp->rcv_nxt = qemu_get_be32(f);
                    977:     tp->rcv_up = qemu_get_be32(f);
                    978:     tp->irs = qemu_get_be32(f);
                    979:     tp->rcv_adv = qemu_get_be32(f);
                    980:     tp->snd_max = qemu_get_be32(f);
                    981:     tp->snd_cwnd = qemu_get_be32(f);
                    982:     tp->snd_ssthresh = qemu_get_be32(f);
                    983:     tp->t_idle = qemu_get_sbe16(f);
                    984:     tp->t_rtt = qemu_get_sbe16(f);
                    985:     tp->t_rtseq = qemu_get_be32(f);
                    986:     tp->t_srtt = qemu_get_sbe16(f);
                    987:     tp->t_rttvar = qemu_get_sbe16(f);
                    988:     tp->t_rttmin = qemu_get_be16(f);
                    989:     tp->max_sndwnd = qemu_get_be32(f);
                    990:     tp->t_oobflags = qemu_get_byte(f);
                    991:     tp->t_iobc = qemu_get_byte(f);
                    992:     tp->t_softerror = qemu_get_sbe16(f);
                    993:     tp->snd_scale = qemu_get_byte(f);
                    994:     tp->rcv_scale = qemu_get_byte(f);
                    995:     tp->request_r_scale = qemu_get_byte(f);
                    996:     tp->requested_s_scale = qemu_get_byte(f);
                    997:     tp->ts_recent = qemu_get_be32(f);
                    998:     tp->ts_recent_age = qemu_get_be32(f);
                    999:     tp->last_ack_sent = qemu_get_be32(f);
                   1000:     tcp_template(tp);
                   1001: }
                   1002: 
                   1003: static int slirp_sbuf_load(QEMUFile *f, struct sbuf *sbuf)
                   1004: {
                   1005:     uint32_t off, sb_cc, sb_datalen;
                   1006: 
                   1007:     sb_cc = qemu_get_be32(f);
                   1008:     sb_datalen = qemu_get_be32(f);
                   1009: 
                   1010:     sbreserve(sbuf, sb_datalen);
                   1011: 
                   1012:     if (sbuf->sb_datalen != sb_datalen)
                   1013:         return -ENOMEM;
                   1014: 
                   1015:     sbuf->sb_cc = sb_cc;
                   1016: 
                   1017:     off = qemu_get_sbe32(f);
                   1018:     sbuf->sb_wptr = sbuf->sb_data + off;
                   1019:     off = qemu_get_sbe32(f);
                   1020:     sbuf->sb_rptr = sbuf->sb_data + off;
                   1021:     qemu_get_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
                   1022: 
                   1023:     return 0;
                   1024: }
                   1025: 
                   1026: static int slirp_socket_load(QEMUFile *f, struct socket *so)
                   1027: {
                   1028:     if (tcp_attach(so) < 0)
                   1029:         return -ENOMEM;
                   1030: 
                   1031:     so->so_urgc = qemu_get_be32(f);
                   1032:     so->so_faddr.s_addr = qemu_get_be32(f);
                   1033:     so->so_laddr.s_addr = qemu_get_be32(f);
                   1034:     so->so_fport = qemu_get_be16(f);
                   1035:     so->so_lport = qemu_get_be16(f);
                   1036:     so->so_iptos = qemu_get_byte(f);
                   1037:     so->so_emu = qemu_get_byte(f);
                   1038:     so->so_type = qemu_get_byte(f);
                   1039:     so->so_state = qemu_get_be32(f);
                   1040:     if (slirp_sbuf_load(f, &so->so_rcv) < 0)
                   1041:         return -ENOMEM;
                   1042:     if (slirp_sbuf_load(f, &so->so_snd) < 0)
                   1043:         return -ENOMEM;
                   1044:     slirp_tcp_load(f, so->so_tcpcb);
                   1045: 
                   1046:     return 0;
                   1047: }
                   1048: 
1.1.1.6 ! root     1049: static void slirp_bootp_load(QEMUFile *f, Slirp *slirp)
        !          1050: {
        !          1051:     int i;
        !          1052: 
        !          1053:     for (i = 0; i < NB_BOOTP_CLIENTS; i++) {
        !          1054:         slirp->bootp_clients[i].allocated = qemu_get_be16(f);
        !          1055:         qemu_get_buffer(f, slirp->bootp_clients[i].macaddr, 6);
        !          1056:     }
        !          1057: }
        !          1058: 
1.1.1.5   root     1059: static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
                   1060: {
1.1.1.6 ! root     1061:     Slirp *slirp = opaque;
1.1.1.5   root     1062:     struct ex_list *ex_ptr;
                   1063:     int r;
                   1064: 
                   1065:     while ((r = qemu_get_byte(f))) {
                   1066:         int ret;
1.1.1.6 ! root     1067:         struct socket *so = socreate(slirp);
1.1.1.5   root     1068: 
                   1069:         if (!so)
                   1070:             return -ENOMEM;
                   1071: 
                   1072:         ret = slirp_socket_load(f, so);
                   1073: 
                   1074:         if (ret < 0)
                   1075:             return ret;
                   1076: 
1.1.1.6 ! root     1077:         if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) !=
        !          1078:             slirp->vnetwork_addr.s_addr) {
1.1.1.5   root     1079:             return -EINVAL;
1.1.1.6 ! root     1080:         }
        !          1081:         for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
1.1.1.5   root     1082:             if (ex_ptr->ex_pty == 3 &&
1.1.1.6 ! root     1083:                 so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr &&
        !          1084:                 so->so_fport == ex_ptr->ex_fport) {
1.1.1.5   root     1085:                 break;
1.1.1.6 ! root     1086:             }
        !          1087:         }
1.1.1.5   root     1088:         if (!ex_ptr)
                   1089:             return -EINVAL;
                   1090: 
                   1091:         so->extra = (void *)ex_ptr->ex_exec;
                   1092:     }
                   1093: 
1.1.1.6 ! root     1094:     if (version_id >= 2) {
        !          1095:         slirp->ip_id = qemu_get_be16(f);
        !          1096:     }
        !          1097: 
        !          1098:     if (version_id >= 3) {
        !          1099:         slirp_bootp_load(f, slirp);
        !          1100:     }
        !          1101: 
1.1.1.5   root     1102:     return 0;
                   1103: }

unix.superglobalmegacorp.com

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