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

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

unix.superglobalmegacorp.com

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