* [Qemu-devel] PATCH, RFC: Slirp improvements @ 2007-10-20 18:42 Blue Swirl 2007-10-23 17:42 ` [Qemu-devel] " Blue Swirl 0 siblings, 1 reply; 4+ messages in thread From: Blue Swirl @ 2007-10-20 18:42 UTC (permalink / raw) To: qemu-devel [-- Attachment #1: Type: text/plain, Size: 525 bytes --] Hi, This patch makes the SLIRP library able to handle more than one instance of itself by putting all globals inside a structure. Qemu needs some rearrangement to make the VLANs separate. The patch is loosely based on VirtualBox SLIRP changes but without the aHungarian nNotation ugliness. There are some other changes too, for example addition of "info slirp" monitor command. I tried to change the mbuf/packet chaining to support 64-bit pointers on x86-64 but the linking code is pretty hard to understand. Any comments? [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: slirp.diff --] [-- Type: text/x-diff; name=slirp.diff, Size: 183501 bytes --] Index: qemu/slirp/bootp.c =================================================================== --- qemu.orig/slirp/bootp.c 2007-10-20 07:33:35.000000000 +0000 +++ qemu/slirp/bootp.c 2007-10-20 13:10:08.000000000 +0000 @@ -25,20 +25,6 @@ /* XXX: only DHCP is supported */ -#define NB_ADDR 16 - -#define START_ADDR 15 - -#define LEASE_TIME (24 * 3600) - -typedef struct { - uint8_t allocated; - uint8_t macaddr[6]; -} BOOTPClient; - -BOOTPClient bootp_clients[NB_ADDR]; - -const char *bootp_filename; static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE }; @@ -49,37 +35,49 @@ #define dprintf(fmt, args...) #endif -static BOOTPClient *get_new_addr(struct in_addr *paddr) +static BOOTPClient *get_new_addr(slirp_state_t *s, struct in_addr *paddr) { BOOTPClient *bc; int i; for(i = 0; i < NB_ADDR; i++) { - if (!bootp_clients[i].allocated) + if (!s->bootp_clients[i].allocated) goto found; } return NULL; found: - bc = &bootp_clients[i]; + bc = &s->bootp_clients[i]; bc->allocated = 1; - paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR)); + paddr->s_addr = htonl(ntohl(s->special_addr.s_addr) | (i + START_ADDR)); return bc; } -static BOOTPClient *find_addr(struct in_addr *paddr, const uint8_t *macaddr) +static void release_addr(slirp_state_t *s, struct in_addr *paddr) +{ + int i; + + i = ntohl(paddr->s_addr) - START_ADDR - ntohl(s->special_addr.s_addr); + if (i >= NB_ADDR) + return; + memset(s->bootp_clients[i].macaddr, '\0', 6); + s->bootp_clients[i].allocated = 0; +} + +static BOOTPClient *find_addr(slirp_state_t *s, struct in_addr *paddr, + const uint8_t *macaddr) { BOOTPClient *bc; int i; for(i = 0; i < NB_ADDR; i++) { - if (!memcmp(macaddr, bootp_clients[i].macaddr, 6)) + if (!memcmp(macaddr, s->bootp_clients[i].macaddr, 6)) goto found; } return NULL; found: - bc = &bootp_clients[i]; + bc = &s->bootp_clients[i]; bc->allocated = 1; - paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR)); + paddr->s_addr = htonl(ntohl(s->special_addr.s_addr) | (i + START_ADDR)); return bc; } @@ -124,7 +122,7 @@ } } -static void bootp_reply(struct bootp_t *bp) +static void bootp_reply(slirp_state_t *s, struct bootp_t *bp) { BOOTPClient *bc; struct mbuf *m; @@ -141,29 +139,39 @@ if (dhcp_msg_type == 0) dhcp_msg_type = DHCPREQUEST; /* Force reply for old BOOTP clients */ + if (dhcp_msg_type == DHCPRELEASE) { + release_addr(s, &bp->bp_ciaddr); + dprintf("released addr=%08x\n", ntohl(bp->bp_ciaddr.s_addr)); + /* This message is not to be answered in any way. */ + return; + } if (dhcp_msg_type != DHCPDISCOVER && dhcp_msg_type != DHCPREQUEST) return; /* XXX: this is a hack to get the client mac address */ - memcpy(client_ethaddr, bp->bp_hwaddr, 6); + memcpy(s->client_ethaddr, bp->bp_hwaddr, 6); - if ((m = m_get()) == NULL) + if ((m = m_get(s)) == NULL) return; - m->m_data += if_maxlinkhdr; + m->m_data += s->if_maxlinkhdr; rbp = (struct bootp_t *)m->m_data; m->m_data += sizeof(struct udpiphdr); memset(rbp, 0, sizeof(struct bootp_t)); if (dhcp_msg_type == DHCPDISCOVER) { - new_addr: - bc = get_new_addr(&daddr.sin_addr); + /* Do not allocate a new lease for clients that forgot that they had a lease. */ + bc = find_addr(s, &daddr.sin_addr, bp->bp_hwaddr); if (!bc) { - dprintf("no address left\n"); - return; + new_addr: + bc = get_new_addr(s, &daddr.sin_addr); + if (!bc) { + dprintf("no address left\n"); + return; + } + memcpy(bc->macaddr, s->client_ethaddr, 6); } - memcpy(bc->macaddr, client_ethaddr, 6); } else { - bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr); + bc = find_addr(s, &daddr.sin_addr, bp->bp_hwaddr); if (!bc) { /* if never assigned, behaves as if it was already assigned (windows fix because it remembers its address) */ @@ -171,12 +179,12 @@ } } - if (bootp_filename) - snprintf(rbp->bp_file, sizeof(rbp->bp_file), "%s", bootp_filename); + if (s->bootp_filename) + snprintf(rbp->bp_file, sizeof(rbp->bp_file), "%s", s->bootp_filename); dprintf("offered addr=%08x\n", ntohl(daddr.sin_addr.s_addr)); - saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS); + saddr.sin_addr.s_addr = htonl(ntohl(s->special_addr.s_addr) | CTL_ALIAS); saddr.sin_port = htons(BOOTP_SERVER); daddr.sin_port = htons(BOOTP_CLIENT); @@ -225,7 +233,7 @@ *q++ = RFC1533_DNS; *q++ = 4; - dns_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_DNS); + dns_addr.s_addr = htonl(ntohl(s->special_addr.s_addr) | CTL_DNS); memcpy(q, &dns_addr, 4); q += 4; @@ -235,11 +243,11 @@ memcpy(q, &val, 4); q += 4; - if (*slirp_hostname) { - val = strlen(slirp_hostname); + if (*s->slirp_hostname) { + val = strlen(s->slirp_hostname); *q++ = RFC1533_HOSTNAME; *q++ = val; - memcpy(q, slirp_hostname, val); + memcpy(q, s->slirp_hostname, val); q += val; } } @@ -247,14 +255,16 @@ m->m_len = sizeof(struct bootp_t) - sizeof(struct ip) - sizeof(struct udphdr); - udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); + /* Reply to the broadcast address, as some clients perform paranoid checks. */ + daddr.sin_addr.s_addr = INADDR_BROADCAST; + udp_output2(s, NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); } -void bootp_input(struct mbuf *m) +void bootp_input(slirp_state_t *s, struct mbuf *m) { struct bootp_t *bp = mtod(m, struct bootp_t *); if (bp->bp_op == BOOTP_REQUEST) { - bootp_reply(bp); + bootp_reply(s, bp); } } Index: qemu/slirp/bootp.h =================================================================== --- qemu.orig/slirp/bootp.h 2007-10-20 07:33:35.000000000 +0000 +++ qemu/slirp/bootp.h 2007-10-20 08:17:51.000000000 +0000 @@ -71,6 +71,7 @@ #define DHCPOFFER 2 #define DHCPREQUEST 3 #define DHCPACK 5 +#define DHCPRELEASE 7 #define RFC1533_VENDOR_MAJOR 0 #define RFC1533_VENDOR_MINOR 0 @@ -110,4 +111,4 @@ uint8_t bp_vend[DHCP_OPT_LEN]; }; -void bootp_input(struct mbuf *m); +void bootp_input(slirp_state_t *s, struct mbuf *m); Index: qemu/slirp/ctl.h =================================================================== --- qemu.orig/slirp/ctl.h 2007-10-20 07:33:35.000000000 +0000 +++ qemu/slirp/ctl.h 2007-10-20 11:46:46.000000000 +0000 @@ -2,6 +2,4 @@ #define CTL_EXEC 1 #define CTL_ALIAS 2 #define CTL_DNS 3 - -#define CTL_SPECIAL "10.0.2.0" -#define CTL_LOCAL "10.0.2.15" +#define CTL_BROADCAST 255 Index: qemu/slirp/if.c =================================================================== --- qemu.orig/slirp/if.c 2007-10-20 07:33:36.000000000 +0000 +++ qemu/slirp/if.c 2007-10-20 12:47:04.000000000 +0000 @@ -7,22 +7,10 @@ #include <slirp.h> -int if_mtu, if_mru; -int if_comp; -int if_maxlinkhdr; -int if_queued = 0; /* Number of packets queued so far */ -int if_thresh = 10; /* Number of packets queued before we start sending - * (to prevent allocing too many mbufs) */ - -struct mbuf if_fastq; /* fast queue (for interactive data) */ -struct mbuf if_batchq; /* queue for non-interactive data */ -struct mbuf *next_m; /* Pointer to next mbuf to output */ #define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm)) -void -ifs_insque(ifm, ifmhead) - struct mbuf *ifm, *ifmhead; +static void ifs_insque(struct mbuf *ifm, struct mbuf *ifmhead) { ifm->ifs_next = ifmhead->ifs_next; ifmhead->ifs_next = ifm; @@ -30,16 +18,14 @@ ifm->ifs_next->ifs_prev = ifm; } -void -ifs_remque(ifm) - struct mbuf *ifm; +static void ifs_remque(struct mbuf *ifm) { ifm->ifs_prev->ifs_next = ifm->ifs_next; ifm->ifs_next->ifs_prev = ifm->ifs_prev; } void -if_init() +if_init(slirp_state_t *s) { #if 0 /* @@ -47,21 +33,23 @@ * and 8 bytes for PPP, but need to have it on an 8byte boundary */ #ifdef USE_PPP - if_maxlinkhdr = 48; + s->if_maxlinkhdr = 48; #else - if_maxlinkhdr = 40; + s->if_maxlinkhdr = 40; #endif #else /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */ - if_maxlinkhdr = 2 + 14 + 40; + s->if_maxlinkhdr = 2 + 14 + 40; #endif - if_mtu = 1500; - if_mru = 1500; - if_comp = IF_AUTOCOMP; - if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq; - if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq; + s->if_queued = 0; + s->if_thresh = 10; + s->if_mtu = 1500; + s->if_mru = 1500; + s->if_comp = IF_AUTOCOMP; + s->if_fastq.ifq_next = s->if_fastq.ifq_prev = &s->if_fastq; + s->if_batchq.ifq_next = s->if_batchq.ifq_prev = &s->if_batchq; // sl_compress_init(&comp_s); - next_m = &if_batchq; + s->next_m = &s->if_batchq; } #if 0 @@ -118,7 +106,7 @@ if (if_n <= 0) { if (if_n == 0 || (errno != EINTR && errno != EAGAIN)) { if (ttyp->up) - link_up--; + s->link_up--; tty_detached(ttyp, 0); } return; @@ -157,9 +145,7 @@ * it'll temporarily get downgraded to the batchq) */ void -if_output(so, ifm) - struct socket *so; - struct mbuf *ifm; +if_output(slirp_state_t *s, struct socket *so, struct mbuf *ifm) { struct mbuf *ifq; int on_fastq = 1; @@ -174,7 +160,7 @@ * XXX Shouldn't need this, gotta change dtom() etc. */ if (ifm->m_flags & M_USEDLIST) { - remque(ifm); + remque(s, ifm); ifm->m_flags &= ~M_USEDLIST; } @@ -185,7 +171,7 @@ * We mustn't put this packet back on the fastq (or we'll send it out of order) * XXX add cache here? */ - for (ifq = if_batchq.ifq_prev; ifq != &if_batchq; ifq = ifq->ifq_prev) { + for (ifq = s->if_batchq.ifq_prev; ifq != &s->if_batchq; ifq = ifq->ifq_prev) { if (so == ifq->ifq_so) { /* A match! */ ifm->ifq_so = so; @@ -196,7 +182,7 @@ /* No match, check which queue to put it on */ if (so && (so->so_iptos & IPTOS_LOWDELAY)) { - ifq = if_fastq.ifq_prev; + ifq = s->if_fastq.ifq_prev; on_fastq = 1; /* * Check if this packet is a part of the last @@ -208,15 +194,15 @@ goto diddit; } } else - ifq = if_batchq.ifq_prev; + ifq = s->if_batchq.ifq_prev; /* Create a new doubly linked list for this session */ ifm->ifq_so = so; ifs_init(ifm); - insque(ifm, ifq); + insque(s, ifm, ifq); diddit: - ++if_queued; + ++s->if_queued; if (so) { /* Update *_queued */ @@ -233,10 +219,10 @@ (so->so_nqueued - so->so_queued) >= 3)) { /* Remove from current queue... */ - remque(ifm->ifs_next); + remque(s, ifm->ifs_next); /* ...And insert in the new. That'll teach ya! */ - insque(ifm->ifs_next, &if_batchq); + insque(s, ifm->ifs_next, &s->if_batchq); } } @@ -244,9 +230,9 @@ /* * This prevents us from malloc()ing too many mbufs */ - if (link_up) { + if (s->link_up) { /* if_start will check towrite */ - if_start(); + if_start(s); } #endif } @@ -264,44 +250,44 @@ * to the first, etc. etc. */ void -if_start(void) +if_start(slirp_state_t *s) { struct mbuf *ifm, *ifqt; DEBUG_CALL("if_start"); - if (if_queued == 0) + if (s->if_queued == 0) return; /* Nothing to do */ again: /* check if we can really output */ - if (!slirp_can_output()) + if (!slirp_can_output(s->user)) return; /* * See which queue to get next packet from * If there's something in the fastq, select it immediately */ - if (if_fastq.ifq_next != &if_fastq) { - ifm = if_fastq.ifq_next; + if (s->if_fastq.ifq_next != &s->if_fastq) { + ifm = s->if_fastq.ifq_next; } else { /* Nothing on fastq, see if next_m is valid */ - if (next_m != &if_batchq) - ifm = next_m; + if (s->next_m != &s->if_batchq) + ifm = s->next_m; else - ifm = if_batchq.ifq_next; + ifm = s->if_batchq.ifq_next; /* Set which packet to send on next iteration */ - next_m = ifm->ifq_next; + s->next_m = ifm->ifq_next; } /* Remove it from the queue */ ifqt = ifm->ifq_prev; - remque(ifm); - --if_queued; + remque(s, ifm); + --s->if_queued; /* If there are more packets for this session, re-queue them */ if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) { - insque(ifm->ifs_next, ifqt); + insque(s, ifm->ifs_next, ifqt); ifs_remque(ifm); } @@ -313,10 +299,10 @@ } /* Encapsulate the packet for sending */ - if_encap(ifm->m_data, ifm->m_len); + if_encap(s, (const uint8_t *)ifm->m_data, ifm->m_len); - m_free(ifm); + m_free(s, ifm); - if (if_queued) + if (s->if_queued) goto again; } Index: qemu/slirp/ip.h =================================================================== --- qemu.orig/slirp/ip.h 2007-10-20 07:33:36.000000000 +0000 +++ qemu/slirp/ip.h 2007-10-20 08:17:51.000000000 +0000 @@ -305,9 +305,5 @@ u_long ips_unaligned; /* times the ip packet was not aligned */ }; -extern struct ipstat ipstat; -extern struct ipq ipq; /* ip reass. queue */ -extern u_int16_t ip_id; /* ip packet ctr, for ids */ -extern int ip_defttl; /* default IP ttl */ #endif Index: qemu/slirp/ip_icmp.c =================================================================== --- qemu.orig/slirp/ip_icmp.c 2007-10-20 07:33:36.000000000 +0000 +++ qemu/slirp/ip_icmp.c 2007-10-20 13:14:00.000000000 +0000 @@ -37,14 +37,13 @@ #include "slirp.h" #include "ip_icmp.h" -struct icmpstat icmpstat; /* The message sent when emulating PING */ -/* Be nice and tell them it's just a psuedo-ping packet */ -char icmp_ping_msg[] = "This is a psuedo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n"; +/* Be nice and tell them it's just a pseudo-ping packet */ +static const char icmp_ping_msg[] = "This is a pseudo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n"; /* list of actions for icmp_error() on RX of an icmp message */ -static int icmp_flush[19] = { +static const int icmp_flush[19] = { /* ECHO REPLY (0) */ 0, 1, 1, @@ -70,9 +69,7 @@ * Process a received ICMP message. */ void -icmp_input(m, hlen) - struct mbuf *m; - int hlen; +icmp_input(slirp_state_t *s, struct mbuf *m, int hlen) { register struct icmp *icp; register struct ip *ip=mtod(m, struct ip *); @@ -83,16 +80,16 @@ DEBUG_ARG("m = %lx", (long )m); DEBUG_ARG("m_len = %d", m->m_len); - icmpstat.icps_received++; + s->icmpstat.icps_received++; /* * Locate icmp structure in mbuf, and check * that its not corrupted and of at least minimum length. */ if (icmplen < ICMP_MINLEN) { /* min 8 bytes payload */ - icmpstat.icps_tooshort++; + s->icmpstat.icps_tooshort++; freeit: - m_freem(m); + m_freem(s, m); goto end_error; } @@ -100,7 +97,7 @@ m->m_data += hlen; icp = mtod(m, struct icmp *); if (cksum(m, icmplen)) { - icmpstat.icps_checksum++; + s->icmpstat.icps_checksum++; goto freeit; } m->m_len += hlen; @@ -114,17 +111,17 @@ case ICMP_ECHO: icp->icmp_type = ICMP_ECHOREPLY; ip->ip_len += hlen; /* since ip_input subtracts this */ - if (ip->ip_dst.s_addr == alias_addr.s_addr) { - icmp_reflect(m); + if (ip->ip_dst.s_addr == s->alias_addr.s_addr) { + icmp_reflect(s, m); } else { struct socket *so; struct sockaddr_in addr; if ((so = socreate()) == NULL) goto freeit; - if(udp_attach(so) == -1) { + if(udp_attach(s, so) == -1) { DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n", errno,strerror(errno))); - sofree(so); - m_free(m); + sofree(s, so); + m_free(s, m); goto end_error; } so->so_m = m; @@ -138,15 +135,15 @@ /* Send the packet */ addr.sin_family = AF_INET; - if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) { + if ((so->so_faddr.s_addr & htonl(0xffffff00)) == s->special_addr.s_addr) { /* It's an alias */ switch(ntohl(so->so_faddr.s_addr) & 0xff) { case CTL_DNS: - addr.sin_addr = dns_addr; + addr.sin_addr = s->dns_addr; break; case CTL_ALIAS: default: - addr.sin_addr = loopback_addr; + addr.sin_addr = s->loopback_addr; break; } } else { @@ -157,8 +154,8 @@ (struct sockaddr *)&addr, sizeof(addr)) == -1) { DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n", errno,strerror(errno))); - icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); - udp_detach(so); + icmp_error(s, m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); + udp_detach(s, so); } } /* if ip->ip_dst.s_addr == alias_addr.s_addr */ break; @@ -170,13 +167,13 @@ case ICMP_TSTAMP: case ICMP_MASKREQ: case ICMP_REDIRECT: - icmpstat.icps_notsupp++; - m_freem(m); + s->icmpstat.icps_notsupp++; + m_freem(s, m); break; default: - icmpstat.icps_badtype++; - m_freem(m); + s->icmpstat.icps_badtype++; + m_freem(s, m); } /* swith */ end_error: @@ -204,13 +201,8 @@ */ #define ICMP_MAXDATALEN (IP_MSS-28) -void -icmp_error(msrc, type, code, minsize, message) - struct mbuf *msrc; - u_char type; - u_char code; - int minsize; - char *message; +void icmp_error(slirp_state_t *s, struct mbuf *msrc, u_char type, u_char code, + int minsize, const char *message) { unsigned hlen, shlen, s_ip_len; register struct ip *ip; @@ -247,10 +239,13 @@ } /* make a copy */ - if(!(m=m_get())) goto end_error; /* get mbuf */ + if (!(m = m_get(s))) + goto end_error; /* get mbuf */ + { int new_m_size; new_m_size=sizeof(struct ip )+ICMP_MINLEN+msrc->m_len+ICMP_MAXDATALEN; - if(new_m_size>m->m_size) m_inc(m, new_m_size); + if (new_m_size > m->m_size) + m_inc(m, new_m_size); } memcpy(m->m_data, msrc->m_data, msrc->m_len); m->m_len = msrc->m_len; /* copy msrc to m */ @@ -310,11 +305,11 @@ ip->ip_ttl = MAXTTL; ip->ip_p = IPPROTO_ICMP; ip->ip_dst = ip->ip_src; /* ip adresses */ - ip->ip_src = alias_addr; + ip->ip_src = s->alias_addr; - (void ) ip_output((struct socket *)NULL, m); + (void ) ip_output(s, (struct socket *)NULL, m); - icmpstat.icps_reflect++; + s->icmpstat.icps_reflect++; end_error: return; @@ -325,8 +320,7 @@ * Reflect the ip packet back to the source */ void -icmp_reflect(m) - struct mbuf *m; +icmp_reflect(slirp_state_t *s, struct mbuf *m) { register struct ip *ip = mtod(m, struct ip *); int hlen = ip->ip_hl << 2; @@ -369,7 +363,7 @@ ip->ip_src = icmp_dst; } - (void ) ip_output((struct socket *)NULL, m); + (void ) ip_output(s, (struct socket *)NULL, m); - icmpstat.icps_reflect++; + s->icmpstat.icps_reflect++; } Index: qemu/slirp/ip_icmp.h =================================================================== --- qemu.orig/slirp/ip_icmp.h 2007-10-20 07:33:36.000000000 +0000 +++ qemu/slirp/ip_icmp.h 2007-10-20 13:15:27.000000000 +0000 @@ -157,8 +157,9 @@ (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) -void icmp_input _P((struct mbuf *, int)); -void icmp_error _P((struct mbuf *, u_char, u_char, int, char *)); -void icmp_reflect _P((struct mbuf *)); +void icmp_input(slirp_state_t *s, struct mbuf *m, int hlen); +void icmp_error(slirp_state_t *s, struct mbuf *msrc, u_char type, u_char code, + int minsize, const char *message); +void icmp_reflect(slirp_state_t *s, struct mbuf *m); #endif Index: qemu/slirp/ip_input.c =================================================================== --- qemu.orig/slirp/ip_input.c 2007-10-20 07:33:36.000000000 +0000 +++ qemu/slirp/ip_input.c 2007-10-20 13:18:38.000000000 +0000 @@ -45,22 +45,25 @@ #include <slirp.h> #include "ip_icmp.h" -int ip_defttl; -struct ipstat ipstat; -struct ipq ipq; + +static struct ip *ip_reass(slirp_state_t *s, register struct ipasfrag *ip, + register struct ipq *fp); +static void ip_freef(slirp_state_t *s, struct ipq *fp); +static void ip_enq(slirp_state_t *s, register struct ipasfrag *p, + register struct ipasfrag *prev); +static void ip_deq(slirp_state_t *s, register struct ipasfrag *p); /* * IP initialization: fill in IP protocol switch table. * All protocols not implemented in kernel go to raw IP protocol handler. */ void -ip_init() +ip_init(slirp_state_t *s) { - ipq.next = ipq.prev = (ipqp_32)&ipq; - ip_id = tt.tv_sec & 0xffff; - udp_init(); - tcp_init(); - ip_defttl = IPDEFTTL; + s->ipq.next = s->ipq.prev = (ipqp_32)&(s->ipq); + s->ip_id = s->tt.tv_sec & 0xffff; + udp_init(s); + tcp_init(s); } /* @@ -68,8 +71,7 @@ * try to reassemble. Process options. Pass to next level. */ void -ip_input(m) - struct mbuf *m; +ip_input(slirp_state_t *s, struct mbuf *m) { register struct ip *ip; int hlen; @@ -78,23 +80,23 @@ DEBUG_ARG("m = %lx", (long)m); DEBUG_ARG("m_len = %d", m->m_len); - ipstat.ips_total++; + s->ipstat.ips_total++; if (m->m_len < sizeof (struct ip)) { - ipstat.ips_toosmall++; + s->ipstat.ips_toosmall++; return; } ip = mtod(m, struct ip *); if (ip->ip_v != IPVERSION) { - ipstat.ips_badvers++; + s->ipstat.ips_badvers++; goto bad; } hlen = ip->ip_hl << 2; if (hlen<sizeof(struct ip ) || hlen>m->m_len) {/* min header length */ - ipstat.ips_badhlen++; /* or packet too short */ + s->ipstat.ips_badhlen++; /* or packet too short */ goto bad; } @@ -103,7 +105,7 @@ * if (ip->ip_sum) { */ if(cksum(m,hlen)) { - ipstat.ips_badsum++; + s->ipstat.ips_badsum++; goto bad; } @@ -112,7 +114,7 @@ */ NTOHS(ip->ip_len); if (ip->ip_len < hlen) { - ipstat.ips_badlen++; + s->ipstat.ips_badlen++; goto bad; } NTOHS(ip->ip_id); @@ -125,7 +127,7 @@ * Drop packet if shorter than we expect. */ if (m->m_len < ip->ip_len) { - ipstat.ips_tooshort++; + s->ipstat.ips_tooshort++; goto bad; } /* Should drop packet if mbuf too long? hmmm... */ @@ -134,7 +136,7 @@ /* check ip_ttl for a correct ICMP reply */ if(ip->ip_ttl==0 || ip->ip_ttl==1) { - icmp_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl"); + icmp_error(s, m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl"); goto bad; } @@ -163,7 +165,7 @@ * Look for queue of fragments * of this datagram. */ - for (fp = (struct ipq *) ipq.next; fp != &ipq; + for (fp = (struct ipq *) s->ipq.next; fp != &s->ipq; fp = (struct ipq *) fp->next) if (ip->ip_id == fp->ipq_id && ip->ip_src.s_addr == fp->ipq_src.s_addr && @@ -192,15 +194,15 @@ * attempt reassembly; if it succeeds, proceed. */ if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) { - ipstat.ips_fragments++; - ip = ip_reass((struct ipasfrag *)ip, fp); + s->ipstat.ips_fragments++; + ip = ip_reass(s, (struct ipasfrag *)ip, fp); if (ip == 0) return; - ipstat.ips_reassembled++; - m = dtom(ip); + s->ipstat.ips_reassembled++; + m = dtom(s, ip); } else if (fp) - ip_freef(fp); + ip_freef(s, fp); } else ip->ip_len -= hlen; @@ -208,24 +210,24 @@ /* * Switch out to protocol's input routine. */ - ipstat.ips_delivered++; + s->ipstat.ips_delivered++; switch (ip->ip_p) { case IPPROTO_TCP: - tcp_input(m, hlen, (struct socket *)NULL); + tcp_input(s, m, hlen, (struct socket *)NULL); break; case IPPROTO_UDP: - udp_input(m, hlen); + udp_input(s, m, hlen); break; case IPPROTO_ICMP: - icmp_input(m, hlen); + icmp_input(s, m, hlen); break; default: - ipstat.ips_noproto++; - m_free(m); + s->ipstat.ips_noproto++; + m_free(s, m); } return; bad: - m_freem(m); + m_freem(s, m); return; } @@ -235,12 +237,11 @@ * reassembly of this datagram already exists, then it * is given as fp; otherwise have to make a chain. */ -struct ip * -ip_reass(ip, fp) - register struct ipasfrag *ip; - register struct ipq *fp; +static struct ip * +ip_reass(slirp_state_t *s, register struct ipasfrag *ip, + register struct ipq *fp) { - register struct mbuf *m = dtom(ip); + register struct mbuf *m = dtom(s, ip); register struct ipasfrag *q; int hlen = ip->ip_hl << 2; int i, next; @@ -263,9 +264,10 @@ */ if (fp == 0) { struct mbuf *t; - if ((t = m_get()) == NULL) goto dropfrag; + if ((t = m_get(s)) == NULL) + goto dropfrag; fp = mtod(t, struct ipq *); - insque_32(fp, &ipq); + insque_32(s, fp, &s->ipq); fp->ipq_ttl = IPFRAGTTL; fp->ipq_p = ip->ip_p; fp->ipq_id = ip->ip_id; @@ -295,7 +297,7 @@ if (i > 0) { if (i >= ip->ip_len) goto dropfrag; - m_adj(dtom(ip), i); + m_adj(dtom(s, ip), i); ip->ip_off += i; ip->ip_len -= i; } @@ -310,12 +312,12 @@ if (i < q->ip_len) { q->ip_len -= i; q->ip_off += i; - m_adj(dtom(q), i); + m_adj(dtom(s, q), i); break; } q = (struct ipasfrag *) q->ipf_next; - m_freem(dtom((struct ipasfrag *) q->ipf_prev)); - ip_deq((struct ipasfrag *) q->ipf_prev); + m_freem(s, dtom(s, (struct ipasfrag *) q->ipf_prev)); + ip_deq(s, (struct ipasfrag *) q->ipf_prev); } insert: @@ -323,7 +325,7 @@ * Stick new segment in its place; * check for complete reassembly. */ - ip_enq(ip, (struct ipasfrag *) q->ipf_prev); + ip_enq(s, ip, (struct ipasfrag *) q->ipf_prev); next = 0; for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp; q = (struct ipasfrag *) q->ipf_next) { @@ -338,14 +340,14 @@ * Reassembly is complete; concatenate fragments. */ q = (struct ipasfrag *) fp->ipq_next; - m = dtom(q); + m = dtom(s, q); q = (struct ipasfrag *) q->ipf_next; while (q != (struct ipasfrag *)fp) { struct mbuf *t; - t = dtom(q); + t = dtom(s, q); q = (struct ipasfrag *) q->ipf_next; - m_cat(m, t); + m_cat(s, m, t); } /* @@ -376,17 +378,17 @@ ip->ipf_mff &= ~1; ((struct ip *)ip)->ip_src = fp->ipq_src; ((struct ip *)ip)->ip_dst = fp->ipq_dst; - remque_32(fp); - (void) m_free(dtom(fp)); - m = dtom(ip); + remque_32(s, fp); + (void) m_free(s, dtom(s, fp)); + m = dtom(s, ip); m->m_len += (ip->ip_hl << 2); m->m_data -= (ip->ip_hl << 2); return ((struct ip *)ip); dropfrag: - ipstat.ips_fragdropped++; - m_freem(m); + s->ipstat.ips_fragdropped++; + m_freem(s, m); return (0); } @@ -394,29 +396,28 @@ * Free a fragment reassembly header and all * associated datagrams. */ -void -ip_freef(fp) - struct ipq *fp; +static void +ip_freef(slirp_state_t *s, struct ipq *fp) { register struct ipasfrag *q, *p; for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp; q = p) { p = (struct ipasfrag *) q->ipf_next; - ip_deq(q); - m_freem(dtom(q)); + ip_deq(s, q); + m_freem(s, dtom(s, q)); } - remque_32(fp); - (void) m_free(dtom(fp)); + remque_32(s, fp); + (void) m_free(s, dtom(s, fp)); } /* * Put an ip fragment on a reassembly chain. * Like insque, but pointers in middle of structure. */ -void -ip_enq(p, prev) - register struct ipasfrag *p, *prev; +static void +ip_enq(slirp_state_t *s, register struct ipasfrag *p, + register struct ipasfrag *prev) { DEBUG_CALL("ip_enq"); DEBUG_ARG("prev = %lx", (long)prev); @@ -429,9 +430,8 @@ /* * To ip_enq as remque is to insque. */ -void -ip_deq(p) - register struct ipasfrag *p; +static void +ip_deq(slirp_state_t *s, register struct ipasfrag *p) { ((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next; ((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev; @@ -443,22 +443,22 @@ * queue, discard it. */ void -ip_slowtimo() +ip_slowtimo(slirp_state_t *s) { register struct ipq *fp; DEBUG_CALL("ip_slowtimo"); - fp = (struct ipq *) ipq.next; + fp = (struct ipq *) s->ipq.next; if (fp == 0) return; - while (fp != &ipq) { + while (fp != &s->ipq) { --fp->ipq_ttl; fp = (struct ipq *) fp->next; if (((struct ipq *)(fp->prev))->ipq_ttl == 0) { - ipstat.ips_fragtimeout++; - ip_freef((struct ipq *) fp->prev); + s->ipstat.ips_fragtimeout++; + ip_freef(s, (struct ipq *) fp->prev); } } } @@ -664,7 +664,7 @@ /* Not yet */ icmp_error(m, type, code, 0, 0); - ipstat.ips_badoptions++; + s->ipstat.ips_badoptions++; return (1); } Index: qemu/slirp/ip_output.c =================================================================== --- qemu.orig/slirp/ip_output.c 2007-10-20 07:33:36.000000000 +0000 +++ qemu/slirp/ip_output.c 2007-10-20 08:17:52.000000000 +0000 @@ -44,7 +44,6 @@ #include <slirp.h> -u_int16_t ip_id; /* * IP output. The packet in mbuf chain m contains a skeletal IP @@ -53,9 +52,7 @@ * The mbuf opt, if present, will not be freed. */ int -ip_output(so, m0) - struct socket *so; - struct mbuf *m0; +ip_output(slirp_state_t *s, struct socket *so, struct mbuf *m0) { register struct ip *ip; register struct mbuf *m = m0; @@ -78,16 +75,16 @@ */ ip->ip_v = IPVERSION; ip->ip_off &= IP_DF; - ip->ip_id = htons(ip_id++); + ip->ip_id = htons(s->ip_id++); ip->ip_hl = hlen >> 2; - ipstat.ips_localout++; + s->ipstat.ips_localout++; /* * Verify that we have any chance at all of being able to queue * the packet or packet fragments */ /* XXX Hmmm... */ -/* if (if_queued > if_thresh && towrite <= 0) { +/* if (s->if_queued > s->if_thresh && towrite <= 0) { * error = ENOBUFS; * goto bad; * } @@ -96,13 +93,13 @@ /* * If small enough for interface, can just send directly. */ - if ((u_int16_t)ip->ip_len <= if_mtu) { + if ((u_int16_t)ip->ip_len <= s->if_mtu) { ip->ip_len = htons((u_int16_t)ip->ip_len); ip->ip_off = htons((u_int16_t)ip->ip_off); ip->ip_sum = 0; ip->ip_sum = cksum(m, hlen); - if_output(so, m); + if_output(s, so, m); goto done; } @@ -112,11 +109,11 @@ */ if (ip->ip_off & IP_DF) { error = -1; - ipstat.ips_cantfrag++; + s->ipstat.ips_cantfrag++; goto bad; } - len = (if_mtu - hlen) &~ 7; /* ip databytes per packet */ + len = (s->if_mtu - hlen) &~ 7; /* ip databytes per packet */ if (len < 8) { error = -1; goto bad; @@ -134,13 +131,13 @@ mhlen = sizeof (struct ip); for (off = hlen + len; off < (u_int16_t)ip->ip_len; off += len) { register struct ip *mhip; - m = m_get(); + m = m_get(s); if (m == 0) { error = -1; - ipstat.ips_odropped++; + s->ipstat.ips_odropped++; goto sendorfree; } - m->m_data += if_maxlinkhdr; + m->m_data += s->if_maxlinkhdr; mhip = mtod(m, struct ip *); *mhip = *ip; @@ -170,7 +167,7 @@ mhip->ip_sum = cksum(m, mhlen); *mnext = m; mnext = &m->m_nextpkt; - ipstat.ips_ofragments++; + s->ipstat.ips_ofragments++; } /* * Update first fragment by trimming what's been copied out @@ -187,19 +184,19 @@ m0 = m->m_nextpkt; m->m_nextpkt = 0; if (error == 0) - if_output(so, m); + if_output(s, so, m); else - m_freem(m); + m_freem(s, m); } if (error == 0) - ipstat.ips_fragmented++; + s->ipstat.ips_fragmented++; } done: return (error); bad: - m_freem(m0); + m_freem(s, m0); goto done; } Index: qemu/slirp/libslirp.h =================================================================== --- qemu.orig/slirp/libslirp.h 2007-10-20 07:33:36.000000000 +0000 +++ qemu/slirp/libslirp.h 2007-10-20 11:50:05.000000000 +0000 @@ -5,26 +5,32 @@ extern "C" { #endif -void slirp_init(void); +typedef struct slirp_state_t slirp_state_t; -void slirp_select_fill(int *pnfds, +slirp_state_t *slirp_init(void *user, const char *slirp_hostname, + const char *tftp_prefix, const char *network); +void slirp_term(slirp_state_t *s); +void slirp_link_up(slirp_state_t *s); +void slirp_link_down(slirp_state_t *s); + +void slirp_select_fill(slirp_state_t *s, int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds); -void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds); +void slirp_select_poll(slirp_state_t *s, fd_set *readfds, fd_set *writefds, + fd_set *xfds); -void slirp_input(const uint8_t *pkt, int pkt_len); +void slirp_input(slirp_state_t *s, const uint8_t *pkt, int pkt_len); /* you must provide the following functions: */ -int slirp_can_output(void); -void slirp_output(const uint8_t *pkt, int pkt_len); +int slirp_can_output(void *user); +void slirp_output(void *user, const uint8_t *pkt, int pkt_len); -int slirp_redir(int is_udp, int host_port, +int slirp_redir(slirp_state_t *s, int is_udp, int host_port, struct in_addr guest_addr, int guest_port); -int slirp_add_exec(int do_pty, const char *args, int addr_low_byte, - int guest_port); +int slirp_add_exec(slirp_state_t *s, int do_pty, const char *args, + int addr_low_byte, int guest_port); -extern const char *tftp_prefix; -extern char slirp_hostname[33]; +void slirp_stats(slirp_state_t *s); #ifdef __cplusplus } Index: qemu/slirp/main.h =================================================================== --- qemu.orig/slirp/main.h 2007-10-20 07:33:36.000000000 +0000 +++ qemu/slirp/main.h 2007-10-20 08:17:52.000000000 +0000 @@ -11,14 +11,6 @@ #define TOWRITEMAX 512 -extern struct timeval tt; -extern int link_up; -extern int slirp_socket; -extern int slirp_socket_unit; -extern int slirp_socket_port; -extern u_int32_t slirp_socket_addr; -extern char *slirp_socket_passwd; -extern int ctty_closed; /* * Get the difference in 2 times from updtim() @@ -28,27 +20,10 @@ */ #define TIME_DIFF(x,y) (x)-(y) < 0 ? ~0-(y)+(x) : (x)-(y) -extern char *slirp_tty; -extern char *exec_shell; -extern u_int curtime; -extern fd_set *global_readfds, *global_writefds, *global_xfds; -extern struct in_addr ctl_addr; -extern struct in_addr special_addr; -extern struct in_addr alias_addr; -extern struct in_addr our_addr; -extern struct in_addr loopback_addr; -extern struct in_addr dns_addr; -extern char *username; -extern char *socket_path; -extern int towrite_max; -extern int ppp_exit; -extern int so_options; -extern int tcp_keepintvl; -extern uint8_t client_ethaddr[6]; #define PROTO_SLIP 0x1 #ifdef USE_PPP #define PROTO_PPP 0x2 #endif -void if_encap(const uint8_t *ip_data, int ip_data_len); +void if_encap(slirp_state_t *s, const uint8_t *ip_data, int ip_data_len); Index: qemu/slirp/mbuf.c =================================================================== --- qemu.orig/slirp/mbuf.c 2007-10-20 07:33:36.000000000 +0000 +++ qemu/slirp/mbuf.c 2007-10-20 17:30:44.000000000 +0000 @@ -17,31 +17,20 @@ #include <slirp.h> -struct mbuf *mbutl; -char *mclrefcnt; -int mbuf_alloced = 0; -struct mbuf m_freelist, m_usedlist; -int mbuf_thresh = 30; -int mbuf_max = 0; -int msize; void -m_init() +m_init(slirp_state_t *s) { - m_freelist.m_next = m_freelist.m_prev = &m_freelist; - m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist; - msize_init(); -} + s->m_freelist.m_next = s->m_freelist.m_prev = &s->m_freelist; + s->m_usedlist.m_next = s->m_usedlist.m_prev = &s->m_usedlist; + s->mbuf_alloced = 0; -void -msize_init() -{ /* * Find a nice value for msize * XXX if_maxlinkhdr already in mtu */ - msize = (if_mtu>if_mru?if_mtu:if_mru) + - if_maxlinkhdr + sizeof(struct m_hdr ) + 6; + s->msize = (s->if_mtu > s->if_mru? s->if_mtu : s->if_mru) + + s->if_maxlinkhdr + sizeof(struct m_hdr ) + 6; } /* @@ -53,32 +42,33 @@ * which tells m_free to actually free() it */ struct mbuf * -m_get() +m_get(slirp_state_t *s) { register struct mbuf *m; int flags = 0; DEBUG_CALL("m_get"); - if (m_freelist.m_next == &m_freelist) { - m = (struct mbuf *)malloc(msize); - if (m == NULL) goto end_error; - mbuf_alloced++; - if (mbuf_alloced > mbuf_thresh) + if (s->m_freelist.m_next == &s->m_freelist) { + m = (struct mbuf *)malloc(s->msize); + if (m == NULL) + goto end_error; + s->mbuf_alloced++; + if (s->mbuf_alloced > MBUF_THRESH) flags = M_DOFREE; - if (mbuf_alloced > mbuf_max) - mbuf_max = mbuf_alloced; + if (s->mbuf_alloced > s->mbuf_max) + s->mbuf_max = s->mbuf_alloced; } else { - m = m_freelist.m_next; - remque(m); + m = s->m_freelist.m_next; + remque(s, m); } /* Insert it in the used list */ - insque(m,&m_usedlist); + insque(s, m, &s->m_usedlist); m->m_flags = (flags | M_USEDLIST); /* Initialise it */ - m->m_size = msize - sizeof(struct m_hdr); + m->m_size = s->msize - sizeof(struct m_hdr); m->m_data = m->m_dat; m->m_len = 0; m->m_nextpkt = 0; @@ -89,8 +79,7 @@ } void -m_free(m) - struct mbuf *m; +m_free(slirp_state_t *s, struct mbuf *m) { DEBUG_CALL("m_free"); @@ -99,7 +88,7 @@ if(m) { /* Remove from m_usedlist */ if (m->m_flags & M_USEDLIST) - remque(m); + remque(s, m); /* If it's M_EXT, free() it */ if (m->m_flags & M_EXT) @@ -110,9 +99,9 @@ */ if (m->m_flags & M_DOFREE) { free(m); - mbuf_alloced--; + s->mbuf_alloced--; } else if ((m->m_flags & M_FREELIST) == 0) { - insque(m,&m_freelist); + insque(s, m, &s->m_freelist); m->m_flags = M_FREELIST; /* Clobber other flags */ } } /* if(m) */ @@ -124,8 +113,7 @@ * an M_EXT data segment */ void -m_cat(m, n) - register struct mbuf *m, *n; +m_cat(slirp_state_t *s, register struct mbuf *m, register struct mbuf *n) { /* * If there's no room, realloc @@ -136,7 +124,7 @@ memcpy(m->m_data+m->m_len, n->m_data, n->m_len); m->m_len += n->m_len; - m_free(n); + m_free(s, n); } @@ -220,8 +208,7 @@ * Fortunately, it's not used often */ struct mbuf * -dtom(dat) - void *dat; +dtom(slirp_state_t *s, void *dat) { struct mbuf *m; @@ -229,7 +216,7 @@ DEBUG_ARG("dat = %lx", (long )dat); /* bug corrected for M_EXT buffers */ - for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next) { + for (m = s->m_usedlist.m_next; m != &s->m_usedlist; m = m->m_next) { if (m->m_flags & M_EXT) { if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) ) return m; Index: qemu/slirp/mbuf.h =================================================================== --- qemu.orig/slirp/mbuf.h 2007-10-20 07:33:37.000000000 +0000 +++ qemu/slirp/mbuf.h 2007-10-20 17:47:12.000000000 +0000 @@ -120,28 +120,13 @@ #define M_DOFREE 0x08 /* when m_free is called on the mbuf, free() * it rather than putting it on the free list */ -/* - * Mbuf statistics. XXX - */ - -struct mbstat { - int mbs_alloced; /* Number of mbufs allocated */ - -}; - -extern struct mbstat mbstat; -extern int mbuf_alloced; -extern struct mbuf m_freelist, m_usedlist; -extern int mbuf_max; - -void m_init _P((void)); -void msize_init _P((void)); -struct mbuf * m_get _P((void)); -void m_free _P((struct mbuf *)); -void m_cat _P((register struct mbuf *, register struct mbuf *)); +void m_init(slirp_state_t *s); +struct mbuf *m_get(slirp_state_t *s); +void m_free(slirp_state_t *s, struct mbuf *m); +void m_cat(slirp_state_t *s, register struct mbuf *m, register struct mbuf *n); void m_inc _P((struct mbuf *, int)); void m_adj _P((struct mbuf *, int)); int m_copy _P((struct mbuf *, struct mbuf *, int, int)); -struct mbuf * dtom _P((void *)); +struct mbuf *dtom(slirp_state_t *s, void *dat); #endif Index: qemu/slirp/misc.c =================================================================== --- qemu.orig/slirp/misc.c 2007-10-20 07:33:37.000000000 +0000 +++ qemu/slirp/misc.c 2007-10-20 18:18:49.000000000 +0000 @@ -8,8 +8,6 @@ #define WANT_SYS_IOCTL_H #include <slirp.h> -u_int curtime, time_fasttimo, last_slowtimo, detach_time; -u_int detach_wait = 600000; /* 10 minutes */ #if 0 int x_port = -1; @@ -25,9 +23,9 @@ lprint("X Redir: X not being redirected.\r\n"); } else { lprint("X Redir: In sh/bash/zsh/etc. type: DISPLAY=%s:%d.%d; export DISPLAY\r\n", - inet_ntoa(our_addr), x_port, x_screen); + inet_ntoa(s->our_addr), x_port, x_screen); lprint("X Redir: In csh/tcsh/etc. type: setenv DISPLAY %s:%d.%d\r\n", - inet_ntoa(our_addr), x_port, x_screen); + inet_ntoa(s->our_addr), x_port, x_screen); if (x_display) lprint("X Redir: Redirecting to display %d\r\n", x_display); } @@ -85,7 +83,7 @@ * Get our IP address and put it in our_addr */ void -getouraddr() +getouraddr(slirp_state_t *s) { char buff[256]; struct hostent *he = NULL; @@ -93,9 +91,9 @@ if (gethostname(buff,256) == 0) he = gethostbyname(buff); if (he) - our_addr = *(struct in_addr *)he->h_addr; - if (our_addr.s_addr == 0) - our_addr.s_addr = loopback_addr.s_addr; + s->our_addr = *(struct in_addr *)he->h_addr; + if (s->our_addr.s_addr == 0) + s->our_addr.s_addr = s->loopback_addr.s_addr; } #if SIZEOF_CHAR_P == 8 @@ -105,10 +103,8 @@ u_int32_t qh_rlink; }; -inline void -insque_32(a, b) - void *a; - void *b; +void +insque_32(slirp_state_t *s, void *a, void *b) { register struct quehead_32 *element = (struct quehead_32 *) a; register struct quehead_32 *head = (struct quehead_32 *) b; @@ -119,9 +115,8 @@ = (u_int32_t)element; } -inline void -remque_32(a) - void *a; +void +remque_32(slirp_state_t *s, void *a) { register struct quehead_32 *element = (struct quehead_32 *) a; ((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink; @@ -136,9 +131,8 @@ struct quehead *qh_rlink; }; -inline void -insque(a, b) - void *a, *b; +void +insque(slirp_state_t *s, void *a, void *b) { register struct quehead *element = (struct quehead *) a; register struct quehead *head = (struct quehead *) b; @@ -149,9 +143,8 @@ = (struct quehead *)element; } -inline void -remque(a) - void *a; +void +remque(slirp_state_t *s, void *a) { register struct quehead *element = (struct quehead *) a; ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink; @@ -214,10 +207,7 @@ #ifdef _WIN32 int -fork_exec(so, ex, do_pty) - struct socket *so; - char *ex; - int do_pty; +fork_exec(slirp_state_t *s, struct socket *so, const char *ex, int do_pty) { /* not implemented */ return 0; @@ -225,6 +215,7 @@ #else +#if 0 int slirp_openpty(amaster, aslave) int *amaster, *aslave; @@ -289,6 +280,7 @@ return (-1); #endif } +#endif /* * XXX This is ugly @@ -302,23 +294,20 @@ * do_ptr = 2 Fork/exec using pty */ int -fork_exec(so, ex, do_pty) - struct socket *so; - char *ex; - int do_pty; +fork_exec(slirp_state_t *s, struct socket *so, const char *ex, int do_pty) { - int s; + int fd = -1; struct sockaddr_in addr; int addrlen = sizeof(addr); int opt; - int master; + int master = -1; char *argv[256]; #if 0 char buff[256]; #endif /* don't want to clobber the original */ char *bptr; - char *curarg; + const char *curarg; int c, i, ret; DEBUG_CALL("fork_exec"); @@ -327,20 +316,22 @@ DEBUG_ARG("do_pty = %lx", (long)do_pty); if (do_pty == 2) { - if (slirp_openpty(&master, &s) == -1) { +#if 0 + if (slirp_openpty(&master, &fd) == -1) { lprint("Error: openpty failed: %s\n", strerror(errno)); return 0; } +#endif } else { addr.sin_family = AF_INET; addr.sin_port = 0; addr.sin_addr.s_addr = INADDR_ANY; - if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 || - bind(s, (struct sockaddr *)&addr, addrlen) < 0 || - listen(s, 1) < 0) { + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0 || + bind(fd, (struct sockaddr *)&addr, addrlen) < 0 || + listen(fd, 1) < 0) { lprint("Error: inet socket: %s\n", strerror(errno)); - closesocket(s); + closesocket(fd); return 0; } @@ -349,7 +340,7 @@ switch(fork()) { case -1: lprint("Error: fork failed: %s\n", strerror(errno)); - close(s); + close(fd); if (do_pty == 2) close(master); return 0; @@ -360,38 +351,38 @@ (void) close(master); #ifdef TIOCSCTTY /* XXXXX */ (void) setsid(); - ioctl(s, TIOCSCTTY, (char *)NULL); + ioctl(fd, TIOCSCTTY, (char *)NULL); #endif } else { - getsockname(s, (struct sockaddr *)&addr, &addrlen); - close(s); + getsockname(fd, (struct sockaddr *)&addr, &addrlen); + close(fd); /* * Connect to the socket * XXX If any of these fail, we're in trouble! */ - s = socket(AF_INET, SOCK_STREAM, 0); - addr.sin_addr = loopback_addr; + fd = socket(AF_INET, SOCK_STREAM, 0); + addr.sin_addr = s->loopback_addr; do { - ret = connect(s, (struct sockaddr *)&addr, addrlen); + ret = connect(fd, (struct sockaddr *)&addr, addrlen); } while (ret < 0 && errno == EINTR); } #if 0 if (x_port >= 0) { #ifdef HAVE_SETENV - sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen); + sprintf(buff, "%s:%d.%d", inet_ntoa(s->our_addr), x_port, x_screen); setenv("DISPLAY", buff, 1); #else - sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen); + sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(s->our_addr), x_port, x_screen); putenv(buff); #endif } #endif - dup2(s, 0); - dup2(s, 1); - dup2(s, 2); - for (s = 3; s <= 255; s++) - close(s); + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + for (fd = getdtablesize() - 1; fd >= 3; fd--) + close(fd); i = 0; bptr = strdup(ex); /* No need to free() this */ @@ -427,7 +418,7 @@ default: if (do_pty == 2) { - close(s); + close(fd); so->s = master; } else { /* @@ -438,9 +429,9 @@ * of connect() fail in the child process */ do { - so->s = accept(s, (struct sockaddr *)&addr, &addrlen); + so->s = accept(fd, (struct sockaddr *)&addr, &addrlen); } while (so->s < 0 && errno == EINTR); - closesocket(s); + closesocket(fd); opt = 1; setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)); opt = 1; @@ -450,7 +441,7 @@ /* Append the telnet options now */ if (so->so_m != 0 && do_pty == 1) { - sbappend(so, so->so_m); + sbappend(s, so, so->so_m); so->so_m = 0; } @@ -603,6 +594,7 @@ } #endif +#if 0 int (*lprint_print) _P((void *, const char *, va_list)); char *lprint_ptr, *lprint_ptr2, **lprint_arg; @@ -754,6 +746,7 @@ lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport); } +#endif #ifdef BAD_SPRINTF @@ -908,10 +901,10 @@ /* Set the DISPLAY */ if (x_port >= 0) { #ifdef HAVE_SETENV - sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen); + sprintf(buff, "%s:%d.%d", inet_ntoa(s->our_addr), x_port, x_screen); setenv("DISPLAY", buff, 1); #else - sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen); + sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(s->our_addr), x_port, x_screen); putenv(buff); #endif } Index: qemu/slirp/misc.h =================================================================== --- qemu.orig/slirp/misc.h 2007-10-20 07:33:37.000000000 +0000 +++ qemu/slirp/misc.h 2007-10-20 13:28:51.000000000 +0000 @@ -16,13 +16,6 @@ struct ex_list *ex_next; }; -extern struct ex_list *exec_list; -extern u_int curtime, time_fasttimo, last_slowtimo, detach_time, detach_wait; - -extern int (*lprint_print) _P((void *, const char *, va_list)); -extern char *lprint_ptr, *lprint_ptr2, **lprint_arg; -extern struct sbuf *lprint_sb; - #ifndef HAVE_STRDUP char *strdup _P((const char *)); #endif @@ -69,12 +62,12 @@ int show_x _P((char *, struct socket *)); void redir_x _P((u_int32_t, int, int, int)); -void getouraddr _P((void)); -inline void slirp_insque _P((void *, void *)); -inline void slirp_remque _P((void *)); +void getouraddr(slirp_state_t *s); +void slirp_insque(slirp_state_t *s, void *a, void *b); +void slirp_remque(slirp_state_t *s, void *a); int add_exec _P((struct ex_list **, int, char *, int, int)); int slirp_openpty _P((int *, int *)); -int fork_exec _P((struct socket *, char *, int)); +int fork_exec(slirp_state_t *s, struct socket *so, const char *ex, int do_pty); void snooze_hup _P((int)); void snooze _P((void)); void relay _P((int)); Index: qemu/slirp/sbuf.c =================================================================== --- qemu.orig/slirp/sbuf.c 2007-10-20 07:33:37.000000000 +0000 +++ qemu/slirp/sbuf.c 2007-10-20 12:36:48.000000000 +0000 @@ -7,6 +7,8 @@ #include <slirp.h> +static void sbappendsb(struct sbuf *sb, struct mbuf *m); + /* Done as a macro in socket.h */ /* int * sbspace(struct sockbuff *sb) @@ -72,9 +74,7 @@ * (the socket is non-blocking, so we won't hang) */ void -sbappend(so, m) - struct socket *so; - struct mbuf *m; +sbappend(slirp_state_t *s, struct socket *so, struct mbuf *m) { int ret = 0; @@ -85,7 +85,7 @@ /* Shouldn't happen, but... e.g. foreign host closes connection */ if (m->m_len <= 0) { - m_free(m); + m_free(s, m); return; } @@ -96,7 +96,7 @@ */ if (so->so_urgc) { sbappendsb(&so->so_rcv, m); - m_free(m); + m_free(s, m); sosendoob(so); return; } @@ -126,17 +126,15 @@ sbappendsb(&so->so_rcv, m); } /* else */ /* Whatever happened, we free the mbuf */ - m_free(m); + m_free(s, m); } /* * Copy the data from m into sb * The caller is responsible to make sure there's enough room */ -void -sbappendsb(sb, m) - struct sbuf *sb; - struct mbuf *m; +static void +sbappendsb(struct sbuf *sb, struct mbuf *m) { int len, n, nn; Index: qemu/slirp/sbuf.h =================================================================== --- qemu.orig/slirp/sbuf.h 2007-10-20 07:33:37.000000000 +0000 +++ qemu/slirp/sbuf.h 2007-10-20 14:46:56.000000000 +0000 @@ -24,8 +24,7 @@ void sbfree _P((struct sbuf *)); void sbdrop _P((struct sbuf *, int)); void sbreserve _P((struct sbuf *, int)); -void sbappend _P((struct socket *, struct mbuf *)); -void sbappendsb _P((struct sbuf *, struct mbuf *)); +void sbappend(slirp_state_t *s, struct socket *so, struct mbuf *m); void sbcopy _P((struct sbuf *, int, int, char *)); #endif Index: qemu/slirp/slirp.c =================================================================== --- qemu.orig/slirp/slirp.c 2007-10-20 07:33:37.000000000 +0000 +++ qemu/slirp/slirp.c 2007-10-20 12:34:47.000000000 +0000 @@ -1,38 +1,14 @@ #include "slirp.h" -/* host address */ -struct in_addr our_addr; -/* host dns address */ -struct in_addr dns_addr; -/* host loopback address */ -struct in_addr loopback_addr; - -/* address for slirp virtual addresses */ -struct in_addr special_addr; -/* virtual address alias for host */ -struct in_addr alias_addr; - -const uint8_t special_ethaddr[6] = { +static const uint8_t special_ethaddr[6] = { 0x52, 0x54, 0x00, 0x12, 0x35, 0x00 }; -uint8_t client_ethaddr[6]; - -int do_slowtimo; -int link_up; -struct timeval tt; -FILE *lfd; -struct ex_list *exec_list; - -/* XXX: suppress those select globals */ -fd_set *global_readfds, *global_writefds, *global_xfds; - -char slirp_hostname[33]; - #ifdef _WIN32 -static int get_dns_addr(struct in_addr *pdns_addr) +static int get_dns_addr(slirp_state_t *s, struct in_addr *pdns_addr) { + int rc = 0; FIXED_INFO *FixedInfo=NULL; ULONG BufLen; DWORD ret; @@ -81,7 +57,7 @@ #else -static int get_dns_addr(struct in_addr *pdns_addr) +static int get_dns_addr(slirp_state_t *s, struct in_addr *pdns_addr) { char buff[512]; char buff2[256]; @@ -98,8 +74,8 @@ if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) { if (!inet_aton(buff2, &tmp_addr)) continue; - if (tmp_addr.s_addr == loopback_addr.s_addr) - tmp_addr = our_addr; + if (tmp_addr.s_addr == s->loopback_addr.s_addr) + tmp_addr = s->our_addr; /* If it's the first one, set it to dns_addr */ if (!found) *pdns_addr = tmp_addr; @@ -121,15 +97,24 @@ #endif #ifdef _WIN32 -void slirp_cleanup(void) +static void slirp_cleanup(void) { WSACleanup(); } #endif -void slirp_init(void) +slirp_state_t *slirp_init(void *user, const char *slirp_hostname, + const char *tftp_prefix, const char *network) { - // debug_init("/tmp/slirp.log", DEBUG_DEFAULT); + slirp_state_t *s; + + s = malloc(sizeof(slirp_state_t)); + if (!s) + return s; + memset(s, 0, sizeof(slirp_state_t)); + s->user = user; + s->slirp_hostname = slirp_hostname; + s->tftp_prefix = tftp_prefix; #ifdef _WIN32 { @@ -139,27 +124,79 @@ } #endif - link_up = 1; + s->link_up = 1; - if_init(); - ip_init(); + if_init(s); + ip_init(s); /* Initialise mbufs *after* setting the MTU */ - m_init(); + m_init(s); /* set default addresses */ - inet_aton("127.0.0.1", &loopback_addr); + inet_aton("127.0.0.1", &s->loopback_addr); + inet_aton("127.0.0.1", &s->dns_addr); - if (get_dns_addr(&dns_addr) < 0) { - dns_addr = loopback_addr; + if (get_dns_addr(s, &s->dns_addr) < 0) { fprintf (stderr, "Warning: No DNS servers found\n"); } - inet_aton(CTL_SPECIAL, &special_addr); - alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS); - getouraddr(); + inet_aton(network, &s->special_addr); + s->alias_addr.s_addr = s->special_addr.s_addr | htonl(CTL_ALIAS); + getouraddr(s); + + return s; } +/** + * Marks the link as up, making it possible to establish new connections. + */ +void slirp_link_up(slirp_state_t *s) +{ + s->link_up = 1; +} + +/** + * Marks the link as down and cleans up the current connections. + */ +void slirp_link_down(slirp_state_t *s) +{ + struct socket *so; + + while ((so = s->tcb.so_next) != &s->tcb) + { + if (so->so_state & SS_NOFDREF || so->s == -1) + sofree(s, so); + else + tcp_drop(s, sototcpcb(so), 0); + } + + while ((so = s->udb.so_next) != &s->udb) + udp_detach(s, so); + + s->link_up = 0; +} + +/** + * Terminates the slirp component. + */ +void slirp_term(slirp_state_t *s) +{ + slirp_link_down(s); +#ifdef WIN32 + WSACleanup(); +#endif +#ifdef LOG_ENABLED + ipstats(s); + tcpstats(s); + udpstats(s); + icmpstats(s); + mbufstats(s); + sockstats(s); +#endif + free(s); +} + + #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED) #define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED) #define UPD_NFDS(x) if (nfds < (x)) nfds = (x) @@ -168,28 +205,28 @@ * curtime kept to an accuracy of 1ms */ #ifdef _WIN32 -static void updtime(void) +static void updtime(slirp_state_t *s) { struct _timeb tb; _ftime(&tb); - curtime = (u_int)tb.time * (u_int)1000; - curtime += (u_int)tb.millitm; + s->curtime = (u_int)tb.time * (u_int)1000; + s->curtime += (u_int)tb.millitm; } #else -static void updtime(void) +static void updtime(slirp_state_t *s) { - gettimeofday(&tt, 0); + gettimeofday(&s->tt, 0); - curtime = (u_int)tt.tv_sec * (u_int)1000; - curtime += (u_int)tt.tv_usec / (u_int)1000; + s->curtime = (u_int)s->tt.tv_sec * (u_int)1000; + s->curtime += (u_int)s->tt.tv_usec / (u_int)1000; - if ((tt.tv_usec % 1000) >= 500) - curtime++; + if ((s->tt.tv_usec % 1000) >= 500) + s->curtime++; } #endif -void slirp_select_fill(int *pnfds, +void slirp_select_fill(slirp_state_t *s, int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds) { struct socket *so, *so_next; @@ -198,31 +235,31 @@ int tmp_time; /* fail safe */ - global_readfds = NULL; - global_writefds = NULL; - global_xfds = NULL; + s->readfds = NULL; + s->writefds = NULL; + s->xfds = NULL; nfds = *pnfds; /* * First, TCP sockets */ - do_slowtimo = 0; - if (link_up) { + s->do_slowtimo = 0; + if (s->link_up) { /* * *_slowtimo needs calling if there are IP fragments * in the fragment queue, or there are TCP connections active */ - do_slowtimo = ((tcb.so_next != &tcb) || - ((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next)); + s->do_slowtimo = ((s->tcb.so_next != &s->tcb) || + ((struct ipasfrag *)&s->ipq != (struct ipasfrag *)s->ipq.next)); - for (so = tcb.so_next; so != &tcb; so = so_next) { + for (so = s->tcb.so_next; so != &s->tcb; so = so_next) { so_next = so->so_next; /* * See if we need a tcp_fasttimo */ - if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK) - time_fasttimo = curtime; /* Flag when we want a fasttimo */ + if (s->time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK) + s->time_fasttimo = s->curtime; /* Flag when we want a fasttimo */ /* * NOFDREF can include still connecting to local-host, @@ -272,18 +309,18 @@ /* * UDP sockets */ - for (so = udb.so_next; so != &udb; so = so_next) { + for (so = s->udb.so_next; so != &s->udb; so = so_next) { so_next = so->so_next; /* * See if it's timed out */ if (so->so_expire) { - if (so->so_expire <= curtime) { - udp_detach(so); + if (so->so_expire <= s->curtime) { + udp_detach(s, so); continue; } else - do_slowtimo = 1; /* Let socket expire */ + s->do_slowtimo = 1; /* Let socket expire */ } /* @@ -317,17 +354,17 @@ * slow timeout. If a fast timeout is needed, set timeout within * 200ms of when it was requested. */ - if (do_slowtimo) { + if (s->do_slowtimo) { /* XXX + 10000 because some select()'s aren't that accurate */ - timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000; + timeout.tv_usec = ((500 - (s->curtime - s->last_slowtimo)) * 1000) + 10000; if (timeout.tv_usec < 0) timeout.tv_usec = 0; else if (timeout.tv_usec > 510000) timeout.tv_usec = 510000; /* Can only fasttimo if we also slowtimo */ - if (time_fasttimo) { - tmp_time = (200 - (curtime - time_fasttimo)) * 1000; + if (s->time_fasttimo) { + tmp_time = (200 - (s->curtime - s->time_fasttimo)) * 1000; if (tmp_time < 0) tmp_time = 0; @@ -339,41 +376,41 @@ *pnfds = nfds; } -void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds) +void slirp_select_poll(slirp_state_t *s, fd_set *readfds, fd_set *writefds, fd_set *xfds) { struct socket *so, *so_next; int ret; - global_readfds = readfds; - global_writefds = writefds; - global_xfds = xfds; + s->readfds = readfds; + s->writefds = writefds; + s->xfds = xfds; /* Update time */ - updtime(); + updtime(s); /* * See if anything has timed out */ - if (link_up) { - if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) { - tcp_fasttimo(); - time_fasttimo = 0; + if (s->link_up) { + if (s->time_fasttimo && ((s->curtime - s->time_fasttimo) >= 2)) { + tcp_fasttimo(s); + s->time_fasttimo = 0; } - if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) { - ip_slowtimo(); - tcp_slowtimo(); - last_slowtimo = curtime; + if (s->do_slowtimo && ((s->curtime - s->last_slowtimo) >= 499)) { + ip_slowtimo(s); + tcp_slowtimo(s); + s->last_slowtimo = s->curtime; } } /* * Check sockets */ - if (link_up) { + if (s->link_up) { /* * Check TCP sockets */ - for (so = tcb.so_next; so != &tcb; so = so_next) { + for (so = s->tcb.so_next; so != &s->tcb; so = so_next) { so_next = so->so_next; /* @@ -389,7 +426,7 @@ * test for readfds below if this succeeds */ if (FD_ISSET(so->s, xfds)) - sorecvoob(so); + sorecvoob(s, so); /* * Check sockets for reading */ @@ -398,14 +435,14 @@ * Check for incoming connections */ if (so->so_state & SS_FACCEPTCONN) { - tcp_connect(so); + tcp_connect(s, so); continue; } /* else */ - ret = soread(so); + ret = soread(s, so); /* Output it if we read something */ if (ret > 0) - tcp_output(sototcpcb(so)); + tcp_output(s, sototcpcb(so)); } /* @@ -434,10 +471,10 @@ /* * Continue tcp_input */ - tcp_input((struct mbuf *)NULL, sizeof(struct ip), so); + tcp_input(s, (struct mbuf *)NULL, sizeof(struct ip), so); /* continue; */ } else - ret = sowrite(so); + ret = sowrite(s, so); /* * XXXXX If we wrote something (a lot), there * could be a need for a window update. @@ -487,11 +524,11 @@ * Incoming packets are sent straight away, they're not buffered. * Incoming UDP data isn't buffered either. */ - for (so = udb.so_next; so != &udb; so = so_next) { + for (so = s->udb.so_next; so != &s->udb; so = so_next) { so_next = so->so_next; if (so->s != -1 && FD_ISSET(so->s, readfds)) { - sorecvfrom(so); + sorecvfrom(s, so); } } } @@ -499,17 +536,17 @@ /* * See if we can start outputting */ - if (if_queued && link_up) - if_start(); + if (s->if_queued && s->link_up) + if_start(s); /* clear global file descriptor sets. * these reside on the stack in vl.c * so they're unusable if we're not in * slirp_select_fill or slirp_select_poll. */ - global_readfds = NULL; - global_writefds = NULL; - global_xfds = NULL; + s->readfds = NULL; + s->writefds = NULL; + s->xfds = NULL; } #define ETH_ALEN 6 @@ -545,7 +582,8 @@ unsigned char ar_tip[4]; /* target IP address */ }; -void arp_input(const uint8_t *pkt, int pkt_len) +static +void arp_input(slirp_state_t *s, const uint8_t *pkt, int pkt_len) { struct ethhdr *eh = (struct ethhdr *)pkt; struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN); @@ -558,17 +596,17 @@ ar_op = ntohs(ah->ar_op); switch(ar_op) { case ARPOP_REQUEST: - if (!memcmp(ah->ar_tip, &special_addr, 3)) { + if (!memcmp(ah->ar_tip, &s->special_addr, 3)) { if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS) goto arp_ok; - for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { + for (ex_ptr = s->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { if (ex_ptr->ex_addr == ah->ar_tip[3]) goto arp_ok; } return; arp_ok: /* XXX: make an ARP request to have the client address */ - memcpy(client_ethaddr, eh->h_source, ETH_ALEN); + memcpy(s->client_ethaddr, eh->h_source, ETH_ALEN); /* ARP request for alias/dns mac address */ memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN); @@ -585,7 +623,7 @@ memcpy(rah->ar_sip, ah->ar_tip, 4); memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN); memcpy(rah->ar_tip, ah->ar_sip, 4); - slirp_output(arp_reply, sizeof(arp_reply)); + slirp_output(s->user, arp_reply, sizeof(arp_reply)); } break; default: @@ -593,7 +631,7 @@ } } -void slirp_input(const uint8_t *pkt, int pkt_len) +void slirp_input(slirp_state_t *s, const uint8_t *pkt, int pkt_len) { struct mbuf *m; int proto; @@ -604,10 +642,14 @@ proto = ntohs(*(uint16_t *)(pkt + 12)); switch(proto) { case ETH_P_ARP: - arp_input(pkt, pkt_len); + arp_input(s, pkt, pkt_len); break; case ETH_P_IP: - m = m_get(); + /* Update time. Important if the network is very quiet, as otherwise + * the first outgoing connection gets an incorrect timestamp. */ + updtime(s); + + m = m_get(s); if (!m) return; /* Note: we add to align the IP header */ @@ -617,7 +659,7 @@ m->m_data += 2 + ETH_HLEN; m->m_len -= 2 + ETH_HLEN; - ip_input(m); + ip_input(s, m); break; default: break; @@ -625,7 +667,7 @@ } /* output the IP packet to the ethernet device */ -void if_encap(const uint8_t *ip_data, int ip_data_len) +void if_encap(slirp_state_t *s, const uint8_t *ip_data, int ip_data_len) { uint8_t buf[1600]; struct ethhdr *eh = (struct ethhdr *)buf; @@ -633,33 +675,33 @@ if (ip_data_len + ETH_HLEN > sizeof(buf)) return; - memcpy(eh->h_dest, client_ethaddr, ETH_ALEN); + memcpy(eh->h_dest, s->client_ethaddr, ETH_ALEN); memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1); /* XXX: not correct */ eh->h_source[5] = CTL_ALIAS; eh->h_proto = htons(ETH_P_IP); memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len); - slirp_output(buf, ip_data_len + ETH_HLEN); + slirp_output(s->user, buf, ip_data_len + ETH_HLEN); } -int slirp_redir(int is_udp, int host_port, +int slirp_redir(slirp_state_t *s, int is_udp, int host_port, struct in_addr guest_addr, int guest_port) { if (is_udp) { - if (!udp_listen(htons(host_port), guest_addr.s_addr, + if (!udp_listen(s, htons(host_port), guest_addr.s_addr, htons(guest_port), 0)) return -1; } else { - if (!solisten(htons(host_port), guest_addr.s_addr, + if (!solisten(s, htons(host_port), guest_addr.s_addr, htons(guest_port), 0)) return -1; } return 0; } -int slirp_add_exec(int do_pty, const char *args, int addr_low_byte, +int slirp_add_exec(slirp_state_t *s, int do_pty, const char *args, int addr_low_byte, int guest_port) { - return add_exec(&exec_list, do_pty, (char *)args, + return add_exec(&s->exec_list, do_pty, (char *)args, addr_low_byte, htons(guest_port)); } Index: qemu/slirp/slirp.h =================================================================== --- qemu.orig/slirp/slirp.h 2007-10-20 07:33:37.000000000 +0000 +++ qemu/slirp/slirp.h 2007-10-20 14:58:01.000000000 +0000 @@ -5,6 +5,9 @@ #define DEBUG 1 +// Uncomment the following line to enable SLIRP statistics printing in Qemu +//#define LOG_ENABLED + #ifndef CONFIG_QEMU #include "version.h" #endif @@ -190,6 +193,8 @@ #include <sys/stropts.h> #endif +#include "libslirp.h" + #include "debug.h" #include "ip.h" @@ -213,19 +218,113 @@ #include "bootp.h" #include "tftp.h" -#include "libslirp.h" -extern struct ttys *ttys_unit[MAX_INTERFACES]; +/** Number of DHCP clients supported by NAT. */ +#define NB_ADDR 16 + +/** Where to start DHCP IP number allocation. */ +#define START_ADDR 15 + +/** DHCP Lease time. */ +#define LEASE_TIME (24 * 3600) + +/** Entry in the table of known DHCP clients. */ +typedef struct { + int allocated; + uint8_t macaddr[6]; +} BOOTPClient; + + +/** TFTP session entry. */ +struct tftp_session { + int in_use; + unsigned char filename[TFTP_FILENAME_MAX]; + + struct in_addr client_ip; + u_int16_t client_port; + + int timestamp; +}; + + +/** Main state/configuration structure for slirp. */ +struct slirp_state_t +{ + /* Stuff from boot.c */ + BOOTPClient bootp_clients[NB_ADDR]; + const char *bootp_filename; + /* Stuff from if.c */ + int if_mtu, if_mru; + int if_comp; + int if_maxlinkhdr; + int if_queued; + int if_thresh; + struct mbuf if_fastq; + struct mbuf if_batchq; + struct mbuf *next_m; + /* Stuff from icmp.c */ + struct icmpstat icmpstat; + /* Stuff from ip_input.c */ + struct ipstat ipstat; + struct ipq ipq; + uint16_t ip_id; + /* Stuff from mbuf.c */ + int mbuf_alloced, mbuf_max; + int msize; + struct mbuf m_freelist, m_usedlist; + /* Stuff from slirp.c */ + fd_set *readfds, *writefds, *xfds; + const char *slirp_hostname; + void *user; + uint32_t curtime; + uint32_t time_fasttimo; + uint32_t last_slowtimo; + int do_slowtimo; + int link_up; + struct timeval tt; + struct in_addr our_addr; + struct in_addr alias_addr; + struct in_addr special_addr; + struct in_addr dns_addr; + struct in_addr loopback_addr; + uint8_t client_ethaddr[6]; + struct ex_list *exec_list; + /* Stuff from tcp_input.c */ + struct socket tcb; + struct socket *tcp_last_so; + tcp_seq tcp_iss; + /* Stuff from tcp_timer.c */ + struct tcpstat tcpstat; + uint32_t tcp_now; + /* Stuff from tftp.c */ + struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX]; + const char *tftp_prefix; + /* Stuff from udp.c */ + struct udpstat udpstat; + struct socket udb; + struct socket *udp_last_so; + // tcp_subr.c + int do_echo; +}; + +/** Number of permanent buffers in mbuf. */ +#define MBUF_THRESH 30 + +/** Default TCP socket options. */ +#define SO_OPTIONS DO_KEEPALIVE + +/** Enable RFC1323 performance enhancements. + * @todo check if it really works, it was turned off before. */ +#define TCP_DO_RFC1323 1 + +/* TCP duplicate ACK retransmit threshold. */ +#define TCPREXMTTHRESH 3 #ifndef NULL #define NULL (void *)0 #endif -#ifndef FULL_BOLT -void if_start _P((void)); -#else -void if_start _P((struct ttys *)); -#endif +void if_start(slirp_state_t *s); #ifdef BAD_SPRINTF # define vsprintf vsprintf_len @@ -253,16 +352,22 @@ long gethostid _P((void)); #endif -void lprint _P((const char *, ...)); - -extern int do_echo; +static inline void lprint(const char *format, ...) +{ +#ifdef LOG_ENABLED + va_list args; + va_start(args, format); + term_vprintf(format, args); + va_end(args); +#endif +} #if SIZEOF_CHAR_P == 4 # define insque_32 insque # define remque_32 remque #else - inline void insque_32 _P((void *, void *)); - inline void remque_32 _P((void *)); +void insque_32(slirp_state_t *s, void *a, void *b); +void remque_32(slirp_state_t *s, void *a); #endif #ifndef _WIN32 @@ -275,48 +380,41 @@ int cksum(struct mbuf *m, int len); /* if.c */ -void if_init _P((void)); -void if_output _P((struct socket *, struct mbuf *)); +void if_init(slirp_state_t *s); +void if_output(slirp_state_t *s, struct socket *so, struct mbuf *ifm); /* ip_input.c */ -void ip_init _P((void)); -void ip_input _P((struct mbuf *)); -struct ip * ip_reass _P((register struct ipasfrag *, register struct ipq *)); -void ip_freef _P((struct ipq *)); -void ip_enq _P((register struct ipasfrag *, register struct ipasfrag *)); -void ip_deq _P((register struct ipasfrag *)); -void ip_slowtimo _P((void)); +void ip_init(slirp_state_t *s); +void ip_input(slirp_state_t *s, struct mbuf *m); +void ip_slowtimo(slirp_state_t *s); void ip_stripoptions _P((register struct mbuf *, struct mbuf *)); /* ip_output.c */ -int ip_output _P((struct socket *, struct mbuf *)); +int ip_output(slirp_state_t *s, struct socket *so, struct mbuf *m0); /* tcp_input.c */ -int tcp_reass _P((register struct tcpcb *, register struct tcpiphdr *, struct mbuf *)); -void tcp_input _P((register struct mbuf *, int, struct socket *)); -void tcp_dooptions _P((struct tcpcb *, u_char *, int, struct tcpiphdr *)); -void tcp_xmit_timer _P((register struct tcpcb *, int)); -int tcp_mss _P((register struct tcpcb *, u_int)); +void tcp_input(slirp_state_t *s, register struct mbuf *m, int iphlen, struct socket *inso); +int tcp_mss(slirp_state_t *s, register struct tcpcb *tp, u_int offer); /* tcp_output.c */ -int tcp_output _P((register struct tcpcb *)); +int tcp_output(slirp_state_t *s, register struct tcpcb *tp); void tcp_setpersist _P((register struct tcpcb *)); /* tcp_subr.c */ -void tcp_init _P((void)); +void tcp_init(slirp_state_t *s); void tcp_template _P((struct tcpcb *)); -void tcp_respond _P((struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int)); -struct tcpcb * tcp_newtcpcb _P((struct socket *)); -struct tcpcb * tcp_close _P((register struct tcpcb *)); -void tcp_drain _P((void)); -void tcp_sockclosed _P((struct tcpcb *)); -int tcp_fconnect _P((struct socket *)); -void tcp_connect _P((struct socket *)); -int tcp_attach _P((struct socket *)); +void tcp_respond(slirp_state_t *s, struct tcpcb *tp, struct tcpiphdr *ti, + struct mbuf *m, tcp_seq ack, tcp_seq seq, int flags); +struct tcpcb *tcp_newtcpcb(slirp_state_t *s, struct socket *so); +struct tcpcb *tcp_close(slirp_state_t *s, register struct tcpcb *tp); +void tcp_sockclosed(slirp_state_t *s, struct tcpcb *tp); +int tcp_fconnect(slirp_state_t *s, struct socket *so); +void tcp_connect(slirp_state_t *s, struct socket *inso); +int tcp_attach(slirp_state_t *s, struct socket *so); u_int8_t tcp_tos _P((struct socket *)); -int tcp_emu _P((struct socket *, struct mbuf *)); -int tcp_ctl _P((struct socket *)); -struct tcpcb *tcp_drop(struct tcpcb *tp, int err); +int tcp_emu(slirp_state_t *s, struct socket *so, struct mbuf *m); +int tcp_ctl(slirp_state_t *s, struct socket *so); +struct tcpcb *tcp_drop(slirp_state_t *s, struct tcpcb *tp, int err); #ifdef USE_PPP #define MIN_MRU MINMRU Index: qemu/slirp/socket.c =================================================================== --- qemu.orig/slirp/socket.c 2007-10-20 07:33:37.000000000 +0000 +++ qemu/slirp/socket.c 2007-10-20 12:33:06.000000000 +0000 @@ -13,12 +13,16 @@ #include <sys/filio.h> #endif -void +static void sofcantrcvmore(slirp_state_t *s, struct socket *so); +static void sofcantsendmore(slirp_state_t *s, struct socket *so); + +#if 0 +static void so_init() { /* Nothing yet */ } - +#endif struct socket * solookup(head, laddr, lport, faddr, fport) @@ -67,22 +71,21 @@ * remque and free a socket, clobber cache */ void -sofree(so) - struct socket *so; +sofree(slirp_state_t *s, struct socket *so) { if (so->so_emu==EMU_RSH && so->extra) { - sofree(so->extra); + sofree(s, so->extra); so->extra=NULL; } - if (so == tcp_last_so) - tcp_last_so = &tcb; - else if (so == udp_last_so) - udp_last_so = &udb; + if (so == s->tcp_last_so) + s->tcp_last_so = &s->tcb; + else if (so == s->udp_last_so) + s->udp_last_so = &s->udb; - m_free(so->so_m); + m_free(s, so->so_m); if(so->so_next && so->so_prev) - remque(so); /* crashes if so is not in a queue */ + remque(s, so); /* crashes if so is not in a queue */ free(so); } @@ -93,8 +96,7 @@ * a read() of 0 (or less) means it's disconnected */ int -soread(so) - struct socket *so; +soread(slirp_state_t *s, struct socket *so) { int n, nn, lss, total; struct sbuf *sb = &so->so_snd; @@ -113,6 +115,8 @@ len = sb->sb_datalen - sb->sb_cc; iov[0].iov_base = sb->sb_wptr; + iov[1].iov_base = 0; + iov[1].iov_len = 0; if (sb->sb_wptr < sb->sb_rptr) { iov[0].iov_len = sb->sb_rptr - sb->sb_wptr; /* Should never succeed, but... */ @@ -162,8 +166,8 @@ return 0; else { DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno))); - sofcantrcvmore(so); - tcp_sockclosed(sototcpcb(so)); + sofcantrcvmore(s, so); + tcp_sockclosed(s, sototcpcb(so)); return -1; } } @@ -204,8 +208,7 @@ * in the send buffer is sent as urgent data */ void -sorecvoob(so) - struct socket *so; +sorecvoob(slirp_state_t *s, struct socket *so) { struct tcpcb *tp = sototcpcb(so); @@ -220,10 +223,10 @@ * urgent data, or the read() doesn't return all the * urgent data. */ - soread(so); + soread(s, so); tp->snd_up = tp->snd_una + so->so_snd.sb_cc; tp->t_force = 1; - tcp_output(tp); + tcp_output(s, tp); tp->t_force = 0; } @@ -291,8 +294,7 @@ * updating all sbuf field as necessary */ int -sowrite(so) - struct socket *so; +sowrite(slirp_state_t *s, struct socket *so) { int n,nn; struct sbuf *sb = &so->so_rcv; @@ -316,6 +318,8 @@ len = sb->sb_cc; iov[0].iov_base = sb->sb_rptr; + iov[1].iov_base = 0; + iov[1].iov_len = 0; if (sb->sb_rptr < sb->sb_wptr) { iov[0].iov_len = sb->sb_wptr - sb->sb_rptr; /* Should never succeed, but... */ @@ -349,8 +353,8 @@ if (nn <= 0) { DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n", so->so_state, errno)); - sofcantsendmore(so); - tcp_sockclosed(sototcpcb(so)); + sofcantsendmore(s, so); + tcp_sockclosed(s, sototcpcb(so)); return -1; } @@ -375,7 +379,7 @@ * it CANTSENDMORE */ if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0) - sofcantsendmore(so); + sofcantsendmore(s,so); return nn; } @@ -384,8 +388,7 @@ * recvfrom() a UDP socket */ void -sorecvfrom(so) - struct socket *so; +sorecvfrom(slirp_state_t *s, struct socket *so) { struct sockaddr_in addr; int addrlen = sizeof(struct sockaddr_in); @@ -409,19 +412,19 @@ DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n", errno,strerror(errno))); - icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno)); + icmp_error(s, so->so_m, ICMP_UNREACH,code, 0,strerror(errno)); } else { - icmp_reflect(so->so_m); + icmp_reflect(s, so->so_m); so->so_m = 0; /* Don't m_free() it again! */ } /* No need for this socket anymore, udp_detach it */ - udp_detach(so); + udp_detach(s, so); } else { /* A "normal" UDP packet */ struct mbuf *m; int len, n; - if (!(m = m_get())) return; - m->m_data += if_maxlinkhdr; + if (!(m = m_get(s))) return; + m->m_data += s->if_maxlinkhdr; /* * XXX Shouldn't FIONREAD packets destined for port 53, @@ -449,8 +452,8 @@ else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET; DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code)); - icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno)); - m_free(m); + icmp_error(s, so->so_m, ICMP_UNREACH,code, 0,strerror(errno)); + m_free(s, m); } else { /* * Hack: domain name lookup will be used the most for UDP, @@ -460,9 +463,9 @@ */ if (so->so_expire) { if (so->so_fport == htons(53)) - so->so_expire = curtime + SO_EXPIREFAST; + so->so_expire = s->curtime + SO_EXPIREFAST; else - so->so_expire = curtime + SO_EXPIRE; + so->so_expire = s->curtime + SO_EXPIRE; } /* if (m->m_len == len) { @@ -475,7 +478,7 @@ * If this packet was destined for CTL_ADDR, * make it look like that's where it came from, done by udp_output */ - udp_output(so, m, &addr); + udp_output(s, so, m, &addr); } /* rx error */ } /* if ping packet */ } @@ -484,9 +487,7 @@ * sendto() a socket */ int -sosendto(so, m) - struct socket *so; - struct mbuf *m; +sosendto(slirp_state_t *s, struct socket *so, struct mbuf *m) { int ret; struct sockaddr_in addr; @@ -496,15 +497,30 @@ DEBUG_ARG("m = %lx", (long)m); addr.sin_family = AF_INET; - if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) { + if ((so->so_faddr.s_addr & htonl(0xffffff00)) == s->special_addr.s_addr) { /* It's an alias */ switch(ntohl(so->so_faddr.s_addr) & 0xff) { + case CTL_BROADCAST: + addr.sin_addr.s_addr = INADDR_BROADCAST; +#if 0 + /* Send the packet to host to fully emulate broadcast */ + /** @todo r=klaus: on Linux host this causes the host to receive + * the packet twice for some reason. And I cannot find any place + * in the man pages which states that sending a broadcast does not + * reach the host itself. */ + host_addr.sin_family = AF_INET; + host_addr.sin_port = so->so_fport; + host_addr.sin_addr = s->our_addr; + sendto(so->s, m->m_data, m->m_len, 0, + (struct sockaddr *)&host_addr, sizeof (struct sockaddr)); +#endif + break; case CTL_DNS: - addr.sin_addr = dns_addr; + addr.sin_addr = s->dns_addr; break; case CTL_ALIAS: default: - addr.sin_addr = loopback_addr; + addr.sin_addr = s->loopback_addr; break; } } else @@ -524,7 +540,7 @@ * but only if it's an expirable socket */ if (so->so_expire) - so->so_expire = curtime + SO_EXPIRE; + so->so_expire = s->curtime + SO_EXPIRE; so->so_state = SS_ISFCONNECTED; /* So that it gets select()ed */ return 0; } @@ -533,15 +549,11 @@ * XXX This should really be tcp_listen */ struct socket * -solisten(port, laddr, lport, flags) - u_int port; - u_int32_t laddr; - u_int lport; - int flags; +solisten(slirp_state_t *s, u_int port, u_int32_t laddr, u_int lport, int flags) { struct sockaddr_in addr; struct socket *so; - int s, addrlen = sizeof(addr), opt = 1; + int fd, addrlen = sizeof(addr), opt = 1; DEBUG_CALL("solisten"); DEBUG_ARG("port = %d", port); @@ -555,11 +567,11 @@ } /* Don't tcp_attach... we don't need so_snd nor so_rcv */ - if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) { + if ((so->so_tcpcb = tcp_newtcpcb(s, so)) == NULL) { free(so); return NULL; } - insque(so,&tcb); + insque(s, so, &s->tcb); /* * SS_FACCEPTONCE sockets must time out. @@ -575,14 +587,14 @@ addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = port; - if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) || - (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) || - (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) || - (listen(s,1) < 0)) { + if (((fd = socket(AF_INET,SOCK_STREAM, 0)) < 0) || + (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int)) < 0) || + (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) || + (listen(fd ,1) < 0)) { int tmperrno = errno; /* Don't clobber the real reason we failed */ - close(s); - sofree(so); + close(fd); + sofree(s, so); /* Restore the real errno */ #ifdef _WIN32 WSASetLastError(tmperrno); @@ -591,25 +603,26 @@ #endif return NULL; } - setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); + setsockopt(fd, SOL_SOCKET,SO_OOBINLINE, (char *)&opt, sizeof(int)); - getsockname(s,(struct sockaddr *)&addr,&addrlen); + getsockname(fd, (struct sockaddr *)&addr, &addrlen); so->so_fport = addr.sin_port; - if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) - so->so_faddr = alias_addr; + if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == s->loopback_addr.s_addr) + so->so_faddr = s->alias_addr; else so->so_faddr = addr.sin_addr; - so->s = s; + so->s = fd; return so; } +#if 0 /* * Data is available in so_rcv * Just write() the data to the socket * XXX not yet... */ -void +static void sorwakeup(so) struct socket *so; { @@ -622,12 +635,13 @@ * We have room for a read() if we want to * For now, don't read, it'll be done in the main loop */ -void +static void sowwakeup(so) struct socket *so; { /* Nothing, yet */ } +#endif /* * Various session state calls @@ -652,14 +666,13 @@ so->so_state |= SS_ISFCONNECTED; /* Clobber other states */ } -void -sofcantrcvmore(so) - struct socket *so; +static void +sofcantrcvmore(slirp_state_t *s, struct socket *so) { if ((so->so_state & SS_NOFDREF) == 0) { shutdown(so->s,0); - if(global_writefds) { - FD_CLR(so->s,global_writefds); + if (s->writefds) { + FD_CLR(so->s, s->writefds); } } so->so_state &= ~(SS_ISFCONNECTING); @@ -669,17 +682,16 @@ so->so_state |= SS_FCANTRCVMORE; } -void -sofcantsendmore(so) - struct socket *so; +static void +sofcantsendmore(slirp_state_t *s, struct socket *so) { if ((so->so_state & SS_NOFDREF) == 0) { shutdown(so->s,1); /* send FIN to fhost */ - if (global_readfds) { - FD_CLR(so->s,global_readfds); + if (s->readfds) { + FD_CLR(so->s, s->readfds); } - if (global_xfds) { - FD_CLR(so->s,global_xfds); + if (s->xfds) { + FD_CLR(so->s, s->xfds); } } so->so_state &= ~(SS_ISFCONNECTING); @@ -706,12 +718,11 @@ * Set CANTSENDMORE once all data has been write()n */ void -sofwdrain(so) - struct socket *so; +sofwdrain(slirp_state_t *s, struct socket *so) { if (so->so_rcv.sb_cc) so->so_state |= SS_FWDRAIN; else - sofcantsendmore(so); + sofcantsendmore(s, so); } Index: qemu/slirp/socket.h =================================================================== --- qemu.orig/slirp/socket.h 2007-10-20 07:33:37.000000000 +0000 +++ qemu/slirp/socket.h 2007-10-20 14:55:25.000000000 +0000 @@ -71,9 +71,6 @@ #define SS_FACCEPTCONN 0x100 /* Socket is accepting connections from a host on the internet */ #define SS_FACCEPTONCE 0x200 /* If set, the SS_FACCEPTCONN socket will die after one accept */ -extern struct socket tcb; - - #if defined(DECLARE_IOVEC) && !defined(HAVE_READV) struct iovec { char *iov_base; @@ -81,24 +78,20 @@ }; #endif -void so_init _P((void)); struct socket * solookup _P((struct socket *, struct in_addr, u_int, struct in_addr, u_int)); struct socket * socreate _P((void)); -void sofree _P((struct socket *)); -int soread _P((struct socket *)); -void sorecvoob _P((struct socket *)); +void sofree(slirp_state_t *s, struct socket *so); +int soread(slirp_state_t *s, struct socket *so); +void sorecvoob(slirp_state_t *s, struct socket *so); int sosendoob _P((struct socket *)); -int sowrite _P((struct socket *)); -void sorecvfrom _P((struct socket *)); -int sosendto _P((struct socket *, struct mbuf *)); -struct socket * solisten _P((u_int, u_int32_t, u_int, int)); -void sorwakeup _P((struct socket *)); -void sowwakeup _P((struct socket *)); +int sowrite(slirp_state_t *s, struct socket *so); +void sorecvfrom(slirp_state_t *s, struct socket *so); +int sosendto(slirp_state_t *s, struct socket *so, struct mbuf *m); +struct socket *solisten(slirp_state_t *s, u_int port, u_int32_t laddr, + u_int lport, int flags); void soisfconnecting _P((register struct socket *)); void soisfconnected _P((register struct socket *)); -void sofcantrcvmore _P((struct socket *)); -void sofcantsendmore _P((struct socket *)); void soisfdisconnected _P((struct socket *)); -void sofwdrain _P((struct socket *)); +void sofwdrain(slirp_state_t *s, struct socket *so); #endif /* _SOCKET_H_ */ Index: qemu/slirp/tcp.h =================================================================== --- qemu.orig/slirp/tcp.h 2007-10-20 07:33:37.000000000 +0000 +++ qemu/slirp/tcp.h 2007-10-20 09:42:26.000000000 +0000 @@ -42,10 +42,6 @@ #define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */ #define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */ -extern int tcp_rcvspace; -extern int tcp_sndspace; -extern struct socket *tcp_last_so; - #define TCP_SNDSPACE 8192 #define TCP_RCVSPACE 8192 @@ -170,8 +166,6 @@ #define TCP_ISSINCR (125*1024) /* increment for tcp_iss each second */ -extern tcp_seq tcp_iss; /* tcp initial send seq # */ - -extern char *tcpstates[]; +extern const char * const tcpstates[]; #endif Index: qemu/slirp/tcp_input.c =================================================================== --- qemu.orig/slirp/tcp_input.c 2007-10-20 07:33:38.000000000 +0000 +++ qemu/slirp/tcp_input.c 2007-10-20 17:08:59.000000000 +0000 @@ -45,12 +45,6 @@ #include <slirp.h> #include "ip_icmp.h" -struct socket tcb; - -int tcprexmtthresh = 3; -struct socket *tcp_last_so = &tcb; - -tcp_seq tcp_iss; /* tcp initial send seq # */ #define TCP_PAWS_IDLE (24 * 24 * 60 * 60 * PR_SLOWHZ) @@ -69,7 +63,7 @@ * when segments are out of order (so fast retransmit can work). */ #ifdef TCP_ACK_HACK -#define TCP_REASS(tp, ti, m, so, flags) {\ +#define TCP_REASS(s, tp, ti, m, so, flags) {\ if ((ti)->ti_seq == (tp)->rcv_nxt && \ (tp)->seg_next == (tcpiphdrp_32)(tp) && \ (tp)->t_state == TCPS_ESTABLISHED) {\ @@ -79,45 +73,49 @@ tp->t_flags |= TF_DELACK; \ (tp)->rcv_nxt += (ti)->ti_len; \ flags = (ti)->ti_flags & TH_FIN; \ - tcpstat.tcps_rcvpack++;\ - tcpstat.tcps_rcvbyte += (ti)->ti_len;\ + s->tcpstat.tcps_rcvpack++;\ + s->tcpstat.tcps_rcvbyte += (ti)->ti_len;\ if (so->so_emu) { \ - if (tcp_emu((so),(m))) sbappend((so), (m)); \ + if (tcp_emu((s), (so), (m))) \ + sbappend((s), (so), (m)); \ } else \ - sbappend((so), (m)); \ + sbappend((s), (so), (m)); \ /* sorwakeup(so); */ \ } else {\ - (flags) = tcp_reass((tp), (ti), (m)); \ + (flags) = tcp_reass((s), (tp), (ti), (m)); \ tp->t_flags |= TF_ACKNOW; \ } \ } #else -#define TCP_REASS(tp, ti, m, so, flags) { \ +#define TCP_REASS(s, tp, ti, m, so, flags) { \ if ((ti)->ti_seq == (tp)->rcv_nxt && \ (tp)->seg_next == (tcpiphdrp_32)(tp) && \ (tp)->t_state == TCPS_ESTABLISHED) { \ tp->t_flags |= TF_DELACK; \ (tp)->rcv_nxt += (ti)->ti_len; \ flags = (ti)->ti_flags & TH_FIN; \ - tcpstat.tcps_rcvpack++;\ - tcpstat.tcps_rcvbyte += (ti)->ti_len;\ + s->tcpstat.tcps_rcvpack++;\ + s->tcpstat.tcps_rcvbyte += (ti)->ti_len;\ if (so->so_emu) { \ - if (tcp_emu((so),(m))) sbappend(so, (m)); \ + if (tcp_emu((s), (so), (m))) \ + sbappend((s), (so), (m)); \ } else \ - sbappend((so), (m)); \ + sbappend((s), (so), (m)); \ /* sorwakeup(so); */ \ } else { \ - (flags) = tcp_reass((tp), (ti), (m)); \ + (flags) = tcp_reass((s), (tp), (ti), (m)); \ tp->t_flags |= TF_ACKNOW; \ } \ } #endif - -int -tcp_reass(tp, ti, m) - register struct tcpcb *tp; - register struct tcpiphdr *ti; - struct mbuf *m; +static void tcp_dooptions(slirp_state_t *s, struct tcpcb *tp, u_char *cp, + int cnt, struct tcpiphdr *ti); +static void tcp_xmit_timer(slirp_state_t *s, register struct tcpcb *tp, + int rtt); + +static int +tcp_reass(slirp_state_t *s, register struct tcpcb *tp, + register struct tcpiphdr *ti, struct mbuf *m) { register struct tcpiphdr *q; struct socket *so = tp->t_socket; @@ -133,8 +131,7 @@ /* * Find a segment which begins after this one does. */ - for (q = (struct tcpiphdr *)tp->seg_next; q != (struct tcpiphdr *)tp; - q = (struct tcpiphdr *)q->ti_next) + for (q = tp->seg_next; q != tp; q = q->ti_next) if (SEQ_GT(q->ti_seq, ti->ti_seq)) break; @@ -150,9 +147,9 @@ i = q->ti_seq + q->ti_len - ti->ti_seq; if (i > 0) { if (i >= ti->ti_len) { - tcpstat.tcps_rcvduppack++; - tcpstat.tcps_rcvdupbyte += ti->ti_len; - m_freem(m); + s->tcpstat.tcps_rcvduppack++; + s->tcpstat.tcps_rcvdupbyte += ti->ti_len; + m_freem(s, m); /* * Try to present any queued data * at the left window edge to the user. @@ -167,9 +164,9 @@ } q = (struct tcpiphdr *)(q->ti_next); } - tcpstat.tcps_rcvoopack++; - tcpstat.tcps_rcvoobyte += ti->ti_len; - REASS_MBUF(ti) = (mbufp_32) m; /* XXX */ + s->tcpstat.tcps_rcvoopack++; + s->tcpstat.tcps_rcvoobyte += ti->ti_len; + REASS_MBUF_SET(ti, m); /* XXX */ /* * While we overlap succeeding segments trim them or, @@ -182,19 +179,19 @@ if (i < q->ti_len) { q->ti_seq += i; q->ti_len -= i; - m_adj((struct mbuf *) REASS_MBUF(q), i); + m_adj(REASS_MBUF_GET(q), i); break; } q = (struct tcpiphdr *)q->ti_next; - m = (struct mbuf *) REASS_MBUF((struct tcpiphdr *)q->ti_prev); - remque_32((void *)(q->ti_prev)); - m_freem(m); + m = (struct mbuf *) REASS_MBUF_GET((struct tcpiphdr *)q->ti_prev); + remque_32(s, (void *)(q->ti_prev)); + m_freem(s, m); } /* * Stick new segment in its place. */ - insque_32(ti, (void *)(q->ti_prev)); + insque_32(s, ti, (void *)(q->ti_prev)); present: /* @@ -211,17 +208,18 @@ do { tp->rcv_nxt += ti->ti_len; flags = ti->ti_flags & TH_FIN; - remque_32(ti); - m = (struct mbuf *) REASS_MBUF(ti); /* XXX */ + remque_32(s, ti); + m = REASS_MBUF_GET(ti); /* XXX */ ti = (struct tcpiphdr *)ti->ti_next; /* if (so->so_state & SS_FCANTRCVMORE) */ if (so->so_state & SS_FCANTSENDMORE) - m_freem(m); + m_freem(s, m); else { if (so->so_emu) { - if (tcp_emu(so,m)) sbappend(so, m); + if (tcp_emu(s, so,m)) + sbappend(s, so, m); } else - sbappend(so, m); + sbappend(s, so, m); } } while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt); /* sorwakeup(so); */ @@ -233,10 +231,7 @@ * protocol specification dated September, 1981 very closely. */ void -tcp_input(m, iphlen, inso) - register struct mbuf *m; - int iphlen; - struct socket *inso; +tcp_input(slirp_state_t *s, register struct mbuf *m, int iphlen, struct socket *inso) { struct ip save_ip, *ip; register struct tcpiphdr *ti; @@ -252,6 +247,7 @@ u_long tiwin; int ret; /* int ts_present = 0; */ + int mbuf_freed = 0; DEBUG_CALL("tcp_input"); DEBUG_ARGS((dfd," m = %8lx iphlen = %2d inso = %lx\n", @@ -275,7 +271,7 @@ } - tcpstat.tcps_rcvtotal++; + s->tcpstat.tcps_rcvtotal++; /* * Get IP and TCP header together in first mbuf. * Note: IP leaves IP header in first mbuf. @@ -308,7 +304,7 @@ * ti->ti_sum = cksum(m, len); * if (ti->ti_sum) { */ if(cksum(m, len)) { - tcpstat.tcps_rcvbadsum++; + s->tcpstat.tcps_rcvbadsum++; goto drop; } @@ -318,7 +314,7 @@ */ off = ti->ti_off << 2; if (off < sizeof (struct tcphdr) || off > tlen) { - tcpstat.tcps_rcvbadoff++; + s->tcpstat.tcps_rcvbadoff++; goto drop; } tlen -= off; @@ -366,16 +362,16 @@ * Locate pcb for segment. */ findso: - so = tcp_last_so; + so = s->tcp_last_so; if (so->so_fport != ti->ti_dport || so->so_lport != ti->ti_sport || so->so_laddr.s_addr != ti->ti_src.s_addr || so->so_faddr.s_addr != ti->ti_dst.s_addr) { - so = solookup(&tcb, ti->ti_src, ti->ti_sport, + so = solookup(&s->tcb, ti->ti_src, ti->ti_sport, ti->ti_dst, ti->ti_dport); if (so) - tcp_last_so = so; - ++tcpstat.tcps_socachemiss; + s->tcp_last_so = so; + ++s->tcpstat.tcps_socachemiss; } /* @@ -397,13 +393,13 @@ if ((so = socreate()) == NULL) goto dropwithreset; - if (tcp_attach(so) < 0) { + if (tcp_attach(s, so) < 0) { free(so); /* Not sofree (if it failed, it's not insqued) */ goto dropwithreset; } - sbreserve(&so->so_snd, tcp_sndspace); - sbreserve(&so->so_rcv, tcp_rcvspace); + sbreserve(&so->so_snd, TCP_SNDSPACE); + sbreserve(&so->so_rcv, TCP_RCVSPACE); /* tcp_last_so = so; */ /* XXX ? */ /* tp = sototcpcb(so); */ @@ -448,17 +444,17 @@ * Reset idle time and keep-alive timer. */ tp->t_idle = 0; - if (so_options) - tp->t_timer[TCPT_KEEP] = tcp_keepintvl; + if (SO_OPTIONS) + tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL; else - tp->t_timer[TCPT_KEEP] = tcp_keepidle; + tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE; /* * Process options if not in LISTEN state, * else do it below (after getting remote address). */ if (optp && tp->t_state != TCPS_LISTEN) - tcp_dooptions(tp, (u_char *)optp, optlen, ti); + tcp_dooptions(s, tp, (u_char *)optp, optlen, ti); /* , */ /* &ts_present, &ts_val, &ts_ecr); */ @@ -503,19 +499,19 @@ /* * this is a pure ack for outstanding data. */ - ++tcpstat.tcps_predack; + ++s->tcpstat.tcps_predack; /* if (ts_present) * tcp_xmit_timer(tp, tcp_now-ts_ecr+1); * else */ if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq)) - tcp_xmit_timer(tp, tp->t_rtt); + tcp_xmit_timer(s, tp, tp->t_rtt); acked = ti->ti_ack - tp->snd_una; - tcpstat.tcps_rcvackpack++; - tcpstat.tcps_rcvackbyte += acked; + s->tcpstat.tcps_rcvackpack++; + s->tcpstat.tcps_rcvackbyte += acked; sbdrop(&so->so_snd, acked); tp->snd_una = ti->ti_ack; - m_freem(m); + m_freem(s, m); /* * If all outstanding data are acked, stop @@ -544,7 +540,7 @@ * we don't need this.. XXX??? */ if (so->so_snd.sb_cc) - (void) tcp_output(tp); + (void) tcp_output(s, tp); return; } @@ -556,17 +552,18 @@ * with nothing on the reassembly queue and * we have enough buffer space to take it. */ - ++tcpstat.tcps_preddat; + ++s->tcpstat.tcps_preddat; tp->rcv_nxt += ti->ti_len; - tcpstat.tcps_rcvpack++; - tcpstat.tcps_rcvbyte += ti->ti_len; + s->tcpstat.tcps_rcvpack++; + s->tcpstat.tcps_rcvbyte += ti->ti_len; /* * Add data to socket buffer. */ if (so->so_emu) { - if (tcp_emu(so,m)) sbappend(so, m); + if (tcp_emu(s, so,m)) + sbappend(s, so, m); } else - sbappend(so, m); + sbappend(s, so, m); /* * XXX This is called when data arrives. Later, check @@ -584,7 +581,7 @@ * TCP throughput. See RFC 2581. */ tp->t_flags |= TF_ACKNOW; - tcp_output(tp); + tcp_output(s, tp); return; } } /* header prediction */ @@ -634,7 +631,8 @@ * If this is destined for the control address, then flag to * tcp_ctl once connected, otherwise connect */ - if ((so->so_faddr.s_addr&htonl(0xffffff00)) == special_addr.s_addr) { + if ((so->so_faddr.s_addr & htonl(0xffffff00)) == + s->special_addr.s_addr) { int lastbyte=ntohl(so->so_faddr.s_addr) & 0xff; if (lastbyte!=CTL_ALIAS && lastbyte!=CTL_DNS) { #if 0 @@ -646,7 +644,7 @@ { /* May be an add exec */ struct ex_list *ex_ptr; - for(ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { + for(ex_ptr = s->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { if(ex_ptr->ex_fport == so->so_fport && lastbyte == ex_ptr->ex_addr) { so->so_state |= SS_CTL; @@ -664,13 +662,14 @@ goto cont_input; } - if((tcp_fconnect(so) == -1) && (errno != EINPROGRESS) && (errno != EWOULDBLOCK)) { + if ((tcp_fconnect(s, so) == -1) && (errno != EINPROGRESS) + && (errno != EWOULDBLOCK)) { u_char code=ICMP_UNREACH_NET; DEBUG_MISC((dfd," tcp fconnect errno = %d-%s\n", errno,strerror(errno))); if(errno == ECONNREFUSED) { /* ACK the SYN, send RST to refuse the connection */ - tcp_respond(tp, ti, m, ti->ti_seq+1, (tcp_seq)0, + tcp_respond(s, tp, ti, m, ti->ti_seq+1, (tcp_seq)0, TH_RST|TH_ACK); } else { if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST; @@ -681,10 +680,10 @@ m->m_data -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); m->m_len += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); *ip=save_ip; - icmp_error(m, ICMP_UNREACH,code, 0,strerror(errno)); + icmp_error(s, m, ICMP_UNREACH,code, 0,strerror(errno)); } - tp = tcp_close(tp); - m_free(m); + tp = tcp_close(s, tp); + m_free(s, m); } else { /* * Haven't connected yet, save the current mbuf @@ -704,29 +703,29 @@ * Check if the connect succeeded */ if (so->so_state & SS_NOFDREF) { - tp = tcp_close(tp); + tp = tcp_close(s, tp); goto dropwithreset; } cont_input: tcp_template(tp); if (optp) - tcp_dooptions(tp, (u_char *)optp, optlen, ti); + tcp_dooptions(s, tp, (u_char *)optp, optlen, ti); /* , */ /* &ts_present, &ts_val, &ts_ecr); */ if (iss) tp->iss = iss; else - tp->iss = tcp_iss; - tcp_iss += TCP_ISSINCR/2; + tp->iss = s->tcp_iss; + s->tcp_iss += TCP_ISSINCR / 2; tp->irs = ti->ti_seq; tcp_sendseqinit(tp); tcp_rcvseqinit(tp); tp->t_flags |= TF_ACKNOW; tp->t_state = TCPS_SYN_RECEIVED; tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; - tcpstat.tcps_accepts++; + s->tcpstat.tcps_accepts++; goto trimthenstep6; } /* case TCPS_LISTEN */ @@ -750,7 +749,7 @@ if (tiflags & TH_RST) { if (tiflags & TH_ACK) - tp = tcp_drop(tp,0); /* XXX Check t_softerror! */ + tp = tcp_drop(s, tp,0); /* XXX Check t_softerror! */ goto drop; } @@ -767,7 +766,7 @@ tcp_rcvseqinit(tp); tp->t_flags |= TF_ACKNOW; if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) { - tcpstat.tcps_connects++; + s->tcpstat.tcps_connects++; soisfconnected(so); tp->t_state = TCPS_ESTABLISHED; @@ -778,14 +777,14 @@ * tp->rcv_scale = tp->request_r_scale; * } */ - (void) tcp_reass(tp, (struct tcpiphdr *)0, + (void) tcp_reass(s, tp, (struct tcpiphdr *)0, (struct mbuf *)0); /* * if we didn't have to retransmit the SYN, * use its rtt as our initial srtt & rtt var. */ if (tp->t_rtt) - tcp_xmit_timer(tp, tp->t_rtt); + tcp_xmit_timer(s, tp, tp->t_rtt); } else tp->t_state = TCPS_SYN_RECEIVED; @@ -801,8 +800,8 @@ m_adj(m, -todrop); ti->ti_len = tp->rcv_wnd; tiflags &= ~TH_FIN; - tcpstat.tcps_rcvpackafterwin++; - tcpstat.tcps_rcvbyteafterwin += todrop; + s->tcpstat.tcps_rcvpackafterwin++; + s->tcpstat.tcps_rcvbyteafterwin += todrop; } tp->snd_wl1 = ti->ti_seq - 1; tp->rcv_up = ti->ti_seq; @@ -873,11 +872,11 @@ */ tp->t_flags |= TF_ACKNOW; todrop = ti->ti_len; - tcpstat.tcps_rcvduppack++; - tcpstat.tcps_rcvdupbyte += todrop; + s->tcpstat.tcps_rcvduppack++; + s->tcpstat.tcps_rcvdupbyte += todrop; } else { - tcpstat.tcps_rcvpartduppack++; - tcpstat.tcps_rcvpartdupbyte += todrop; + s->tcpstat.tcps_rcvpartduppack++; + s->tcpstat.tcps_rcvpartdupbyte += todrop; } m_adj(m, todrop); ti->ti_seq += todrop; @@ -895,8 +894,8 @@ */ if ((so->so_state & SS_NOFDREF) && tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) { - tp = tcp_close(tp); - tcpstat.tcps_rcvafterclose++; + tp = tcp_close(s, tp); + s->tcpstat.tcps_rcvafterclose++; goto dropwithreset; } @@ -906,9 +905,9 @@ */ todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd); if (todrop > 0) { - tcpstat.tcps_rcvpackafterwin++; + s->tcpstat.tcps_rcvpackafterwin++; if (todrop >= ti->ti_len) { - tcpstat.tcps_rcvbyteafterwin += ti->ti_len; + s->tcpstat.tcps_rcvbyteafterwin += ti->ti_len; /* * If a new connection request is received * while in TIME_WAIT, drop the old connection @@ -919,7 +918,7 @@ tp->t_state == TCPS_TIME_WAIT && SEQ_GT(ti->ti_seq, tp->rcv_nxt)) { iss = tp->rcv_nxt + TCP_ISSINCR; - tp = tcp_close(tp); + tp = tcp_close(s, tp); goto findso; } /* @@ -931,11 +930,11 @@ */ if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) { tp->t_flags |= TF_ACKNOW; - tcpstat.tcps_rcvwinprobe++; + s->tcpstat.tcps_rcvwinprobe++; } else goto dropafterack; } else - tcpstat.tcps_rcvbyteafterwin += todrop; + s->tcpstat.tcps_rcvbyteafterwin += todrop; m_adj(m, -todrop); ti->ti_len -= todrop; tiflags &= ~(TH_PUSH|TH_FIN); @@ -976,14 +975,14 @@ /* so->so_error = ECONNRESET; */ close: tp->t_state = TCPS_CLOSED; - tcpstat.tcps_drops++; - tp = tcp_close(tp); + s->tcpstat.tcps_drops++; + tp = tcp_close(s, tp); goto drop; case TCPS_CLOSING: case TCPS_LAST_ACK: case TCPS_TIME_WAIT: - tp = tcp_close(tp); + tp = tcp_close(s, tp); goto drop; } @@ -992,7 +991,7 @@ * error and we send an RST and drop the connection. */ if (tiflags & TH_SYN) { - tp = tcp_drop(tp,0); + tp = tcp_drop(s, tp,0); goto dropwithreset; } @@ -1015,7 +1014,7 @@ if (SEQ_GT(tp->snd_una, ti->ti_ack) || SEQ_GT(ti->ti_ack, tp->snd_max)) goto dropwithreset; - tcpstat.tcps_connects++; + s->tcpstat.tcps_connects++; tp->t_state = TCPS_ESTABLISHED; /* * The sent SYN is ack'ed with our sequence number +1 @@ -1027,7 +1026,7 @@ tp->snd_una=ti->ti_ack; if (so->so_state & SS_CTL) { /* So tcp_ctl reports the right state */ - ret = tcp_ctl(so); + ret = tcp_ctl(s, so); if (ret == 1) { soisfconnected(so); so->so_state &= ~SS_CTL; /* success XXX */ @@ -1048,7 +1047,7 @@ * tp->rcv_scale = tp->request_r_scale; * } */ - (void) tcp_reass(tp, (struct tcpiphdr *)0, (struct mbuf *)0); + (void) tcp_reass(s, tp, (struct tcpiphdr *)0, (struct mbuf *)0); tp->snd_wl1 = ti->ti_seq - 1; /* Avoid ack processing; snd_una==ti_ack => dup ack */ goto synrx_to_est; @@ -1072,7 +1071,7 @@ if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) { if (ti->ti_len == 0 && tiwin == tp->snd_wnd) { - tcpstat.tcps_rcvdupack++; + s->tcpstat.tcps_rcvdupack++; DEBUG_MISC((dfd," dup ack m = %lx so = %lx \n", (long )m, (long )so)); /* @@ -1102,7 +1101,7 @@ if (tp->t_timer[TCPT_REXMT] == 0 || ti->ti_ack != tp->snd_una) tp->t_dupacks = 0; - else if (++tp->t_dupacks == tcprexmtthresh) { + else if (++tp->t_dupacks == TCPREXMTTHRESH) { tcp_seq onxt = tp->snd_nxt; u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / @@ -1115,15 +1114,15 @@ tp->t_rtt = 0; tp->snd_nxt = ti->ti_ack; tp->snd_cwnd = tp->t_maxseg; - (void) tcp_output(tp); + (void) tcp_output(s, tp); tp->snd_cwnd = tp->snd_ssthresh + tp->t_maxseg * tp->t_dupacks; if (SEQ_GT(onxt, tp->snd_nxt)) tp->snd_nxt = onxt; goto drop; - } else if (tp->t_dupacks > tcprexmtthresh) { + } else if (tp->t_dupacks > TCPREXMTTHRESH) { tp->snd_cwnd += tp->t_maxseg; - (void) tcp_output(tp); + (void) tcp_output(s, tp); goto drop; } } else @@ -1135,17 +1134,17 @@ * If the congestion window was inflated to account * for the other side's cached packets, retract it. */ - if (tp->t_dupacks > tcprexmtthresh && + if (tp->t_dupacks > TCPREXMTTHRESH && tp->snd_cwnd > tp->snd_ssthresh) tp->snd_cwnd = tp->snd_ssthresh; tp->t_dupacks = 0; if (SEQ_GT(ti->ti_ack, tp->snd_max)) { - tcpstat.tcps_rcvacktoomuch++; + s->tcpstat.tcps_rcvacktoomuch++; goto dropafterack; } acked = ti->ti_ack - tp->snd_una; - tcpstat.tcps_rcvackpack++; - tcpstat.tcps_rcvackbyte += acked; + s->tcpstat.tcps_rcvackpack++; + s->tcpstat.tcps_rcvackbyte += acked; /* * If we have a timestamp reply, update smoothed @@ -1161,7 +1160,7 @@ * else */ if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq)) - tcp_xmit_timer(tp,tp->t_rtt); + tcp_xmit_timer(s, tp,tp->t_rtt); /* * If all outstanding data is acked, stop retransmit @@ -1227,7 +1226,7 @@ */ if (so->so_state & SS_FCANTRCVMORE) { soisfdisconnected(so); - tp->t_timer[TCPT_2MSL] = tcp_maxidle; + tp->t_timer[TCPT_2MSL] = TCP_MAXIDLE; } tp->t_state = TCPS_FIN_WAIT_2; } @@ -1256,7 +1255,7 @@ */ case TCPS_LAST_ACK: if (ourfinisacked) { - tp = tcp_close(tp); + tp = tcp_close(s, tp); goto drop; } break; @@ -1284,7 +1283,7 @@ /* keep track of pure window updates */ if (ti->ti_len == 0 && tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd) - tcpstat.tcps_rcvwinupd++; + s->tcpstat.tcps_rcvwinupd++; tp->snd_wnd = tiwin; tp->snd_wl1 = ti->ti_seq; tp->snd_wl2 = ti->ti_ack; @@ -1350,7 +1349,7 @@ */ if ((ti->ti_len || (tiflags&TH_FIN)) && TCPS_HAVERCVDFIN(tp->t_state) == 0) { - TCP_REASS(tp, ti, m, so, tiflags); + TCP_REASS(s, tp, ti, m, so, tiflags); /* * Note the amount of data that peer has sent into * our window, in order to estimate the sender's @@ -1358,7 +1357,7 @@ */ len = so->so_rcv.sb_datalen - (tp->rcv_adv - tp->rcv_nxt); } else { - m_free(m); + mbuf_freed = 1; /* The mbuf must be freed, but only when its content is not needed anymore. */ tiflags &= ~TH_FIN; } @@ -1378,7 +1377,7 @@ * to send the FIN. */ /* sofcantrcvmore(so); */ - sofwdrain(so); + sofwdrain(s, so); tp->t_flags |= TF_ACKNOW; tp->rcv_nxt++; @@ -1445,11 +1444,14 @@ tp->t_flags |= TF_ACKNOW; } + if (mbuf_freed) { + m_free(s, m); + } /* * Return any desired output. */ if (needoutput || (tp->t_flags & TF_ACKNOW)) { - (void) tcp_output(tp); + (void) tcp_output(s, tp); } return; @@ -1460,18 +1462,18 @@ */ if (tiflags & TH_RST) goto drop; - m_freem(m); + m_freem(s, m); tp->t_flags |= TF_ACKNOW; - (void) tcp_output(tp); + (void) tcp_output(s, tp); return; dropwithreset: /* reuses m if m!=NULL, m_free() unnecessary */ if (tiflags & TH_ACK) - tcp_respond(tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST); + tcp_respond(s, tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST); else { if (tiflags & TH_SYN) ti->ti_len++; - tcp_respond(tp, ti, m, ti->ti_seq+ti->ti_len, (tcp_seq)0, + tcp_respond(s, tp, ti, m, ti->ti_seq+ti->ti_len, (tcp_seq)0, TH_RST|TH_ACK); } @@ -1481,7 +1483,7 @@ /* * Drop space held by incoming segment and return. */ - m_free(m); + m_free(s, m); return; } @@ -1490,12 +1492,9 @@ /* int *ts_present; * u_int32_t *ts_val, *ts_ecr; */ -void -tcp_dooptions(tp, cp, cnt, ti) - struct tcpcb *tp; - u_char *cp; - int cnt; - struct tcpiphdr *ti; +static void +tcp_dooptions(slirp_state_t *s, struct tcpcb *tp, u_char *cp, int cnt, + struct tcpiphdr *ti) { u_int16_t mss; int opt, optlen; @@ -1526,7 +1525,7 @@ continue; memcpy((char *) &mss, (char *) cp + 2, sizeof(mss)); NTOHS(mss); - (void) tcp_mss(tp, mss); /* sets t_maxseg */ + (void) tcp_mss(s, tp, mss); /* sets t_maxseg */ break; /* case TCPOPT_WINDOW: @@ -1605,10 +1604,8 @@ * and update averages and current timeout. */ -void -tcp_xmit_timer(tp, rtt) - register struct tcpcb *tp; - int rtt; +static void +tcp_xmit_timer(slirp_state_t *s, register struct tcpcb *tp, int rtt) { register short delta; @@ -1616,7 +1613,7 @@ DEBUG_ARG("tp = %lx", (long)tp); DEBUG_ARG("rtt = %d", rtt); - tcpstat.tcps_rttupdated++; + s->tcpstat.tcps_rttupdated++; if (tp->t_srtt != 0) { /* * srtt is stored as fixed point with 3 bits after the @@ -1696,9 +1693,7 @@ */ int -tcp_mss(tp, offer) - register struct tcpcb *tp; - u_int offer; +tcp_mss(slirp_state_t *s, register struct tcpcb *tp, u_int offer) { struct socket *so = tp->t_socket; int mss; @@ -1707,7 +1702,7 @@ DEBUG_ARG("tp = %lx", (long)tp); DEBUG_ARG("offer = %d", offer); - mss = min(if_mtu, if_mru) - sizeof(struct tcpiphdr); + mss = min(s->if_mtu, s->if_mru) - sizeof(struct tcpiphdr); if (offer) mss = min(mss, offer); mss = max(mss, 32); @@ -1716,8 +1711,12 @@ tp->snd_cwnd = mss; - sbreserve(&so->so_snd, tcp_sndspace+((tcp_sndspace%mss)?(mss-(tcp_sndspace%mss)):0)); - sbreserve(&so->so_rcv, tcp_rcvspace+((tcp_rcvspace%mss)?(mss-(tcp_rcvspace%mss)):0)); + sbreserve(&so->so_snd, TCP_SNDSPACE + ((TCP_SNDSPACE % mss) ? + (mss - (TCP_SNDSPACE % mss)) : + 0)); + sbreserve(&so->so_rcv, TCP_RCVSPACE + ((TCP_RCVSPACE % mss) ? + (mss - (TCP_RCVSPACE % mss)) : + 0)); DEBUG_MISC((dfd, " returning mss = %d\n", mss)); Index: qemu/slirp/tcp_output.c =================================================================== --- qemu.orig/slirp/tcp_output.c 2007-10-20 07:33:38.000000000 +0000 +++ qemu/slirp/tcp_output.c 2007-10-20 13:49:13.000000000 +0000 @@ -48,14 +48,14 @@ * Since this is only used in "stats socket", we give meaning * names instead of the REAL names */ -char *tcpstates[] = { +const char * const tcpstates[] = { /* "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", */ "REDIRECT", "LISTEN", "SYN_SENT", "SYN_RCVD", "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING", "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT", }; -u_char tcp_outflags[TCP_NSTATES] = { +static const u_char tcp_outflags[TCP_NSTATES] = { TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK, TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK, TH_ACK, TH_ACK, @@ -68,8 +68,7 @@ * Tcp output routine: figure out what should be sent and send it. */ int -tcp_output(tp) - register struct tcpcb *tp; +tcp_output(slirp_state_t *s, register struct tcpcb *tp) { register struct socket *so = tp->t_socket; register long len, win; @@ -263,7 +262,7 @@ /* * No reason to send a segment, just return. */ - tcpstat.tcps_didnuttin++; + s->tcpstat.tcps_didnuttin++; return (0); @@ -285,7 +284,7 @@ opt[0] = TCPOPT_MAXSEG; opt[1] = 4; - mss = htons((u_int16_t) tcp_mss(tp, 0)); + mss = htons((u_int16_t) tcp_mss(s, tp, 0)); memcpy((caddr_t)(opt + 2), (caddr_t)&mss, sizeof(mss)); optlen = 4; @@ -339,22 +338,22 @@ */ if (len) { if (tp->t_force && len == 1) - tcpstat.tcps_sndprobe++; + s->tcpstat.tcps_sndprobe++; else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) { - tcpstat.tcps_sndrexmitpack++; - tcpstat.tcps_sndrexmitbyte += len; + s->tcpstat.tcps_sndrexmitpack++; + s->tcpstat.tcps_sndrexmitbyte += len; } else { - tcpstat.tcps_sndpack++; - tcpstat.tcps_sndbyte += len; + s->tcpstat.tcps_sndpack++; + s->tcpstat.tcps_sndbyte += len; } - m = m_get(); + m = m_get(s); if (m == NULL) { /* error = ENOBUFS; */ error = 1; goto out; } - m->m_data += if_maxlinkhdr; + m->m_data += s->if_maxlinkhdr; m->m_len = hdrlen; /* @@ -382,21 +381,21 @@ flags |= TH_PUSH; } else { if (tp->t_flags & TF_ACKNOW) - tcpstat.tcps_sndacks++; + s->tcpstat.tcps_sndacks++; else if (flags & (TH_SYN|TH_FIN|TH_RST)) - tcpstat.tcps_sndctrl++; + s->tcpstat.tcps_sndctrl++; else if (SEQ_GT(tp->snd_up, tp->snd_una)) - tcpstat.tcps_sndurg++; + s->tcpstat.tcps_sndurg++; else - tcpstat.tcps_sndwinup++; + s->tcpstat.tcps_sndwinup++; - m = m_get(); + m = m_get(s); if (m == NULL) { /* error = ENOBUFS; */ error = 1; goto out; } - m->m_data += if_maxlinkhdr; + m->m_data += s->if_maxlinkhdr; m->m_len = hdrlen; } @@ -500,7 +499,7 @@ if (tp->t_rtt == 0) { tp->t_rtt = 1; tp->t_rtseq = startseq; - tcpstat.tcps_segstimed++; + s->tcpstat.tcps_segstimed++; } } @@ -536,7 +535,7 @@ ((struct ip *)ti)->ip_len = m->m_len; - ((struct ip *)ti)->ip_ttl = ip_defttl; + ((struct ip *)ti)->ip_ttl = IPDEFTTL; ((struct ip *)ti)->ip_tos = so->so_iptos; /* #if BSD >= 43 */ @@ -544,7 +543,7 @@ /* error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route, * so->so_options & SO_DONTROUTE, 0); */ - error = ip_output(so, m); + error = ip_output(s, so, m); /* #else * error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route, @@ -567,7 +566,7 @@ */ return (error); } - tcpstat.tcps_sndtotal++; + s->tcpstat.tcps_sndtotal++; /* * Data sent (as far as we can tell). Index: qemu/slirp/tcp_subr.c =================================================================== --- qemu.orig/slirp/tcp_subr.c 2007-10-20 07:33:38.000000000 +0000 +++ qemu/slirp/tcp_subr.c 2007-10-20 16:46:29.000000000 +0000 @@ -45,29 +45,16 @@ #define WANT_SYS_IOCTL_H #include <slirp.h> -/* patchable/settable parameters for tcp */ -int tcp_mssdflt = TCP_MSS; -int tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ; -int tcp_do_rfc1323 = 0; /* Don't do rfc1323 performance enhancements */ -int tcp_rcvspace; /* You may want to change this */ -int tcp_sndspace; /* Keep small if you have an error prone link */ /* * Tcp initialization */ void -tcp_init() +tcp_init(slirp_state_t *s) { - tcp_iss = 1; /* wrong */ - tcb.so_next = tcb.so_prev = &tcb; - - /* tcp_rcvspace = our Window we advertise to the remote */ - tcp_rcvspace = TCP_RCVSPACE; - tcp_sndspace = TCP_SNDSPACE; - - /* Make sure tcp_sndspace is at least 2*MSS */ - if (tcp_sndspace < 2*(min(if_mtu, if_mru) - sizeof(struct tcpiphdr))) - tcp_sndspace = 2*(min(if_mtu, if_mru) - sizeof(struct tcpiphdr)); + s->tcp_iss = 1; /* wrong */ + s->tcb.so_next = s->tcb.so_prev = &s->tcb; + s->tcp_last_so = &s->tcb; } /* @@ -117,12 +104,8 @@ * segment are as specified by the parameters. */ void -tcp_respond(tp, ti, m, ack, seq, flags) - struct tcpcb *tp; - register struct tcpiphdr *ti; - register struct mbuf *m; - tcp_seq ack, seq; - int flags; +tcp_respond(slirp_state_t *s, struct tcpcb *tp, struct tcpiphdr *ti, + struct mbuf *m, tcp_seq ack, tcp_seq seq, int flags) { register int tlen; int win = 0; @@ -138,14 +121,14 @@ if (tp) win = sbspace(&tp->t_socket->so_rcv); if (m == 0) { - if ((m = m_get()) == NULL) + if ((m = m_get(s)) == NULL) return; #ifdef TCP_COMPAT_42 tlen = 1; #else tlen = 0; #endif - m->m_data += if_maxlinkhdr; + m->m_data += s->if_maxlinkhdr; *mtod(m, struct tcpiphdr *) = *ti; ti = mtod(m, struct tcpiphdr *); flags = TH_ACK; @@ -186,9 +169,9 @@ if(flags & TH_RST) ((struct ip *)ti)->ip_ttl = MAXTTL; else - ((struct ip *)ti)->ip_ttl = ip_defttl; + ((struct ip *)ti)->ip_ttl = IPDEFTTL; - (void) ip_output((struct socket *)0, m); + (void) ip_output(s, (struct socket *)0, m); } /* @@ -197,8 +180,7 @@ * protocol control block. */ struct tcpcb * -tcp_newtcpcb(so) - struct socket *so; +tcp_newtcpcb(slirp_state_t *s, struct socket *so) { register struct tcpcb *tp; @@ -207,10 +189,10 @@ return ((struct tcpcb *)0); memset((char *) tp, 0, sizeof(struct tcpcb)); - tp->seg_next = tp->seg_prev = (tcpiphdrp_32)tp; - tp->t_maxseg = tcp_mssdflt; + tp->seg_next = tp->seg_prev = tp; + tp->t_maxseg = TCP_MSS; - tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0; + tp->t_flags = TCP_DO_RFC1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0; tp->t_socket = so; /* @@ -219,7 +201,7 @@ * reasonable initial retransmit time. */ tp->t_srtt = TCPTV_SRTTBASE; - tp->t_rttvar = tcp_rttdflt * PR_SLOWHZ << 2; + tp->t_rttvar = TCPTV_SRTTDFLT << 2; tp->t_rttmin = TCPTV_MIN; TCPT_RANGESET(tp->t_rxtcur, @@ -240,7 +222,7 @@ * the specified error. If connection is synchronized, * then send a RST to peer. */ -struct tcpcb *tcp_drop(struct tcpcb *tp, int err) +struct tcpcb *tcp_drop(slirp_state_t *s, struct tcpcb *tp, int err) { /* tcp_drop(tp, errno) register struct tcpcb *tp; @@ -254,15 +236,15 @@ if (TCPS_HAVERCVDSYN(tp->t_state)) { tp->t_state = TCPS_CLOSED; - (void) tcp_output(tp); - tcpstat.tcps_drops++; + (void) tcp_output(s, tp); + s->tcpstat.tcps_drops++; } else - tcpstat.tcps_conndrops++; + s->tcpstat.tcps_conndrops++; /* if (errno == ETIMEDOUT && tp->t_softerror) * errno = tp->t_softerror; */ /* so->so_error = errno; */ - return (tcp_close(tp)); + return (tcp_close(s, tp)); } /* @@ -272,8 +254,7 @@ * wake up any sleepers */ struct tcpcb * -tcp_close(tp) - register struct tcpcb *tp; +tcp_close(slirp_state_t *s, register struct tcpcb *tp) { register struct tcpiphdr *t; struct socket *so = tp->t_socket; @@ -286,9 +267,9 @@ t = (struct tcpiphdr *) tp->seg_next; while (t != (struct tcpiphdr *)tp) { t = (struct tcpiphdr *)t->ti_next; - m = (struct mbuf *) REASS_MBUF((struct tcpiphdr *)t->ti_prev); - remque_32((struct tcpiphdr *) t->ti_prev); - m_freem(m); + m = REASS_MBUF_GET((struct tcpiphdr *)t->ti_prev); + remque_32(s, (struct tcpiphdr *) t->ti_prev); + m_freem(s, m); } /* It's static */ /* if (tp->t_template) @@ -299,16 +280,17 @@ so->so_tcpcb = 0; soisfdisconnected(so); /* clobber input socket cache if we're closing the cached connection */ - if (so == tcp_last_so) - tcp_last_so = &tcb; + if (so == s->tcp_last_so) + s->tcp_last_so = &s->tcb; closesocket(so->s); sbfree(&so->so_rcv); sbfree(&so->so_snd); - sofree(so); - tcpstat.tcps_closed++; + sofree(s, so); + s->tcpstat.tcps_closed++; return ((struct tcpcb *)0); } +#ifdef notdef void tcp_drain() { @@ -319,9 +301,6 @@ * When a source quench is received, close congestion window * to one segment. We will gradually open it again as we proceed. */ - -#ifdef notdef - void tcp_quench(i, errno) @@ -350,8 +329,7 @@ * We can let the user exit from the close as soon as the FIN is acked. */ void -tcp_sockclosed(tp) - struct tcpcb *tp; +tcp_sockclosed(slirp_state_t *s, struct tcpcb *tp) { DEBUG_CALL("tcp_sockclosed"); @@ -363,7 +341,7 @@ case TCPS_LISTEN: case TCPS_SYN_SENT: tp->t_state = TCPS_CLOSED; - tp = tcp_close(tp); + tp = tcp_close(s, tp); break; case TCPS_SYN_RECEIVED: @@ -379,7 +357,7 @@ if (tp && tp->t_state >= TCPS_FIN_WAIT_2) soisfdisconnected(tp->t_socket); if (tp) - tcp_output(tp); + tcp_output(s, tp); } /* @@ -392,8 +370,7 @@ * nonblocking. Connect returns after the SYN is sent, and does * not wait for ACK+SYN. */ -int tcp_fconnect(so) - struct socket *so; +int tcp_fconnect(slirp_state_t *s, struct socket *so) { int ret=0; @@ -401,25 +378,25 @@ DEBUG_ARG("so = %lx", (long )so); if( (ret=so->s=socket(AF_INET,SOCK_STREAM,0)) >= 0) { - int opt, s=so->s; + int opt, fd = so->s; struct sockaddr_in addr; - fd_nonblock(s); + fd_nonblock(fd); opt = 1; - setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(opt )); + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)); opt = 1; - setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(opt )); + setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, (char *)&opt, sizeof(opt)); addr.sin_family = AF_INET; - if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) { + if ((so->so_faddr.s_addr & htonl(0xffffff00)) == s->special_addr.s_addr) { /* It's an alias */ switch(ntohl(so->so_faddr.s_addr) & 0xff) { case CTL_DNS: - addr.sin_addr = dns_addr; + addr.sin_addr = s->dns_addr; break; case CTL_ALIAS: default: - addr.sin_addr = loopback_addr; + addr.sin_addr = s->loopback_addr; break; } } else @@ -430,7 +407,7 @@ "addr.sin_addr.s_addr=%.16s\n", ntohs(addr.sin_port), inet_ntoa(addr.sin_addr))); /* We don't care what port we get */ - ret = connect(s,(struct sockaddr *)&addr,sizeof (addr)); + ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); /* * If it's not in progress, it failed, so we just return 0, @@ -455,14 +432,13 @@ * here and SYN the local-host. */ void -tcp_connect(inso) - struct socket *inso; +tcp_connect(slirp_state_t *s, struct socket *inso) { struct socket *so; struct sockaddr_in addr; int addrlen = sizeof(struct sockaddr_in); struct tcpcb *tp; - int s, opt; + int fd, opt; DEBUG_CALL("tcp_connect"); DEBUG_ARG("inso = %lx", (long)inso); @@ -480,7 +456,7 @@ closesocket(accept(inso->s,(struct sockaddr *)&addr,&addrlen)); return; } - if (tcp_attach(so) < 0) { + if (tcp_attach(s, so) < 0) { free(so); /* NOT sofree */ return; } @@ -488,25 +464,25 @@ so->so_lport = inso->so_lport; } - (void) tcp_mss(sototcpcb(so), 0); + (void) tcp_mss(s, sototcpcb(so), 0); - if ((s = accept(inso->s,(struct sockaddr *)&addr,&addrlen)) < 0) { - tcp_close(sototcpcb(so)); /* This will sofree() as well */ + if ((fd = accept(inso->s, (struct sockaddr *)&addr, &addrlen)) < 0) { + tcp_close(s, sototcpcb(so)); /* This will sofree() as well */ return; } - fd_nonblock(s); + fd_nonblock(fd); opt = 1; - setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)); + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int)); opt = 1; - setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); + setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, (char *)&opt, sizeof(int)); opt = 1; - setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char *)&opt,sizeof(int)); + setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&opt, sizeof(int)); so->so_fport = addr.sin_port; so->so_faddr = addr.sin_addr; /* Translate connections from localhost to the real hostname */ - if (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == loopback_addr.s_addr) - so->so_faddr = alias_addr; + if (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == s->loopback_addr.s_addr) + so->so_faddr = s->alias_addr; /* Close the accept() socket, set right state */ if (inso->so_state & SS_FACCEPTONCE) { @@ -514,7 +490,7 @@ so->so_state = SS_NOFDREF; /* Don't select it yet, even though we have an FD */ /* if it's not FACCEPTONCE, it's already NOFDREF */ } - so->s = s; + so->s = fd; so->so_iptos = tcp_tos(so); tp = sototcpcb(so); @@ -528,27 +504,26 @@ */ /* soisconnecting(so); */ /* NOFDREF used instead */ - tcpstat.tcps_connattempt++; + s->tcpstat.tcps_connattempt++; tp->t_state = TCPS_SYN_SENT; tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; - tp->iss = tcp_iss; - tcp_iss += TCP_ISSINCR/2; + tp->iss = s->tcp_iss; + s->tcp_iss += TCP_ISSINCR / 2; tcp_sendseqinit(tp); - tcp_output(tp); + tcp_output(s, tp); } /* * Attach a TCPCB to a socket. */ int -tcp_attach(so) - struct socket *so; +tcp_attach(slirp_state_t *s, struct socket *so) { - if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) + if ((so->so_tcpcb = tcp_newtcpcb(s, so)) == NULL) return -1; - insque(so, &tcb); + insque(s, so, &s->tcb); return 0; } @@ -556,7 +531,7 @@ /* * Set the socket's type of service field */ -struct tos_t tcptos[] = { +static const struct tos_t tcptos[] = { {0, 20, IPTOS_THROUGHPUT, 0}, /* ftp data */ {21, 21, IPTOS_LOWDELAY, EMU_FTP}, /* ftp control */ {0, 23, IPTOS_LOWDELAY, 0}, /* telnet */ @@ -572,8 +547,6 @@ {0, 0, 0, 0} }; -struct emu_t *tcpemu = 0; - /* * Return TOS according to the above table */ @@ -582,7 +555,6 @@ struct socket *so; { int i = 0; - struct emu_t *emup; while(tcptos[i].tos) { if ((tcptos[i].fport && (ntohs(so->so_fport) == tcptos[i].fport)) || @@ -593,20 +565,9 @@ i++; } - /* Nope, lets see if there's a user-added one */ - for (emup = tcpemu; emup; emup = emup->next) { - if ((emup->fport && (ntohs(so->so_fport) == emup->fport)) || - (emup->lport && (ntohs(so->so_lport) == emup->lport))) { - so->so_emu = emup->emu; - return emup->tos; - } - } - return 0; } -int do_echo = -1; - /* * Emulate programs that try and connect to us * This includes ftp (the data connection is @@ -632,9 +593,7 @@ * NOTE: if you return 0 you MUST m_free() the mbuf! */ int -tcp_emu(so, m) - struct socket *so; - struct mbuf *m; +tcp_emu(slirp_state_t *s, struct socket *so, struct mbuf *m) { u_int n1, n2, n3, n4, n5, n6; char buff[256]; @@ -665,11 +624,11 @@ so_rcv->sb_rptr += m->m_len; m->m_data[m->m_len] = 0; /* NULL terminate */ if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n')) { - if (sscanf(so_rcv->sb_data, "%d%*[ ,]%d", &n1, &n2) == 2) { + if (sscanf(so_rcv->sb_data, "%u%*[ ,]%u", &n1, &n2) == 2) { HTONS(n1); HTONS(n2); /* n2 is the one on our host */ - for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) { + for (tmpso = s->tcb.so_next; tmpso != &s->tcb; tmpso = tmpso->so_next) { if (tmpso->so_laddr.s_addr == so->so_laddr.s_addr && tmpso->so_lport == n2 && tmpso->so_faddr.s_addr == so->so_faddr.s_addr && @@ -685,7 +644,7 @@ so_rcv->sb_rptr = so_rcv->sb_data; so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc; } - m_free(m); + m_free(s, m); return 0; } @@ -841,8 +800,8 @@ ns->so_fport=htons(IPPORT_RESERVED-1); /* Use a fake port. */ if (ns->so_faddr.s_addr == 0 || - ns->so_faddr.s_addr == loopback_addr.s_addr) - ns->so_faddr = alias_addr; + ns->so_faddr.s_addr == s->loopback_addr.s_addr) + ns->so_faddr = s->alias_addr; ns->so_iptos = tcp_tos(ns); tp = sototcpcb(ns); @@ -857,12 +816,12 @@ /*soisfconnecting(ns);*/ - tcpstat.tcps_connattempt++; + s->tcpstat.tcps_connattempt++; tp->t_state = TCPS_SYN_SENT; tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; - tp->iss = tcp_iss; - tcp_iss += TCP_ISSINCR/2; + tp->iss = s->tcp_iss; + s->tcp_iss += TCP_ISSINCR / 2; tcp_sendseqinit(tp); tcp_output(tp); so->extra=ns; @@ -931,11 +890,13 @@ * because in linemode, the line is already echoed * XXX two or more control connections won't work */ - if (do_echo == -1) { - if (m->m_len == 1) do_echo = 1; - else do_echo = 0; + if (s->do_echo == -1) { + if (m->m_len == 1) + s->do_echo = 1; + else + s->do_echo = 0; } - if (do_echo) { + if (s->do_echo) { sbappendsb(so_snd, m); m_free(m); tcp_output(sototcpcb(so)); /* XXX */ @@ -991,7 +952,7 @@ /* * Need to emulate the PORT command */ - x = sscanf(bptr, "ORT %d,%d,%d,%d,%d,%d\r\n%256[^\177]", + x = sscanf(bptr, "ORT %u,%u,%u,%u,%u,%u\r\n%256[^\177]", &n1, &n2, &n3, &n4, &n5, &n6, buff); if (x < 6) return 1; @@ -999,7 +960,7 @@ laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4)); lport = htons((n5 << 8) | (n6)); - if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL) + if ((so = solisten(s, 0, laddr, lport, SS_FACCEPTONCE)) == NULL) return 1; n6 = ntohs(so->so_fport); @@ -1022,7 +983,7 @@ /* * Need to emulate the PASV response */ - x = sscanf(bptr, "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%256[^\177]", + x = sscanf(bptr, "27 Entering Passive Mode (%u,%u,%u,%u,%u,%u)\r\n%256[^\177]", &n1, &n2, &n3, &n4, &n5, &n6, buff); if (x < 6) return 1; @@ -1030,7 +991,7 @@ laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4)); lport = htons((n5 << 8) | (n6)); - if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL) + if ((so = solisten(s, 0, laddr, lport, SS_FACCEPTONCE)) == NULL) return 1; n6 = ntohs(so->so_fport); @@ -1069,7 +1030,7 @@ lport += m->m_data[i] - '0'; } if (m->m_data[m->m_len-1] == '\0' && lport != 0 && - (so = solisten(0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL) + (so = solisten(s, 0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL) m->m_len = sprintf(m->m_data, "%d", ntohs(so->so_fport))+1; return 1; @@ -1083,7 +1044,7 @@ /* The %256s is for the broken mIRC */ if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3) { - if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL) + if ((so = solisten(s, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL) return 1; m->m_len = bptr - m->m_data; /* Adjust length */ @@ -1091,7 +1052,7 @@ (unsigned long)ntohl(so->so_faddr.s_addr), ntohs(so->so_fport), 1); } else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) { - if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL) + if ((so = solisten(s, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL) return 1; m->m_len = bptr - m->m_data; /* Adjust length */ @@ -1099,7 +1060,7 @@ buff, (unsigned long)ntohl(so->so_faddr.s_addr), ntohs(so->so_fport), n1, 1); } else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) { - if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL) + if ((so = solisten(s, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL) return 1; m->m_len = bptr - m->m_data; /* Adjust length */ @@ -1109,6 +1070,11 @@ } return 1; +#if 1 +//def VBOX + /** @todo Disabled EMU_REALAUDIO, because it uses a static variable. + * This is not legal when more than one slirp instance is active. */ +#else /* !VBOX */ case EMU_REALAUDIO: /* * RealAudio emulation - JP. We must try to parse the incoming @@ -1234,6 +1200,7 @@ ra++; } return 1; +#endif /* !VBOX */ default: /* Ooops, not emulated, won't call tcp_emu again */ @@ -1248,8 +1215,7 @@ * return 2 if this is a command-line connection */ int -tcp_ctl(so) - struct socket *so; +tcp_ctl(slirp_state_t *s, struct socket *so) { struct sbuf *sb = &so->so_snd; int command; @@ -1278,7 +1244,7 @@ /* * Check if it's pty_exec */ - for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { + for (ex_ptr = s->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { if (ex_ptr->ex_fport == so->so_fport && command == ex_ptr->ex_addr) { do_pty = ex_ptr->ex_pty; @@ -1300,11 +1266,11 @@ do_exec: DEBUG_MISC((dfd, " executing %s \n",ex_ptr->ex_exec)); - return(fork_exec(so, ex_ptr->ex_exec, do_pty)); + return(fork_exec(s, so, ex_ptr->ex_exec, do_pty)); #if 0 case CTL_CMD: - for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) { + for (tmpso = s->tcb.so_next; tmpso != &s->tcb; tmpso = tmpso->so_next) { if (tmpso->so_emu == EMU_CTL && !(tmpso->so_tcpcb? (tmpso->so_tcpcb->t_state & (TCPS_TIME_WAIT|TCPS_LAST_ACK)) @@ -1319,7 +1285,7 @@ ctl_password_ok = 0; sb->sb_cc = sprintf(sb->sb_wptr, "Slirp command-line ready (type \"help\" for help).\r\nSlirp> "); sb->sb_wptr += sb->sb_cc; - do_echo=-1; + s->do_echo = -1; return(2); #endif } Index: qemu/slirp/tcp_timer.c =================================================================== --- qemu.orig/slirp/tcp_timer.c 2007-10-20 07:33:38.000000000 +0000 +++ qemu/slirp/tcp_timer.c 2007-10-20 13:50:20.000000000 +0000 @@ -36,34 +36,29 @@ #include <slirp.h> -int tcp_keepidle = TCPTV_KEEP_IDLE; -int tcp_keepintvl = TCPTV_KEEPINTVL; -int tcp_maxidle; -int so_options = DO_KEEPALIVE; - -struct tcpstat tcpstat; /* tcp statistics */ -u_int32_t tcp_now; /* for RFC 1323 timestamps */ +static struct tcpcb *tcp_timers(slirp_state_t *s, register struct tcpcb *tp, + int timer); /* * Fast timeout routine for processing delayed acks */ void -tcp_fasttimo() +tcp_fasttimo(slirp_state_t *s) { register struct socket *so; register struct tcpcb *tp; DEBUG_CALL("tcp_fasttimo"); - so = tcb.so_next; + so = s->tcb.so_next; if (so) - for (; so != &tcb; so = so->so_next) + for (; so != &s->tcb; so = so->so_next) if ((tp = (struct tcpcb *)so->so_tcpcb) && (tp->t_flags & TF_DELACK)) { tp->t_flags &= ~TF_DELACK; tp->t_flags |= TF_ACKNOW; - tcpstat.tcps_delack++; - (void) tcp_output(tp); + s->tcpstat.tcps_delack++; + (void) tcp_output(s, tp); } } @@ -73,7 +68,7 @@ * causes finite state machine actions if timers expire. */ void -tcp_slowtimo() +tcp_slowtimo(slirp_state_t *s) { register struct socket *ip, *ipnxt; register struct tcpcb *tp; @@ -81,21 +76,20 @@ DEBUG_CALL("tcp_slowtimo"); - tcp_maxidle = TCPTV_KEEPCNT * tcp_keepintvl; /* * Search through tcb's and update active timers. */ - ip = tcb.so_next; + ip = s->tcb.so_next; if (ip == 0) return; - for (; ip != &tcb; ip = ipnxt) { + for (; ip != &s->tcb; ip = ipnxt) { ipnxt = ip->so_next; tp = sototcpcb(ip); if (tp == 0) continue; for (i = 0; i < TCPT_NTIMERS; i++) { if (tp->t_timer[i] && --tp->t_timer[i] == 0) { - tcp_timers(tp,i); + tcp_timers(s, tp,i); if (ipnxt->so_prev != ip) goto tpgone; } @@ -106,20 +100,19 @@ tpgone: ; } - tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ + s->tcp_iss += TCP_ISSINCR / PR_SLOWHZ; /* increment iss */ #ifdef TCP_COMPAT_42 - if ((int)tcp_iss < 0) - tcp_iss = 0; /* XXX */ + if ((int)s->tcp_iss < 0) + s->tcp_iss = 0; /* XXX */ #endif - tcp_now++; /* for timestamps */ + s->tcp_now++; /* for timestamps */ } /* * Cancel all timers for TCP tp. */ void -tcp_canceltimers(tp) - struct tcpcb *tp; +tcp_canceltimers(struct tcpcb *tp) { register int i; @@ -127,16 +120,14 @@ tp->t_timer[i] = 0; } -int tcp_backoff[TCP_MAXRXTSHIFT + 1] = +const int tcp_backoff[TCP_MAXRXTSHIFT + 1] = { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 }; /* * TCP timer processing. */ -struct tcpcb * -tcp_timers(tp, timer) - register struct tcpcb *tp; - int timer; +static struct tcpcb * +tcp_timers(slirp_state_t *s, register struct tcpcb *tp, int timer) { register int rexmt; @@ -152,10 +143,10 @@ */ case TCPT_2MSL: if (tp->t_state != TCPS_TIME_WAIT && - tp->t_idle <= tcp_maxidle) - tp->t_timer[TCPT_2MSL] = tcp_keepintvl; + tp->t_idle <= TCP_MAXIDLE) + tp->t_timer[TCPT_2MSL] = TCPTV_KEEPINTVL; else - tp = tcp_close(tp); + tp = tcp_close(s, tp); break; /* @@ -192,8 +183,8 @@ * We tried our best, now the connection must die! */ tp->t_rxtshift = TCP_MAXRXTSHIFT; - tcpstat.tcps_timeoutdrop++; - tp = tcp_drop(tp, tp->t_softerror); + s->tcpstat.tcps_timeoutdrop++; + tp = tcp_drop(s, tp, tp->t_softerror); /* tp->t_softerror : ETIMEDOUT); */ /* XXX */ return (tp); /* XXX */ } @@ -204,7 +195,7 @@ */ tp->t_rxtshift = 6; } - tcpstat.tcps_rexmttimeo++; + s->tcpstat.tcps_rexmttimeo++; rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift]; TCPT_RANGESET(tp->t_rxtcur, rexmt, (short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */ @@ -259,7 +250,7 @@ tp->snd_ssthresh = win * tp->t_maxseg; tp->t_dupacks = 0; } - (void) tcp_output(tp); + (void) tcp_output(s, tp); break; /* @@ -267,10 +258,10 @@ * Force a byte to be output, if possible. */ case TCPT_PERSIST: - tcpstat.tcps_persisttimeo++; + s->tcpstat.tcps_persisttimeo++; tcp_setpersist(tp); tp->t_force = 1; - (void) tcp_output(tp); + (void) tcp_output(s, tp); tp->t_force = 0; break; @@ -279,13 +270,13 @@ * or drop connection if idle for too long. */ case TCPT_KEEP: - tcpstat.tcps_keeptimeo++; + s->tcpstat.tcps_keeptimeo++; if (tp->t_state < TCPS_ESTABLISHED) goto dropit; /* if (tp->t_socket->so_options & SO_KEEPALIVE && */ - if ((so_options) && tp->t_state <= TCPS_CLOSE_WAIT) { - if (tp->t_idle >= tcp_keepidle + tcp_maxidle) + if ((SO_OPTIONS) && tp->t_state <= TCPS_CLOSE_WAIT) { + if (tp->t_idle >= TCPTV_KEEP_IDLE + TCP_MAXIDLE) goto dropit; /* * Send a packet designed to force a response @@ -299,7 +290,7 @@ * by the protocol spec, this requires the * correspondent TCP to respond. */ - tcpstat.tcps_keepprobe++; + s->tcpstat.tcps_keepprobe++; #ifdef TCP_COMPAT_42 /* * The keepalive packet must have nonzero length @@ -308,17 +299,17 @@ tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL, tp->rcv_nxt - 1, tp->snd_una - 1, 0); #else - tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL, + tcp_respond(s, tp, &tp->t_template, (struct mbuf *)NULL, tp->rcv_nxt, tp->snd_una - 1, 0); #endif - tp->t_timer[TCPT_KEEP] = tcp_keepintvl; + tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL; } else - tp->t_timer[TCPT_KEEP] = tcp_keepidle; + tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE; break; dropit: - tcpstat.tcps_keepdrops++; - tp = tcp_drop(tp, 0); /* ETIMEDOUT); */ + s->tcpstat.tcps_keepdrops++; + tp = tcp_drop(s, tp, 0); /* ETIMEDOUT); */ break; } Index: qemu/slirp/tcp_timer.h =================================================================== --- qemu.orig/slirp/tcp_timer.h 2007-10-20 07:33:38.000000000 +0000 +++ qemu/slirp/tcp_timer.h 2007-10-20 14:56:41.000000000 +0000 @@ -108,6 +108,9 @@ #define TCP_LINGERTIME 120 /* linger at most 2 minutes */ #define TCP_MAXRXTSHIFT 12 /* maximum retransmits */ +/** Maximum idle time before timing out a connection. */ +#define TCP_MAXIDLE (TCPTV_KEEPCNT * TCPTV_KEEPINTVL) + #ifdef TCPTIMERS @@ -126,17 +129,12 @@ (tv) = (tvmax); \ } -extern int tcp_keepidle; /* time before keepalive probes begin */ -extern int tcp_keepintvl; /* time between keepalive probes */ -extern int tcp_maxidle; /* time to drop after starting probes */ -extern int tcp_ttl; /* time to live for TCP segs */ -extern int tcp_backoff[]; +extern const int tcp_backoff[]; struct tcpcb; -void tcp_fasttimo _P((void)); -void tcp_slowtimo _P((void)); +void tcp_fasttimo(slirp_state_t *s); +void tcp_slowtimo(slirp_state_t *s); void tcp_canceltimers _P((struct tcpcb *)); -struct tcpcb * tcp_timers _P((register struct tcpcb *, int)); #endif Index: qemu/slirp/tcp_var.h =================================================================== --- qemu.orig/slirp/tcp_var.h 2007-10-20 07:33:38.000000000 +0000 +++ qemu/slirp/tcp_var.h 2007-10-20 17:10:54.000000000 +0000 @@ -45,7 +45,6 @@ #else typedef u_int32_t tcpiphdrp_32; #endif - /* * Tcp control block, one per tcp; fields: */ @@ -183,7 +182,10 @@ #else typedef u_int32_t mbufp_32; #endif -#define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t)) +/* VBox change which is too much bother to #ifdef */ +# define REASS_MBUF_SET(ti, p) (*(mbufp_32 *)&((ti)->ti_t)) = (p) +# define REASS_MBUF_GET(ti) ((struct mbuf *)(*(mbufp_32 *)&((ti)->ti_t))) +/*#define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t)) - replaced by REASS_MBUF_GET/SET */ /* * TCP statistics. @@ -246,7 +248,5 @@ u_long tcps_didnuttin; /* Times tcp_output didn't do anything XXX */ }; -extern struct tcpstat tcpstat; /* tcp statistics */ -extern u_int32_t tcp_now; /* for RFC 1323 timestamps */ #endif Index: qemu/slirp/tftp.c =================================================================== --- qemu.orig/slirp/tftp.c 2007-10-20 07:33:38.000000000 +0000 +++ qemu/slirp/tftp.c 2007-10-20 09:55:19.000000000 +0000 @@ -24,23 +24,10 @@ #include <slirp.h> -struct tftp_session { - int in_use; - unsigned char filename[TFTP_FILENAME_MAX]; - struct in_addr client_ip; - u_int16_t client_port; - - int timestamp; -}; - -struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX]; - -const char *tftp_prefix; - -static void tftp_session_update(struct tftp_session *spt) +static void tftp_session_update(slirp_state_t *s, struct tftp_session *spt) { - spt->timestamp = curtime; + spt->timestamp = s->curtime; spt->in_use = 1; } @@ -49,19 +36,19 @@ spt->in_use = 0; } -static int tftp_session_allocate(struct tftp_t *tp) +static int tftp_session_allocate(slirp_state_t *s, struct tftp_t *tp) { struct tftp_session *spt; int k; for (k = 0; k < TFTP_SESSIONS_MAX; k++) { - spt = &tftp_sessions[k]; + spt = &s->tftp_sessions[k]; if (!spt->in_use) goto found; /* sessions time out after 5 inactive seconds */ - if ((int)(curtime - spt->timestamp) > 5000) + if ((int)(s->curtime - spt->timestamp) > 5000) goto found; } @@ -72,18 +59,18 @@ memcpy(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip)); spt->client_port = tp->udp.uh_sport; - tftp_session_update(spt); + tftp_session_update(s, spt); return k; } -static int tftp_session_find(struct tftp_t *tp) +static int tftp_session_find(slirp_state_t *s, struct tftp_t *tp) { struct tftp_session *spt; int k; for (k = 0; k < TFTP_SESSIONS_MAX; k++) { - spt = &tftp_sessions[k]; + spt = &s->tftp_sessions[k]; if (spt->in_use) { if (!memcmp(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip))) { @@ -97,7 +84,7 @@ return -1; } -static int tftp_read_data(struct tftp_session *spt, u_int16_t block_nr, +static int tftp_read_data(slirp_state_t *s, struct tftp_session *spt, u_int16_t block_nr, u_int8_t *buf, int len) { int fd; @@ -106,7 +93,7 @@ int n; n = snprintf(buffer, sizeof(buffer), "%s/%s", - tftp_prefix, spt->filename); + s->tftp_prefix, spt->filename); if (n >= sizeof(buffer)) return -1; @@ -127,7 +114,8 @@ return bytes_read; } -static int tftp_send_oack(struct tftp_session *spt, +static int tftp_send_oack(slirp_state_t *s, + struct tftp_session *spt, const char *key, uint32_t value, struct tftp_t *recv_tp) { @@ -136,14 +124,14 @@ struct tftp_t *tp; int n = 0; - m = m_get(); + m = m_get(s); if (!m) return -1; memset(m->m_data, 0, m->m_size); - m->m_data += if_maxlinkhdr; + m->m_data += s->if_maxlinkhdr; tp = (void *)m->m_data; m->m_data += sizeof(struct udpiphdr); @@ -159,14 +147,15 @@ m->m_len = sizeof(struct tftp_t) - 514 + n - sizeof(struct ip) - sizeof(struct udphdr); - udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); + udp_output2(s, NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); return 0; } -static int tftp_send_error(struct tftp_session *spt, +static int tftp_send_error(slirp_state_t *s, + struct tftp_session *spt, u_int16_t errorcode, const char *msg, struct tftp_t *recv_tp) { @@ -175,7 +164,7 @@ struct tftp_t *tp; int nobytes; - m = m_get(); + m = m_get(s); if (!m) { return -1; @@ -183,7 +172,7 @@ memset(m->m_data, 0, m->m_size); - m->m_data += if_maxlinkhdr; + m->m_data += s->if_maxlinkhdr; tp = (void *)m->m_data; m->m_data += sizeof(struct udpiphdr); @@ -202,14 +191,15 @@ m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg) - sizeof(struct ip) - sizeof(struct udphdr); - udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); + udp_output2(s, NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); tftp_session_terminate(spt); return 0; } -static int tftp_send_data(struct tftp_session *spt, +static int tftp_send_data(slirp_state_t *s, + struct tftp_session *spt, u_int16_t block_nr, struct tftp_t *recv_tp) { @@ -222,7 +212,7 @@ return -1; } - m = m_get(); + m = m_get(s); if (!m) { return -1; @@ -230,7 +220,7 @@ memset(m->m_data, 0, m->m_size); - m->m_data += if_maxlinkhdr; + m->m_data += s->if_maxlinkhdr; tp = (void *)m->m_data; m->m_data += sizeof(struct udpiphdr); @@ -243,14 +233,14 @@ daddr.sin_addr = spt->client_ip; daddr.sin_port = spt->client_port; - nobytes = tftp_read_data(spt, block_nr - 1, tp->x.tp_data.tp_buf, 512); + nobytes = tftp_read_data(s, spt, block_nr - 1, tp->x.tp_data.tp_buf, 512); if (nobytes < 0) { - m_free(m); + m_free(s, m); /* send "file not found" error back */ - tftp_send_error(spt, 1, "File not found", tp); + tftp_send_error(s, spt, 1, "File not found", tp); return -1; } @@ -258,10 +248,10 @@ m->m_len = sizeof(struct tftp_t) - (512 - nobytes) - sizeof(struct ip) - sizeof(struct udphdr); - udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); + udp_output2(s, NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); if (nobytes == 512) { - tftp_session_update(spt); + tftp_session_update(s, spt); } else { tftp_session_terminate(spt); @@ -270,19 +260,19 @@ return 0; } -static void tftp_handle_rrq(struct tftp_t *tp, int pktlen) +static void tftp_handle_rrq(slirp_state_t *s, struct tftp_t *tp, int pktlen) { struct tftp_session *spt; - int s, k, n; + int session, k, n; u_int8_t *src, *dst; - s = tftp_session_allocate(tp); + session = tftp_session_allocate(s, tp); - if (s < 0) { + if (session < 0) { return; } - spt = &tftp_sessions[s]; + spt = &s->tftp_sessions[session]; src = tp->x.tp_buf; dst = spt->filename; @@ -315,7 +305,7 @@ } if (memcmp(&src[k], "octet\0", 6) != 0) { - tftp_send_error(spt, 4, "Unsupported transfer mode", tp); + tftp_send_error(s, spt, 4, "Unsupported transfer mode", tp); return; } @@ -326,26 +316,26 @@ if ((spt->filename[0] != '/') || (spt->filename[strlen(spt->filename) - 1] == '/') || strstr(spt->filename, "/../")) { - tftp_send_error(spt, 2, "Access violation", tp); + tftp_send_error(s, spt, 2, "Access violation", tp); return; } /* only allow exported prefixes */ - if (!tftp_prefix) { - tftp_send_error(spt, 2, "Access violation", tp); + if (!s->tftp_prefix) { + tftp_send_error(s, spt, 2, "Access violation", tp); return; } /* check if the file exists */ - if (tftp_read_data(spt, 0, spt->filename, 0) < 0) { - tftp_send_error(spt, 1, "File not found", tp); + if (tftp_read_data(s, spt, 0, spt->filename, 0) < 0) { + tftp_send_error(s, spt, 1, "File not found", tp); return; } if (src[n - 1] != 0) { - tftp_send_error(spt, 2, "Access violation", tp); + tftp_send_error(s, spt, 2, "Access violation", tp); return; } @@ -356,7 +346,7 @@ k += strlen(key) + 1; if (k >= n) { - tftp_send_error(spt, 2, "Access violation", tp); + tftp_send_error(s, spt, 2, "Access violation", tp); return; } @@ -367,56 +357,56 @@ int tsize = atoi(value); struct stat stat_p; - if (tsize == 0 && tftp_prefix) { + if (tsize == 0 && s->tftp_prefix) { char buffer[1024]; int len; len = snprintf(buffer, sizeof(buffer), "%s/%s", - tftp_prefix, spt->filename); + s->tftp_prefix, spt->filename); if (stat(buffer, &stat_p) == 0) tsize = stat_p.st_size; else { - tftp_send_error(spt, 1, "File not found", tp); + tftp_send_error(s, spt, 1, "File not found", tp); return; } } - tftp_send_oack(spt, "tsize", tsize, tp); + tftp_send_oack(s, spt, "tsize", tsize, tp); } } - tftp_send_data(spt, 1, tp); + tftp_send_data(s, spt, 1, tp); } -static void tftp_handle_ack(struct tftp_t *tp, int pktlen) +static void tftp_handle_ack(slirp_state_t *s, struct tftp_t *tp, int pktlen) { - int s; + int session; - s = tftp_session_find(tp); + session = tftp_session_find(s, tp); - if (s < 0) { + if (session < 0) { return; } - if (tftp_send_data(&tftp_sessions[s], + if (tftp_send_data(s, &s->tftp_sessions[session], ntohs(tp->x.tp_data.tp_block_nr) + 1, tp) < 0) { return; } } -void tftp_input(struct mbuf *m) +void tftp_input(slirp_state_t *s, struct mbuf *m) { struct tftp_t *tp = (struct tftp_t *)m->m_data; switch(ntohs(tp->tp_op)) { case TFTP_RRQ: - tftp_handle_rrq(tp, m->m_len); + tftp_handle_rrq(s, tp, m->m_len); break; case TFTP_ACK: - tftp_handle_ack(tp, m->m_len); + tftp_handle_ack(s, tp, m->m_len); break; } } Index: qemu/slirp/tftp.h =================================================================== --- qemu.orig/slirp/tftp.h 2007-10-20 07:33:38.000000000 +0000 +++ qemu/slirp/tftp.h 2007-10-20 08:17:52.000000000 +0000 @@ -30,4 +30,4 @@ } x; }; -void tftp_input(struct mbuf *m); +void tftp_input(slirp_state_t *s, struct mbuf *m); Index: qemu/slirp/udp.c =================================================================== --- qemu.orig/slirp/udp.c 2007-10-20 07:33:38.000000000 +0000 +++ qemu/slirp/udp.c 2007-10-20 17:13:45.000000000 +0000 @@ -45,35 +45,28 @@ #include <slirp.h> #include "ip_icmp.h" -struct udpstat udpstat; - -struct socket udb; +static u_int8_t udp_tos(struct socket *so); +static void udp_emu(slirp_state_t *s, struct socket *so, struct mbuf *m); /* * UDP protocol implementation. * Per RFC 768, August, 1980. */ -#ifndef COMPAT_42 -int udpcksum = 1; -#else -int udpcksum = 0; /* XXX */ -#endif - -struct socket *udp_last_so = &udb; +#define udpcksum 1 void -udp_init() +udp_init(slirp_state_t *s) { - udb.so_next = udb.so_prev = &udb; + s->udp_last_so = &s->udb; + s->udb.so_next = s->udb.so_prev = &s->udb; } + /* m->m_data points at ip packet header * m->m_len length ip packet * ip->ip_len length data (IPDU) */ void -udp_input(m, iphlen) - register struct mbuf *m; - int iphlen; +udp_input(slirp_state_t *s, register struct mbuf *m, int iphlen) { register struct ip *ip; register struct udphdr *uh; @@ -86,7 +79,7 @@ DEBUG_ARG("m = %lx", (long)m); DEBUG_ARG("iphlen = %d", iphlen); - udpstat.udps_ipackets++; + s->udpstat.udps_ipackets++; /* * Strip IP options, if any; should skip this, @@ -113,7 +106,7 @@ if (ip->ip_len != len) { if (len > ip->ip_len) { - udpstat.udps_badlen++; + s->udpstat.udps_badlen++; goto bad; } m_adj(m, len - ip->ip_len); @@ -140,7 +133,7 @@ * if (uh->uh_sum) { */ if(cksum(m, len + sizeof(struct ip))) { - udpstat.udps_badsum++; + s->udpstat.udps_badsum++; goto bad; } } @@ -149,7 +142,7 @@ * handle DHCP/BOOTP */ if (ntohs(uh->uh_dport) == BOOTP_SERVER) { - bootp_input(m); + bootp_input(s, m); goto bad; } @@ -157,19 +150,19 @@ * handle TFTP */ if (ntohs(uh->uh_dport) == TFTP_SERVER) { - tftp_input(m); + tftp_input(s, m); goto bad; } /* * Locate pcb for datagram. */ - so = udp_last_so; + so = s->udp_last_so; if (so->so_lport != uh->uh_sport || so->so_laddr.s_addr != ip->ip_src.s_addr) { struct socket *tmp; - for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) { + for (tmp = s->udb.so_next; tmp != &s->udb; tmp = tmp->so_next) { if (tmp->so_lport == uh->uh_sport && tmp->so_laddr.s_addr == ip->ip_src.s_addr) { tmp->so_faddr.s_addr = ip->ip_dst.s_addr; @@ -178,11 +171,11 @@ break; } } - if (tmp == &udb) { + if (tmp == &s->udb) { so = NULL; } else { - udpstat.udpps_pcbcachemiss++; - udp_last_so = so; + s->udpstat.udpps_pcbcachemiss++; + s->udp_last_so = so; } } @@ -192,10 +185,10 @@ * create one */ if ((so = socreate()) == NULL) goto bad; - if(udp_attach(so) == -1) { + if(udp_attach(s, so) == -1) { DEBUG_MISC((dfd," udp_attach errno = %d-%s\n", errno,strerror(errno))); - sofree(so); + sofree(s, so); goto bad; } @@ -226,17 +219,17 @@ * Now we sendto() the packet. */ if (so->so_emu) - udp_emu(so, m); + udp_emu(s, so, m); - if(sosendto(so,m) == -1) { + if(sosendto(s, so,m) == -1) { m->m_len += iphlen; m->m_data -= iphlen; *ip=save_ip; DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno))); - icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); + icmp_error(s, m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); } - m_free(so->so_m); /* used for ICMP if error on sorecvfrom */ + m_free(s, so->so_m); /* used for ICMP if error on sorecvfrom */ /* restore the orig mbuf packet */ m->m_len += iphlen; @@ -246,12 +239,12 @@ return; bad: - m_freem(m); + m_freem(s, m); /* if (opts) m_freem(opts); */ return; } -int udp_output2(struct socket *so, struct mbuf *m, +int udp_output2(slirp_state_t *s, struct socket *so, struct mbuf *m, struct sockaddr_in *saddr, struct sockaddr_in *daddr, int iptos) { @@ -296,37 +289,35 @@ } ((struct ip *)ui)->ip_len = m->m_len; - ((struct ip *)ui)->ip_ttl = ip_defttl; + ((struct ip *)ui)->ip_ttl = IPDEFTTL; ((struct ip *)ui)->ip_tos = iptos; - udpstat.udps_opackets++; + s->udpstat.udps_opackets++; - error = ip_output(so, m); + error = ip_output(s, so, m); return (error); } -int udp_output(struct socket *so, struct mbuf *m, +int udp_output(slirp_state_t *s, struct socket *so, struct mbuf *m, struct sockaddr_in *addr) - { struct sockaddr_in saddr, daddr; saddr = *addr; - if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) { + if ((so->so_faddr.s_addr & htonl(0xffffff00)) == s->special_addr.s_addr) { saddr.sin_addr.s_addr = so->so_faddr.s_addr; if ((so->so_faddr.s_addr & htonl(0x000000ff)) == htonl(0xff)) - saddr.sin_addr.s_addr = alias_addr.s_addr; + saddr.sin_addr.s_addr = s->alias_addr.s_addr; } daddr.sin_addr = so->so_laddr; daddr.sin_port = so->so_lport; - return udp_output2(so, m, &saddr, &daddr, so->so_iptos); + return udp_output2(s, so, m, &saddr, &daddr, so->so_iptos); } int -udp_attach(so) - struct socket *so; +udp_attach(slirp_state_t *s, struct socket *so) { struct sockaddr_in addr; @@ -349,25 +340,30 @@ errno=lasterrno; #endif } else { + int opt = 1; /* success, insert in queue */ - so->so_expire = curtime + SO_EXPIRE; - insque(so,&udb); + so->so_expire = s->curtime + SO_EXPIRE; + /* enable broadcast for later use */ + setsockopt(so->s, SOL_SOCKET, SO_BROADCAST, (const char *)&opt, sizeof(opt)); + insque(s, so, &s->udb); } } return(so->s); } void -udp_detach(so) - struct socket *so; +udp_detach(slirp_state_t *s, struct socket *so) { + /* Correctly update list if detaching last socket in list. */ + if (so == s->udp_last_so) + s->udp_last_so = &s->udb; closesocket(so->s); /* if (so->so_m) m_free(so->so_m); done by sofree */ - sofree(so); + sofree(s, so); } -struct tos_t udptos[] = { +static const struct tos_t udptos[] = { {0, 53, IPTOS_LOWDELAY, 0}, /* DNS */ {517, 517, IPTOS_LOWDELAY, EMU_TALK}, /* talk */ {518, 518, IPTOS_LOWDELAY, EMU_NTALK}, /* ntalk */ @@ -375,9 +371,8 @@ {0, 0, 0, 0} }; -u_int8_t -udp_tos(so) - struct socket *so; +static u_int8_t +udp_tos(struct socket *so) { int i = 0; @@ -400,10 +395,8 @@ /* * Here, talk/ytalk/ntalk requests must be emulated */ -void -udp_emu(so, m) - struct socket *so; - struct mbuf *m; +static void +udp_emu(slirp_state_t *s, struct socket *so, struct mbuf *m) { struct sockaddr_in addr; int addrlen = sizeof(addr); @@ -470,14 +463,14 @@ nmsg = (CTL_MSG *) buff; type = omsg->type; OTOSIN(omsg, ctl_addr)->sin_port = addr.sin_port; - OTOSIN(omsg, ctl_addr)->sin_addr = our_addr; + OTOSIN(omsg, ctl_addr)->sin_addr = s->our_addr; strncpy(omsg->l_name, getlogin(), NAME_SIZE_OLD); } else { /* new talk */ omsg = (CTL_MSG_OLD *) buff; nmsg = mtod(m, CTL_MSG *); type = nmsg->type; OTOSIN(nmsg, ctl_addr)->sin_port = addr.sin_port; - OTOSIN(nmsg, ctl_addr)->sin_addr = our_addr; + OTOSIN(nmsg, ctl_addr)->sin_addr = s->our_addr; strncpy(nmsg->l_name, getlogin(), NAME_SIZE_OLD); } @@ -530,9 +523,9 @@ (struct sockaddr *) &addr, &addrlen); OTOSIN(omsg, addr)->sin_port = addr.sin_port; - OTOSIN(omsg, addr)->sin_addr = our_addr; + OTOSIN(omsg, addr)->sin_addr = s->our_addr; OTOSIN(nmsg, addr)->sin_port = addr.sin_port; - OTOSIN(nmsg, addr)->sin_addr = our_addr; + OTOSIN(nmsg, addr)->sin_addr = s->our_addr; /* send LEAVE_INVITEs */ temp_port = OTOSIN(omsg, ctl_addr)->sin_port; @@ -541,7 +534,7 @@ omsg->type = nmsg->type = LEAVE_INVITE; s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); - addr.sin_addr = our_addr; + addr.sin_addr = s->our_addr; addr.sin_family = AF_INET; addr.sin_port = htons(517); sendto(s, (char *)omsg, sizeof(*omsg), 0, @@ -572,7 +565,7 @@ OTOSIN(nmsg, ctl_addr)->sin_port = 0; s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); - addr.sin_addr = our_addr; + addr.sin_addr = s->our_addr; addr.sin_family = AF_INET; addr.sin_port = htons(517); sendto(s, (char *)omsg, sizeof(*omsg), 0, @@ -621,7 +614,7 @@ return; cu_head = mtod(m, struct cu_header *); cu_head->s_port = addr.sin_port; - cu_head->so_addr = our_addr.s_addr; + cu_head->so_addr = s->our_addr.s_addr; } return; @@ -629,11 +622,8 @@ } struct socket * -udp_listen(port, laddr, lport, flags) - u_int port; - u_int32_t laddr; - u_int lport; - int flags; +udp_listen(slirp_state_t *s, u_int port, u_int32_t laddr, u_int lport, + int flags) { struct sockaddr_in addr; struct socket *so; @@ -644,15 +634,15 @@ return NULL; } so->s = socket(AF_INET,SOCK_DGRAM,0); - so->so_expire = curtime + SO_EXPIRE; - insque(so,&udb); + so->so_expire = s->curtime + SO_EXPIRE; + insque(s, so, &s->udb); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = port; if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) { - udp_detach(so); + udp_detach(s, so); return NULL; } setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)); @@ -660,8 +650,8 @@ getsockname(so->s,(struct sockaddr *)&addr,&addrlen); so->so_fport = addr.sin_port; - if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) - so->so_faddr = alias_addr; + if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == s->loopback_addr.s_addr) + so->so_faddr = s->alias_addr; else so->so_faddr = addr.sin_addr; Index: qemu/slirp/udp.h =================================================================== --- qemu.orig/slirp/udp.h 2007-10-20 07:33:38.000000000 +0000 +++ qemu/slirp/udp.h 2007-10-20 17:20:01.000000000 +0000 @@ -40,8 +40,6 @@ #define UDP_TTL 0x60 #define UDP_UDPDATALEN 16192 -extern struct socket *udp_last_so; - /* * Udp protocol header. * Per RFC 768, September, 1981. @@ -92,19 +90,17 @@ #define UDPCTL_CHECKSUM 1 /* checksum UDP packets */ #define UDPCTL_MAXID 2 -extern struct udpstat udpstat; -extern struct socket udb; struct mbuf; -void udp_init _P((void)); -void udp_input _P((register struct mbuf *, int)); -int udp_output _P((struct socket *, struct mbuf *, struct sockaddr_in *)); -int udp_attach _P((struct socket *)); -void udp_detach _P((struct socket *)); -u_int8_t udp_tos _P((struct socket *)); -void udp_emu _P((struct socket *, struct mbuf *)); -struct socket * udp_listen _P((u_int, u_int32_t, u_int, int)); -int udp_output2(struct socket *so, struct mbuf *m, +void udp_init(slirp_state_t *s); +void udp_input(slirp_state_t *s, register struct mbuf *m, int iphlen); +int udp_output(slirp_state_t *s, struct socket *so, struct mbuf *m, + struct sockaddr_in *addr); +int udp_attach(slirp_state_t *s, struct socket *so); +void udp_detach(slirp_state_t *s, struct socket *so); +struct socket *udp_listen(slirp_state_t *s, u_int port, u_int32_t laddr, + u_int lport, int flags); +int udp_output2(slirp_state_t *s, struct socket *so, struct mbuf *m, struct sockaddr_in *saddr, struct sockaddr_in *daddr, int iptos); #endif Index: qemu/slirp/debug.c =================================================================== --- qemu.orig/slirp/debug.c 2007-10-20 07:33:39.000000000 +0000 +++ qemu/slirp/debug.c 2007-10-20 12:52:40.000000000 +0000 @@ -9,10 +9,12 @@ #include <slirp.h> FILE *dfd = NULL; +#if 0 #ifdef DEBUG -int dostats = 1; +static int dostats = 1; #else -int dostats = 0; +static int dostats = 0; +#endif #endif int slirp_debug = 0; @@ -20,10 +22,10 @@ /* Carry over one item from main.c so that the tty's restored. * Only done when the tty being used is /dev/tty --RedWolf */ +#if 0 extern struct termios slirp_tty_settings; extern int slirp_tty_restore; - void debug_init(file, dbg) char *file; @@ -70,7 +72,16 @@ } } #endif +#endif +#ifdef LOG_ENABLED +//static void ttystats(struct ttys *); +static void ipstats(slirp_state_t *s); +static void tcpstats(slirp_state_t *s); +static void udpstats(slirp_state_t *s); +static void icmpstats(slirp_state_t *s); +static void mbufstats(slirp_state_t *s); +static void sockstats(slirp_state_t *s); #if 0 /* * Statistic routines @@ -80,7 +91,7 @@ * the link as well. */ -void +static void ttystats(ttyp) struct ttys *ttyp; { @@ -89,9 +100,9 @@ lprint(" \r\n"); - if (if_comp & IF_COMPRESS) + if (s->if_comp & IF_COMPRESS) strcpy(buff, "on"); - else if (if_comp & IF_NOCOMPRESS) + else if (s->if_comp & IF_NOCOMPRESS) strcpy(buff, "off"); else strcpy(buff, "off (for now)"); @@ -129,28 +140,28 @@ } #endif -void -ipstats() +static void +ipstats(slirp_state_t *s) { lprint(" \r\n"); lprint("IP stats:\r\n"); lprint(" %6d total packets received (%d were unaligned)\r\n", - ipstat.ips_total, ipstat.ips_unaligned); - lprint(" %6d with incorrect version\r\n", ipstat.ips_badvers); - lprint(" %6d with bad header checksum\r\n", ipstat.ips_badsum); - lprint(" %6d with length too short (len < sizeof(iphdr))\r\n", ipstat.ips_tooshort); - lprint(" %6d with length too small (len < ip->len)\r\n", ipstat.ips_toosmall); - lprint(" %6d with bad header length\r\n", ipstat.ips_badhlen); - lprint(" %6d with bad packet length\r\n", ipstat.ips_badlen); - lprint(" %6d fragments received\r\n", ipstat.ips_fragments); - lprint(" %6d fragments dropped\r\n", ipstat.ips_fragdropped); - lprint(" %6d fragments timed out\r\n", ipstat.ips_fragtimeout); - lprint(" %6d packets reassembled ok\r\n", ipstat.ips_reassembled); - lprint(" %6d outgoing packets fragmented\r\n", ipstat.ips_fragmented); - lprint(" %6d total outgoing fragments\r\n", ipstat.ips_ofragments); - lprint(" %6d with bad protocol field\r\n", ipstat.ips_noproto); - lprint(" %6d total packets delivered\r\n", ipstat.ips_delivered); + s->ipstat.ips_total, s->ipstat.ips_unaligned); + lprint(" %6d with incorrect version\r\n", s->ipstat.ips_badvers); + lprint(" %6d with bad header checksum\r\n", s->ipstat.ips_badsum); + lprint(" %6d with length too short (len < sizeof(iphdr))\r\n", s->ipstat.ips_tooshort); + lprint(" %6d with length too small (len < ip->len)\r\n", s->ipstat.ips_toosmall); + lprint(" %6d with bad header length\r\n", s->ipstat.ips_badhlen); + lprint(" %6d with bad packet length\r\n", s->ipstat.ips_badlen); + lprint(" %6d fragments received\r\n", s->ipstat.ips_fragments); + lprint(" %6d fragments dropped\r\n", s->ipstat.ips_fragdropped); + lprint(" %6d fragments timed out\r\n", s->ipstat.ips_fragtimeout); + lprint(" %6d packets reassembled ok\r\n", s->ipstat.ips_reassembled); + lprint(" %6d outgoing packets fragmented\r\n", s->ipstat.ips_fragmented); + lprint(" %6d total outgoing fragments\r\n", s->ipstat.ips_ofragments); + lprint(" %6d with bad protocol field\r\n", s->ipstat.ips_noproto); + lprint(" %6d total packets delivered\r\n", s->ipstat.ips_delivered); } #if 0 @@ -172,67 +183,67 @@ } #endif -void -tcpstats() +static void +tcpstats(slirp_state_t *s) { lprint(" \r\n"); lprint("TCP stats:\r\n"); - lprint(" %6d packets sent\r\n", tcpstat.tcps_sndtotal); + lprint(" %6d packets sent\r\n", s->tcpstat.tcps_sndtotal); lprint(" %6d data packets (%d bytes)\r\n", - tcpstat.tcps_sndpack, tcpstat.tcps_sndbyte); + s->tcpstat.tcps_sndpack, s->tcpstat.tcps_sndbyte); lprint(" %6d data packets retransmitted (%d bytes)\r\n", - tcpstat.tcps_sndrexmitpack, tcpstat.tcps_sndrexmitbyte); + s->tcpstat.tcps_sndrexmitpack, s->tcpstat.tcps_sndrexmitbyte); lprint(" %6d ack-only packets (%d delayed)\r\n", - tcpstat.tcps_sndacks, tcpstat.tcps_delack); - lprint(" %6d URG only packets\r\n", tcpstat.tcps_sndurg); - lprint(" %6d window probe packets\r\n", tcpstat.tcps_sndprobe); - lprint(" %6d window update packets\r\n", tcpstat.tcps_sndwinup); - lprint(" %6d control (SYN/FIN/RST) packets\r\n", tcpstat.tcps_sndctrl); - lprint(" %6d times tcp_output did nothing\r\n", tcpstat.tcps_didnuttin); + s->tcpstat.tcps_sndacks, s->tcpstat.tcps_delack); + lprint(" %6d URG only packets\r\n", s->tcpstat.tcps_sndurg); + lprint(" %6d window probe packets\r\n", s->tcpstat.tcps_sndprobe); + lprint(" %6d window update packets\r\n", s->tcpstat.tcps_sndwinup); + lprint(" %6d control (SYN/FIN/RST) packets\r\n", s->tcpstat.tcps_sndctrl); + lprint(" %6d times tcp_output did nothing\r\n", s->tcpstat.tcps_didnuttin); - lprint(" %6d packets received\r\n", tcpstat.tcps_rcvtotal); + lprint(" %6d packets received\r\n", s->tcpstat.tcps_rcvtotal); lprint(" %6d acks (for %d bytes)\r\n", - tcpstat.tcps_rcvackpack, tcpstat.tcps_rcvackbyte); - lprint(" %6d duplicate acks\r\n", tcpstat.tcps_rcvdupack); - lprint(" %6d acks for unsent data\r\n", tcpstat.tcps_rcvacktoomuch); + s->tcpstat.tcps_rcvackpack, s->tcpstat.tcps_rcvackbyte); + lprint(" %6d duplicate acks\r\n", s->tcpstat.tcps_rcvdupack); + lprint(" %6d acks for unsent data\r\n", s->tcpstat.tcps_rcvacktoomuch); lprint(" %6d packets received in sequence (%d bytes)\r\n", - tcpstat.tcps_rcvpack, tcpstat.tcps_rcvbyte); + s->tcpstat.tcps_rcvpack, s->tcpstat.tcps_rcvbyte); lprint(" %6d completely duplicate packets (%d bytes)\r\n", - tcpstat.tcps_rcvduppack, tcpstat.tcps_rcvdupbyte); + s->tcpstat.tcps_rcvduppack, s->tcpstat.tcps_rcvdupbyte); lprint(" %6d packets with some duplicate data (%d bytes duped)\r\n", - tcpstat.tcps_rcvpartduppack, tcpstat.tcps_rcvpartdupbyte); + s->tcpstat.tcps_rcvpartduppack, s->tcpstat.tcps_rcvpartdupbyte); lprint(" %6d out-of-order packets (%d bytes)\r\n", - tcpstat.tcps_rcvoopack, tcpstat.tcps_rcvoobyte); + s->tcpstat.tcps_rcvoopack, s->tcpstat.tcps_rcvoobyte); lprint(" %6d packets of data after window (%d bytes)\r\n", - tcpstat.tcps_rcvpackafterwin, tcpstat.tcps_rcvbyteafterwin); - lprint(" %6d window probes\r\n", tcpstat.tcps_rcvwinprobe); - lprint(" %6d window update packets\r\n", tcpstat.tcps_rcvwinupd); - lprint(" %6d packets received after close\r\n", tcpstat.tcps_rcvafterclose); - lprint(" %6d discarded for bad checksums\r\n", tcpstat.tcps_rcvbadsum); + s->tcpstat.tcps_rcvpackafterwin, s->tcpstat.tcps_rcvbyteafterwin); + lprint(" %6d window probes\r\n", s->tcpstat.tcps_rcvwinprobe); + lprint(" %6d window update packets\r\n", s->tcpstat.tcps_rcvwinupd); + lprint(" %6d packets received after close\r\n", s->tcpstat.tcps_rcvafterclose); + lprint(" %6d discarded for bad checksums\r\n", s->tcpstat.tcps_rcvbadsum); lprint(" %6d discarded for bad header offset fields\r\n", - tcpstat.tcps_rcvbadoff); + s->tcpstat.tcps_rcvbadoff); - lprint(" %6d connection requests\r\n", tcpstat.tcps_connattempt); - lprint(" %6d connection accepts\r\n", tcpstat.tcps_accepts); - lprint(" %6d connections established (including accepts)\r\n", tcpstat.tcps_connects); + lprint(" %6d connection requests\r\n", s->tcpstat.tcps_connattempt); + lprint(" %6d connection accepts\r\n", s->tcpstat.tcps_accepts); + lprint(" %6d connections established (including accepts)\r\n", s->tcpstat.tcps_connects); lprint(" %6d connections closed (including %d drop)\r\n", - tcpstat.tcps_closed, tcpstat.tcps_drops); - lprint(" %6d embryonic connections dropped\r\n", tcpstat.tcps_conndrops); + s->tcpstat.tcps_closed, s->tcpstat.tcps_drops); + lprint(" %6d embryonic connections dropped\r\n", s->tcpstat.tcps_conndrops); lprint(" %6d segments we tried to get rtt (%d succeeded)\r\n", - tcpstat.tcps_segstimed, tcpstat.tcps_rttupdated); - lprint(" %6d retransmit timeouts\r\n", tcpstat.tcps_rexmttimeo); + s->tcpstat.tcps_segstimed, s->tcpstat.tcps_rttupdated); + lprint(" %6d retransmit timeouts\r\n", s->tcpstat.tcps_rexmttimeo); lprint(" %6d connections dropped by rxmt timeout\r\n", - tcpstat.tcps_timeoutdrop); - lprint(" %6d persist timeouts\r\n", tcpstat.tcps_persisttimeo); - lprint(" %6d keepalive timeouts\r\n", tcpstat.tcps_keeptimeo); - lprint(" %6d keepalive probes sent\r\n", tcpstat.tcps_keepprobe); - lprint(" %6d connections dropped by keepalive\r\n", tcpstat.tcps_keepdrops); - lprint(" %6d correct ACK header predictions\r\n", tcpstat.tcps_predack); - lprint(" %6d correct data packet header predictions\n", tcpstat.tcps_preddat); - lprint(" %6d TCP cache misses\r\n", tcpstat.tcps_socachemiss); + s->tcpstat.tcps_timeoutdrop); + lprint(" %6d persist timeouts\r\n", s->tcpstat.tcps_persisttimeo); + lprint(" %6d keepalive timeouts\r\n", s->tcpstat.tcps_keeptimeo); + lprint(" %6d keepalive probes sent\r\n", s->tcpstat.tcps_keepprobe); + lprint(" %6d connections dropped by keepalive\r\n", s->tcpstat.tcps_keepdrops); + lprint(" %6d correct ACK header predictions\r\n", s->tcpstat.tcps_predack); + lprint(" %6d correct data packet header predictions\n", s->tcpstat.tcps_preddat); + lprint(" %6d TCP cache misses\r\n", s->tcpstat.tcps_socachemiss); /* lprint(" Packets received too short: %d\r\n", tcpstat.tcps_rcvshort); */ @@ -240,35 +251,35 @@ } -void -udpstats() +static void +udpstats(slirp_state_t *s) { lprint(" \r\n"); lprint("UDP stats:\r\n"); - lprint(" %6d datagrams received\r\n", udpstat.udps_ipackets); - lprint(" %6d with packets shorter than header\r\n", udpstat.udps_hdrops); - lprint(" %6d with bad checksums\r\n", udpstat.udps_badsum); - lprint(" %6d with data length larger than packet\r\n", udpstat.udps_badlen); - lprint(" %6d UDP socket cache misses\r\n", udpstat.udpps_pcbcachemiss); - lprint(" %6d datagrams sent\r\n", udpstat.udps_opackets); + lprint(" %6d datagrams received\r\n", s->udpstat.udps_ipackets); + lprint(" %6d with packets shorter than header\r\n", s->udpstat.udps_hdrops); + lprint(" %6d with bad checksums\r\n", s->udpstat.udps_badsum); + lprint(" %6d with data length larger than packet\r\n", s->udpstat.udps_badlen); + lprint(" %6d UDP socket cache misses\r\n", s->udpstat.udpps_pcbcachemiss); + lprint(" %6d datagrams sent\r\n", s->udpstat.udps_opackets); } -void -icmpstats() +static void +icmpstats(slirp_state_t *s) { lprint(" \r\n"); lprint("ICMP stats:\r\n"); - lprint(" %6d ICMP packets received\r\n", icmpstat.icps_received); - lprint(" %6d were too short\r\n", icmpstat.icps_tooshort); - lprint(" %6d with bad checksums\r\n", icmpstat.icps_checksum); - lprint(" %6d with type not supported\r\n", icmpstat.icps_notsupp); - lprint(" %6d with bad type feilds\r\n", icmpstat.icps_badtype); - lprint(" %6d ICMP packets sent in reply\r\n", icmpstat.icps_reflect); + lprint(" %6d ICMP packets received\r\n", s->icmpstat.icps_received); + lprint(" %6d were too short\r\n", s->icmpstat.icps_tooshort); + lprint(" %6d with bad checksums\r\n", s->icmpstat.icps_checksum); + lprint(" %6d with type not supported\r\n", s->icmpstat.icps_notsupp); + lprint(" %6d with bad type feilds\r\n", s->icmpstat.icps_badtype); + lprint(" %6d ICMP packets sent in reply\r\n", s->icmpstat.icps_reflect); } -void -mbufstats() +static void +mbufstats(slirp_state_t *s) { struct mbuf *m; int i; @@ -277,22 +288,22 @@ lprint("Mbuf stats:\r\n"); - lprint(" %6d mbufs allocated (%d max)\r\n", mbuf_alloced, mbuf_max); + lprint(" %6d mbufs allocated (%d max)\r\n", s->mbuf_alloced, s->mbuf_max); i = 0; - for (m = m_freelist.m_next; m != &m_freelist; m = m->m_next) + for (m = s->m_freelist.m_next; m != &s->m_freelist; m = m->m_next) i++; lprint(" %6d mbufs on free list\r\n", i); i = 0; - for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next) + for (m = s->m_usedlist.m_next; m != &s->m_usedlist; m = m->m_next) i++; lprint(" %6d mbufs on used list\r\n", i); - lprint(" %6d mbufs queued as packets\r\n\r\n", if_queued); + lprint(" %6d mbufs queued as packets\r\n\r\n", s->if_queued); } -void -sockstats() +static void +sockstats(slirp_state_t *s) { char buff[256]; int n; @@ -303,7 +314,7 @@ lprint( "Proto[state] Sock Local Address, Port Remote Address, Port RecvQ SendQ\r\n"); - for (so = tcb.so_next; so != &tcb; so = so->so_next) { + for (so = s->tcb.so_next; so != &s->tcb; so = so->so_next) { n = sprintf(buff, "tcp[%s]", so->so_tcpcb?tcpstates[so->so_tcpcb->t_state]:"NONE"); while (n < 17) @@ -317,9 +328,9 @@ so->so_rcv.sb_cc, so->so_snd.sb_cc); } - for (so = udb.so_next; so != &udb; so = so->so_next) { + for (so = s->udb.so_next; so != &s->udb; so = so->so_next) { - n = sprintf(buff, "udp[%d sec]", (so->so_expire - curtime) / 1000); + n = sprintf(buff, "udp[%d sec]", (so->so_expire - s->curtime) / 1000); while (n < 17) buff[n++] = ' '; buff[17] = 0; @@ -331,6 +342,7 @@ so->so_rcv.sb_cc, so->so_snd.sb_cc); } } +#endif #if 0 void @@ -374,3 +386,18 @@ exit(exit_status); } #endif + +void +slirp_stats(slirp_state_t *s) +{ +#ifdef LOG_ENABLED + ipstats(s); + tcpstats(s); + udpstats(s); + icmpstats(s); + mbufstats(s); + sockstats(s); +#else + fprintf(stderr, "SLIRP statistics not compiled\n"); +#endif +} Index: qemu/slirp/debug.h =================================================================== --- qemu.orig/slirp/debug.h 2007-10-20 07:33:39.000000000 +0000 +++ qemu/slirp/debug.h 2007-10-20 12:50:47.000000000 +0000 @@ -37,14 +37,4 @@ #endif void debug_init _P((char *, int)); -//void ttystats _P((struct ttys *)); -void allttystats _P((void)); -void ipstats _P((void)); -void vjstats _P((void)); -void tcpstats _P((void)); -void udpstats _P((void)); -void icmpstats _P((void)); -void mbufstats _P((void)); -void sockstats _P((void)); -void slirp_exit _P((int)); Index: qemu/slirp/icmp_var.h =================================================================== --- qemu.orig/slirp/icmp_var.h 2007-10-20 07:33:39.000000000 +0000 +++ qemu/slirp/icmp_var.h 2007-10-20 08:17:52.000000000 +0000 @@ -64,6 +64,4 @@ { "stats", CTLTYPE_STRUCT }, \ } -extern struct icmpstat icmpstat; - #endif Index: qemu/slirp/if.h =================================================================== --- qemu.orig/slirp/if.h 2007-10-20 07:33:39.000000000 +0000 +++ qemu/slirp/if.h 2007-10-20 08:17:52.000000000 +0000 @@ -13,20 +13,6 @@ #define IF_AUTOCOMP 0x04 /* Autodetect (default) */ #define IF_NOCIDCOMP 0x08 /* CID compression */ -/* Needed for FreeBSD */ -#undef if_mtu -extern int if_mtu; -extern int if_mru; /* MTU and MRU */ -extern int if_comp; /* Flags for compression */ -extern int if_maxlinkhdr; -extern int if_queued; /* Number of packets queued so far */ -extern int if_thresh; /* Number of packets queued before we start sending - * (to prevent allocing too many mbufs) */ - -extern struct mbuf if_fastq; /* fast queue (for interactive data) */ -extern struct mbuf if_batchq; /* queue for non-interactive data */ -extern struct mbuf *next_m; - #define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm)) /* Interface statistics */ Index: qemu/vl.c =================================================================== --- qemu.orig/vl.c 2007-10-20 07:33:39.000000000 +0000 +++ qemu/vl.c 2007-10-20 17:16:26.000000000 +0000 @@ -3608,13 +3608,28 @@ static int slirp_inited; static VLANClientState *slirp_vc; +static const char *tftp_prefix; +static const char *bootp_filename; +static const char *slirp_hostname; +static void *slirp_opaque; +static char slirp_network[32]; -int slirp_can_output(void) +void slirp_maybe_init(void) +{ + if (!slirp_inited) { + slirp_inited = 1; + sprintf(slirp_network, "10.0.%d.0", slirp_vc->vlan->id + 2); + slirp_opaque = slirp_init(slirp_vc, slirp_hostname, tftp_prefix, + slirp_network); + } +} + +int slirp_can_output(void *user) { return !slirp_vc || qemu_can_send_packet(slirp_vc); } -void slirp_output(const uint8_t *pkt, int pkt_len) +void slirp_output(void *user, const uint8_t *pkt, int pkt_len) { #if 0 printf("slirp output:\n"); @@ -3631,17 +3646,13 @@ printf("slirp input:\n"); hex_dump(stdout, buf, size); #endif - slirp_input(buf, size); + slirp_input(slirp_opaque, buf, size); } static int net_slirp_init(VLANState *vlan) { - if (!slirp_inited) { - slirp_inited = 1; - slirp_init(); - } - slirp_vc = qemu_new_vlan_client(vlan, - slirp_receive, NULL, NULL); + slirp_vc = qemu_new_vlan_client(vlan, slirp_receive, NULL, NULL); + slirp_maybe_init(); snprintf(slirp_vc->info_str, sizeof(slirp_vc->info_str), "user redirector"); return 0; } @@ -3654,11 +3665,7 @@ struct in_addr guest_addr; int host_port, guest_port; - if (!slirp_inited) { - slirp_inited = 1; - slirp_init(); - } - + slirp_maybe_init(); p = redir_str; if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) goto fail; @@ -3688,7 +3695,8 @@ if (r == p) goto fail; - if (slirp_redir(is_udp, host_port, guest_addr, guest_port) < 0) { + if (slirp_redir(slirp_opaque, is_udp, host_port, guest_addr, + guest_port) < 0) { fprintf(stderr, "qemu: could not set up redirection\n"); exit(1); } @@ -3732,11 +3740,7 @@ char smb_cmdline[1024]; FILE *f; - if (!slirp_inited) { - slirp_inited = 1; - slirp_init(); - } - + slirp_maybe_init(); /* XXX: better tmp dir construction */ snprintf(smb_dir, sizeof(smb_dir), "/tmp/qemu-smb.%d", getpid()); if (mkdir(smb_dir, 0700) < 0) { @@ -3777,10 +3781,14 @@ snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s", SMBD_COMMAND, smb_conf); - slirp_add_exec(0, smb_cmdline, 4, 139); + slirp_add_exec(slirp_opaque, 0, smb_cmdline, 4, 139); } #endif /* !defined(_WIN32) */ +void do_info_slirp(void) +{ + slirp_stats(slirp_opaque); +} #endif /* CONFIG_SLIRP */ @@ -4600,8 +4608,8 @@ } else #ifdef CONFIG_SLIRP if (!strcmp(device, "user")) { - if (get_param_value(buf, sizeof(buf), "hostname", p)) { - pstrcpy(slirp_hostname, sizeof(slirp_hostname), buf); + if (get_param_value(buf, sizeof(buf), "hostname", p) <= 0) { + slirp_hostname = strdup(buf); } vlan->nb_host_devs++; ret = net_slirp_init(vlan); @@ -6823,7 +6831,7 @@ #endif #if defined(CONFIG_SLIRP) if (slirp_inited) { - slirp_select_fill(&nfds, &rfds, &wfds, &xfds); + slirp_select_fill(slirp_opaque, &nfds, &rfds, &wfds, &xfds); } #endif ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv); @@ -6857,7 +6865,7 @@ FD_ZERO(&wfds); FD_ZERO(&xfds); } - slirp_select_poll(&rfds, &wfds, &xfds); + slirp_select_poll(slirp_opaque, &rfds, &wfds, &xfds); } #endif qemu_aio_poll(); Index: qemu/vl.h =================================================================== --- qemu.orig/vl.h 2007-10-20 07:33:39.000000000 +0000 +++ qemu/vl.h 2007-10-20 08:17:52.000000000 +0000 @@ -183,7 +183,6 @@ extern int semihosting_enabled; extern int autostart; extern int old_param; -extern const char *bootp_filename; #define MAX_OPTION_ROMS 16 extern const char *option_rom[MAX_OPTION_ROMS]; @@ -439,6 +438,9 @@ extern int nb_nics; extern NICInfo nd_table[MAX_NICS]; +/* SLIRP */ +void do_info_slirp(void); + /* timers */ typedef struct QEMUClock QEMUClock; Index: qemu/monitor.c =================================================================== --- qemu.orig/monitor.c 2007-10-20 07:33:39.000000000 +0000 +++ qemu/monitor.c 2007-10-20 08:17:52.000000000 +0000 @@ -1365,6 +1365,10 @@ { "cpustats", "", do_info_cpu_stats, "", "show CPU statistics", }, #endif +#if defined(CONFIG_SLIRP) + { "slirp", "", do_info_slirp, + "", "show SLIRP statistics", }, +#endif { NULL, NULL, }, }; ^ permalink raw reply [flat|nested] 4+ messages in thread
* [Qemu-devel] Re: PATCH, RFC: Slirp improvements 2007-10-20 18:42 [Qemu-devel] PATCH, RFC: Slirp improvements Blue Swirl @ 2007-10-23 17:42 ` Blue Swirl 0 siblings, 0 replies; 4+ messages in thread From: Blue Swirl @ 2007-10-23 17:42 UTC (permalink / raw) To: qemu-devel [-- Attachment #1: Type: text/plain, Size: 663 bytes --] I tried harder to change the SLIRP queue stuff to something saner by hiding the pointer access inside inlined functions. Still when I changed the 32 bit pointers to native 64 bit (or moved the pointers outside the packet), qemu crashes. Must be some devilishly hidden access somewhere. I already fixed one, which involved recycling port number fields for buffer pointers. IMHO there should be some kind of corporeal punishments mandated by law for writing this kind of mess. Maybe it would even be easier to create a new userland IP stack based on Linux from scratch instead of fixing this. I think I'll just commit in the log part, unless there are objections. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: slirp_all.diff --] [-- Type: text/x-diff; name=slirp_all.diff, Size: 207996 bytes --] Index: qemu/monitor.c =================================================================== --- qemu.orig/monitor.c 2007-10-21 18:47:08.000000000 +0000 +++ qemu/monitor.c 2007-10-21 18:47:11.000000000 +0000 @@ -1365,6 +1365,10 @@ { "cpustats", "", do_info_cpu_stats, "", "show CPU statistics", }, #endif +#if defined(CONFIG_SLIRP) + { "slirp", "", do_info_slirp, + "", "show SLIRP statistics", }, +#endif { NULL, NULL, }, }; Index: qemu/slirp/bootp.c =================================================================== --- qemu.orig/slirp/bootp.c 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/bootp.c 2007-10-22 19:35:29.000000000 +0000 @@ -25,20 +25,6 @@ /* XXX: only DHCP is supported */ -#define NB_ADDR 16 - -#define START_ADDR 15 - -#define LEASE_TIME (24 * 3600) - -typedef struct { - uint8_t allocated; - uint8_t macaddr[6]; -} BOOTPClient; - -BOOTPClient bootp_clients[NB_ADDR]; - -const char *bootp_filename; static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE }; @@ -49,37 +35,49 @@ #define dprintf(fmt, args...) #endif -static BOOTPClient *get_new_addr(struct in_addr *paddr) +static BOOTPClient *get_new_addr(slirp_state_t *s, struct in_addr *paddr) { BOOTPClient *bc; int i; for(i = 0; i < NB_ADDR; i++) { - if (!bootp_clients[i].allocated) + if (!s->bootp_clients[i].allocated) goto found; } return NULL; found: - bc = &bootp_clients[i]; + bc = &s->bootp_clients[i]; bc->allocated = 1; - paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR)); + paddr->s_addr = htonl(ntohl(s->special_addr.s_addr) | (i + START_ADDR)); return bc; } -static BOOTPClient *find_addr(struct in_addr *paddr, const uint8_t *macaddr) +static void release_addr(slirp_state_t *s, struct in_addr *paddr) +{ + int i; + + i = ntohl(paddr->s_addr) - START_ADDR - ntohl(s->special_addr.s_addr); + if (i >= NB_ADDR) + return; + memset(s->bootp_clients[i].macaddr, '\0', 6); + s->bootp_clients[i].allocated = 0; +} + +static BOOTPClient *find_addr(slirp_state_t *s, struct in_addr *paddr, + const uint8_t *macaddr) { BOOTPClient *bc; int i; for(i = 0; i < NB_ADDR; i++) { - if (!memcmp(macaddr, bootp_clients[i].macaddr, 6)) + if (!memcmp(macaddr, s->bootp_clients[i].macaddr, 6)) goto found; } return NULL; found: - bc = &bootp_clients[i]; + bc = &s->bootp_clients[i]; bc->allocated = 1; - paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR)); + paddr->s_addr = htonl(ntohl(s->special_addr.s_addr) | (i + START_ADDR)); return bc; } @@ -124,7 +122,7 @@ } } -static void bootp_reply(struct bootp_t *bp) +static void bootp_reply(slirp_state_t *s, struct bootp_t *bp) { BOOTPClient *bc; struct mbuf *m; @@ -141,29 +139,39 @@ if (dhcp_msg_type == 0) dhcp_msg_type = DHCPREQUEST; /* Force reply for old BOOTP clients */ + if (dhcp_msg_type == DHCPRELEASE) { + release_addr(s, &bp->bp_ciaddr); + dprintf("released addr=%08x\n", ntohl(bp->bp_ciaddr.s_addr)); + /* This message is not to be answered in any way. */ + return; + } if (dhcp_msg_type != DHCPDISCOVER && dhcp_msg_type != DHCPREQUEST) return; /* XXX: this is a hack to get the client mac address */ - memcpy(client_ethaddr, bp->bp_hwaddr, 6); + memcpy(s->client_ethaddr, bp->bp_hwaddr, 6); - if ((m = m_get()) == NULL) + if ((m = m_get(s)) == NULL) return; - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; rbp = (struct bootp_t *)m->m_data; m->m_data += sizeof(struct udpiphdr); memset(rbp, 0, sizeof(struct bootp_t)); if (dhcp_msg_type == DHCPDISCOVER) { - new_addr: - bc = get_new_addr(&daddr.sin_addr); + /* Do not allocate a new lease for clients that forgot that they had a lease. */ + bc = find_addr(s, &daddr.sin_addr, bp->bp_hwaddr); if (!bc) { - dprintf("no address left\n"); - return; + new_addr: + bc = get_new_addr(s, &daddr.sin_addr); + if (!bc) { + dprintf("no address left\n"); + return; + } + memcpy(bc->macaddr, s->client_ethaddr, 6); } - memcpy(bc->macaddr, client_ethaddr, 6); } else { - bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr); + bc = find_addr(s, &daddr.sin_addr, bp->bp_hwaddr); if (!bc) { /* if never assigned, behaves as if it was already assigned (windows fix because it remembers its address) */ @@ -171,12 +179,12 @@ } } - if (bootp_filename) - snprintf(rbp->bp_file, sizeof(rbp->bp_file), "%s", bootp_filename); + if (s->bootp_filename) + snprintf(rbp->bp_file, sizeof(rbp->bp_file), "%s", s->bootp_filename); dprintf("offered addr=%08x\n", ntohl(daddr.sin_addr.s_addr)); - saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS); + saddr.sin_addr.s_addr = htonl(ntohl(s->special_addr.s_addr) | CTL_ALIAS); saddr.sin_port = htons(BOOTP_SERVER); daddr.sin_port = htons(BOOTP_CLIENT); @@ -225,7 +233,7 @@ *q++ = RFC1533_DNS; *q++ = 4; - dns_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_DNS); + dns_addr.s_addr = htonl(ntohl(s->special_addr.s_addr) | CTL_DNS); memcpy(q, &dns_addr, 4); q += 4; @@ -235,11 +243,11 @@ memcpy(q, &val, 4); q += 4; - if (*slirp_hostname) { - val = strlen(slirp_hostname); + if (*s->slirp_hostname) { + val = strlen(s->slirp_hostname); *q++ = RFC1533_HOSTNAME; *q++ = val; - memcpy(q, slirp_hostname, val); + memcpy(q, s->slirp_hostname, val); q += val; } } @@ -247,14 +255,16 @@ m->m_len = sizeof(struct bootp_t) - sizeof(struct ip) - sizeof(struct udphdr); - udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); + /* Reply to the broadcast address, as some clients perform paranoid checks. */ + daddr.sin_addr.s_addr = INADDR_BROADCAST; + udp_output2(s, NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); } -void bootp_input(struct mbuf *m) +void bootp_input(slirp_state_t *s, struct mbuf *m) { struct bootp_t *bp = mtod(m, struct bootp_t *); if (bp->bp_op == BOOTP_REQUEST) { - bootp_reply(bp); + bootp_reply(s, bp); } } Index: qemu/slirp/bootp.h =================================================================== --- qemu.orig/slirp/bootp.h 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/bootp.h 2007-10-21 18:47:11.000000000 +0000 @@ -71,6 +71,7 @@ #define DHCPOFFER 2 #define DHCPREQUEST 3 #define DHCPACK 5 +#define DHCPRELEASE 7 #define RFC1533_VENDOR_MAJOR 0 #define RFC1533_VENDOR_MINOR 0 @@ -110,4 +111,4 @@ uint8_t bp_vend[DHCP_OPT_LEN]; }; -void bootp_input(struct mbuf *m); +void bootp_input(slirp_state_t *s, struct mbuf *m); Index: qemu/slirp/ctl.h =================================================================== --- qemu.orig/slirp/ctl.h 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/ctl.h 2007-10-21 18:47:11.000000000 +0000 @@ -2,6 +2,4 @@ #define CTL_EXEC 1 #define CTL_ALIAS 2 #define CTL_DNS 3 - -#define CTL_SPECIAL "10.0.2.0" -#define CTL_LOCAL "10.0.2.15" +#define CTL_BROADCAST 255 Index: qemu/slirp/debug.c =================================================================== --- qemu.orig/slirp/debug.c 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/debug.c 2007-10-22 20:00:01.000000000 +0000 @@ -9,10 +9,12 @@ #include <slirp.h> FILE *dfd = NULL; +#if 0 #ifdef DEBUG -int dostats = 1; +static int dostats = 1; #else -int dostats = 0; +static int dostats = 0; +#endif #endif int slirp_debug = 0; @@ -20,10 +22,10 @@ /* Carry over one item from main.c so that the tty's restored. * Only done when the tty being used is /dev/tty --RedWolf */ +#if 0 extern struct termios slirp_tty_settings; extern int slirp_tty_restore; - void debug_init(file, dbg) char *file; @@ -70,7 +72,16 @@ } } #endif +#endif +#ifdef LOG_ENABLED +//static void ttystats(struct ttys *); +static void ipstats(slirp_state_t *s); +static void tcpstats(slirp_state_t *s); +static void udpstats(slirp_state_t *s); +static void icmpstats(slirp_state_t *s); +static void mbufstats(slirp_state_t *s); +static void sockstats(slirp_state_t *s); #if 0 /* * Statistic routines @@ -80,7 +91,7 @@ * the link as well. */ -void +static void ttystats(ttyp) struct ttys *ttyp; { @@ -89,9 +100,9 @@ lprint(" \r\n"); - if (if_comp & IF_COMPRESS) + if (s->if_comp & IF_COMPRESS) strcpy(buff, "on"); - else if (if_comp & IF_NOCOMPRESS) + else if (s->if_comp & IF_NOCOMPRESS) strcpy(buff, "off"); else strcpy(buff, "off (for now)"); @@ -129,28 +140,28 @@ } #endif -void -ipstats() +static void +ipstats(slirp_state_t *s) { lprint(" \r\n"); lprint("IP stats:\r\n"); lprint(" %6d total packets received (%d were unaligned)\r\n", - ipstat.ips_total, ipstat.ips_unaligned); - lprint(" %6d with incorrect version\r\n", ipstat.ips_badvers); - lprint(" %6d with bad header checksum\r\n", ipstat.ips_badsum); - lprint(" %6d with length too short (len < sizeof(iphdr))\r\n", ipstat.ips_tooshort); - lprint(" %6d with length too small (len < ip->len)\r\n", ipstat.ips_toosmall); - lprint(" %6d with bad header length\r\n", ipstat.ips_badhlen); - lprint(" %6d with bad packet length\r\n", ipstat.ips_badlen); - lprint(" %6d fragments received\r\n", ipstat.ips_fragments); - lprint(" %6d fragments dropped\r\n", ipstat.ips_fragdropped); - lprint(" %6d fragments timed out\r\n", ipstat.ips_fragtimeout); - lprint(" %6d packets reassembled ok\r\n", ipstat.ips_reassembled); - lprint(" %6d outgoing packets fragmented\r\n", ipstat.ips_fragmented); - lprint(" %6d total outgoing fragments\r\n", ipstat.ips_ofragments); - lprint(" %6d with bad protocol field\r\n", ipstat.ips_noproto); - lprint(" %6d total packets delivered\r\n", ipstat.ips_delivered); + s->ipstat.ips_total, s->ipstat.ips_unaligned); + lprint(" %6d with incorrect version\r\n", s->ipstat.ips_badvers); + lprint(" %6d with bad header checksum\r\n", s->ipstat.ips_badsum); + lprint(" %6d with length too short (len < sizeof(iphdr))\r\n", s->ipstat.ips_tooshort); + lprint(" %6d with length too small (len < ip->len)\r\n", s->ipstat.ips_toosmall); + lprint(" %6d with bad header length\r\n", s->ipstat.ips_badhlen); + lprint(" %6d with bad packet length\r\n", s->ipstat.ips_badlen); + lprint(" %6d fragments received\r\n", s->ipstat.ips_fragments); + lprint(" %6d fragments dropped\r\n", s->ipstat.ips_fragdropped); + lprint(" %6d fragments timed out\r\n", s->ipstat.ips_fragtimeout); + lprint(" %6d packets reassembled ok\r\n", s->ipstat.ips_reassembled); + lprint(" %6d outgoing packets fragmented\r\n", s->ipstat.ips_fragmented); + lprint(" %6d total outgoing fragments\r\n", s->ipstat.ips_ofragments); + lprint(" %6d with bad protocol field\r\n", s->ipstat.ips_noproto); + lprint(" %6d total packets delivered\r\n", s->ipstat.ips_delivered); } #if 0 @@ -172,67 +183,67 @@ } #endif -void -tcpstats() +static void +tcpstats(slirp_state_t *s) { lprint(" \r\n"); lprint("TCP stats:\r\n"); - lprint(" %6d packets sent\r\n", tcpstat.tcps_sndtotal); + lprint(" %6d packets sent\r\n", s->tcpstat.tcps_sndtotal); lprint(" %6d data packets (%d bytes)\r\n", - tcpstat.tcps_sndpack, tcpstat.tcps_sndbyte); + s->tcpstat.tcps_sndpack, s->tcpstat.tcps_sndbyte); lprint(" %6d data packets retransmitted (%d bytes)\r\n", - tcpstat.tcps_sndrexmitpack, tcpstat.tcps_sndrexmitbyte); + s->tcpstat.tcps_sndrexmitpack, s->tcpstat.tcps_sndrexmitbyte); lprint(" %6d ack-only packets (%d delayed)\r\n", - tcpstat.tcps_sndacks, tcpstat.tcps_delack); - lprint(" %6d URG only packets\r\n", tcpstat.tcps_sndurg); - lprint(" %6d window probe packets\r\n", tcpstat.tcps_sndprobe); - lprint(" %6d window update packets\r\n", tcpstat.tcps_sndwinup); - lprint(" %6d control (SYN/FIN/RST) packets\r\n", tcpstat.tcps_sndctrl); - lprint(" %6d times tcp_output did nothing\r\n", tcpstat.tcps_didnuttin); + s->tcpstat.tcps_sndacks, s->tcpstat.tcps_delack); + lprint(" %6d URG only packets\r\n", s->tcpstat.tcps_sndurg); + lprint(" %6d window probe packets\r\n", s->tcpstat.tcps_sndprobe); + lprint(" %6d window update packets\r\n", s->tcpstat.tcps_sndwinup); + lprint(" %6d control (SYN/FIN/RST) packets\r\n", s->tcpstat.tcps_sndctrl); + lprint(" %6d times tcp_output did nothing\r\n", s->tcpstat.tcps_didnuttin); - lprint(" %6d packets received\r\n", tcpstat.tcps_rcvtotal); + lprint(" %6d packets received\r\n", s->tcpstat.tcps_rcvtotal); lprint(" %6d acks (for %d bytes)\r\n", - tcpstat.tcps_rcvackpack, tcpstat.tcps_rcvackbyte); - lprint(" %6d duplicate acks\r\n", tcpstat.tcps_rcvdupack); - lprint(" %6d acks for unsent data\r\n", tcpstat.tcps_rcvacktoomuch); + s->tcpstat.tcps_rcvackpack, s->tcpstat.tcps_rcvackbyte); + lprint(" %6d duplicate acks\r\n", s->tcpstat.tcps_rcvdupack); + lprint(" %6d acks for unsent data\r\n", s->tcpstat.tcps_rcvacktoomuch); lprint(" %6d packets received in sequence (%d bytes)\r\n", - tcpstat.tcps_rcvpack, tcpstat.tcps_rcvbyte); + s->tcpstat.tcps_rcvpack, s->tcpstat.tcps_rcvbyte); lprint(" %6d completely duplicate packets (%d bytes)\r\n", - tcpstat.tcps_rcvduppack, tcpstat.tcps_rcvdupbyte); + s->tcpstat.tcps_rcvduppack, s->tcpstat.tcps_rcvdupbyte); lprint(" %6d packets with some duplicate data (%d bytes duped)\r\n", - tcpstat.tcps_rcvpartduppack, tcpstat.tcps_rcvpartdupbyte); + s->tcpstat.tcps_rcvpartduppack, s->tcpstat.tcps_rcvpartdupbyte); lprint(" %6d out-of-order packets (%d bytes)\r\n", - tcpstat.tcps_rcvoopack, tcpstat.tcps_rcvoobyte); + s->tcpstat.tcps_rcvoopack, s->tcpstat.tcps_rcvoobyte); lprint(" %6d packets of data after window (%d bytes)\r\n", - tcpstat.tcps_rcvpackafterwin, tcpstat.tcps_rcvbyteafterwin); - lprint(" %6d window probes\r\n", tcpstat.tcps_rcvwinprobe); - lprint(" %6d window update packets\r\n", tcpstat.tcps_rcvwinupd); - lprint(" %6d packets received after close\r\n", tcpstat.tcps_rcvafterclose); - lprint(" %6d discarded for bad checksums\r\n", tcpstat.tcps_rcvbadsum); + s->tcpstat.tcps_rcvpackafterwin, s->tcpstat.tcps_rcvbyteafterwin); + lprint(" %6d window probes\r\n", s->tcpstat.tcps_rcvwinprobe); + lprint(" %6d window update packets\r\n", s->tcpstat.tcps_rcvwinupd); + lprint(" %6d packets received after close\r\n", s->tcpstat.tcps_rcvafterclose); + lprint(" %6d discarded for bad checksums\r\n", s->tcpstat.tcps_rcvbadsum); lprint(" %6d discarded for bad header offset fields\r\n", - tcpstat.tcps_rcvbadoff); + s->tcpstat.tcps_rcvbadoff); - lprint(" %6d connection requests\r\n", tcpstat.tcps_connattempt); - lprint(" %6d connection accepts\r\n", tcpstat.tcps_accepts); - lprint(" %6d connections established (including accepts)\r\n", tcpstat.tcps_connects); + lprint(" %6d connection requests\r\n", s->tcpstat.tcps_connattempt); + lprint(" %6d connection accepts\r\n", s->tcpstat.tcps_accepts); + lprint(" %6d connections established (including accepts)\r\n", s->tcpstat.tcps_connects); lprint(" %6d connections closed (including %d drop)\r\n", - tcpstat.tcps_closed, tcpstat.tcps_drops); - lprint(" %6d embryonic connections dropped\r\n", tcpstat.tcps_conndrops); + s->tcpstat.tcps_closed, s->tcpstat.tcps_drops); + lprint(" %6d embryonic connections dropped\r\n", s->tcpstat.tcps_conndrops); lprint(" %6d segments we tried to get rtt (%d succeeded)\r\n", - tcpstat.tcps_segstimed, tcpstat.tcps_rttupdated); - lprint(" %6d retransmit timeouts\r\n", tcpstat.tcps_rexmttimeo); + s->tcpstat.tcps_segstimed, s->tcpstat.tcps_rttupdated); + lprint(" %6d retransmit timeouts\r\n", s->tcpstat.tcps_rexmttimeo); lprint(" %6d connections dropped by rxmt timeout\r\n", - tcpstat.tcps_timeoutdrop); - lprint(" %6d persist timeouts\r\n", tcpstat.tcps_persisttimeo); - lprint(" %6d keepalive timeouts\r\n", tcpstat.tcps_keeptimeo); - lprint(" %6d keepalive probes sent\r\n", tcpstat.tcps_keepprobe); - lprint(" %6d connections dropped by keepalive\r\n", tcpstat.tcps_keepdrops); - lprint(" %6d correct ACK header predictions\r\n", tcpstat.tcps_predack); - lprint(" %6d correct data packet header predictions\n", tcpstat.tcps_preddat); - lprint(" %6d TCP cache misses\r\n", tcpstat.tcps_socachemiss); + s->tcpstat.tcps_timeoutdrop); + lprint(" %6d persist timeouts\r\n", s->tcpstat.tcps_persisttimeo); + lprint(" %6d keepalive timeouts\r\n", s->tcpstat.tcps_keeptimeo); + lprint(" %6d keepalive probes sent\r\n", s->tcpstat.tcps_keepprobe); + lprint(" %6d connections dropped by keepalive\r\n", s->tcpstat.tcps_keepdrops); + lprint(" %6d correct ACK header predictions\r\n", s->tcpstat.tcps_predack); + lprint(" %6d correct data packet header predictions\n", s->tcpstat.tcps_preddat); + lprint(" %6d TCP cache misses\r\n", s->tcpstat.tcps_socachemiss); /* lprint(" Packets received too short: %d\r\n", tcpstat.tcps_rcvshort); */ @@ -240,35 +251,35 @@ } -void -udpstats() +static void +udpstats(slirp_state_t *s) { lprint(" \r\n"); lprint("UDP stats:\r\n"); - lprint(" %6d datagrams received\r\n", udpstat.udps_ipackets); - lprint(" %6d with packets shorter than header\r\n", udpstat.udps_hdrops); - lprint(" %6d with bad checksums\r\n", udpstat.udps_badsum); - lprint(" %6d with data length larger than packet\r\n", udpstat.udps_badlen); - lprint(" %6d UDP socket cache misses\r\n", udpstat.udpps_pcbcachemiss); - lprint(" %6d datagrams sent\r\n", udpstat.udps_opackets); + lprint(" %6d datagrams received\r\n", s->udpstat.udps_ipackets); + lprint(" %6d with packets shorter than header\r\n", s->udpstat.udps_hdrops); + lprint(" %6d with bad checksums\r\n", s->udpstat.udps_badsum); + lprint(" %6d with data length larger than packet\r\n", s->udpstat.udps_badlen); + lprint(" %6d UDP socket cache misses\r\n", s->udpstat.udpps_pcbcachemiss); + lprint(" %6d datagrams sent\r\n", s->udpstat.udps_opackets); } -void -icmpstats() +static void +icmpstats(slirp_state_t *s) { lprint(" \r\n"); lprint("ICMP stats:\r\n"); - lprint(" %6d ICMP packets received\r\n", icmpstat.icps_received); - lprint(" %6d were too short\r\n", icmpstat.icps_tooshort); - lprint(" %6d with bad checksums\r\n", icmpstat.icps_checksum); - lprint(" %6d with type not supported\r\n", icmpstat.icps_notsupp); - lprint(" %6d with bad type feilds\r\n", icmpstat.icps_badtype); - lprint(" %6d ICMP packets sent in reply\r\n", icmpstat.icps_reflect); + lprint(" %6d ICMP packets received\r\n", s->icmpstat.icps_received); + lprint(" %6d were too short\r\n", s->icmpstat.icps_tooshort); + lprint(" %6d with bad checksums\r\n", s->icmpstat.icps_checksum); + lprint(" %6d with type not supported\r\n", s->icmpstat.icps_notsupp); + lprint(" %6d with bad type feilds\r\n", s->icmpstat.icps_badtype); + lprint(" %6d ICMP packets sent in reply\r\n", s->icmpstat.icps_reflect); } -void -mbufstats() +static void +mbufstats(slirp_state_t *s) { struct mbuf *m; int i; @@ -277,22 +288,22 @@ lprint("Mbuf stats:\r\n"); - lprint(" %6d mbufs allocated (%d max)\r\n", mbuf_alloced, mbuf_max); + lprint(" %6d mbufs allocated (%d max)\r\n", s->mbuf_alloced, s->mbuf_max); i = 0; - for (m = m_freelist.m_next; m != &m_freelist; m = m->m_next) + for (m = m_get_next(&s->m_freelist); m != &s->m_freelist; m = m_get_next(m)) i++; lprint(" %6d mbufs on free list\r\n", i); i = 0; - for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next) + for (m = m_get_next(&s->m_usedlist); m != &s->m_usedlist; m = m_get_next(m)) i++; lprint(" %6d mbufs on used list\r\n", i); - lprint(" %6d mbufs queued as packets\r\n\r\n", if_queued); + lprint(" %6d mbufs queued as packets\r\n\r\n", s->if_queued); } -void -sockstats() +static void +sockstats(slirp_state_t *s) { char buff[256]; int n; @@ -303,7 +314,7 @@ lprint( "Proto[state] Sock Local Address, Port Remote Address, Port RecvQ SendQ\r\n"); - for (so = tcb.so_next; so != &tcb; so = so->so_next) { + for (so = s->tcb.so_next; so != &s->tcb; so = so->so_next) { n = sprintf(buff, "tcp[%s]", so->so_tcpcb?tcpstates[so->so_tcpcb->t_state]:"NONE"); while (n < 17) @@ -317,9 +328,9 @@ so->so_rcv.sb_cc, so->so_snd.sb_cc); } - for (so = udb.so_next; so != &udb; so = so->so_next) { + for (so = s->udb.so_next; so != &s->udb; so = so->so_next) { - n = sprintf(buff, "udp[%d sec]", (so->so_expire - curtime) / 1000); + n = sprintf(buff, "udp[%d sec]", (so->so_expire - s->curtime) / 1000); while (n < 17) buff[n++] = ' '; buff[17] = 0; @@ -331,6 +342,7 @@ so->so_rcv.sb_cc, so->so_snd.sb_cc); } } +#endif #if 0 void @@ -374,3 +386,18 @@ exit(exit_status); } #endif + +void +slirp_stats(slirp_state_t *s) +{ +#ifdef LOG_ENABLED + ipstats(s); + tcpstats(s); + udpstats(s); + icmpstats(s); + mbufstats(s); + sockstats(s); +#else + lprint("SLIRP statistics not compiled\n"); +#endif +} Index: qemu/slirp/debug.h =================================================================== --- qemu.orig/slirp/debug.h 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/debug.h 2007-10-22 16:17:48.000000000 +0000 @@ -37,14 +37,4 @@ #endif void debug_init _P((char *, int)); -//void ttystats _P((struct ttys *)); -void allttystats _P((void)); -void ipstats _P((void)); -void vjstats _P((void)); -void tcpstats _P((void)); -void udpstats _P((void)); -void icmpstats _P((void)); -void mbufstats _P((void)); -void sockstats _P((void)); -void slirp_exit _P((int)); Index: qemu/slirp/icmp_var.h =================================================================== --- qemu.orig/slirp/icmp_var.h 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/icmp_var.h 2007-10-21 18:47:11.000000000 +0000 @@ -64,6 +64,4 @@ { "stats", CTLTYPE_STRUCT }, \ } -extern struct icmpstat icmpstat; - #endif Index: qemu/slirp/if.c =================================================================== --- qemu.orig/slirp/if.c 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/if.c 2007-10-22 20:13:17.000000000 +0000 @@ -7,61 +7,39 @@ #include <slirp.h> -int if_mtu, if_mru; -int if_comp; -int if_maxlinkhdr; -int if_queued = 0; /* Number of packets queued so far */ -int if_thresh = 10; /* Number of packets queued before we start sending - * (to prevent allocing too many mbufs) */ - -struct mbuf if_fastq; /* fast queue (for interactive data) */ -struct mbuf if_batchq; /* queue for non-interactive data */ -struct mbuf *next_m; /* Pointer to next mbuf to output */ -#define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm)) +static void ifs_init(struct mbuf *ifm) +{ + ifs_set_next(ifm, ifm); + ifs_set_prev(ifm, ifm); +} -void -ifs_insque(ifm, ifmhead) - struct mbuf *ifm, *ifmhead; +static void ifs_insque(struct mbuf *ifm, struct mbuf *ifmhead) { - ifm->ifs_next = ifmhead->ifs_next; - ifmhead->ifs_next = ifm; - ifm->ifs_prev = ifmhead; - ifm->ifs_next->ifs_prev = ifm; + ifs_set_next(ifm, ifs_get_next(ifmhead)); + ifs_set_next(ifmhead, ifm); + ifs_set_prev(ifm, ifmhead); + ifs_set_prev(ifs_get_next(ifm), ifm); } -void -ifs_remque(ifm) - struct mbuf *ifm; +static void ifs_remque(struct mbuf *ifm) { - ifm->ifs_prev->ifs_next = ifm->ifs_next; - ifm->ifs_next->ifs_prev = ifm->ifs_prev; + ifs_set_next(ifs_get_prev(ifm), ifs_get_next(ifm)); + ifs_set_prev(ifs_get_next(ifm), ifs_get_prev(ifm)); } void -if_init() +if_init(slirp_state_t *s) { -#if 0 - /* - * Set if_maxlinkhdr to 48 because it's 40 bytes for TCP/IP, - * and 8 bytes for PPP, but need to have it on an 8byte boundary - */ -#ifdef USE_PPP - if_maxlinkhdr = 48; -#else - if_maxlinkhdr = 40; -#endif -#else - /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */ - if_maxlinkhdr = 2 + 14 + 40; -#endif - if_mtu = 1500; - if_mru = 1500; - if_comp = IF_AUTOCOMP; - if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq; - if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq; + s->if_queued = 0; + s->if_thresh = 10; + s->if_comp = IF_AUTOCOMP; + ifq_set_next(&s->if_fastq, &s->if_fastq); + ifq_set_prev(&s->if_fastq, &s->if_fastq); + ifq_set_next(&s->if_batchq, &s->if_batchq); + ifq_set_prev(&s->if_batchq, &s->if_batchq); // sl_compress_init(&comp_s); - next_m = &if_batchq; + s->next_m = &s->if_batchq; } #if 0 @@ -118,7 +96,7 @@ if (if_n <= 0) { if (if_n == 0 || (errno != EINTR && errno != EAGAIN)) { if (ttyp->up) - link_up--; + s->link_up--; tty_detached(ttyp, 0); } return; @@ -157,9 +135,7 @@ * it'll temporarily get downgraded to the batchq) */ void -if_output(so, ifm) - struct socket *so; - struct mbuf *ifm; +if_output(slirp_state_t *s, struct socket *so, struct mbuf *ifm) { struct mbuf *ifq; int on_fastq = 1; @@ -174,7 +150,7 @@ * XXX Shouldn't need this, gotta change dtom() etc. */ if (ifm->m_flags & M_USEDLIST) { - remque(ifm); + remque(s, ifm); ifm->m_flags &= ~M_USEDLIST; } @@ -185,18 +161,18 @@ * We mustn't put this packet back on the fastq (or we'll send it out of order) * XXX add cache here? */ - for (ifq = if_batchq.ifq_prev; ifq != &if_batchq; ifq = ifq->ifq_prev) { + for (ifq = ifq_get_prev(&s->if_batchq); ifq != &s->if_batchq; ifq = ifq_get_prev(ifq)) { if (so == ifq->ifq_so) { /* A match! */ ifm->ifq_so = so; - ifs_insque(ifm, ifq->ifs_prev); + ifs_insque(ifm, ifs_get_prev(ifq)); goto diddit; } } /* No match, check which queue to put it on */ if (so && (so->so_iptos & IPTOS_LOWDELAY)) { - ifq = if_fastq.ifq_prev; + ifq = ifq_get_prev(&s->if_fastq); on_fastq = 1; /* * Check if this packet is a part of the last @@ -204,19 +180,19 @@ */ if (ifq->ifq_so == so) { ifm->ifq_so = so; - ifs_insque(ifm, ifq->ifs_prev); + ifs_insque(ifm, ifs_get_prev(ifq)); goto diddit; } } else - ifq = if_batchq.ifq_prev; + ifq = ifq_get_prev(&s->if_batchq); /* Create a new doubly linked list for this session */ ifm->ifq_so = so; ifs_init(ifm); - insque(ifm, ifq); + insque(s, ifm, ifq); diddit: - ++if_queued; + ++s->if_queued; if (so) { /* Update *_queued */ @@ -233,10 +209,10 @@ (so->so_nqueued - so->so_queued) >= 3)) { /* Remove from current queue... */ - remque(ifm->ifs_next); + remque(s, ifs_get_next(ifm)); /* ...And insert in the new. That'll teach ya! */ - insque(ifm->ifs_next, &if_batchq); + insque(s, ifs_get_next(ifm), &s->if_batchq); } } @@ -244,9 +220,9 @@ /* * This prevents us from malloc()ing too many mbufs */ - if (link_up) { + if (s->link_up) { /* if_start will check towrite */ - if_start(); + if_start(s); } #endif } @@ -264,44 +240,44 @@ * to the first, etc. etc. */ void -if_start(void) +if_start(slirp_state_t *s) { struct mbuf *ifm, *ifqt; DEBUG_CALL("if_start"); - if (if_queued == 0) + if (s->if_queued == 0) return; /* Nothing to do */ again: /* check if we can really output */ - if (!slirp_can_output()) + if (!slirp_can_output(s->user)) return; /* * See which queue to get next packet from * If there's something in the fastq, select it immediately */ - if (if_fastq.ifq_next != &if_fastq) { - ifm = if_fastq.ifq_next; + if (ifq_get_next(&s->if_fastq) != &s->if_fastq) { + ifm = ifq_get_next(&s->if_fastq); } else { /* Nothing on fastq, see if next_m is valid */ - if (next_m != &if_batchq) - ifm = next_m; + if (s->next_m != &s->if_batchq) + ifm = s->next_m; else - ifm = if_batchq.ifq_next; + ifm = ifq_get_next(&s->if_batchq); /* Set which packet to send on next iteration */ - next_m = ifm->ifq_next; + s->next_m = ifq_get_next(ifm); } /* Remove it from the queue */ - ifqt = ifm->ifq_prev; - remque(ifm); - --if_queued; + ifqt = ifq_get_prev(ifm); + remque(s, ifm); + --s->if_queued; /* If there are more packets for this session, re-queue them */ - if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) { - insque(ifm->ifs_next, ifqt); + if (ifs_get_next(ifm) != /* ifm->ifs_prev != */ ifm) { + insque(s, ifs_get_next(ifm), ifqt); ifs_remque(ifm); } @@ -313,10 +289,10 @@ } /* Encapsulate the packet for sending */ - if_encap(ifm->m_data, ifm->m_len); + if_encap(s, (const uint8_t *)ifm->m_data, ifm->m_len); - m_free(ifm); + m_free(s, ifm); - if (if_queued) + if (s->if_queued) goto again; } Index: qemu/slirp/if.h =================================================================== --- qemu.orig/slirp/if.h 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/if.h 2007-10-21 18:47:11.000000000 +0000 @@ -13,22 +13,6 @@ #define IF_AUTOCOMP 0x04 /* Autodetect (default) */ #define IF_NOCIDCOMP 0x08 /* CID compression */ -/* Needed for FreeBSD */ -#undef if_mtu -extern int if_mtu; -extern int if_mru; /* MTU and MRU */ -extern int if_comp; /* Flags for compression */ -extern int if_maxlinkhdr; -extern int if_queued; /* Number of packets queued so far */ -extern int if_thresh; /* Number of packets queued before we start sending - * (to prevent allocing too many mbufs) */ - -extern struct mbuf if_fastq; /* fast queue (for interactive data) */ -extern struct mbuf if_batchq; /* queue for non-interactive data */ -extern struct mbuf *next_m; - -#define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm)) - /* Interface statistics */ struct slirp_ifstats { u_int out_pkts; /* Output packets */ Index: qemu/slirp/ip.h =================================================================== --- qemu.orig/slirp/ip.h 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/ip.h 2007-10-22 17:49:21.000000000 +0000 @@ -37,6 +37,8 @@ #ifndef _IP_H_ #define _IP_H_ +#include "mbuf.h" + #ifdef WORDS_BIGENDIAN # ifndef NTOHL # define NTOHL(d) @@ -213,6 +215,50 @@ struct in_addr ih_dst; /* destination internet address */ }; +#if 0 +static inline struct ipovly *ih_get_next(slirp_state_t *s, struct ipovly *ih) +{ + return (struct ipovly *)(unsigned long)ih->ih_next; +} + +static inline struct ipovly *ih_get_prev(slirp_state_t *s, struct ipovly *ih) +{ + return (struct ipovly *)(unsigned long)ih->ih_prev; +} + +static inline void ih_set_next(slirp_state_t *s, struct ipovly *ih, struct ipovly *next) +{ + ih->ih_next = (caddr32_t)(unsigned long)next; +} + +static inline void ih_set_prev(slirp_state_t *s, struct ipovly *ih, struct ipovly *prev) +{ + ih->ih_prev = (caddr32_t)(unsigned long)prev; +} +#else +static inline struct ipovly *ih_get_next(slirp_state_t *s, struct ipovly *ih) +{ + return mtod(dtom(s, ih)->m_hdr.next_ip, struct ipovly *); +} + +static inline struct ipovly *ih_get_prev(slirp_state_t *s, struct ipovly *ih) +{ + return mtod(dtom(s, ih)->m_hdr.prev_ip, struct ipovly *); +} + +static inline void ih_set_next(slirp_state_t *s, struct ipovly *ih, struct ipovly *next) +{ + ih->ih_next = (caddr32_t)(unsigned long)next; + dtom(s, ih)->m_hdr.next_ip = dtom(s, next); +} + +static inline void ih_set_prev(slirp_state_t *s, struct ipovly *ih, struct ipovly *prev) +{ + ih->ih_prev = (caddr32_t)(unsigned long)prev; + dtom(s, ih)->m_hdr.prev_ip = dtom(s, prev); +} +#endif + /* * Ip reassembly queue structure. Each fragment * being reassembled is attached to one of these structures. @@ -221,15 +267,109 @@ * size 28 bytes */ struct ipq { - ipqp_32 next,prev; /* to other reass headers */ + ipqp_32 ipq_r_next, ipq_r_prev; /* to other reass headers */ u_int8_t ipq_ttl; /* time for reass q to live */ u_int8_t ipq_p; /* protocol of this fragment */ u_int16_t ipq_id; /* sequence id for reassembly */ - ipasfragp_32 ipq_next,ipq_prev; + ipasfragp_32 ipq_next_frag, ipq_prev_frag; /* to ip headers of fragments */ - struct in_addr ipq_src,ipq_dst; + struct in_addr ipq_src, ipq_dst; }; +#if 1 +static inline struct ipq *ipq_get_next(slirp_state_t *s, struct ipq *ipq) +{ + return (struct ipq *)(unsigned long)ipq->ipq_r_next; +} + +static inline struct ipq *ipq_get_prev(slirp_state_t *s, struct ipq *ipq) +{ + return (struct ipq *)(unsigned long)ipq->ipq_r_prev; +} + +static inline void ipq_set_next(slirp_state_t *s, struct ipq *ipq, struct ipq *next) +{ + ipq->ipq_r_next = (ipqp_32)(unsigned long)next; +} + +static inline void ipq_set_prev(slirp_state_t *s, struct ipq *ipq, struct ipq *prev) +{ + ipq->ipq_r_prev = (ipqp_32)(unsigned long)prev; +} + +static inline struct ipasfrag *ipq_get_next_frag(slirp_state_t *s, struct ipq *ipq) +{ + return (struct ipasfrag *)(unsigned long)ipq->ipq_next_frag; +} + +static inline struct ipasfrag *ipq_get_prev_frag(slirp_state_t *s, struct ipq *ipq) +{ + return (struct ipasfrag *)(unsigned long)ipq->ipq_prev_frag; +} + +static inline void ipq_set_next_frag(slirp_state_t *s, struct ipq *ipq, struct ipasfrag *next) +{ + ipq->ipq_next_frag = (ipasfragp_32)(unsigned long)next; +} + +static inline void ipq_set_prev_frag(slirp_state_t *s, struct ipq *ipq, struct ipasfrag *prev) +{ + ipq->ipq_prev_frag = (ipasfragp_32)(unsigned long)prev; +} +#else +static inline struct ipq *ipq_get_next(slirp_state_t *s, struct ipq *ipq) +{ + fprintf(stderr, "%s: ipq %p m %p\n", __func__, ipq, dtom(s, ipq)); + return mtod(dtom(s, ipq)->m_hdr.next_ip, struct ipq *); +} + +static inline struct ipq *ipq_get_prev(slirp_state_t *s, struct ipq *ipq) +{ + fprintf(stderr, "%s: ipq %p m %p\n", __func__, ipq, dtom(s, ipq)); + return mtod(dtom(s, ipq)->m_hdr.prev_ip, struct ipq *); +} + +static inline void ipq_set_next(slirp_state_t *s, struct ipq *ipq, struct ipq *next) +{ + fprintf(stderr, "%s: ipq %p m %p next %p\n", __func__, ipq, dtom(s, ipq), next); + ipq->ipq_r_next = (ipqp_32)(unsigned long)next; + dtom(s, ipq)->m_hdr.next_ip = dtom(s, next); +} + +static inline void ipq_set_prev(slirp_state_t *s, struct ipq *ipq, struct ipq *prev) +{ + fprintf(stderr, "%s: ipq %p m %p next %p\n", __func__, ipq, dtom(s, ipq), prev); + ipq->ipq_r_prev = (ipqp_32)(unsigned long)prev; + dtom(s, ipq)->m_hdr.prev_ip = dtom(s, prev); +} + +static inline struct ipasfrag *ipq_get_next_frag(slirp_state_t *s, struct ipq *ipq) +{ + fprintf(stderr, "%s: ipq %p m %p\n", __func__, ipq, dtom(s, ipq)); + return mtod(dtom(s, ipq)->m_hdr.next_frag, struct ipasfrag *); +} + +static inline struct ipasfrag *ipq_get_prev_frag(slirp_state_t *s, struct ipq *ipq) +{ + fprintf(stderr, "%s: ipq %p m %p\n", __func__, ipq, dtom(s, ipq)); + return mtod(dtom(s, ipq)->m_hdr.prev_frag, struct ipasfrag *); +} + +static inline void ipq_set_next_frag(slirp_state_t *s, struct ipq *ipq, struct ipasfrag *next) +{ + fprintf(stderr, "%s: ipq %p m %p next %p\n", __func__, ipq, dtom(s, ipq), next); + ipq->ipq_next_frag = (ipasfragp_32)(unsigned long)next; + dtom(s, ipq)->m_hdr.next_frag = dtom(s, next); +} + +static inline void ipq_set_prev_frag(slirp_state_t *s, struct ipq *ipq, struct ipasfrag *prev) +{ + fprintf(stderr, "%s: ipq %p m %p next %p\n", __func__, ipq, dtom(s, ipq), prev); + ipq->ipq_prev_frag = (ipasfragp_32)(unsigned long)prev; + dtom(s, ipq)->m_hdr.prev_frag = dtom(s, prev); +} +#endif + /* * Ip header, when holding a fragment. * @@ -255,10 +395,56 @@ u_int8_t ip_ttl; u_int8_t ip_p; u_int16_t ip_sum; - ipasfragp_32 ipf_next; /* next fragment */ - ipasfragp_32 ipf_prev; /* previous fragment */ + ipasfragp_32 ipf_next_frag; /* next fragment */ + ipasfragp_32 ipf_prev_frag; /* previous fragment */ }; - +#if 1 +static inline struct ipasfrag *ipasfrag_get_next_frag(struct ipasfrag *ipasfrag) +{ + return (struct ipasfrag *)(unsigned long)ipasfrag->ipf_next_frag; +} + +static inline struct ipasfrag *ipasfrag_get_prev_frag(struct ipasfrag *ipasfrag) +{ + return (struct ipasfrag *)(unsigned long)ipasfrag->ipf_prev_frag; +} + +static inline void ipasfrag_set_next_frag(struct ipasfrag *ipasfrag, struct ipasfrag *next) +{ + ipasfrag->ipf_next_frag = (ipasfragp_32)(unsigned long)next; +} + +static inline void ipasfrag_set_prev_frag(struct ipasfrag *ipasfrag, struct ipasfrag *prev) +{ + ipasfrag->ipf_prev_frag = (ipasfragp_32)(unsigned long)prev; +} +#else +static inline struct ipasfrag *ipasfrag_get_next_frag(slirp_state_t *s, struct ipasfrag *ipasfrag) +{ + fprintf(stderr, "%s: ipasfrag %p m %p\n", __func__, ipasfrag, dtom(s, ipasfrag)); + return mtod(dtom(s, ipasfrag)->m_hdr.next_frag, struct ipasfrag *); +} + +static inline struct ipasfrag *ipasfrag_get_prev_frag(slirp_state_t *s, struct ipasfrag *ipasfrag) +{ + fprintf(stderr, "%s: ipasfrag %p m %p\n", __func__, ipasfrag, dtom(s, ipasfrag)); + return mtod(dtom(s, ipasfrag)->m_hdr.prev_frag, struct ipasfrag *); +} + +static inline void ipasfrag_set_next_frag(slirp_state_t *s, struct ipasfrag *ipasfrag, struct ipasfrag *next) +{ + fprintf(stderr, "%s: ipasfrag %p m %p next %p\n", __func__, ipasfrag, dtom(s, ipasfrag), next); + ipasfrag->ipf_next_frag = (ipasfragp_32)(unsigned long)next; + dtom(s, ipasfrag)->m_hdr.next_frag = dtom(s, next); +} + +static inline void ipasfrag_set_prev_frag(slirp_state_t *s, struct ipasfrag *ipasfrag, struct ipasfrag *prev) +{ + fprintf(stderr, "%s: ipasfrag %p m %p next %p\n", __func__, ipasfrag, dtom(s, ipasfrag), prev); + ipasfrag->ipf_prev_frag = (ipasfragp_32)(unsigned long)prev; + dtom(s, ipasfrag)->m_hdr.prev_frag = dtom(s, prev); +} +#endif /* * Structure stored in mbuf in inpcb.ip_options * and passed to ip_output when ip options are in use. @@ -305,9 +491,5 @@ u_long ips_unaligned; /* times the ip packet was not aligned */ }; -extern struct ipstat ipstat; -extern struct ipq ipq; /* ip reass. queue */ -extern u_int16_t ip_id; /* ip packet ctr, for ids */ -extern int ip_defttl; /* default IP ttl */ #endif Index: qemu/slirp/ip_icmp.c =================================================================== --- qemu.orig/slirp/ip_icmp.c 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/ip_icmp.c 2007-10-21 18:47:16.000000000 +0000 @@ -37,14 +37,13 @@ #include "slirp.h" #include "ip_icmp.h" -struct icmpstat icmpstat; /* The message sent when emulating PING */ -/* Be nice and tell them it's just a psuedo-ping packet */ -char icmp_ping_msg[] = "This is a psuedo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n"; +/* Be nice and tell them it's just a pseudo-ping packet */ +static const char icmp_ping_msg[] = "This is a pseudo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n"; /* list of actions for icmp_error() on RX of an icmp message */ -static int icmp_flush[19] = { +static const int icmp_flush[19] = { /* ECHO REPLY (0) */ 0, 1, 1, @@ -70,9 +69,7 @@ * Process a received ICMP message. */ void -icmp_input(m, hlen) - struct mbuf *m; - int hlen; +icmp_input(slirp_state_t *s, struct mbuf *m, int hlen) { register struct icmp *icp; register struct ip *ip=mtod(m, struct ip *); @@ -83,16 +80,16 @@ DEBUG_ARG("m = %lx", (long )m); DEBUG_ARG("m_len = %d", m->m_len); - icmpstat.icps_received++; + STAT(s->icmpstat.icps_received++); /* * Locate icmp structure in mbuf, and check * that its not corrupted and of at least minimum length. */ if (icmplen < ICMP_MINLEN) { /* min 8 bytes payload */ - icmpstat.icps_tooshort++; + STAT(s->icmpstat.icps_tooshort++); freeit: - m_freem(m); + m_freem(s, m); goto end_error; } @@ -100,7 +97,7 @@ m->m_data += hlen; icp = mtod(m, struct icmp *); if (cksum(m, icmplen)) { - icmpstat.icps_checksum++; + STAT(s->icmpstat.icps_checksum++); goto freeit; } m->m_len += hlen; @@ -114,17 +111,17 @@ case ICMP_ECHO: icp->icmp_type = ICMP_ECHOREPLY; ip->ip_len += hlen; /* since ip_input subtracts this */ - if (ip->ip_dst.s_addr == alias_addr.s_addr) { - icmp_reflect(m); + if (ip->ip_dst.s_addr == s->alias_addr.s_addr) { + icmp_reflect(s, m); } else { struct socket *so; struct sockaddr_in addr; if ((so = socreate()) == NULL) goto freeit; - if(udp_attach(so) == -1) { + if(udp_attach(s, so) == -1) { DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n", errno,strerror(errno))); - sofree(so); - m_free(m); + sofree(s, so); + m_free(s, m); goto end_error; } so->so_m = m; @@ -138,15 +135,15 @@ /* Send the packet */ addr.sin_family = AF_INET; - if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) { + if ((so->so_faddr.s_addr & htonl(0xffffff00)) == s->special_addr.s_addr) { /* It's an alias */ switch(ntohl(so->so_faddr.s_addr) & 0xff) { case CTL_DNS: - addr.sin_addr = dns_addr; + addr.sin_addr = s->dns_addr; break; case CTL_ALIAS: default: - addr.sin_addr = loopback_addr; + addr.sin_addr = s->loopback_addr; break; } } else { @@ -157,8 +154,8 @@ (struct sockaddr *)&addr, sizeof(addr)) == -1) { DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n", errno,strerror(errno))); - icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); - udp_detach(so); + icmp_error(s, m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); + udp_detach(s, so); } } /* if ip->ip_dst.s_addr == alias_addr.s_addr */ break; @@ -170,13 +167,13 @@ case ICMP_TSTAMP: case ICMP_MASKREQ: case ICMP_REDIRECT: - icmpstat.icps_notsupp++; - m_freem(m); + STAT(s->icmpstat.icps_notsupp++); + m_freem(s, m); break; default: - icmpstat.icps_badtype++; - m_freem(m); + STAT(s->icmpstat.icps_badtype++); + m_freem(s, m); } /* swith */ end_error: @@ -204,13 +201,8 @@ */ #define ICMP_MAXDATALEN (IP_MSS-28) -void -icmp_error(msrc, type, code, minsize, message) - struct mbuf *msrc; - u_char type; - u_char code; - int minsize; - char *message; +void icmp_error(slirp_state_t *s, struct mbuf *msrc, u_char type, u_char code, + int minsize, const char *message) { unsigned hlen, shlen, s_ip_len; register struct ip *ip; @@ -247,10 +239,13 @@ } /* make a copy */ - if(!(m=m_get())) goto end_error; /* get mbuf */ + if (!(m = m_get(s))) + goto end_error; /* get mbuf */ + { int new_m_size; new_m_size=sizeof(struct ip )+ICMP_MINLEN+msrc->m_len+ICMP_MAXDATALEN; - if(new_m_size>m->m_size) m_inc(m, new_m_size); + if (new_m_size > m->m_size) + m_inc(m, new_m_size); } memcpy(m->m_data, msrc->m_data, msrc->m_len); m->m_len = msrc->m_len; /* copy msrc to m */ @@ -310,11 +305,11 @@ ip->ip_ttl = MAXTTL; ip->ip_p = IPPROTO_ICMP; ip->ip_dst = ip->ip_src; /* ip adresses */ - ip->ip_src = alias_addr; + ip->ip_src = s->alias_addr; - (void ) ip_output((struct socket *)NULL, m); + (void ) ip_output(s, (struct socket *)NULL, m); - icmpstat.icps_reflect++; + STAT(s->icmpstat.icps_reflect++); end_error: return; @@ -325,8 +320,7 @@ * Reflect the ip packet back to the source */ void -icmp_reflect(m) - struct mbuf *m; +icmp_reflect(slirp_state_t *s, struct mbuf *m) { register struct ip *ip = mtod(m, struct ip *); int hlen = ip->ip_hl << 2; @@ -369,7 +363,7 @@ ip->ip_src = icmp_dst; } - (void ) ip_output((struct socket *)NULL, m); + (void ) ip_output(s, (struct socket *)NULL, m); - icmpstat.icps_reflect++; + STAT(s->icmpstat.icps_reflect++); } Index: qemu/slirp/ip_icmp.h =================================================================== --- qemu.orig/slirp/ip_icmp.h 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/ip_icmp.h 2007-10-21 18:47:11.000000000 +0000 @@ -157,8 +157,9 @@ (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) -void icmp_input _P((struct mbuf *, int)); -void icmp_error _P((struct mbuf *, u_char, u_char, int, char *)); -void icmp_reflect _P((struct mbuf *)); +void icmp_input(slirp_state_t *s, struct mbuf *m, int hlen); +void icmp_error(slirp_state_t *s, struct mbuf *msrc, u_char type, u_char code, + int minsize, const char *message); +void icmp_reflect(slirp_state_t *s, struct mbuf *m); #endif Index: qemu/slirp/ip_input.c =================================================================== --- qemu.orig/slirp/ip_input.c 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/ip_input.c 2007-10-22 17:32:35.000000000 +0000 @@ -45,22 +45,31 @@ #include <slirp.h> #include "ip_icmp.h" -int ip_defttl; -struct ipstat ipstat; -struct ipq ipq; + +static struct ip *ip_reass(slirp_state_t *s, register struct ipasfrag *ip, + register struct ipq *fp); +static void ip_freef(slirp_state_t *s, struct ipq *fp); +static void ip_enq(slirp_state_t *s, register struct ipasfrag *p, + register struct ipasfrag *prev); +static void ip_deq(slirp_state_t *s, register struct ipasfrag *p); /* * IP initialization: fill in IP protocol switch table. * All protocols not implemented in kernel go to raw IP protocol handler. */ void -ip_init() +ip_init(slirp_state_t *s) { - ipq.next = ipq.prev = (ipqp_32)&ipq; - ip_id = tt.tv_sec & 0xffff; - udp_init(); - tcp_init(); - ip_defttl = IPDEFTTL; +#if 0 + ipq_set_next(s, &s->ipq, &s->ipq); + ipq_set_prev(s, &s->ipq, &s->ipq); +#else + s->ipq.ipq_r_next = &s->ipq; + s->ipq.ipq_r_prev = &s->ipq; +#endif + s->ip_id = s->tt.tv_sec & 0xffff; + udp_init(s); + tcp_init(s); } /* @@ -68,8 +77,7 @@ * try to reassemble. Process options. Pass to next level. */ void -ip_input(m) - struct mbuf *m; +ip_input(slirp_state_t *s, struct mbuf *m) { register struct ip *ip; int hlen; @@ -78,23 +86,23 @@ DEBUG_ARG("m = %lx", (long)m); DEBUG_ARG("m_len = %d", m->m_len); - ipstat.ips_total++; + STAT(s->ipstat.ips_total++); if (m->m_len < sizeof (struct ip)) { - ipstat.ips_toosmall++; + STAT(s->ipstat.ips_toosmall++); return; } ip = mtod(m, struct ip *); if (ip->ip_v != IPVERSION) { - ipstat.ips_badvers++; + STAT(s->ipstat.ips_badvers++); goto bad; } hlen = ip->ip_hl << 2; if (hlen<sizeof(struct ip ) || hlen>m->m_len) {/* min header length */ - ipstat.ips_badhlen++; /* or packet too short */ + STAT(s->ipstat.ips_badhlen++); /* or packet too short */ goto bad; } @@ -103,7 +111,7 @@ * if (ip->ip_sum) { */ if(cksum(m,hlen)) { - ipstat.ips_badsum++; + STAT(s->ipstat.ips_badsum++); goto bad; } @@ -112,7 +120,7 @@ */ NTOHS(ip->ip_len); if (ip->ip_len < hlen) { - ipstat.ips_badlen++; + STAT(s->ipstat.ips_badlen++); goto bad; } NTOHS(ip->ip_id); @@ -125,7 +133,7 @@ * Drop packet if shorter than we expect. */ if (m->m_len < ip->ip_len) { - ipstat.ips_tooshort++; + STAT(s->ipstat.ips_tooshort++); goto bad; } /* Should drop packet if mbuf too long? hmmm... */ @@ -134,7 +142,7 @@ /* check ip_ttl for a correct ICMP reply */ if(ip->ip_ttl==0 || ip->ip_ttl==1) { - icmp_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl"); + icmp_error(s, m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl"); goto bad; } @@ -163,8 +171,8 @@ * Look for queue of fragments * of this datagram. */ - for (fp = (struct ipq *) ipq.next; fp != &ipq; - fp = (struct ipq *) fp->next) + for (fp = ipq_get_next(s, &s->ipq); fp != &s->ipq; + fp = ipq_get_next(s, fp)) if (ip->ip_id == fp->ipq_id && ip->ip_src.s_addr == fp->ipq_src.s_addr && ip->ip_dst.s_addr == fp->ipq_dst.s_addr && @@ -192,15 +200,15 @@ * attempt reassembly; if it succeeds, proceed. */ if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) { - ipstat.ips_fragments++; - ip = ip_reass((struct ipasfrag *)ip, fp); + STAT(s->ipstat.ips_fragments++); + ip = ip_reass(s, (struct ipasfrag *)ip, fp); if (ip == 0) return; - ipstat.ips_reassembled++; - m = dtom(ip); + STAT(s->ipstat.ips_reassembled++); + m = dtom(s, ip); } else if (fp) - ip_freef(fp); + ip_freef(s, fp); } else ip->ip_len -= hlen; @@ -208,24 +216,24 @@ /* * Switch out to protocol's input routine. */ - ipstat.ips_delivered++; + STAT(s->ipstat.ips_delivered++); switch (ip->ip_p) { case IPPROTO_TCP: - tcp_input(m, hlen, (struct socket *)NULL); + tcp_input(s, m, hlen, (struct socket *)NULL); break; case IPPROTO_UDP: - udp_input(m, hlen); + udp_input(s, m, hlen); break; case IPPROTO_ICMP: - icmp_input(m, hlen); + icmp_input(s, m, hlen); break; default: - ipstat.ips_noproto++; - m_free(m); + STAT(s->ipstat.ips_noproto++); + m_free(s, m); } return; bad: - m_freem(m); + m_freem(s, m); return; } @@ -235,12 +243,11 @@ * reassembly of this datagram already exists, then it * is given as fp; otherwise have to make a chain. */ -struct ip * -ip_reass(ip, fp) - register struct ipasfrag *ip; - register struct ipq *fp; +static struct ip * +ip_reass(slirp_state_t *s, register struct ipasfrag *ip, + register struct ipq *fp) { - register struct mbuf *m = dtom(ip); + register struct mbuf *m = dtom(s, ip); register struct ipasfrag *q; int hlen = ip->ip_hl << 2; int i, next; @@ -263,13 +270,15 @@ */ if (fp == 0) { struct mbuf *t; - if ((t = m_get()) == NULL) goto dropfrag; + if ((t = m_get(s)) == NULL) + goto dropfrag; fp = mtod(t, struct ipq *); - insque_32(fp, &ipq); + insque_32(s, fp, &s->ipq); fp->ipq_ttl = IPFRAGTTL; fp->ipq_p = ip->ip_p; fp->ipq_id = ip->ip_id; - fp->ipq_next = fp->ipq_prev = (ipasfragp_32)fp; + ipq_set_next_frag(s, fp, (struct ipasfrag *)fp); + ipq_set_prev_frag(s, fp, (struct ipasfrag *)fp); fp->ipq_src = ((struct ip *)ip)->ip_src; fp->ipq_dst = ((struct ip *)ip)->ip_dst; q = (struct ipasfrag *)fp; @@ -279,8 +288,8 @@ /* * Find a segment which begins after this one does. */ - for (q = (struct ipasfrag *)fp->ipq_next; q != (struct ipasfrag *)fp; - q = (struct ipasfrag *)q->ipf_next) + for (q = ipq_get_next_frag(s, fp); q != (struct ipasfrag *)fp; + q = ipq_get_next_frag(s, (struct ipq *)q)) if (q->ip_off > ip->ip_off) break; @@ -289,13 +298,13 @@ * our data already. If so, drop the data from the incoming * segment. If it provides all of our data, drop us. */ - if (q->ipf_prev != (ipasfragp_32)fp) { - i = ((struct ipasfrag *)(q->ipf_prev))->ip_off + - ((struct ipasfrag *)(q->ipf_prev))->ip_len - ip->ip_off; + if (ipasfrag_get_prev_frag(q) != (struct ipasfrag *)fp) { + i = ipasfrag_get_prev_frag(q)->ip_off + + ipasfrag_get_prev_frag(q)->ip_len - ip->ip_off; if (i > 0) { if (i >= ip->ip_len) goto dropfrag; - m_adj(dtom(ip), i); + m_adj(dtom(s, ip), i); ip->ip_off += i; ip->ip_len -= i; } @@ -310,12 +319,12 @@ if (i < q->ip_len) { q->ip_len -= i; q->ip_off += i; - m_adj(dtom(q), i); + m_adj(dtom(s, q), i); break; } - q = (struct ipasfrag *) q->ipf_next; - m_freem(dtom((struct ipasfrag *) q->ipf_prev)); - ip_deq((struct ipasfrag *) q->ipf_prev); + q = ipasfrag_get_next_frag(q); + m_freem(s, dtom(s, ipasfrag_get_prev_frag(q))); + ip_deq(s, ipasfrag_get_prev_frag(q)); } insert: @@ -323,29 +332,29 @@ * Stick new segment in its place; * check for complete reassembly. */ - ip_enq(ip, (struct ipasfrag *) q->ipf_prev); + ip_enq(s, ip, ipasfrag_get_prev_frag(q)); next = 0; - for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp; - q = (struct ipasfrag *) q->ipf_next) { + for (q = ipq_get_next_frag(s, fp); q != (struct ipasfrag *)fp; + q = ipq_get_next_frag(s, (struct ipq *)q)) { if (q->ip_off != next) return (0); next += q->ip_len; } - if (((struct ipasfrag *)(q->ipf_prev))->ipf_mff & 1) + if (ipasfrag_get_prev_frag(q)->ipf_mff & 1) return (0); /* * Reassembly is complete; concatenate fragments. */ - q = (struct ipasfrag *) fp->ipq_next; - m = dtom(q); + q = ipq_get_next_frag(s, fp); + m = dtom(s, q); - q = (struct ipasfrag *) q->ipf_next; + q = ipq_get_next_frag(s, (struct ipq *)q); while (q != (struct ipasfrag *)fp) { struct mbuf *t; - t = dtom(q); - q = (struct ipasfrag *) q->ipf_next; - m_cat(m, t); + t = dtom(s, q); + q = ipq_get_next_frag(s, (struct ipq *)q); + m_cat(s, m, t); } /* @@ -354,7 +363,7 @@ * dequeue and discard fragment reassembly header. * Make header visible. */ - ip = (struct ipasfrag *) fp->ipq_next; + ip = ipq_get_next_frag(s, fp); /* * If the fragments concatenated to an mbuf that's @@ -376,17 +385,17 @@ ip->ipf_mff &= ~1; ((struct ip *)ip)->ip_src = fp->ipq_src; ((struct ip *)ip)->ip_dst = fp->ipq_dst; - remque_32(fp); - (void) m_free(dtom(fp)); - m = dtom(ip); + remque_32(s, fp); + (void) m_free(s, dtom(s, fp)); + m = dtom(s, ip); m->m_len += (ip->ip_hl << 2); m->m_data -= (ip->ip_hl << 2); return ((struct ip *)ip); dropfrag: - ipstat.ips_fragdropped++; - m_freem(m); + STAT(s->ipstat.ips_fragdropped++); + m_freem(s, m); return (0); } @@ -394,47 +403,45 @@ * Free a fragment reassembly header and all * associated datagrams. */ -void -ip_freef(fp) - struct ipq *fp; +static void +ip_freef(slirp_state_t *s, struct ipq *fp) { register struct ipasfrag *q, *p; - for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp; + for (q = ipq_get_next_frag(s, fp); q != (struct ipasfrag *)fp; q = p) { - p = (struct ipasfrag *) q->ipf_next; - ip_deq(q); - m_freem(dtom(q)); + p = ipasfrag_get_next_frag(q); + ip_deq(s, q); + m_freem(s, dtom(s, q)); } - remque_32(fp); - (void) m_free(dtom(fp)); + remque_32(s, fp); + (void) m_free(s, dtom(s, fp)); } /* * Put an ip fragment on a reassembly chain. * Like insque, but pointers in middle of structure. */ -void -ip_enq(p, prev) - register struct ipasfrag *p, *prev; +static void +ip_enq(slirp_state_t *s, register struct ipasfrag *p, + register struct ipasfrag *prev) { DEBUG_CALL("ip_enq"); DEBUG_ARG("prev = %lx", (long)prev); - p->ipf_prev = (ipasfragp_32) prev; - p->ipf_next = prev->ipf_next; - ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = (ipasfragp_32) p; - prev->ipf_next = (ipasfragp_32) p; + ipasfrag_set_prev_frag(p, prev); + ipasfrag_set_next_frag(p, ipasfrag_get_next_frag(prev)); + ipasfrag_set_prev_frag(ipasfrag_get_next_frag(prev), p); + ipasfrag_set_next_frag(prev, p); } /* * To ip_enq as remque is to insque. */ -void -ip_deq(p) - register struct ipasfrag *p; +static void +ip_deq(slirp_state_t *s, register struct ipasfrag *p) { - ((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next; - ((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev; + ipasfrag_set_next_frag(ipasfrag_get_prev_frag(p), ipasfrag_get_next_frag(p)); + ipasfrag_set_prev_frag(ipasfrag_get_next_frag(p), ipasfrag_get_prev_frag(p)); } /* @@ -443,22 +450,22 @@ * queue, discard it. */ void -ip_slowtimo() +ip_slowtimo(slirp_state_t *s) { register struct ipq *fp; DEBUG_CALL("ip_slowtimo"); - fp = (struct ipq *) ipq.next; + fp = ipq_get_next(s, &s->ipq); if (fp == 0) return; - while (fp != &ipq) { + while (fp != &s->ipq) { --fp->ipq_ttl; - fp = (struct ipq *) fp->next; - if (((struct ipq *)(fp->prev))->ipq_ttl == 0) { - ipstat.ips_fragtimeout++; - ip_freef((struct ipq *) fp->prev); + fp = ipq_get_next(s, fp); + if (ipq_get_prev(s, fp)->ipq_ttl == 0) { + STAT(s->ipstat.ips_fragtimeout++); + ip_freef(s, ipq_get_prev(s, fp)); } } } @@ -664,7 +671,7 @@ /* Not yet */ icmp_error(m, type, code, 0, 0); - ipstat.ips_badoptions++; + STAT(s->ipstat.ips_badoptions++); return (1); } Index: qemu/slirp/ip_output.c =================================================================== --- qemu.orig/slirp/ip_output.c 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/ip_output.c 2007-10-22 19:35:12.000000000 +0000 @@ -44,7 +44,6 @@ #include <slirp.h> -u_int16_t ip_id; /* * IP output. The packet in mbuf chain m contains a skeletal IP @@ -53,9 +52,7 @@ * The mbuf opt, if present, will not be freed. */ int -ip_output(so, m0) - struct socket *so; - struct mbuf *m0; +ip_output(slirp_state_t *s, struct socket *so, struct mbuf *m0) { register struct ip *ip; register struct mbuf *m = m0; @@ -78,16 +75,16 @@ */ ip->ip_v = IPVERSION; ip->ip_off &= IP_DF; - ip->ip_id = htons(ip_id++); + ip->ip_id = htons(s->ip_id++); ip->ip_hl = hlen >> 2; - ipstat.ips_localout++; + STAT(s->ipstat.ips_localout++); /* * Verify that we have any chance at all of being able to queue * the packet or packet fragments */ /* XXX Hmmm... */ -/* if (if_queued > if_thresh && towrite <= 0) { +/* if (s->if_queued > s->if_thresh && towrite <= 0) { * error = ENOBUFS; * goto bad; * } @@ -96,13 +93,13 @@ /* * If small enough for interface, can just send directly. */ - if ((u_int16_t)ip->ip_len <= if_mtu) { + if ((u_int16_t)ip->ip_len <= IF_MTU) { ip->ip_len = htons((u_int16_t)ip->ip_len); ip->ip_off = htons((u_int16_t)ip->ip_off); ip->ip_sum = 0; ip->ip_sum = cksum(m, hlen); - if_output(so, m); + if_output(s, so, m); goto done; } @@ -112,11 +109,11 @@ */ if (ip->ip_off & IP_DF) { error = -1; - ipstat.ips_cantfrag++; + STAT(s->ipstat.ips_cantfrag++); goto bad; } - len = (if_mtu - hlen) &~ 7; /* ip databytes per packet */ + len = (IF_MTU - hlen) &~ 7; /* ip databytes per packet */ if (len < 8) { error = -1; goto bad; @@ -124,7 +121,7 @@ { int mhlen, firstlen = len; - struct mbuf **mnext = &m->m_nextpkt; + struct mbuf **mnext = m_get_nextpktaddr(m); /* * Loop through length of segment after first fragment, @@ -134,13 +131,13 @@ mhlen = sizeof (struct ip); for (off = hlen + len; off < (u_int16_t)ip->ip_len; off += len) { register struct ip *mhip; - m = m_get(); + m = m_get(s); if (m == 0) { error = -1; - ipstat.ips_odropped++; + STAT(s->ipstat.ips_odropped++); goto sendorfree; } - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; mhip = mtod(m, struct ip *); *mhip = *ip; @@ -169,8 +166,8 @@ mhip->ip_sum = 0; mhip->ip_sum = cksum(m, mhlen); *mnext = m; - mnext = &m->m_nextpkt; - ipstat.ips_ofragments++; + mnext = m_get_nextpktaddr(m); + STAT(s->ipstat.ips_ofragments++); } /* * Update first fragment by trimming what's been copied out @@ -184,22 +181,22 @@ ip->ip_sum = cksum(m, hlen); sendorfree: for (m = m0; m; m = m0) { - m0 = m->m_nextpkt; - m->m_nextpkt = 0; + m0 = m_get_nextpkt(m); + m_set_nextpkt(m, 0); if (error == 0) - if_output(so, m); + if_output(s, so, m); else - m_freem(m); + m_freem(s, m); } if (error == 0) - ipstat.ips_fragmented++; + STAT(s->ipstat.ips_fragmented++); } done: return (error); bad: - m_freem(m0); + m_freem(s, m0); goto done; } Index: qemu/slirp/libslirp.h =================================================================== --- qemu.orig/slirp/libslirp.h 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/libslirp.h 2007-10-21 18:47:11.000000000 +0000 @@ -5,26 +5,32 @@ extern "C" { #endif -void slirp_init(void); +typedef struct slirp_state_t slirp_state_t; -void slirp_select_fill(int *pnfds, +slirp_state_t *slirp_init(void *user, const char *slirp_hostname, + const char *tftp_prefix, const char *network); +void slirp_term(slirp_state_t *s); +void slirp_link_up(slirp_state_t *s); +void slirp_link_down(slirp_state_t *s); + +void slirp_select_fill(slirp_state_t *s, int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds); -void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds); +void slirp_select_poll(slirp_state_t *s, fd_set *readfds, fd_set *writefds, + fd_set *xfds); -void slirp_input(const uint8_t *pkt, int pkt_len); +void slirp_input(slirp_state_t *s, const uint8_t *pkt, int pkt_len); /* you must provide the following functions: */ -int slirp_can_output(void); -void slirp_output(const uint8_t *pkt, int pkt_len); +int slirp_can_output(void *user); +void slirp_output(void *user, const uint8_t *pkt, int pkt_len); -int slirp_redir(int is_udp, int host_port, +int slirp_redir(slirp_state_t *s, int is_udp, int host_port, struct in_addr guest_addr, int guest_port); -int slirp_add_exec(int do_pty, const char *args, int addr_low_byte, - int guest_port); +int slirp_add_exec(slirp_state_t *s, int do_pty, const char *args, + int addr_low_byte, int guest_port); -extern const char *tftp_prefix; -extern char slirp_hostname[33]; +void slirp_stats(slirp_state_t *s); #ifdef __cplusplus } Index: qemu/slirp/main.h =================================================================== --- qemu.orig/slirp/main.h 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/main.h 2007-10-21 18:47:11.000000000 +0000 @@ -11,14 +11,6 @@ #define TOWRITEMAX 512 -extern struct timeval tt; -extern int link_up; -extern int slirp_socket; -extern int slirp_socket_unit; -extern int slirp_socket_port; -extern u_int32_t slirp_socket_addr; -extern char *slirp_socket_passwd; -extern int ctty_closed; /* * Get the difference in 2 times from updtim() @@ -28,27 +20,10 @@ */ #define TIME_DIFF(x,y) (x)-(y) < 0 ? ~0-(y)+(x) : (x)-(y) -extern char *slirp_tty; -extern char *exec_shell; -extern u_int curtime; -extern fd_set *global_readfds, *global_writefds, *global_xfds; -extern struct in_addr ctl_addr; -extern struct in_addr special_addr; -extern struct in_addr alias_addr; -extern struct in_addr our_addr; -extern struct in_addr loopback_addr; -extern struct in_addr dns_addr; -extern char *username; -extern char *socket_path; -extern int towrite_max; -extern int ppp_exit; -extern int so_options; -extern int tcp_keepintvl; -extern uint8_t client_ethaddr[6]; #define PROTO_SLIP 0x1 #ifdef USE_PPP #define PROTO_PPP 0x2 #endif -void if_encap(const uint8_t *ip_data, int ip_data_len); +void if_encap(slirp_state_t *s, const uint8_t *ip_data, int ip_data_len); Index: qemu/slirp/mbuf.c =================================================================== --- qemu.orig/slirp/mbuf.c 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/mbuf.c 2007-10-22 20:25:32.000000000 +0000 @@ -17,31 +17,21 @@ #include <slirp.h> -struct mbuf *mbutl; -char *mclrefcnt; -int mbuf_alloced = 0; -struct mbuf m_freelist, m_usedlist; -int mbuf_thresh = 30; -int mbuf_max = 0; -int msize; -void -m_init() -{ - m_freelist.m_next = m_freelist.m_prev = &m_freelist; - m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist; - msize_init(); -} +/* + * Find a nice value for msize + * XXX if_maxlinkhdr already in mtu + */ +#define MSIZE (IF_MTU + IF_MAXLINKHDR + sizeof(struct m_hdr ) + 6) void -msize_init() +m_init(slirp_state_t *s) { - /* - * Find a nice value for msize - * XXX if_maxlinkhdr already in mtu - */ - msize = (if_mtu>if_mru?if_mtu:if_mru) + - if_maxlinkhdr + sizeof(struct m_hdr ) + 6; + m_set_next(&s->m_freelist, &s->m_freelist); + m_set_prev(&s->m_freelist, &s->m_freelist); + m_set_next(&s->m_usedlist, &s->m_usedlist); + m_set_prev(&s->m_usedlist, &s->m_usedlist); + s->mbuf_alloced = 0; } /* @@ -53,44 +43,46 @@ * which tells m_free to actually free() it */ struct mbuf * -m_get() +m_get(slirp_state_t *s) { register struct mbuf *m; int flags = 0; DEBUG_CALL("m_get"); - if (m_freelist.m_next == &m_freelist) { - m = (struct mbuf *)malloc(msize); - if (m == NULL) goto end_error; - mbuf_alloced++; - if (mbuf_alloced > mbuf_thresh) + if (m_get_next(&s->m_freelist) == &s->m_freelist) { + m = (struct mbuf *)malloc(MSIZE); + if (m == NULL) + goto end_error; + s->mbuf_alloced++; + if (s->mbuf_alloced > MBUF_THRESH) flags = M_DOFREE; - if (mbuf_alloced > mbuf_max) - mbuf_max = mbuf_alloced; + if (s->mbuf_alloced > s->mbuf_max) + s->mbuf_max = s->mbuf_alloced; } else { - m = m_freelist.m_next; - remque(m); + m = m_get_next(&s->m_freelist); + remque(s, m); } /* Insert it in the used list */ - insque(m,&m_usedlist); + insque(s, m, &s->m_usedlist); m->m_flags = (flags | M_USEDLIST); /* Initialise it */ - m->m_size = msize - sizeof(struct m_hdr); + m->m_size = MSIZE - sizeof(struct m_hdr); m->m_data = m->m_dat; m->m_len = 0; - m->m_nextpkt = 0; - m->m_prevpkt = 0; + m_set_nextpkt(m, 0); + m_set_prevpkt(m, 0); + m->m_hdr.next_ip = m->m_hdr.prev_ip = NULL; + m->m_hdr.next_frag = m->m_hdr.prev_frag = NULL; end_error: DEBUG_ARG("m = %lx", (long )m); return m; } void -m_free(m) - struct mbuf *m; +m_free(slirp_state_t *s, struct mbuf *m) { DEBUG_CALL("m_free"); @@ -99,7 +91,7 @@ if(m) { /* Remove from m_usedlist */ if (m->m_flags & M_USEDLIST) - remque(m); + remque(s, m); /* If it's M_EXT, free() it */ if (m->m_flags & M_EXT) @@ -110,9 +102,9 @@ */ if (m->m_flags & M_DOFREE) { free(m); - mbuf_alloced--; + s->mbuf_alloced--; } else if ((m->m_flags & M_FREELIST) == 0) { - insque(m,&m_freelist); + insque(s, m, &s->m_freelist); m->m_flags = M_FREELIST; /* Clobber other flags */ } } /* if(m) */ @@ -124,8 +116,7 @@ * an M_EXT data segment */ void -m_cat(m, n) - register struct mbuf *m, *n; +m_cat(slirp_state_t *s, register struct mbuf *m, register struct mbuf *n) { /* * If there's no room, realloc @@ -136,7 +127,7 @@ memcpy(m->m_data+m->m_len, n->m_data, n->m_len); m->m_len += n->m_len; - m_free(n); + m_free(s, n); } @@ -220,8 +211,7 @@ * Fortunately, it's not used often */ struct mbuf * -dtom(dat) - void *dat; +dtom(slirp_state_t *s, void *dat) { struct mbuf *m; @@ -229,7 +219,7 @@ DEBUG_ARG("dat = %lx", (long )dat); /* bug corrected for M_EXT buffers */ - for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next) { + for (m = m_get_next(&s->m_usedlist); m != &s->m_usedlist; m = m_get_next(m)) { if (m->m_flags & M_EXT) { if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) ) return m; Index: qemu/slirp/mbuf.h =================================================================== --- qemu.orig/slirp/mbuf.h 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/mbuf.h 2007-10-22 15:06:17.000000000 +0000 @@ -61,15 +61,18 @@ /* XXX should union some of these! */ /* header at beginning of each mbuf: */ struct m_hdr { - struct mbuf *mh_next; /* Linked list of mbufs */ - struct mbuf *mh_prev; - struct mbuf *mh_nextpkt; /* Next packet in queue/record */ - struct mbuf *mh_prevpkt; /* Flags aren't used in the output queue */ + struct mbuf *_mh_next; /* Linked list of mbufs */ + struct mbuf *_mh_prev; + struct mbuf *_mh_nextpkt; /* Next packet in queue/record */ + struct mbuf *_mh_prevpkt; /* Flags aren't used in the output queue */ int mh_flags; /* Misc flags */ int mh_size; /* Size of data */ struct socket *mh_so; + struct mbuf *next_ip, *prev_ip; + struct mbuf *next_frag, *prev_frag; + caddr_t mh_data; /* Location of data */ int mh_len; /* Amount of data in this mbuf */ }; @@ -96,10 +99,51 @@ } M_dat; }; -#define m_next m_hdr.mh_next -#define m_prev m_hdr.mh_prev -#define m_nextpkt m_hdr.mh_nextpkt -#define m_prevpkt m_hdr.mh_prevpkt +static inline struct mbuf *m_get_next(struct mbuf *m) +{ + return m->m_hdr._mh_next; +} + +static inline struct mbuf *m_get_prev(struct mbuf *m) +{ + return m->m_hdr._mh_prev; +} + +static inline void m_set_next(struct mbuf *m, struct mbuf *next) +{ + m->m_hdr._mh_next = next; +} + +static inline void m_set_prev(struct mbuf *m, struct mbuf *prev) +{ + m->m_hdr._mh_prev = prev; +} + +static inline struct mbuf *m_get_nextpkt(struct mbuf *m) +{ + return m->m_hdr._mh_nextpkt; +} + +static inline struct mbuf **m_get_nextpktaddr(struct mbuf *m) +{ + return &m->m_hdr._mh_nextpkt; +} + +static inline struct mbuf *m_get_prevpkt(struct mbuf *m) +{ + return m->m_hdr._mh_prevpkt; +} + +static inline void m_set_nextpkt(struct mbuf *m, struct mbuf *next) +{ + m->m_hdr._mh_nextpkt = next; +} + +static inline void m_set_prevpkt(struct mbuf *m, struct mbuf *prev) +{ + m->m_hdr._mh_prevpkt = prev; +} + #define m_flags m_hdr.mh_flags #define m_len m_hdr.mh_len #define m_data m_hdr.mh_data @@ -108,10 +152,16 @@ #define m_ext M_dat.m_ext_ #define m_so m_hdr.mh_so -#define ifq_prev m_prev -#define ifq_next m_next -#define ifs_prev m_prevpkt -#define ifs_next m_nextpkt +#define ifq_get_prev(m) m_get_prev(m) +#define ifq_set_prev(m, prev) m_set_prev(m, prev) +#define ifq_get_next(m) m_get_next(m) +#define ifq_set_next(m, next) m_set_next(m, next) + +#define ifs_get_prev(m) m_get_prevpkt(m) +#define ifs_set_prev(m, prev) m_set_prevpkt(m, prev) +#define ifs_get_next(m) m_get_nextpkt(m) +#define ifs_set_next(m, next) m_set_nextpkt(m, next) + #define ifq_so m_so #define M_EXT 0x01 /* m_ext points to more (malloced) data */ @@ -120,28 +170,13 @@ #define M_DOFREE 0x08 /* when m_free is called on the mbuf, free() * it rather than putting it on the free list */ -/* - * Mbuf statistics. XXX - */ - -struct mbstat { - int mbs_alloced; /* Number of mbufs allocated */ - -}; - -extern struct mbstat mbstat; -extern int mbuf_alloced; -extern struct mbuf m_freelist, m_usedlist; -extern int mbuf_max; - -void m_init _P((void)); -void msize_init _P((void)); -struct mbuf * m_get _P((void)); -void m_free _P((struct mbuf *)); -void m_cat _P((register struct mbuf *, register struct mbuf *)); +void m_init(slirp_state_t *s); +struct mbuf *m_get(slirp_state_t *s); +void m_free(slirp_state_t *s, struct mbuf *m); +void m_cat(slirp_state_t *s, register struct mbuf *m, register struct mbuf *n); void m_inc _P((struct mbuf *, int)); void m_adj _P((struct mbuf *, int)); int m_copy _P((struct mbuf *, struct mbuf *, int, int)); -struct mbuf * dtom _P((void *)); +struct mbuf *dtom(slirp_state_t *s, void *dat); #endif Index: qemu/slirp/misc.c =================================================================== --- qemu.orig/slirp/misc.c 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/misc.c 2007-10-21 18:47:11.000000000 +0000 @@ -8,8 +8,6 @@ #define WANT_SYS_IOCTL_H #include <slirp.h> -u_int curtime, time_fasttimo, last_slowtimo, detach_time; -u_int detach_wait = 600000; /* 10 minutes */ #if 0 int x_port = -1; @@ -25,9 +23,9 @@ lprint("X Redir: X not being redirected.\r\n"); } else { lprint("X Redir: In sh/bash/zsh/etc. type: DISPLAY=%s:%d.%d; export DISPLAY\r\n", - inet_ntoa(our_addr), x_port, x_screen); + inet_ntoa(s->our_addr), x_port, x_screen); lprint("X Redir: In csh/tcsh/etc. type: setenv DISPLAY %s:%d.%d\r\n", - inet_ntoa(our_addr), x_port, x_screen); + inet_ntoa(s->our_addr), x_port, x_screen); if (x_display) lprint("X Redir: Redirecting to display %d\r\n", x_display); } @@ -85,7 +83,7 @@ * Get our IP address and put it in our_addr */ void -getouraddr() +getouraddr(slirp_state_t *s) { char buff[256]; struct hostent *he = NULL; @@ -93,9 +91,9 @@ if (gethostname(buff,256) == 0) he = gethostbyname(buff); if (he) - our_addr = *(struct in_addr *)he->h_addr; - if (our_addr.s_addr == 0) - our_addr.s_addr = loopback_addr.s_addr; + s->our_addr = *(struct in_addr *)he->h_addr; + if (s->our_addr.s_addr == 0) + s->our_addr.s_addr = s->loopback_addr.s_addr; } #if SIZEOF_CHAR_P == 8 @@ -105,27 +103,23 @@ u_int32_t qh_rlink; }; -inline void -insque_32(a, b) - void *a; - void *b; +void +insque_32(slirp_state_t *s, void *a, void *b) { register struct quehead_32 *element = (struct quehead_32 *) a; register struct quehead_32 *head = (struct quehead_32 *) b; element->qh_link = head->qh_link; - head->qh_link = (u_int32_t)element; - element->qh_rlink = (u_int32_t)head; - ((struct quehead_32 *)(element->qh_link))->qh_rlink - = (u_int32_t)element; + head->qh_link = (u_int32_t)(unsigned long)element; + element->qh_rlink = (u_int32_t)(unsigned long)head; + ((struct quehead_32 *)(unsigned long)(element->qh_link))->qh_rlink = (u_int32_t)(unsigned long)element; } -inline void -remque_32(a) - void *a; +void +remque_32(slirp_state_t *s, void *a) { register struct quehead_32 *element = (struct quehead_32 *) a; - ((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink; - ((struct quehead_32 *)(element->qh_rlink))->qh_link = element->qh_link; + ((struct quehead_32 *)(unsigned long)(element->qh_link))->qh_rlink = element->qh_rlink; + ((struct quehead_32 *)(unsigned long)(element->qh_rlink))->qh_link = element->qh_link; element->qh_rlink = 0; } @@ -136,9 +130,8 @@ struct quehead *qh_rlink; }; -inline void -insque(a, b) - void *a, *b; +void +insque(slirp_state_t *s, void *a, void *b) { register struct quehead *element = (struct quehead *) a; register struct quehead *head = (struct quehead *) b; @@ -149,9 +142,8 @@ = (struct quehead *)element; } -inline void -remque(a) - void *a; +void +remque(slirp_state_t *s, void *a) { register struct quehead *element = (struct quehead *) a; ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink; @@ -214,10 +206,7 @@ #ifdef _WIN32 int -fork_exec(so, ex, do_pty) - struct socket *so; - char *ex; - int do_pty; +fork_exec(slirp_state_t *s, struct socket *so, const char *ex, int do_pty) { /* not implemented */ return 0; @@ -225,6 +214,7 @@ #else +#if 0 int slirp_openpty(amaster, aslave) int *amaster, *aslave; @@ -289,6 +279,7 @@ return (-1); #endif } +#endif /* * XXX This is ugly @@ -302,23 +293,20 @@ * do_ptr = 2 Fork/exec using pty */ int -fork_exec(so, ex, do_pty) - struct socket *so; - char *ex; - int do_pty; +fork_exec(slirp_state_t *s, struct socket *so, const char *ex, int do_pty) { - int s; + int fd = -1; struct sockaddr_in addr; int addrlen = sizeof(addr); int opt; - int master; + int master = -1; char *argv[256]; #if 0 char buff[256]; #endif /* don't want to clobber the original */ char *bptr; - char *curarg; + const char *curarg; int c, i, ret; DEBUG_CALL("fork_exec"); @@ -327,20 +315,22 @@ DEBUG_ARG("do_pty = %lx", (long)do_pty); if (do_pty == 2) { - if (slirp_openpty(&master, &s) == -1) { +#if 0 + if (slirp_openpty(&master, &fd) == -1) { lprint("Error: openpty failed: %s\n", strerror(errno)); return 0; } +#endif } else { addr.sin_family = AF_INET; addr.sin_port = 0; addr.sin_addr.s_addr = INADDR_ANY; - if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 || - bind(s, (struct sockaddr *)&addr, addrlen) < 0 || - listen(s, 1) < 0) { + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0 || + bind(fd, (struct sockaddr *)&addr, addrlen) < 0 || + listen(fd, 1) < 0) { lprint("Error: inet socket: %s\n", strerror(errno)); - closesocket(s); + closesocket(fd); return 0; } @@ -349,7 +339,7 @@ switch(fork()) { case -1: lprint("Error: fork failed: %s\n", strerror(errno)); - close(s); + close(fd); if (do_pty == 2) close(master); return 0; @@ -360,38 +350,38 @@ (void) close(master); #ifdef TIOCSCTTY /* XXXXX */ (void) setsid(); - ioctl(s, TIOCSCTTY, (char *)NULL); + ioctl(fd, TIOCSCTTY, (char *)NULL); #endif } else { - getsockname(s, (struct sockaddr *)&addr, &addrlen); - close(s); + getsockname(fd, (struct sockaddr *)&addr, &addrlen); + close(fd); /* * Connect to the socket * XXX If any of these fail, we're in trouble! */ - s = socket(AF_INET, SOCK_STREAM, 0); - addr.sin_addr = loopback_addr; + fd = socket(AF_INET, SOCK_STREAM, 0); + addr.sin_addr = s->loopback_addr; do { - ret = connect(s, (struct sockaddr *)&addr, addrlen); + ret = connect(fd, (struct sockaddr *)&addr, addrlen); } while (ret < 0 && errno == EINTR); } #if 0 if (x_port >= 0) { #ifdef HAVE_SETENV - sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen); + sprintf(buff, "%s:%d.%d", inet_ntoa(s->our_addr), x_port, x_screen); setenv("DISPLAY", buff, 1); #else - sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen); + sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(s->our_addr), x_port, x_screen); putenv(buff); #endif } #endif - dup2(s, 0); - dup2(s, 1); - dup2(s, 2); - for (s = 3; s <= 255; s++) - close(s); + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + for (fd = getdtablesize() - 1; fd >= 3; fd--) + close(fd); i = 0; bptr = strdup(ex); /* No need to free() this */ @@ -427,7 +417,7 @@ default: if (do_pty == 2) { - close(s); + close(fd); so->s = master; } else { /* @@ -438,9 +428,9 @@ * of connect() fail in the child process */ do { - so->s = accept(s, (struct sockaddr *)&addr, &addrlen); + so->s = accept(fd, (struct sockaddr *)&addr, &addrlen); } while (so->s < 0 && errno == EINTR); - closesocket(s); + closesocket(fd); opt = 1; setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)); opt = 1; @@ -450,7 +440,7 @@ /* Append the telnet options now */ if (so->so_m != 0 && do_pty == 1) { - sbappend(so, so->so_m); + sbappend(s, so, so->so_m); so->so_m = 0; } @@ -603,6 +593,7 @@ } #endif +#if 0 int (*lprint_print) _P((void *, const char *, va_list)); char *lprint_ptr, *lprint_ptr2, **lprint_arg; @@ -754,6 +745,7 @@ lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport); } +#endif #ifdef BAD_SPRINTF @@ -908,10 +900,10 @@ /* Set the DISPLAY */ if (x_port >= 0) { #ifdef HAVE_SETENV - sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen); + sprintf(buff, "%s:%d.%d", inet_ntoa(s->our_addr), x_port, x_screen); setenv("DISPLAY", buff, 1); #else - sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen); + sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(s->our_addr), x_port, x_screen); putenv(buff); #endif } Index: qemu/slirp/misc.h =================================================================== --- qemu.orig/slirp/misc.h 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/misc.h 2007-10-21 18:56:23.000000000 +0000 @@ -12,17 +12,10 @@ int ex_pty; /* Do we want a pty? */ int ex_addr; /* The last byte of the address */ int ex_fport; /* Port to telnet to */ - char *ex_exec; /* Command line of what to exec */ + const char *ex_exec; /* Command line of what to exec */ struct ex_list *ex_next; }; -extern struct ex_list *exec_list; -extern u_int curtime, time_fasttimo, last_slowtimo, detach_time, detach_wait; - -extern int (*lprint_print) _P((void *, const char *, va_list)); -extern char *lprint_ptr, *lprint_ptr2, **lprint_arg; -extern struct sbuf *lprint_sb; - #ifndef HAVE_STRDUP char *strdup _P((const char *)); #endif @@ -69,12 +62,12 @@ int show_x _P((char *, struct socket *)); void redir_x _P((u_int32_t, int, int, int)); -void getouraddr _P((void)); -inline void slirp_insque _P((void *, void *)); -inline void slirp_remque _P((void *)); +void getouraddr(slirp_state_t *s); +void slirp_insque(slirp_state_t *s, void *a, void *b); +void slirp_remque(slirp_state_t *s, void *a); int add_exec _P((struct ex_list **, int, char *, int, int)); int slirp_openpty _P((int *, int *)); -int fork_exec _P((struct socket *, char *, int)); +int fork_exec(slirp_state_t *s, struct socket *so, const char *ex, int do_pty); void snooze_hup _P((int)); void snooze _P((void)); void relay _P((int)); Index: qemu/slirp/sbuf.c =================================================================== --- qemu.orig/slirp/sbuf.c 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/sbuf.c 2007-10-21 18:47:11.000000000 +0000 @@ -7,6 +7,8 @@ #include <slirp.h> +static void sbappendsb(struct sbuf *sb, struct mbuf *m); + /* Done as a macro in socket.h */ /* int * sbspace(struct sockbuff *sb) @@ -72,9 +74,7 @@ * (the socket is non-blocking, so we won't hang) */ void -sbappend(so, m) - struct socket *so; - struct mbuf *m; +sbappend(slirp_state_t *s, struct socket *so, struct mbuf *m) { int ret = 0; @@ -85,7 +85,7 @@ /* Shouldn't happen, but... e.g. foreign host closes connection */ if (m->m_len <= 0) { - m_free(m); + m_free(s, m); return; } @@ -96,7 +96,7 @@ */ if (so->so_urgc) { sbappendsb(&so->so_rcv, m); - m_free(m); + m_free(s, m); sosendoob(so); return; } @@ -126,17 +126,15 @@ sbappendsb(&so->so_rcv, m); } /* else */ /* Whatever happened, we free the mbuf */ - m_free(m); + m_free(s, m); } /* * Copy the data from m into sb * The caller is responsible to make sure there's enough room */ -void -sbappendsb(sb, m) - struct sbuf *sb; - struct mbuf *m; +static void +sbappendsb(struct sbuf *sb, struct mbuf *m) { int len, n, nn; Index: qemu/slirp/sbuf.h =================================================================== --- qemu.orig/slirp/sbuf.h 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/sbuf.h 2007-10-21 18:47:11.000000000 +0000 @@ -24,8 +24,7 @@ void sbfree _P((struct sbuf *)); void sbdrop _P((struct sbuf *, int)); void sbreserve _P((struct sbuf *, int)); -void sbappend _P((struct socket *, struct mbuf *)); -void sbappendsb _P((struct sbuf *, struct mbuf *)); +void sbappend(slirp_state_t *s, struct socket *so, struct mbuf *m); void sbcopy _P((struct sbuf *, int, int, char *)); #endif Index: qemu/slirp/slirp.c =================================================================== --- qemu.orig/slirp/slirp.c 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/slirp.c 2007-10-22 19:31:32.000000000 +0000 @@ -1,38 +1,14 @@ #include "slirp.h" -/* host address */ -struct in_addr our_addr; -/* host dns address */ -struct in_addr dns_addr; -/* host loopback address */ -struct in_addr loopback_addr; - -/* address for slirp virtual addresses */ -struct in_addr special_addr; -/* virtual address alias for host */ -struct in_addr alias_addr; - -const uint8_t special_ethaddr[6] = { +static const uint8_t special_ethaddr[6] = { 0x52, 0x54, 0x00, 0x12, 0x35, 0x00 }; -uint8_t client_ethaddr[6]; - -int do_slowtimo; -int link_up; -struct timeval tt; -FILE *lfd; -struct ex_list *exec_list; - -/* XXX: suppress those select globals */ -fd_set *global_readfds, *global_writefds, *global_xfds; - -char slirp_hostname[33]; - #ifdef _WIN32 -static int get_dns_addr(struct in_addr *pdns_addr) +static int get_dns_addr(slirp_state_t *s, struct in_addr *pdns_addr) { + int rc = 0; FIXED_INFO *FixedInfo=NULL; ULONG BufLen; DWORD ret; @@ -81,7 +57,7 @@ #else -static int get_dns_addr(struct in_addr *pdns_addr) +static int get_dns_addr(slirp_state_t *s, struct in_addr *pdns_addr) { char buff[512]; char buff2[256]; @@ -93,23 +69,25 @@ if (!f) return -1; - lprint("IP address of your DNS(s): "); + //lprint("IP address of your DNS(s): "); while (fgets(buff, 512, f) != NULL) { if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) { if (!inet_aton(buff2, &tmp_addr)) continue; - if (tmp_addr.s_addr == loopback_addr.s_addr) - tmp_addr = our_addr; + if (tmp_addr.s_addr == s->loopback_addr.s_addr) + tmp_addr = s->our_addr; /* If it's the first one, set it to dns_addr */ if (!found) *pdns_addr = tmp_addr; +#if 0 else lprint(", "); +#endif if (++found > 3) { - lprint("(more)"); + //lprint("(more)"); break; - } else - lprint("%s", inet_ntoa(tmp_addr)); + } // else + //lprint("%s", inet_ntoa(tmp_addr)); } } fclose(f); @@ -121,15 +99,24 @@ #endif #ifdef _WIN32 -void slirp_cleanup(void) +static void slirp_cleanup(void) { WSACleanup(); } #endif -void slirp_init(void) +slirp_state_t *slirp_init(void *user, const char *slirp_hostname, + const char *tftp_prefix, const char *network) { - // debug_init("/tmp/slirp.log", DEBUG_DEFAULT); + slirp_state_t *s; + + s = malloc(sizeof(slirp_state_t)); + if (!s) + return s; + memset(s, 0, sizeof(slirp_state_t)); + s->user = user; + s->slirp_hostname = slirp_hostname; + s->tftp_prefix = tftp_prefix; #ifdef _WIN32 { @@ -139,27 +126,73 @@ } #endif - link_up = 1; + s->link_up = 1; - if_init(); - ip_init(); + m_init(s); - /* Initialise mbufs *after* setting the MTU */ - m_init(); + if_init(s); + ip_init(s); /* set default addresses */ - inet_aton("127.0.0.1", &loopback_addr); + inet_aton("127.0.0.1", &s->loopback_addr); + inet_aton("127.0.0.1", &s->dns_addr); - if (get_dns_addr(&dns_addr) < 0) { - dns_addr = loopback_addr; + if (get_dns_addr(s, &s->dns_addr) < 0) { fprintf (stderr, "Warning: No DNS servers found\n"); } - inet_aton(CTL_SPECIAL, &special_addr); - alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS); - getouraddr(); + inet_aton(network, &s->special_addr); + s->alias_addr.s_addr = s->special_addr.s_addr | htonl(CTL_ALIAS); + getouraddr(s); + + return s; +} + +/** + * Marks the link as up, making it possible to establish new connections. + */ +void slirp_link_up(slirp_state_t *s) +{ + s->link_up = 1; } +/** + * Marks the link as down and cleans up the current connections. + */ +void slirp_link_down(slirp_state_t *s) +{ + struct socket *so; + + while ((so = s->tcb.so_next) != &s->tcb) + { + if (so->so_state & SS_NOFDREF || so->s == -1) + sofree(s, so); + else + tcp_drop(s, sototcpcb(so), 0); + } + + while ((so = s->udb.so_next) != &s->udb) + udp_detach(s, so); + + s->link_up = 0; +} + +/** + * Terminates the slirp component. + */ +void slirp_term(slirp_state_t *s) +{ + slirp_link_down(s); +#ifdef WIN32 + WSACleanup(); +#endif +#ifdef LOG_ENABLED + slirp_stats(s); +#endif + free(s); +} + + #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED) #define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED) #define UPD_NFDS(x) if (nfds < (x)) nfds = (x) @@ -168,28 +201,28 @@ * curtime kept to an accuracy of 1ms */ #ifdef _WIN32 -static void updtime(void) +static void updtime(slirp_state_t *s) { struct _timeb tb; _ftime(&tb); - curtime = (u_int)tb.time * (u_int)1000; - curtime += (u_int)tb.millitm; + s->curtime = (u_int)tb.time * (u_int)1000; + s->curtime += (u_int)tb.millitm; } #else -static void updtime(void) +static void updtime(slirp_state_t *s) { - gettimeofday(&tt, 0); + gettimeofday(&s->tt, 0); - curtime = (u_int)tt.tv_sec * (u_int)1000; - curtime += (u_int)tt.tv_usec / (u_int)1000; + s->curtime = (u_int)s->tt.tv_sec * (u_int)1000; + s->curtime += (u_int)s->tt.tv_usec / (u_int)1000; - if ((tt.tv_usec % 1000) >= 500) - curtime++; + if ((s->tt.tv_usec % 1000) >= 500) + s->curtime++; } #endif -void slirp_select_fill(int *pnfds, +void slirp_select_fill(slirp_state_t *s, int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds) { struct socket *so, *so_next; @@ -198,31 +231,31 @@ int tmp_time; /* fail safe */ - global_readfds = NULL; - global_writefds = NULL; - global_xfds = NULL; + s->readfds = NULL; + s->writefds = NULL; + s->xfds = NULL; nfds = *pnfds; /* * First, TCP sockets */ - do_slowtimo = 0; - if (link_up) { + s->do_slowtimo = 0; + if (s->link_up) { /* * *_slowtimo needs calling if there are IP fragments * in the fragment queue, or there are TCP connections active */ - do_slowtimo = ((tcb.so_next != &tcb) || - ((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next)); + s->do_slowtimo = ((s->tcb.so_next != &s->tcb) || + ((struct ipasfrag *)&s->ipq != (struct ipasfrag *)ipq_get_next(s, &s->ipq))); - for (so = tcb.so_next; so != &tcb; so = so_next) { + for (so = s->tcb.so_next; so != &s->tcb; so = so_next) { so_next = so->so_next; /* * See if we need a tcp_fasttimo */ - if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK) - time_fasttimo = curtime; /* Flag when we want a fasttimo */ + if (s->time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK) + s->time_fasttimo = s->curtime; /* Flag when we want a fasttimo */ /* * NOFDREF can include still connecting to local-host, @@ -272,18 +305,18 @@ /* * UDP sockets */ - for (so = udb.so_next; so != &udb; so = so_next) { + for (so = s->udb.so_next; so != &s->udb; so = so_next) { so_next = so->so_next; /* * See if it's timed out */ if (so->so_expire) { - if (so->so_expire <= curtime) { - udp_detach(so); + if (so->so_expire <= s->curtime) { + udp_detach(s, so); continue; } else - do_slowtimo = 1; /* Let socket expire */ + s->do_slowtimo = 1; /* Let socket expire */ } /* @@ -317,17 +350,17 @@ * slow timeout. If a fast timeout is needed, set timeout within * 200ms of when it was requested. */ - if (do_slowtimo) { + if (s->do_slowtimo) { /* XXX + 10000 because some select()'s aren't that accurate */ - timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000; + timeout.tv_usec = ((500 - (s->curtime - s->last_slowtimo)) * 1000) + 10000; if (timeout.tv_usec < 0) timeout.tv_usec = 0; else if (timeout.tv_usec > 510000) timeout.tv_usec = 510000; /* Can only fasttimo if we also slowtimo */ - if (time_fasttimo) { - tmp_time = (200 - (curtime - time_fasttimo)) * 1000; + if (s->time_fasttimo) { + tmp_time = (200 - (s->curtime - s->time_fasttimo)) * 1000; if (tmp_time < 0) tmp_time = 0; @@ -339,41 +372,41 @@ *pnfds = nfds; } -void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds) +void slirp_select_poll(slirp_state_t *s, fd_set *readfds, fd_set *writefds, fd_set *xfds) { struct socket *so, *so_next; int ret; - global_readfds = readfds; - global_writefds = writefds; - global_xfds = xfds; + s->readfds = readfds; + s->writefds = writefds; + s->xfds = xfds; /* Update time */ - updtime(); + updtime(s); /* * See if anything has timed out */ - if (link_up) { - if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) { - tcp_fasttimo(); - time_fasttimo = 0; + if (s->link_up) { + if (s->time_fasttimo && ((s->curtime - s->time_fasttimo) >= 2)) { + tcp_fasttimo(s); + s->time_fasttimo = 0; } - if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) { - ip_slowtimo(); - tcp_slowtimo(); - last_slowtimo = curtime; + if (s->do_slowtimo && ((s->curtime - s->last_slowtimo) >= 499)) { + ip_slowtimo(s); + tcp_slowtimo(s); + s->last_slowtimo = s->curtime; } } /* * Check sockets */ - if (link_up) { + if (s->link_up) { /* * Check TCP sockets */ - for (so = tcb.so_next; so != &tcb; so = so_next) { + for (so = s->tcb.so_next; so != &s->tcb; so = so_next) { so_next = so->so_next; /* @@ -389,7 +422,7 @@ * test for readfds below if this succeeds */ if (FD_ISSET(so->s, xfds)) - sorecvoob(so); + sorecvoob(s, so); /* * Check sockets for reading */ @@ -398,14 +431,14 @@ * Check for incoming connections */ if (so->so_state & SS_FACCEPTCONN) { - tcp_connect(so); + tcp_connect(s, so); continue; } /* else */ - ret = soread(so); + ret = soread(s, so); /* Output it if we read something */ if (ret > 0) - tcp_output(sototcpcb(so)); + tcp_output(s, sototcpcb(so)); } /* @@ -434,10 +467,10 @@ /* * Continue tcp_input */ - tcp_input((struct mbuf *)NULL, sizeof(struct ip), so); + tcp_input(s, (struct mbuf *)NULL, sizeof(struct ip), so); /* continue; */ } else - ret = sowrite(so); + ret = sowrite(s, so); /* * XXXXX If we wrote something (a lot), there * could be a need for a window update. @@ -487,11 +520,11 @@ * Incoming packets are sent straight away, they're not buffered. * Incoming UDP data isn't buffered either. */ - for (so = udb.so_next; so != &udb; so = so_next) { + for (so = s->udb.so_next; so != &s->udb; so = so_next) { so_next = so->so_next; if (so->s != -1 && FD_ISSET(so->s, readfds)) { - sorecvfrom(so); + sorecvfrom(s, so); } } } @@ -499,17 +532,17 @@ /* * See if we can start outputting */ - if (if_queued && link_up) - if_start(); + if (s->if_queued && s->link_up) + if_start(s); /* clear global file descriptor sets. * these reside on the stack in vl.c * so they're unusable if we're not in * slirp_select_fill or slirp_select_poll. */ - global_readfds = NULL; - global_writefds = NULL; - global_xfds = NULL; + s->readfds = NULL; + s->writefds = NULL; + s->xfds = NULL; } #define ETH_ALEN 6 @@ -545,7 +578,8 @@ unsigned char ar_tip[4]; /* target IP address */ }; -void arp_input(const uint8_t *pkt, int pkt_len) +static +void arp_input(slirp_state_t *s, const uint8_t *pkt, int pkt_len) { struct ethhdr *eh = (struct ethhdr *)pkt; struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN); @@ -558,17 +592,17 @@ ar_op = ntohs(ah->ar_op); switch(ar_op) { case ARPOP_REQUEST: - if (!memcmp(ah->ar_tip, &special_addr, 3)) { + if (!memcmp(ah->ar_tip, &s->special_addr, 3)) { if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS) goto arp_ok; - for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { + for (ex_ptr = s->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { if (ex_ptr->ex_addr == ah->ar_tip[3]) goto arp_ok; } return; arp_ok: /* XXX: make an ARP request to have the client address */ - memcpy(client_ethaddr, eh->h_source, ETH_ALEN); + memcpy(s->client_ethaddr, eh->h_source, ETH_ALEN); /* ARP request for alias/dns mac address */ memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN); @@ -585,7 +619,7 @@ memcpy(rah->ar_sip, ah->ar_tip, 4); memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN); memcpy(rah->ar_tip, ah->ar_sip, 4); - slirp_output(arp_reply, sizeof(arp_reply)); + slirp_output(s->user, arp_reply, sizeof(arp_reply)); } break; default: @@ -593,7 +627,7 @@ } } -void slirp_input(const uint8_t *pkt, int pkt_len) +void slirp_input(slirp_state_t *s, const uint8_t *pkt, int pkt_len) { struct mbuf *m; int proto; @@ -604,10 +638,14 @@ proto = ntohs(*(uint16_t *)(pkt + 12)); switch(proto) { case ETH_P_ARP: - arp_input(pkt, pkt_len); + arp_input(s, pkt, pkt_len); break; case ETH_P_IP: - m = m_get(); + /* Update time. Important if the network is very quiet, as otherwise + * the first outgoing connection gets an incorrect timestamp. */ + updtime(s); + + m = m_get(s); if (!m) return; /* Note: we add to align the IP header */ @@ -617,7 +655,7 @@ m->m_data += 2 + ETH_HLEN; m->m_len -= 2 + ETH_HLEN; - ip_input(m); + ip_input(s, m); break; default: break; @@ -625,7 +663,7 @@ } /* output the IP packet to the ethernet device */ -void if_encap(const uint8_t *ip_data, int ip_data_len) +void if_encap(slirp_state_t *s, const uint8_t *ip_data, int ip_data_len) { uint8_t buf[1600]; struct ethhdr *eh = (struct ethhdr *)buf; @@ -633,33 +671,33 @@ if (ip_data_len + ETH_HLEN > sizeof(buf)) return; - memcpy(eh->h_dest, client_ethaddr, ETH_ALEN); + memcpy(eh->h_dest, s->client_ethaddr, ETH_ALEN); memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1); /* XXX: not correct */ eh->h_source[5] = CTL_ALIAS; eh->h_proto = htons(ETH_P_IP); memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len); - slirp_output(buf, ip_data_len + ETH_HLEN); + slirp_output(s->user, buf, ip_data_len + ETH_HLEN); } -int slirp_redir(int is_udp, int host_port, +int slirp_redir(slirp_state_t *s, int is_udp, int host_port, struct in_addr guest_addr, int guest_port) { if (is_udp) { - if (!udp_listen(htons(host_port), guest_addr.s_addr, + if (!udp_listen(s, htons(host_port), guest_addr.s_addr, htons(guest_port), 0)) return -1; } else { - if (!solisten(htons(host_port), guest_addr.s_addr, + if (!solisten(s, htons(host_port), guest_addr.s_addr, htons(guest_port), 0)) return -1; } return 0; } -int slirp_add_exec(int do_pty, const char *args, int addr_low_byte, +int slirp_add_exec(slirp_state_t *s, int do_pty, const char *args, int addr_low_byte, int guest_port) { - return add_exec(&exec_list, do_pty, (char *)args, + return add_exec(&s->exec_list, do_pty, (char *)args, addr_low_byte, htons(guest_port)); } Index: qemu/slirp/slirp.h =================================================================== --- qemu.orig/slirp/slirp.h 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/slirp.h 2007-10-22 20:31:54.000000000 +0000 @@ -3,7 +3,16 @@ #define CONFIG_QEMU -#define DEBUG 1 +//#define DEBUG 1 + +// Uncomment the following line to enable SLIRP statistics printing in Qemu +//#define LOG_ENABLED + +#ifdef LOG_ENABLED +#define STAT(expr) expr +#else +#define STAT(expr) do { } while(0) +#endif #ifndef CONFIG_QEMU #include "version.h" @@ -190,6 +199,8 @@ #include <sys/stropts.h> #endif +#include "libslirp.h" + #include "debug.h" #include "ip.h" @@ -213,19 +224,134 @@ #include "bootp.h" #include "tftp.h" -#include "libslirp.h" -extern struct ttys *ttys_unit[MAX_INTERFACES]; +/** Number of DHCP clients supported by NAT. */ +#define NB_ADDR 16 + +/** Where to start DHCP IP number allocation. */ +#define START_ADDR 15 + +/** DHCP Lease time. */ +#define LEASE_TIME (24 * 3600) + +/** Entry in the table of known DHCP clients. */ +typedef struct { + int allocated; + uint8_t macaddr[6]; +} BOOTPClient; + + +/** TFTP session entry. */ +struct tftp_session { + int in_use; + unsigned char filename[TFTP_FILENAME_MAX]; + + struct in_addr client_ip; + u_int16_t client_port; + + int timestamp; +}; + + +/** Main state/configuration structure for slirp. */ +struct slirp_state_t +{ + /* Stuff from boot.c */ + BOOTPClient bootp_clients[NB_ADDR]; + const char *bootp_filename; + /* Stuff from if.c */ + int if_comp; + int if_queued; + int if_thresh; + struct mbuf if_fastq; + struct mbuf if_batchq; + struct mbuf *next_m; +#ifdef LOG_ENABLED + /* Stuff from icmp.c */ + struct icmpstat icmpstat; + /* Stuff from ip_input.c */ + struct ipstat ipstat; +#endif + struct ipq ipq; + uint16_t ip_id; + /* Stuff from mbuf.c */ + int mbuf_alloced, mbuf_max; + struct mbuf m_freelist, m_usedlist; + /* Stuff from slirp.c */ + fd_set *readfds, *writefds, *xfds; + const char *slirp_hostname; + void *user; + uint32_t curtime; + uint32_t time_fasttimo; + uint32_t last_slowtimo; + int do_slowtimo; + int link_up; + struct timeval tt; + struct in_addr our_addr; + struct in_addr alias_addr; + struct in_addr special_addr; + struct in_addr dns_addr; + struct in_addr loopback_addr; + uint8_t client_ethaddr[6]; + struct ex_list *exec_list; + /* Stuff from tcp_input.c */ + struct socket tcb; + struct socket *tcp_last_so; + tcp_seq tcp_iss; +#ifdef LOG_ENABLED + /* Stuff from tcp_timer.c */ + struct tcpstat tcpstat; +#endif + uint32_t tcp_now; + /* Stuff from tftp.c */ + struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX]; + const char *tftp_prefix; +#ifdef LOG_ENABLED + /* Stuff from udp.c */ + struct udpstat udpstat; +#endif + struct socket udb; + struct socket *udp_last_so; + // tcp_subr.c + int do_echo; +}; + +/** Number of permanent buffers in mbuf. */ +#define MBUF_THRESH 30 + +/** Default TCP socket options. */ +#define SO_OPTIONS DO_KEEPALIVE + +/** Enable RFC1323 performance enhancements. + * @todo check if it really works, it was turned off before. */ +#define TCP_DO_RFC1323 1 + +/* TCP duplicate ACK retransmit threshold. */ +#define TCPREXMTTHRESH 3 + +#define IF_MTU 1500 +#define IF_MRU 1500 + +#if 0 +/* + * Set if_maxlinkhdr to 48 because it's 40 bytes for TCP/IP, + * and 8 bytes for PPP, but need to have it on an 8byte boundary + */ +#ifdef USE_PPP +#define IF_MAXLINKHDR 48 +#else +#define IF_MAXLINKHDR 40 +#endif +#else + /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */ +#define IF_MAXLINKHDR (2 + 14 + 40) +#endif #ifndef NULL #define NULL (void *)0 #endif -#ifndef FULL_BOLT -void if_start _P((void)); -#else -void if_start _P((struct ttys *)); -#endif +void if_start(slirp_state_t *s); #ifdef BAD_SPRINTF # define vsprintf vsprintf_len @@ -253,16 +379,22 @@ long gethostid _P((void)); #endif -void lprint _P((const char *, ...)); - -extern int do_echo; +static inline void lprint(const char *format, ...) +{ +#ifdef LOG_ENABLED + va_list args; + va_start(args, format); + term_vprintf(format, args); + va_end(args); +#endif +} #if SIZEOF_CHAR_P == 4 # define insque_32 insque # define remque_32 remque #else - inline void insque_32 _P((void *, void *)); - inline void remque_32 _P((void *)); +void insque_32(slirp_state_t *s, void *a, void *b); +void remque_32(slirp_state_t *s, void *a); #endif #ifndef _WIN32 @@ -275,48 +407,41 @@ int cksum(struct mbuf *m, int len); /* if.c */ -void if_init _P((void)); -void if_output _P((struct socket *, struct mbuf *)); +void if_init(slirp_state_t *s); +void if_output(slirp_state_t *s, struct socket *so, struct mbuf *ifm); /* ip_input.c */ -void ip_init _P((void)); -void ip_input _P((struct mbuf *)); -struct ip * ip_reass _P((register struct ipasfrag *, register struct ipq *)); -void ip_freef _P((struct ipq *)); -void ip_enq _P((register struct ipasfrag *, register struct ipasfrag *)); -void ip_deq _P((register struct ipasfrag *)); -void ip_slowtimo _P((void)); +void ip_init(slirp_state_t *s); +void ip_input(slirp_state_t *s, struct mbuf *m); +void ip_slowtimo(slirp_state_t *s); void ip_stripoptions _P((register struct mbuf *, struct mbuf *)); /* ip_output.c */ -int ip_output _P((struct socket *, struct mbuf *)); +int ip_output(slirp_state_t *s, struct socket *so, struct mbuf *m0); /* tcp_input.c */ -int tcp_reass _P((register struct tcpcb *, register struct tcpiphdr *, struct mbuf *)); -void tcp_input _P((register struct mbuf *, int, struct socket *)); -void tcp_dooptions _P((struct tcpcb *, u_char *, int, struct tcpiphdr *)); -void tcp_xmit_timer _P((register struct tcpcb *, int)); -int tcp_mss _P((register struct tcpcb *, u_int)); +void tcp_input(slirp_state_t *s, register struct mbuf *m, int iphlen, struct socket *inso); +int tcp_mss(slirp_state_t *s, register struct tcpcb *tp, u_int offer); /* tcp_output.c */ -int tcp_output _P((register struct tcpcb *)); +int tcp_output(slirp_state_t *s, register struct tcpcb *tp); void tcp_setpersist _P((register struct tcpcb *)); /* tcp_subr.c */ -void tcp_init _P((void)); -void tcp_template _P((struct tcpcb *)); -void tcp_respond _P((struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int)); -struct tcpcb * tcp_newtcpcb _P((struct socket *)); -struct tcpcb * tcp_close _P((register struct tcpcb *)); -void tcp_drain _P((void)); -void tcp_sockclosed _P((struct tcpcb *)); -int tcp_fconnect _P((struct socket *)); -void tcp_connect _P((struct socket *)); -int tcp_attach _P((struct socket *)); +void tcp_init(slirp_state_t *s); +void tcp_template(slirp_state_t *s, struct tcpcb *tp); +void tcp_respond(slirp_state_t *s, struct tcpcb *tp, struct tcpiphdr *ti, + struct mbuf *m, tcp_seq ack, tcp_seq seq, int flags); +struct tcpcb *tcp_newtcpcb(slirp_state_t *s, struct socket *so); +struct tcpcb *tcp_close(slirp_state_t *s, register struct tcpcb *tp); +void tcp_sockclosed(slirp_state_t *s, struct tcpcb *tp); +int tcp_fconnect(slirp_state_t *s, struct socket *so); +void tcp_connect(slirp_state_t *s, struct socket *inso); +int tcp_attach(slirp_state_t *s, struct socket *so); u_int8_t tcp_tos _P((struct socket *)); -int tcp_emu _P((struct socket *, struct mbuf *)); -int tcp_ctl _P((struct socket *)); -struct tcpcb *tcp_drop(struct tcpcb *tp, int err); +int tcp_emu(slirp_state_t *s, struct socket *so, struct mbuf *m); +int tcp_ctl(slirp_state_t *s, struct socket *so); +struct tcpcb *tcp_drop(slirp_state_t *s, struct tcpcb *tp, int err); #ifdef USE_PPP #define MIN_MRU MINMRU Index: qemu/slirp/socket.c =================================================================== --- qemu.orig/slirp/socket.c 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/socket.c 2007-10-22 19:34:21.000000000 +0000 @@ -13,12 +13,16 @@ #include <sys/filio.h> #endif -void +static void sofcantrcvmore(slirp_state_t *s, struct socket *so); +static void sofcantsendmore(slirp_state_t *s, struct socket *so); + +#if 0 +static void so_init() { /* Nothing yet */ } - +#endif struct socket * solookup(head, laddr, lport, faddr, fport) @@ -67,22 +71,21 @@ * remque and free a socket, clobber cache */ void -sofree(so) - struct socket *so; +sofree(slirp_state_t *s, struct socket *so) { if (so->so_emu==EMU_RSH && so->extra) { - sofree(so->extra); + sofree(s, so->extra); so->extra=NULL; } - if (so == tcp_last_so) - tcp_last_so = &tcb; - else if (so == udp_last_so) - udp_last_so = &udb; + if (so == s->tcp_last_so) + s->tcp_last_so = &s->tcb; + else if (so == s->udp_last_so) + s->udp_last_so = &s->udb; - m_free(so->so_m); + m_free(s, so->so_m); if(so->so_next && so->so_prev) - remque(so); /* crashes if so is not in a queue */ + remque(s, so); /* crashes if so is not in a queue */ free(so); } @@ -93,8 +96,7 @@ * a read() of 0 (or less) means it's disconnected */ int -soread(so) - struct socket *so; +soread(slirp_state_t *s, struct socket *so) { int n, nn, lss, total; struct sbuf *sb = &so->so_snd; @@ -113,6 +115,8 @@ len = sb->sb_datalen - sb->sb_cc; iov[0].iov_base = sb->sb_wptr; + iov[1].iov_base = 0; + iov[1].iov_len = 0; if (sb->sb_wptr < sb->sb_rptr) { iov[0].iov_len = sb->sb_rptr - sb->sb_wptr; /* Should never succeed, but... */ @@ -162,8 +166,8 @@ return 0; else { DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno))); - sofcantrcvmore(so); - tcp_sockclosed(sototcpcb(so)); + sofcantrcvmore(s, so); + tcp_sockclosed(s, sototcpcb(so)); return -1; } } @@ -204,8 +208,7 @@ * in the send buffer is sent as urgent data */ void -sorecvoob(so) - struct socket *so; +sorecvoob(slirp_state_t *s, struct socket *so) { struct tcpcb *tp = sototcpcb(so); @@ -220,10 +223,10 @@ * urgent data, or the read() doesn't return all the * urgent data. */ - soread(so); + soread(s, so); tp->snd_up = tp->snd_una + so->so_snd.sb_cc; tp->t_force = 1; - tcp_output(tp); + tcp_output(s, tp); tp->t_force = 0; } @@ -291,8 +294,7 @@ * updating all sbuf field as necessary */ int -sowrite(so) - struct socket *so; +sowrite(slirp_state_t *s, struct socket *so) { int n,nn; struct sbuf *sb = &so->so_rcv; @@ -316,6 +318,8 @@ len = sb->sb_cc; iov[0].iov_base = sb->sb_rptr; + iov[1].iov_base = 0; + iov[1].iov_len = 0; if (sb->sb_rptr < sb->sb_wptr) { iov[0].iov_len = sb->sb_wptr - sb->sb_rptr; /* Should never succeed, but... */ @@ -349,8 +353,8 @@ if (nn <= 0) { DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n", so->so_state, errno)); - sofcantsendmore(so); - tcp_sockclosed(sototcpcb(so)); + sofcantsendmore(s, so); + tcp_sockclosed(s, sototcpcb(so)); return -1; } @@ -375,7 +379,7 @@ * it CANTSENDMORE */ if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0) - sofcantsendmore(so); + sofcantsendmore(s,so); return nn; } @@ -384,8 +388,7 @@ * recvfrom() a UDP socket */ void -sorecvfrom(so) - struct socket *so; +sorecvfrom(slirp_state_t *s, struct socket *so) { struct sockaddr_in addr; int addrlen = sizeof(struct sockaddr_in); @@ -409,19 +412,19 @@ DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n", errno,strerror(errno))); - icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno)); + icmp_error(s, so->so_m, ICMP_UNREACH,code, 0,strerror(errno)); } else { - icmp_reflect(so->so_m); + icmp_reflect(s, so->so_m); so->so_m = 0; /* Don't m_free() it again! */ } /* No need for this socket anymore, udp_detach it */ - udp_detach(so); + udp_detach(s, so); } else { /* A "normal" UDP packet */ struct mbuf *m; int len, n; - if (!(m = m_get())) return; - m->m_data += if_maxlinkhdr; + if (!(m = m_get(s))) return; + m->m_data += IF_MAXLINKHDR; /* * XXX Shouldn't FIONREAD packets destined for port 53, @@ -449,8 +452,8 @@ else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET; DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code)); - icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno)); - m_free(m); + icmp_error(s, so->so_m, ICMP_UNREACH,code, 0,strerror(errno)); + m_free(s, m); } else { /* * Hack: domain name lookup will be used the most for UDP, @@ -460,9 +463,9 @@ */ if (so->so_expire) { if (so->so_fport == htons(53)) - so->so_expire = curtime + SO_EXPIREFAST; + so->so_expire = s->curtime + SO_EXPIREFAST; else - so->so_expire = curtime + SO_EXPIRE; + so->so_expire = s->curtime + SO_EXPIRE; } /* if (m->m_len == len) { @@ -475,7 +478,7 @@ * If this packet was destined for CTL_ADDR, * make it look like that's where it came from, done by udp_output */ - udp_output(so, m, &addr); + udp_output(s, so, m, &addr); } /* rx error */ } /* if ping packet */ } @@ -484,9 +487,7 @@ * sendto() a socket */ int -sosendto(so, m) - struct socket *so; - struct mbuf *m; +sosendto(slirp_state_t *s, struct socket *so, struct mbuf *m) { int ret; struct sockaddr_in addr; @@ -496,15 +497,30 @@ DEBUG_ARG("m = %lx", (long)m); addr.sin_family = AF_INET; - if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) { + if ((so->so_faddr.s_addr & htonl(0xffffff00)) == s->special_addr.s_addr) { /* It's an alias */ switch(ntohl(so->so_faddr.s_addr) & 0xff) { + case CTL_BROADCAST: + addr.sin_addr.s_addr = INADDR_BROADCAST; +#if 0 + /* Send the packet to host to fully emulate broadcast */ + /** @todo r=klaus: on Linux host this causes the host to receive + * the packet twice for some reason. And I cannot find any place + * in the man pages which states that sending a broadcast does not + * reach the host itself. */ + host_addr.sin_family = AF_INET; + host_addr.sin_port = so->so_fport; + host_addr.sin_addr = s->our_addr; + sendto(so->s, m->m_data, m->m_len, 0, + (struct sockaddr *)&host_addr, sizeof (struct sockaddr)); +#endif + break; case CTL_DNS: - addr.sin_addr = dns_addr; + addr.sin_addr = s->dns_addr; break; case CTL_ALIAS: default: - addr.sin_addr = loopback_addr; + addr.sin_addr = s->loopback_addr; break; } } else @@ -524,7 +540,7 @@ * but only if it's an expirable socket */ if (so->so_expire) - so->so_expire = curtime + SO_EXPIRE; + so->so_expire = s->curtime + SO_EXPIRE; so->so_state = SS_ISFCONNECTED; /* So that it gets select()ed */ return 0; } @@ -533,15 +549,11 @@ * XXX This should really be tcp_listen */ struct socket * -solisten(port, laddr, lport, flags) - u_int port; - u_int32_t laddr; - u_int lport; - int flags; +solisten(slirp_state_t *s, u_int port, u_int32_t laddr, u_int lport, int flags) { struct sockaddr_in addr; struct socket *so; - int s, addrlen = sizeof(addr), opt = 1; + int fd, addrlen = sizeof(addr), opt = 1; DEBUG_CALL("solisten"); DEBUG_ARG("port = %d", port); @@ -555,11 +567,11 @@ } /* Don't tcp_attach... we don't need so_snd nor so_rcv */ - if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) { + if ((so->so_tcpcb = tcp_newtcpcb(s, so)) == NULL) { free(so); return NULL; } - insque(so,&tcb); + insque(s, so, &s->tcb); /* * SS_FACCEPTONCE sockets must time out. @@ -575,14 +587,14 @@ addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = port; - if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) || - (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) || - (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) || - (listen(s,1) < 0)) { + if (((fd = socket(AF_INET,SOCK_STREAM, 0)) < 0) || + (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int)) < 0) || + (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) || + (listen(fd ,1) < 0)) { int tmperrno = errno; /* Don't clobber the real reason we failed */ - close(s); - sofree(so); + close(fd); + sofree(s, so); /* Restore the real errno */ #ifdef _WIN32 WSASetLastError(tmperrno); @@ -591,25 +603,26 @@ #endif return NULL; } - setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); + setsockopt(fd, SOL_SOCKET,SO_OOBINLINE, (char *)&opt, sizeof(int)); - getsockname(s,(struct sockaddr *)&addr,&addrlen); + getsockname(fd, (struct sockaddr *)&addr, &addrlen); so->so_fport = addr.sin_port; - if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) - so->so_faddr = alias_addr; + if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == s->loopback_addr.s_addr) + so->so_faddr = s->alias_addr; else so->so_faddr = addr.sin_addr; - so->s = s; + so->s = fd; return so; } +#if 0 /* * Data is available in so_rcv * Just write() the data to the socket * XXX not yet... */ -void +static void sorwakeup(so) struct socket *so; { @@ -622,12 +635,13 @@ * We have room for a read() if we want to * For now, don't read, it'll be done in the main loop */ -void +static void sowwakeup(so) struct socket *so; { /* Nothing, yet */ } +#endif /* * Various session state calls @@ -652,14 +666,13 @@ so->so_state |= SS_ISFCONNECTED; /* Clobber other states */ } -void -sofcantrcvmore(so) - struct socket *so; +static void +sofcantrcvmore(slirp_state_t *s, struct socket *so) { if ((so->so_state & SS_NOFDREF) == 0) { shutdown(so->s,0); - if(global_writefds) { - FD_CLR(so->s,global_writefds); + if (s->writefds) { + FD_CLR(so->s, s->writefds); } } so->so_state &= ~(SS_ISFCONNECTING); @@ -669,17 +682,16 @@ so->so_state |= SS_FCANTRCVMORE; } -void -sofcantsendmore(so) - struct socket *so; +static void +sofcantsendmore(slirp_state_t *s, struct socket *so) { if ((so->so_state & SS_NOFDREF) == 0) { shutdown(so->s,1); /* send FIN to fhost */ - if (global_readfds) { - FD_CLR(so->s,global_readfds); + if (s->readfds) { + FD_CLR(so->s, s->readfds); } - if (global_xfds) { - FD_CLR(so->s,global_xfds); + if (s->xfds) { + FD_CLR(so->s, s->xfds); } } so->so_state &= ~(SS_ISFCONNECTING); @@ -706,12 +718,11 @@ * Set CANTSENDMORE once all data has been write()n */ void -sofwdrain(so) - struct socket *so; +sofwdrain(slirp_state_t *s, struct socket *so) { if (so->so_rcv.sb_cc) so->so_state |= SS_FWDRAIN; else - sofcantsendmore(so); + sofcantsendmore(s, so); } Index: qemu/slirp/socket.h =================================================================== --- qemu.orig/slirp/socket.h 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/socket.h 2007-10-21 18:47:11.000000000 +0000 @@ -71,9 +71,6 @@ #define SS_FACCEPTCONN 0x100 /* Socket is accepting connections from a host on the internet */ #define SS_FACCEPTONCE 0x200 /* If set, the SS_FACCEPTCONN socket will die after one accept */ -extern struct socket tcb; - - #if defined(DECLARE_IOVEC) && !defined(HAVE_READV) struct iovec { char *iov_base; @@ -81,24 +78,20 @@ }; #endif -void so_init _P((void)); struct socket * solookup _P((struct socket *, struct in_addr, u_int, struct in_addr, u_int)); struct socket * socreate _P((void)); -void sofree _P((struct socket *)); -int soread _P((struct socket *)); -void sorecvoob _P((struct socket *)); +void sofree(slirp_state_t *s, struct socket *so); +int soread(slirp_state_t *s, struct socket *so); +void sorecvoob(slirp_state_t *s, struct socket *so); int sosendoob _P((struct socket *)); -int sowrite _P((struct socket *)); -void sorecvfrom _P((struct socket *)); -int sosendto _P((struct socket *, struct mbuf *)); -struct socket * solisten _P((u_int, u_int32_t, u_int, int)); -void sorwakeup _P((struct socket *)); -void sowwakeup _P((struct socket *)); +int sowrite(slirp_state_t *s, struct socket *so); +void sorecvfrom(slirp_state_t *s, struct socket *so); +int sosendto(slirp_state_t *s, struct socket *so, struct mbuf *m); +struct socket *solisten(slirp_state_t *s, u_int port, u_int32_t laddr, + u_int lport, int flags); void soisfconnecting _P((register struct socket *)); void soisfconnected _P((register struct socket *)); -void sofcantrcvmore _P((struct socket *)); -void sofcantsendmore _P((struct socket *)); void soisfdisconnected _P((struct socket *)); -void sofwdrain _P((struct socket *)); +void sofwdrain(slirp_state_t *s, struct socket *so); #endif /* _SOCKET_H_ */ Index: qemu/slirp/tcp.h =================================================================== --- qemu.orig/slirp/tcp.h 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/tcp.h 2007-10-21 18:47:11.000000000 +0000 @@ -42,10 +42,6 @@ #define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */ #define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */ -extern int tcp_rcvspace; -extern int tcp_sndspace; -extern struct socket *tcp_last_so; - #define TCP_SNDSPACE 8192 #define TCP_RCVSPACE 8192 @@ -170,8 +166,6 @@ #define TCP_ISSINCR (125*1024) /* increment for tcp_iss each second */ -extern tcp_seq tcp_iss; /* tcp initial send seq # */ - -extern char *tcpstates[]; +extern const char * const tcpstates[]; #endif Index: qemu/slirp/tcp_input.c =================================================================== --- qemu.orig/slirp/tcp_input.c 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/tcp_input.c 2007-10-22 19:29:58.000000000 +0000 @@ -45,12 +45,6 @@ #include <slirp.h> #include "ip_icmp.h" -struct socket tcb; - -int tcprexmtthresh = 3; -struct socket *tcp_last_so = &tcb; - -tcp_seq tcp_iss; /* tcp initial send seq # */ #define TCP_PAWS_IDLE (24 * 24 * 60 * 60 * PR_SLOWHZ) @@ -69,9 +63,9 @@ * when segments are out of order (so fast retransmit can work). */ #ifdef TCP_ACK_HACK -#define TCP_REASS(tp, ti, m, so, flags) {\ +#define TCP_REASS(s, tp, ti, m, so, flags) {\ if ((ti)->ti_seq == (tp)->rcv_nxt && \ - (tp)->seg_next == (tcpiphdrp_32)(tp) && \ + tcpcb_get_next(tp) == (tp) && \ (tp)->t_state == TCPS_ESTABLISHED) {\ if (ti->ti_flags & TH_PUSH) \ tp->t_flags |= TF_ACKNOW; \ @@ -79,45 +73,49 @@ tp->t_flags |= TF_DELACK; \ (tp)->rcv_nxt += (ti)->ti_len; \ flags = (ti)->ti_flags & TH_FIN; \ - tcpstat.tcps_rcvpack++;\ - tcpstat.tcps_rcvbyte += (ti)->ti_len;\ + STAT(s->tcpstat.tcps_rcvpack++); \ + STAT(s->tcpstat.tcps_rcvbyte += (ti)->ti_len); \ if (so->so_emu) { \ - if (tcp_emu((so),(m))) sbappend((so), (m)); \ + if (tcp_emu((s), (so), (m))) \ + sbappend((s), (so), (m)); \ } else \ - sbappend((so), (m)); \ + sbappend((s), (so), (m)); \ /* sorwakeup(so); */ \ } else {\ - (flags) = tcp_reass((tp), (ti), (m)); \ + (flags) = tcp_reass((s), (tp), (ti), (m)); \ tp->t_flags |= TF_ACKNOW; \ } \ } #else -#define TCP_REASS(tp, ti, m, so, flags) { \ +#define TCP_REASS(s, tp, ti, m, so, flags) { \ if ((ti)->ti_seq == (tp)->rcv_nxt && \ - (tp)->seg_next == (tcpiphdrp_32)(tp) && \ + tcpcb_get_next(tp) == (tp) && \ (tp)->t_state == TCPS_ESTABLISHED) { \ tp->t_flags |= TF_DELACK; \ (tp)->rcv_nxt += (ti)->ti_len; \ flags = (ti)->ti_flags & TH_FIN; \ - tcpstat.tcps_rcvpack++;\ - tcpstat.tcps_rcvbyte += (ti)->ti_len;\ + STAT(s->tcpstat.tcps_rcvpack++); \ + STAT(s->tcpstat.tcps_rcvbyte += (ti)->ti_len); \ if (so->so_emu) { \ - if (tcp_emu((so),(m))) sbappend(so, (m)); \ + if (tcp_emu((s), (so), (m))) \ + sbappend((s), (so), (m)); \ } else \ - sbappend((so), (m)); \ + sbappend((s), (so), (m)); \ /* sorwakeup(so); */ \ } else { \ - (flags) = tcp_reass((tp), (ti), (m)); \ + (flags) = tcp_reass((s), (tp), (ti), (m)); \ tp->t_flags |= TF_ACKNOW; \ } \ } #endif - -int -tcp_reass(tp, ti, m) - register struct tcpcb *tp; - register struct tcpiphdr *ti; - struct mbuf *m; +static void tcp_dooptions(slirp_state_t *s, struct tcpcb *tp, u_char *cp, + int cnt, struct tcpiphdr *ti); +static void tcp_xmit_timer(slirp_state_t *s, register struct tcpcb *tp, + int rtt); + +static int +tcp_reass(slirp_state_t *s, register struct tcpcb *tp, + register struct tcpiphdr *ti, struct mbuf *m) { register struct tcpiphdr *q; struct socket *so = tp->t_socket; @@ -133,8 +131,7 @@ /* * Find a segment which begins after this one does. */ - for (q = (struct tcpiphdr *)tp->seg_next; q != (struct tcpiphdr *)tp; - q = (struct tcpiphdr *)q->ti_next) + for (q = (struct tcpiphdr *)tcpcb_get_next(tp); q != (struct tcpiphdr *)tp; q = ti_get_next(s, q)) if (SEQ_GT(q->ti_seq, ti->ti_seq)) break; @@ -143,16 +140,16 @@ * our data already. If so, drop the data from the incoming * segment. If it provides all of our data, drop us. */ - if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) { + if (ti_get_prev(s, q) != (struct tcpiphdr *)tp) { register int i; - q = (struct tcpiphdr *)q->ti_prev; + q = ti_get_prev(s, q); /* conversion to int (in i) handles seq wraparound */ i = q->ti_seq + q->ti_len - ti->ti_seq; if (i > 0) { if (i >= ti->ti_len) { - tcpstat.tcps_rcvduppack++; - tcpstat.tcps_rcvdupbyte += ti->ti_len; - m_freem(m); + STAT(s->tcpstat.tcps_rcvduppack++); + STAT(s->tcpstat.tcps_rcvdupbyte += ti->ti_len); + m_freem(s, m); /* * Try to present any queued data * at the left window edge to the user. @@ -165,11 +162,11 @@ ti->ti_len -= i; ti->ti_seq += i; } - q = (struct tcpiphdr *)(q->ti_next); + q = ti_get_next(s, q); } - tcpstat.tcps_rcvoopack++; - tcpstat.tcps_rcvoobyte += ti->ti_len; - REASS_MBUF(ti) = (mbufp_32) m; /* XXX */ + STAT(s->tcpstat.tcps_rcvoopack++); + STAT(s->tcpstat.tcps_rcvoobyte += ti->ti_len); + ti_set_mbuf(ti, m); /* XXX */ /* * While we overlap succeeding segments trim them or, @@ -182,19 +179,19 @@ if (i < q->ti_len) { q->ti_seq += i; q->ti_len -= i; - m_adj((struct mbuf *) REASS_MBUF(q), i); + m_adj(ti_get_mbuf(s, q), i); break; } - q = (struct tcpiphdr *)q->ti_next; - m = (struct mbuf *) REASS_MBUF((struct tcpiphdr *)q->ti_prev); - remque_32((void *)(q->ti_prev)); - m_freem(m); + q = ti_get_next(s, q); + m = ti_get_mbuf(s, ti_get_prev(s, q)); + remque_32(s, ti_get_prev(s, q)); + m_freem(s, m); } /* * Stick new segment in its place. */ - insque_32(ti, (void *)(q->ti_prev)); + insque_32(s, ti, ti_get_prev(s, q)); present: /* @@ -203,7 +200,7 @@ */ if (!TCPS_HAVEESTABLISHED(tp->t_state)) return (0); - ti = (struct tcpiphdr *) tp->seg_next; + ti = (struct tcpiphdr *)tcpcb_get_next(tp); if (ti == (struct tcpiphdr *)tp || ti->ti_seq != tp->rcv_nxt) return (0); if (tp->t_state == TCPS_SYN_RECEIVED && ti->ti_len) @@ -211,17 +208,18 @@ do { tp->rcv_nxt += ti->ti_len; flags = ti->ti_flags & TH_FIN; - remque_32(ti); - m = (struct mbuf *) REASS_MBUF(ti); /* XXX */ - ti = (struct tcpiphdr *)ti->ti_next; + remque_32(s, ti); + m = ti_get_mbuf(s, ti); /* XXX */ + ti = ti_get_next(s, ti); /* if (so->so_state & SS_FCANTRCVMORE) */ if (so->so_state & SS_FCANTSENDMORE) - m_freem(m); + m_freem(s, m); else { if (so->so_emu) { - if (tcp_emu(so,m)) sbappend(so, m); + if (tcp_emu(s, so,m)) + sbappend(s, so, m); } else - sbappend(so, m); + sbappend(s, so, m); } } while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt); /* sorwakeup(so); */ @@ -233,10 +231,7 @@ * protocol specification dated September, 1981 very closely. */ void -tcp_input(m, iphlen, inso) - register struct mbuf *m; - int iphlen; - struct socket *inso; +tcp_input(slirp_state_t *s, register struct mbuf *m, int iphlen, struct socket *inso) { struct ip save_ip, *ip; register struct tcpiphdr *ti; @@ -252,6 +247,7 @@ u_long tiwin; int ret; /* int ts_present = 0; */ + int mbuf_freed = 0; DEBUG_CALL("tcp_input"); DEBUG_ARGS((dfd," m = %8lx iphlen = %2d inso = %lx\n", @@ -275,7 +271,7 @@ } - tcpstat.tcps_rcvtotal++; + STAT(s->tcpstat.tcps_rcvtotal++); /* * Get IP and TCP header together in first mbuf. * Note: IP leaves IP header in first mbuf. @@ -300,7 +296,8 @@ * Checksum extended TCP header and data. */ tlen = ((struct ip *)ti)->ip_len; - ti->ti_next = ti->ti_prev = 0; + ti_set_next(s, ti, NULL); + ti_set_prev(s, ti, NULL); ti->ti_x1 = 0; ti->ti_len = htons((u_int16_t)tlen); len = sizeof(struct ip ) + tlen; @@ -308,7 +305,7 @@ * ti->ti_sum = cksum(m, len); * if (ti->ti_sum) { */ if(cksum(m, len)) { - tcpstat.tcps_rcvbadsum++; + STAT(s->tcpstat.tcps_rcvbadsum++); goto drop; } @@ -318,7 +315,7 @@ */ off = ti->ti_off << 2; if (off < sizeof (struct tcphdr) || off > tlen) { - tcpstat.tcps_rcvbadoff++; + STAT(s->tcpstat.tcps_rcvbadoff++); goto drop; } tlen -= off; @@ -366,16 +363,16 @@ * Locate pcb for segment. */ findso: - so = tcp_last_so; + so = s->tcp_last_so; if (so->so_fport != ti->ti_dport || so->so_lport != ti->ti_sport || so->so_laddr.s_addr != ti->ti_src.s_addr || so->so_faddr.s_addr != ti->ti_dst.s_addr) { - so = solookup(&tcb, ti->ti_src, ti->ti_sport, + so = solookup(&s->tcb, ti->ti_src, ti->ti_sport, ti->ti_dst, ti->ti_dport); if (so) - tcp_last_so = so; - ++tcpstat.tcps_socachemiss; + s->tcp_last_so = so; + STAT(s->tcpstat.tcps_socachemiss++); } /* @@ -397,13 +394,13 @@ if ((so = socreate()) == NULL) goto dropwithreset; - if (tcp_attach(so) < 0) { + if (tcp_attach(s, so) < 0) { free(so); /* Not sofree (if it failed, it's not insqued) */ goto dropwithreset; } - sbreserve(&so->so_snd, tcp_sndspace); - sbreserve(&so->so_rcv, tcp_rcvspace); + sbreserve(&so->so_snd, TCP_SNDSPACE); + sbreserve(&so->so_rcv, TCP_RCVSPACE); /* tcp_last_so = so; */ /* XXX ? */ /* tp = sototcpcb(so); */ @@ -448,17 +445,17 @@ * Reset idle time and keep-alive timer. */ tp->t_idle = 0; - if (so_options) - tp->t_timer[TCPT_KEEP] = tcp_keepintvl; + if (SO_OPTIONS) + tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL; else - tp->t_timer[TCPT_KEEP] = tcp_keepidle; + tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE; /* * Process options if not in LISTEN state, * else do it below (after getting remote address). */ if (optp && tp->t_state != TCPS_LISTEN) - tcp_dooptions(tp, (u_char *)optp, optlen, ti); + tcp_dooptions(s, tp, (u_char *)optp, optlen, ti); /* , */ /* &ts_present, &ts_val, &ts_ecr); */ @@ -503,19 +500,20 @@ /* * this is a pure ack for outstanding data. */ - ++tcpstat.tcps_predack; + STAT(s->tcpstat.tcps_predack++); +; /* if (ts_present) * tcp_xmit_timer(tp, tcp_now-ts_ecr+1); * else */ if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq)) - tcp_xmit_timer(tp, tp->t_rtt); + tcp_xmit_timer(s, tp, tp->t_rtt); acked = ti->ti_ack - tp->snd_una; - tcpstat.tcps_rcvackpack++; - tcpstat.tcps_rcvackbyte += acked; + STAT(s->tcpstat.tcps_rcvackpack++); + STAT(s->tcpstat.tcps_rcvackbyte += acked); sbdrop(&so->so_snd, acked); tp->snd_una = ti->ti_ack; - m_freem(m); + m_freem(s, m); /* * If all outstanding data are acked, stop @@ -544,29 +542,30 @@ * we don't need this.. XXX??? */ if (so->so_snd.sb_cc) - (void) tcp_output(tp); + (void) tcp_output(s, tp); return; } } else if (ti->ti_ack == tp->snd_una && - tp->seg_next == (tcpiphdrp_32)tp && + tcpcb_get_next(tp) == tp && ti->ti_len <= sbspace(&so->so_rcv)) { /* * this is a pure, in-sequence data packet * with nothing on the reassembly queue and * we have enough buffer space to take it. */ - ++tcpstat.tcps_preddat; + STAT(s->tcpstat.tcps_preddat++); tp->rcv_nxt += ti->ti_len; - tcpstat.tcps_rcvpack++; - tcpstat.tcps_rcvbyte += ti->ti_len; + STAT(s->tcpstat.tcps_rcvpack++); + STAT(s->tcpstat.tcps_rcvbyte += ti->ti_len); /* * Add data to socket buffer. */ if (so->so_emu) { - if (tcp_emu(so,m)) sbappend(so, m); + if (tcp_emu(s, so,m)) + sbappend(s, so, m); } else - sbappend(so, m); + sbappend(s, so, m); /* * XXX This is called when data arrives. Later, check @@ -584,7 +583,7 @@ * TCP throughput. See RFC 2581. */ tp->t_flags |= TF_ACKNOW; - tcp_output(tp); + tcp_output(s, tp); return; } } /* header prediction */ @@ -634,7 +633,8 @@ * If this is destined for the control address, then flag to * tcp_ctl once connected, otherwise connect */ - if ((so->so_faddr.s_addr&htonl(0xffffff00)) == special_addr.s_addr) { + if ((so->so_faddr.s_addr & htonl(0xffffff00)) == + s->special_addr.s_addr) { int lastbyte=ntohl(so->so_faddr.s_addr) & 0xff; if (lastbyte!=CTL_ALIAS && lastbyte!=CTL_DNS) { #if 0 @@ -646,7 +646,7 @@ { /* May be an add exec */ struct ex_list *ex_ptr; - for(ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { + for(ex_ptr = s->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { if(ex_ptr->ex_fport == so->so_fport && lastbyte == ex_ptr->ex_addr) { so->so_state |= SS_CTL; @@ -664,13 +664,14 @@ goto cont_input; } - if((tcp_fconnect(so) == -1) && (errno != EINPROGRESS) && (errno != EWOULDBLOCK)) { + if ((tcp_fconnect(s, so) == -1) && (errno != EINPROGRESS) + && (errno != EWOULDBLOCK)) { u_char code=ICMP_UNREACH_NET; DEBUG_MISC((dfd," tcp fconnect errno = %d-%s\n", errno,strerror(errno))); if(errno == ECONNREFUSED) { /* ACK the SYN, send RST to refuse the connection */ - tcp_respond(tp, ti, m, ti->ti_seq+1, (tcp_seq)0, + tcp_respond(s, tp, ti, m, ti->ti_seq+1, (tcp_seq)0, TH_RST|TH_ACK); } else { if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST; @@ -681,10 +682,10 @@ m->m_data -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); m->m_len += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); *ip=save_ip; - icmp_error(m, ICMP_UNREACH,code, 0,strerror(errno)); + icmp_error(s, m, ICMP_UNREACH, code, 0, strerror(errno)); } - tp = tcp_close(tp); - m_free(m); + tp = tcp_close(s, tp); + m_free(s, m); } else { /* * Haven't connected yet, save the current mbuf @@ -704,29 +705,29 @@ * Check if the connect succeeded */ if (so->so_state & SS_NOFDREF) { - tp = tcp_close(tp); + tp = tcp_close(s, tp); goto dropwithreset; } cont_input: - tcp_template(tp); + tcp_template(s, tp); if (optp) - tcp_dooptions(tp, (u_char *)optp, optlen, ti); + tcp_dooptions(s, tp, (u_char *)optp, optlen, ti); /* , */ /* &ts_present, &ts_val, &ts_ecr); */ if (iss) tp->iss = iss; else - tp->iss = tcp_iss; - tcp_iss += TCP_ISSINCR/2; + tp->iss = s->tcp_iss; + s->tcp_iss += TCP_ISSINCR / 2; tp->irs = ti->ti_seq; tcp_sendseqinit(tp); tcp_rcvseqinit(tp); tp->t_flags |= TF_ACKNOW; tp->t_state = TCPS_SYN_RECEIVED; tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; - tcpstat.tcps_accepts++; + STAT(s->tcpstat.tcps_accepts++); goto trimthenstep6; } /* case TCPS_LISTEN */ @@ -750,7 +751,7 @@ if (tiflags & TH_RST) { if (tiflags & TH_ACK) - tp = tcp_drop(tp,0); /* XXX Check t_softerror! */ + tp = tcp_drop(s, tp, 0); /* XXX Check t_softerror! */ goto drop; } @@ -767,7 +768,7 @@ tcp_rcvseqinit(tp); tp->t_flags |= TF_ACKNOW; if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) { - tcpstat.tcps_connects++; + STAT(s->tcpstat.tcps_connects++); soisfconnected(so); tp->t_state = TCPS_ESTABLISHED; @@ -778,14 +779,14 @@ * tp->rcv_scale = tp->request_r_scale; * } */ - (void) tcp_reass(tp, (struct tcpiphdr *)0, + (void) tcp_reass(s, tp, (struct tcpiphdr *)0, (struct mbuf *)0); /* * if we didn't have to retransmit the SYN, * use its rtt as our initial srtt & rtt var. */ if (tp->t_rtt) - tcp_xmit_timer(tp, tp->t_rtt); + tcp_xmit_timer(s, tp, tp->t_rtt); } else tp->t_state = TCPS_SYN_RECEIVED; @@ -801,8 +802,8 @@ m_adj(m, -todrop); ti->ti_len = tp->rcv_wnd; tiflags &= ~TH_FIN; - tcpstat.tcps_rcvpackafterwin++; - tcpstat.tcps_rcvbyteafterwin += todrop; + STAT(s->tcpstat.tcps_rcvpackafterwin++); + STAT(s->tcpstat.tcps_rcvbyteafterwin += todrop); } tp->snd_wl1 = ti->ti_seq - 1; tp->rcv_up = ti->ti_seq; @@ -873,11 +874,11 @@ */ tp->t_flags |= TF_ACKNOW; todrop = ti->ti_len; - tcpstat.tcps_rcvduppack++; - tcpstat.tcps_rcvdupbyte += todrop; + STAT(s->tcpstat.tcps_rcvduppack++); + STAT(s->tcpstat.tcps_rcvdupbyte += todrop); } else { - tcpstat.tcps_rcvpartduppack++; - tcpstat.tcps_rcvpartdupbyte += todrop; + STAT(s->tcpstat.tcps_rcvpartduppack++); + STAT(s->tcpstat.tcps_rcvpartdupbyte += todrop); } m_adj(m, todrop); ti->ti_seq += todrop; @@ -895,8 +896,8 @@ */ if ((so->so_state & SS_NOFDREF) && tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) { - tp = tcp_close(tp); - tcpstat.tcps_rcvafterclose++; + tp = tcp_close(s, tp); + STAT(s->tcpstat.tcps_rcvafterclose++); goto dropwithreset; } @@ -906,9 +907,9 @@ */ todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd); if (todrop > 0) { - tcpstat.tcps_rcvpackafterwin++; + STAT(s->tcpstat.tcps_rcvpackafterwin++); if (todrop >= ti->ti_len) { - tcpstat.tcps_rcvbyteafterwin += ti->ti_len; + STAT(s->tcpstat.tcps_rcvbyteafterwin += ti->ti_len); /* * If a new connection request is received * while in TIME_WAIT, drop the old connection @@ -919,7 +920,7 @@ tp->t_state == TCPS_TIME_WAIT && SEQ_GT(ti->ti_seq, tp->rcv_nxt)) { iss = tp->rcv_nxt + TCP_ISSINCR; - tp = tcp_close(tp); + tp = tcp_close(s, tp); goto findso; } /* @@ -931,11 +932,11 @@ */ if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) { tp->t_flags |= TF_ACKNOW; - tcpstat.tcps_rcvwinprobe++; + STAT(s->tcpstat.tcps_rcvwinprobe++); } else goto dropafterack; } else - tcpstat.tcps_rcvbyteafterwin += todrop; + STAT(s->tcpstat.tcps_rcvbyteafterwin += todrop); m_adj(m, -todrop); ti->ti_len -= todrop; tiflags &= ~(TH_PUSH|TH_FIN); @@ -976,14 +977,14 @@ /* so->so_error = ECONNRESET; */ close: tp->t_state = TCPS_CLOSED; - tcpstat.tcps_drops++; - tp = tcp_close(tp); + STAT(s->tcpstat.tcps_drops++); + tp = tcp_close(s, tp); goto drop; case TCPS_CLOSING: case TCPS_LAST_ACK: case TCPS_TIME_WAIT: - tp = tcp_close(tp); + tp = tcp_close(s, tp); goto drop; } @@ -992,7 +993,7 @@ * error and we send an RST and drop the connection. */ if (tiflags & TH_SYN) { - tp = tcp_drop(tp,0); + tp = tcp_drop(s, tp, 0); goto dropwithreset; } @@ -1015,7 +1016,7 @@ if (SEQ_GT(tp->snd_una, ti->ti_ack) || SEQ_GT(ti->ti_ack, tp->snd_max)) goto dropwithreset; - tcpstat.tcps_connects++; + STAT(s->tcpstat.tcps_connects++); tp->t_state = TCPS_ESTABLISHED; /* * The sent SYN is ack'ed with our sequence number +1 @@ -1027,7 +1028,7 @@ tp->snd_una=ti->ti_ack; if (so->so_state & SS_CTL) { /* So tcp_ctl reports the right state */ - ret = tcp_ctl(so); + ret = tcp_ctl(s, so); if (ret == 1) { soisfconnected(so); so->so_state &= ~SS_CTL; /* success XXX */ @@ -1048,7 +1049,7 @@ * tp->rcv_scale = tp->request_r_scale; * } */ - (void) tcp_reass(tp, (struct tcpiphdr *)0, (struct mbuf *)0); + (void) tcp_reass(s, tp, (struct tcpiphdr *)0, (struct mbuf *)0); tp->snd_wl1 = ti->ti_seq - 1; /* Avoid ack processing; snd_una==ti_ack => dup ack */ goto synrx_to_est; @@ -1072,7 +1073,7 @@ if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) { if (ti->ti_len == 0 && tiwin == tp->snd_wnd) { - tcpstat.tcps_rcvdupack++; + STAT(s->tcpstat.tcps_rcvdupack++); DEBUG_MISC((dfd," dup ack m = %lx so = %lx \n", (long )m, (long )so)); /* @@ -1102,7 +1103,7 @@ if (tp->t_timer[TCPT_REXMT] == 0 || ti->ti_ack != tp->snd_una) tp->t_dupacks = 0; - else if (++tp->t_dupacks == tcprexmtthresh) { + else if (++tp->t_dupacks == TCPREXMTTHRESH) { tcp_seq onxt = tp->snd_nxt; u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / @@ -1115,15 +1116,15 @@ tp->t_rtt = 0; tp->snd_nxt = ti->ti_ack; tp->snd_cwnd = tp->t_maxseg; - (void) tcp_output(tp); + (void) tcp_output(s, tp); tp->snd_cwnd = tp->snd_ssthresh + tp->t_maxseg * tp->t_dupacks; if (SEQ_GT(onxt, tp->snd_nxt)) tp->snd_nxt = onxt; goto drop; - } else if (tp->t_dupacks > tcprexmtthresh) { + } else if (tp->t_dupacks > TCPREXMTTHRESH) { tp->snd_cwnd += tp->t_maxseg; - (void) tcp_output(tp); + (void) tcp_output(s, tp); goto drop; } } else @@ -1135,17 +1136,17 @@ * If the congestion window was inflated to account * for the other side's cached packets, retract it. */ - if (tp->t_dupacks > tcprexmtthresh && + if (tp->t_dupacks > TCPREXMTTHRESH && tp->snd_cwnd > tp->snd_ssthresh) tp->snd_cwnd = tp->snd_ssthresh; tp->t_dupacks = 0; if (SEQ_GT(ti->ti_ack, tp->snd_max)) { - tcpstat.tcps_rcvacktoomuch++; + STAT(s->tcpstat.tcps_rcvacktoomuch++); goto dropafterack; } acked = ti->ti_ack - tp->snd_una; - tcpstat.tcps_rcvackpack++; - tcpstat.tcps_rcvackbyte += acked; + STAT(s->tcpstat.tcps_rcvackpack++); + STAT(s->tcpstat.tcps_rcvackbyte += acked); /* * If we have a timestamp reply, update smoothed @@ -1161,7 +1162,7 @@ * else */ if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq)) - tcp_xmit_timer(tp,tp->t_rtt); + tcp_xmit_timer(s, tp, tp->t_rtt); /* * If all outstanding data is acked, stop retransmit @@ -1227,7 +1228,7 @@ */ if (so->so_state & SS_FCANTRCVMORE) { soisfdisconnected(so); - tp->t_timer[TCPT_2MSL] = tcp_maxidle; + tp->t_timer[TCPT_2MSL] = TCP_MAXIDLE; } tp->t_state = TCPS_FIN_WAIT_2; } @@ -1256,7 +1257,7 @@ */ case TCPS_LAST_ACK: if (ourfinisacked) { - tp = tcp_close(tp); + tp = tcp_close(s, tp); goto drop; } break; @@ -1284,7 +1285,7 @@ /* keep track of pure window updates */ if (ti->ti_len == 0 && tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd) - tcpstat.tcps_rcvwinupd++; + STAT(s->tcpstat.tcps_rcvwinupd++); tp->snd_wnd = tiwin; tp->snd_wl1 = ti->ti_seq; tp->snd_wl2 = ti->ti_ack; @@ -1350,7 +1351,7 @@ */ if ((ti->ti_len || (tiflags&TH_FIN)) && TCPS_HAVERCVDFIN(tp->t_state) == 0) { - TCP_REASS(tp, ti, m, so, tiflags); + TCP_REASS(s, tp, ti, m, so, tiflags); /* * Note the amount of data that peer has sent into * our window, in order to estimate the sender's @@ -1358,7 +1359,7 @@ */ len = so->so_rcv.sb_datalen - (tp->rcv_adv - tp->rcv_nxt); } else { - m_free(m); + mbuf_freed = 1; /* The mbuf must be freed, but only when its content is not needed anymore. */ tiflags &= ~TH_FIN; } @@ -1378,7 +1379,7 @@ * to send the FIN. */ /* sofcantrcvmore(so); */ - sofwdrain(so); + sofwdrain(s, so); tp->t_flags |= TF_ACKNOW; tp->rcv_nxt++; @@ -1445,11 +1446,14 @@ tp->t_flags |= TF_ACKNOW; } + if (mbuf_freed) { + m_free(s, m); + } /* * Return any desired output. */ if (needoutput || (tp->t_flags & TF_ACKNOW)) { - (void) tcp_output(tp); + (void) tcp_output(s, tp); } return; @@ -1460,19 +1464,19 @@ */ if (tiflags & TH_RST) goto drop; - m_freem(m); + m_freem(s, m); tp->t_flags |= TF_ACKNOW; - (void) tcp_output(tp); + (void) tcp_output(s, tp); return; dropwithreset: /* reuses m if m!=NULL, m_free() unnecessary */ if (tiflags & TH_ACK) - tcp_respond(tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST); + tcp_respond(s, tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST); else { if (tiflags & TH_SYN) ti->ti_len++; - tcp_respond(tp, ti, m, ti->ti_seq+ti->ti_len, (tcp_seq)0, - TH_RST|TH_ACK); + tcp_respond(s, tp, ti, m, ti->ti_seq + ti->ti_len, (tcp_seq)0, + TH_RST | TH_ACK); } return; @@ -1481,7 +1485,7 @@ /* * Drop space held by incoming segment and return. */ - m_free(m); + m_free(s, m); return; } @@ -1490,12 +1494,9 @@ /* int *ts_present; * u_int32_t *ts_val, *ts_ecr; */ -void -tcp_dooptions(tp, cp, cnt, ti) - struct tcpcb *tp; - u_char *cp; - int cnt; - struct tcpiphdr *ti; +static void +tcp_dooptions(slirp_state_t *s, struct tcpcb *tp, u_char *cp, int cnt, + struct tcpiphdr *ti) { u_int16_t mss; int opt, optlen; @@ -1526,7 +1527,7 @@ continue; memcpy((char *) &mss, (char *) cp + 2, sizeof(mss)); NTOHS(mss); - (void) tcp_mss(tp, mss); /* sets t_maxseg */ + (void) tcp_mss(s, tp, mss); /* sets t_maxseg */ break; /* case TCPOPT_WINDOW: @@ -1605,10 +1606,8 @@ * and update averages and current timeout. */ -void -tcp_xmit_timer(tp, rtt) - register struct tcpcb *tp; - int rtt; +static void +tcp_xmit_timer(slirp_state_t *s, register struct tcpcb *tp, int rtt) { register short delta; @@ -1616,7 +1615,7 @@ DEBUG_ARG("tp = %lx", (long)tp); DEBUG_ARG("rtt = %d", rtt); - tcpstat.tcps_rttupdated++; + STAT(s->tcpstat.tcps_rttupdated++); if (tp->t_srtt != 0) { /* * srtt is stored as fixed point with 3 bits after the @@ -1696,9 +1695,7 @@ */ int -tcp_mss(tp, offer) - register struct tcpcb *tp; - u_int offer; +tcp_mss(slirp_state_t *s, register struct tcpcb *tp, u_int offer) { struct socket *so = tp->t_socket; int mss; @@ -1707,7 +1704,7 @@ DEBUG_ARG("tp = %lx", (long)tp); DEBUG_ARG("offer = %d", offer); - mss = min(if_mtu, if_mru) - sizeof(struct tcpiphdr); + mss = IF_MTU - sizeof(struct tcpiphdr); if (offer) mss = min(mss, offer); mss = max(mss, 32); @@ -1716,8 +1713,12 @@ tp->snd_cwnd = mss; - sbreserve(&so->so_snd, tcp_sndspace+((tcp_sndspace%mss)?(mss-(tcp_sndspace%mss)):0)); - sbreserve(&so->so_rcv, tcp_rcvspace+((tcp_rcvspace%mss)?(mss-(tcp_rcvspace%mss)):0)); + sbreserve(&so->so_snd, TCP_SNDSPACE + ((TCP_SNDSPACE % mss) ? + (mss - (TCP_SNDSPACE % mss)) : + 0)); + sbreserve(&so->so_rcv, TCP_RCVSPACE + ((TCP_RCVSPACE % mss) ? + (mss - (TCP_RCVSPACE % mss)) : + 0)); DEBUG_MISC((dfd, " returning mss = %d\n", mss)); Index: qemu/slirp/tcp_output.c =================================================================== --- qemu.orig/slirp/tcp_output.c 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/tcp_output.c 2007-10-22 19:34:40.000000000 +0000 @@ -48,14 +48,14 @@ * Since this is only used in "stats socket", we give meaning * names instead of the REAL names */ -char *tcpstates[] = { +const char * const tcpstates[] = { /* "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", */ "REDIRECT", "LISTEN", "SYN_SENT", "SYN_RCVD", "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING", "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT", }; -u_char tcp_outflags[TCP_NSTATES] = { +static const u_char tcp_outflags[TCP_NSTATES] = { TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK, TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK, TH_ACK, TH_ACK, @@ -68,8 +68,7 @@ * Tcp output routine: figure out what should be sent and send it. */ int -tcp_output(tp) - register struct tcpcb *tp; +tcp_output(slirp_state_t *s, register struct tcpcb *tp) { register struct socket *so = tp->t_socket; register long len, win; @@ -263,7 +262,7 @@ /* * No reason to send a segment, just return. */ - tcpstat.tcps_didnuttin++; + STAT(s->tcpstat.tcps_didnuttin++); return (0); @@ -285,7 +284,7 @@ opt[0] = TCPOPT_MAXSEG; opt[1] = 4; - mss = htons((u_int16_t) tcp_mss(tp, 0)); + mss = htons((u_int16_t) tcp_mss(s, tp, 0)); memcpy((caddr_t)(opt + 2), (caddr_t)&mss, sizeof(mss)); optlen = 4; @@ -339,22 +338,22 @@ */ if (len) { if (tp->t_force && len == 1) - tcpstat.tcps_sndprobe++; + STAT(s->tcpstat.tcps_sndprobe++); else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) { - tcpstat.tcps_sndrexmitpack++; - tcpstat.tcps_sndrexmitbyte += len; + STAT(s->tcpstat.tcps_sndrexmitpack++); + STAT(s->tcpstat.tcps_sndrexmitbyte += len); } else { - tcpstat.tcps_sndpack++; - tcpstat.tcps_sndbyte += len; + STAT(s->tcpstat.tcps_sndpack++); + STAT(s->tcpstat.tcps_sndbyte += len); } - m = m_get(); + m = m_get(s); if (m == NULL) { /* error = ENOBUFS; */ error = 1; goto out; } - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; m->m_len = hdrlen; /* @@ -382,21 +381,21 @@ flags |= TH_PUSH; } else { if (tp->t_flags & TF_ACKNOW) - tcpstat.tcps_sndacks++; + STAT(s->tcpstat.tcps_sndacks++); else if (flags & (TH_SYN|TH_FIN|TH_RST)) - tcpstat.tcps_sndctrl++; + STAT(s->tcpstat.tcps_sndctrl++); else if (SEQ_GT(tp->snd_up, tp->snd_una)) - tcpstat.tcps_sndurg++; + STAT(s->tcpstat.tcps_sndurg++); else - tcpstat.tcps_sndwinup++; + STAT(s->tcpstat.tcps_sndwinup++); - m = m_get(); + m = m_get(s); if (m == NULL) { /* error = ENOBUFS; */ error = 1; goto out; } - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; m->m_len = hdrlen; } @@ -500,7 +499,7 @@ if (tp->t_rtt == 0) { tp->t_rtt = 1; tp->t_rtseq = startseq; - tcpstat.tcps_segstimed++; + STAT(s->tcpstat.tcps_segstimed++); } } @@ -536,7 +535,7 @@ ((struct ip *)ti)->ip_len = m->m_len; - ((struct ip *)ti)->ip_ttl = ip_defttl; + ((struct ip *)ti)->ip_ttl = IPDEFTTL; ((struct ip *)ti)->ip_tos = so->so_iptos; /* #if BSD >= 43 */ @@ -544,7 +543,7 @@ /* error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route, * so->so_options & SO_DONTROUTE, 0); */ - error = ip_output(so, m); + error = ip_output(s, so, m); /* #else * error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route, @@ -567,7 +566,7 @@ */ return (error); } - tcpstat.tcps_sndtotal++; + STAT(s->tcpstat.tcps_sndtotal++); /* * Data sent (as far as we can tell). Index: qemu/slirp/tcp_subr.c =================================================================== --- qemu.orig/slirp/tcp_subr.c 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/tcp_subr.c 2007-10-22 19:34:49.000000000 +0000 @@ -45,29 +45,16 @@ #define WANT_SYS_IOCTL_H #include <slirp.h> -/* patchable/settable parameters for tcp */ -int tcp_mssdflt = TCP_MSS; -int tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ; -int tcp_do_rfc1323 = 0; /* Don't do rfc1323 performance enhancements */ -int tcp_rcvspace; /* You may want to change this */ -int tcp_sndspace; /* Keep small if you have an error prone link */ /* * Tcp initialization */ void -tcp_init() +tcp_init(slirp_state_t *s) { - tcp_iss = 1; /* wrong */ - tcb.so_next = tcb.so_prev = &tcb; - - /* tcp_rcvspace = our Window we advertise to the remote */ - tcp_rcvspace = TCP_RCVSPACE; - tcp_sndspace = TCP_SNDSPACE; - - /* Make sure tcp_sndspace is at least 2*MSS */ - if (tcp_sndspace < 2*(min(if_mtu, if_mru) - sizeof(struct tcpiphdr))) - tcp_sndspace = 2*(min(if_mtu, if_mru) - sizeof(struct tcpiphdr)); + s->tcp_iss = 1; /* wrong */ + s->tcb.so_next = s->tcb.so_prev = &s->tcb; + s->tcp_last_so = &s->tcb; } /* @@ -78,13 +65,18 @@ */ /* struct tcpiphdr * */ void -tcp_template(tp) - struct tcpcb *tp; +tcp_template(slirp_state_t *s, struct tcpcb *tp) { struct socket *so = tp->t_socket; register struct tcpiphdr *n = &tp->t_template; - n->ti_next = n->ti_prev = 0; +#if 0 + ti_set_next(s, n, NULL); + ti_set_prev(s, n, NULL); +#else + n->ti_i.ih_next = 0; + n->ti_i.ih_prev = 0; +#endif n->ti_x1 = 0; n->ti_pr = IPPROTO_TCP; n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip)); @@ -117,12 +109,8 @@ * segment are as specified by the parameters. */ void -tcp_respond(tp, ti, m, ack, seq, flags) - struct tcpcb *tp; - register struct tcpiphdr *ti; - register struct mbuf *m; - tcp_seq ack, seq; - int flags; +tcp_respond(slirp_state_t *s, struct tcpcb *tp, struct tcpiphdr *ti, + struct mbuf *m, tcp_seq ack, tcp_seq seq, int flags) { register int tlen; int win = 0; @@ -138,14 +126,14 @@ if (tp) win = sbspace(&tp->t_socket->so_rcv); if (m == 0) { - if ((m = m_get()) == NULL) + if ((m = m_get(s)) == NULL) return; #ifdef TCP_COMPAT_42 tlen = 1; #else tlen = 0; #endif - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; *mtod(m, struct tcpiphdr *) = *ti; ti = mtod(m, struct tcpiphdr *); flags = TH_ACK; @@ -167,7 +155,8 @@ tlen += sizeof (struct tcpiphdr); m->m_len = tlen; - ti->ti_next = ti->ti_prev = 0; + ti_set_next(s, ti, NULL); + ti_set_prev(s, ti, NULL); ti->ti_x1 = 0; ti->ti_seq = htonl(seq); ti->ti_ack = htonl(ack); @@ -186,9 +175,9 @@ if(flags & TH_RST) ((struct ip *)ti)->ip_ttl = MAXTTL; else - ((struct ip *)ti)->ip_ttl = ip_defttl; + ((struct ip *)ti)->ip_ttl = IPDEFTTL; - (void) ip_output((struct socket *)0, m); + (void) ip_output(s, (struct socket *)0, m); } /* @@ -197,8 +186,7 @@ * protocol control block. */ struct tcpcb * -tcp_newtcpcb(so) - struct socket *so; +tcp_newtcpcb(slirp_state_t *s, struct socket *so) { register struct tcpcb *tp; @@ -207,10 +195,11 @@ return ((struct tcpcb *)0); memset((char *) tp, 0, sizeof(struct tcpcb)); - tp->seg_next = tp->seg_prev = (tcpiphdrp_32)tp; - tp->t_maxseg = tcp_mssdflt; + tcpcb_set_next(tp, tp); + tcpcb_set_prev(tp, tp); + tp->t_maxseg = TCP_MSS; - tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0; + tp->t_flags = TCP_DO_RFC1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0; tp->t_socket = so; /* @@ -219,7 +208,7 @@ * reasonable initial retransmit time. */ tp->t_srtt = TCPTV_SRTTBASE; - tp->t_rttvar = tcp_rttdflt * PR_SLOWHZ << 2; + tp->t_rttvar = TCPTV_SRTTDFLT << 2; tp->t_rttmin = TCPTV_MIN; TCPT_RANGESET(tp->t_rxtcur, @@ -240,7 +229,7 @@ * the specified error. If connection is synchronized, * then send a RST to peer. */ -struct tcpcb *tcp_drop(struct tcpcb *tp, int err) +struct tcpcb *tcp_drop(slirp_state_t *s, struct tcpcb *tp, int err) { /* tcp_drop(tp, errno) register struct tcpcb *tp; @@ -254,15 +243,15 @@ if (TCPS_HAVERCVDSYN(tp->t_state)) { tp->t_state = TCPS_CLOSED; - (void) tcp_output(tp); - tcpstat.tcps_drops++; + (void) tcp_output(s, tp); + STAT(s->tcpstat.tcps_drops++); } else - tcpstat.tcps_conndrops++; + STAT(s->tcpstat.tcps_conndrops++); /* if (errno == ETIMEDOUT && tp->t_softerror) * errno = tp->t_softerror; */ /* so->so_error = errno; */ - return (tcp_close(tp)); + return (tcp_close(s, tp)); } /* @@ -272,8 +261,7 @@ * wake up any sleepers */ struct tcpcb * -tcp_close(tp) - register struct tcpcb *tp; +tcp_close(slirp_state_t *s, register struct tcpcb *tp) { register struct tcpiphdr *t; struct socket *so = tp->t_socket; @@ -283,12 +271,12 @@ DEBUG_ARG("tp = %lx", (long )tp); /* free the reassembly queue, if any */ - t = (struct tcpiphdr *) tp->seg_next; + t = (struct tcpiphdr *)tcpcb_get_next(tp); while (t != (struct tcpiphdr *)tp) { - t = (struct tcpiphdr *)t->ti_next; - m = (struct mbuf *) REASS_MBUF((struct tcpiphdr *)t->ti_prev); - remque_32((struct tcpiphdr *) t->ti_prev); - m_freem(m); + t = ti_get_next(s, t); + m = ti_get_mbuf(s, ti_get_prev(s, t)); + remque_32(s, ti_get_prev(s, t)); + m_freem(s, m); } /* It's static */ /* if (tp->t_template) @@ -299,16 +287,17 @@ so->so_tcpcb = 0; soisfdisconnected(so); /* clobber input socket cache if we're closing the cached connection */ - if (so == tcp_last_so) - tcp_last_so = &tcb; + if (so == s->tcp_last_so) + s->tcp_last_so = &s->tcb; closesocket(so->s); sbfree(&so->so_rcv); sbfree(&so->so_snd); - sofree(so); - tcpstat.tcps_closed++; + sofree(s, so); + STAT(s->tcpstat.tcps_closed++); return ((struct tcpcb *)0); } +#ifdef notdef void tcp_drain() { @@ -319,9 +308,6 @@ * When a source quench is received, close congestion window * to one segment. We will gradually open it again as we proceed. */ - -#ifdef notdef - void tcp_quench(i, errno) @@ -350,8 +336,7 @@ * We can let the user exit from the close as soon as the FIN is acked. */ void -tcp_sockclosed(tp) - struct tcpcb *tp; +tcp_sockclosed(slirp_state_t *s, struct tcpcb *tp) { DEBUG_CALL("tcp_sockclosed"); @@ -363,7 +348,7 @@ case TCPS_LISTEN: case TCPS_SYN_SENT: tp->t_state = TCPS_CLOSED; - tp = tcp_close(tp); + tp = tcp_close(s, tp); break; case TCPS_SYN_RECEIVED: @@ -379,7 +364,7 @@ if (tp && tp->t_state >= TCPS_FIN_WAIT_2) soisfdisconnected(tp->t_socket); if (tp) - tcp_output(tp); + tcp_output(s, tp); } /* @@ -392,8 +377,7 @@ * nonblocking. Connect returns after the SYN is sent, and does * not wait for ACK+SYN. */ -int tcp_fconnect(so) - struct socket *so; +int tcp_fconnect(slirp_state_t *s, struct socket *so) { int ret=0; @@ -401,25 +385,25 @@ DEBUG_ARG("so = %lx", (long )so); if( (ret=so->s=socket(AF_INET,SOCK_STREAM,0)) >= 0) { - int opt, s=so->s; + int opt, fd = so->s; struct sockaddr_in addr; - fd_nonblock(s); + fd_nonblock(fd); opt = 1; - setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(opt )); + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)); opt = 1; - setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(opt )); + setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, (char *)&opt, sizeof(opt)); addr.sin_family = AF_INET; - if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) { + if ((so->so_faddr.s_addr & htonl(0xffffff00)) == s->special_addr.s_addr) { /* It's an alias */ switch(ntohl(so->so_faddr.s_addr) & 0xff) { case CTL_DNS: - addr.sin_addr = dns_addr; + addr.sin_addr = s->dns_addr; break; case CTL_ALIAS: default: - addr.sin_addr = loopback_addr; + addr.sin_addr = s->loopback_addr; break; } } else @@ -430,7 +414,7 @@ "addr.sin_addr.s_addr=%.16s\n", ntohs(addr.sin_port), inet_ntoa(addr.sin_addr))); /* We don't care what port we get */ - ret = connect(s,(struct sockaddr *)&addr,sizeof (addr)); + ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); /* * If it's not in progress, it failed, so we just return 0, @@ -455,14 +439,13 @@ * here and SYN the local-host. */ void -tcp_connect(inso) - struct socket *inso; +tcp_connect(slirp_state_t *s, struct socket *inso) { struct socket *so; struct sockaddr_in addr; int addrlen = sizeof(struct sockaddr_in); struct tcpcb *tp; - int s, opt; + int fd, opt; DEBUG_CALL("tcp_connect"); DEBUG_ARG("inso = %lx", (long)inso); @@ -480,7 +463,7 @@ closesocket(accept(inso->s,(struct sockaddr *)&addr,&addrlen)); return; } - if (tcp_attach(so) < 0) { + if (tcp_attach(s, so) < 0) { free(so); /* NOT sofree */ return; } @@ -488,25 +471,25 @@ so->so_lport = inso->so_lport; } - (void) tcp_mss(sototcpcb(so), 0); + (void) tcp_mss(s, sototcpcb(so), 0); - if ((s = accept(inso->s,(struct sockaddr *)&addr,&addrlen)) < 0) { - tcp_close(sototcpcb(so)); /* This will sofree() as well */ + if ((fd = accept(inso->s, (struct sockaddr *)&addr, &addrlen)) < 0) { + tcp_close(s, sototcpcb(so)); /* This will sofree() as well */ return; } - fd_nonblock(s); + fd_nonblock(fd); opt = 1; - setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)); + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int)); opt = 1; - setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); + setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, (char *)&opt, sizeof(int)); opt = 1; - setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char *)&opt,sizeof(int)); + setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&opt, sizeof(int)); so->so_fport = addr.sin_port; so->so_faddr = addr.sin_addr; /* Translate connections from localhost to the real hostname */ - if (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == loopback_addr.s_addr) - so->so_faddr = alias_addr; + if (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == s->loopback_addr.s_addr) + so->so_faddr = s->alias_addr; /* Close the accept() socket, set right state */ if (inso->so_state & SS_FACCEPTONCE) { @@ -514,12 +497,12 @@ so->so_state = SS_NOFDREF; /* Don't select it yet, even though we have an FD */ /* if it's not FACCEPTONCE, it's already NOFDREF */ } - so->s = s; + so->s = fd; so->so_iptos = tcp_tos(so); tp = sototcpcb(so); - tcp_template(tp); + tcp_template(s, tp); /* Compute window scaling to request. */ /* while (tp->request_r_scale < TCP_MAX_WINSHIFT && @@ -528,27 +511,26 @@ */ /* soisconnecting(so); */ /* NOFDREF used instead */ - tcpstat.tcps_connattempt++; + STAT(s->tcpstat.tcps_connattempt++); tp->t_state = TCPS_SYN_SENT; tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; - tp->iss = tcp_iss; - tcp_iss += TCP_ISSINCR/2; + tp->iss = s->tcp_iss; + s->tcp_iss += TCP_ISSINCR / 2; tcp_sendseqinit(tp); - tcp_output(tp); + tcp_output(s, tp); } /* * Attach a TCPCB to a socket. */ int -tcp_attach(so) - struct socket *so; +tcp_attach(slirp_state_t *s, struct socket *so) { - if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) + if ((so->so_tcpcb = tcp_newtcpcb(s, so)) == NULL) return -1; - insque(so, &tcb); + insque(s, so, &s->tcb); return 0; } @@ -556,7 +538,7 @@ /* * Set the socket's type of service field */ -struct tos_t tcptos[] = { +static const struct tos_t tcptos[] = { {0, 20, IPTOS_THROUGHPUT, 0}, /* ftp data */ {21, 21, IPTOS_LOWDELAY, EMU_FTP}, /* ftp control */ {0, 23, IPTOS_LOWDELAY, 0}, /* telnet */ @@ -572,8 +554,6 @@ {0, 0, 0, 0} }; -struct emu_t *tcpemu = 0; - /* * Return TOS according to the above table */ @@ -582,7 +562,6 @@ struct socket *so; { int i = 0; - struct emu_t *emup; while(tcptos[i].tos) { if ((tcptos[i].fport && (ntohs(so->so_fport) == tcptos[i].fport)) || @@ -593,20 +572,9 @@ i++; } - /* Nope, lets see if there's a user-added one */ - for (emup = tcpemu; emup; emup = emup->next) { - if ((emup->fport && (ntohs(so->so_fport) == emup->fport)) || - (emup->lport && (ntohs(so->so_lport) == emup->lport))) { - so->so_emu = emup->emu; - return emup->tos; - } - } - return 0; } -int do_echo = -1; - /* * Emulate programs that try and connect to us * This includes ftp (the data connection is @@ -632,9 +600,7 @@ * NOTE: if you return 0 you MUST m_free() the mbuf! */ int -tcp_emu(so, m) - struct socket *so; - struct mbuf *m; +tcp_emu(slirp_state_t *s, struct socket *so, struct mbuf *m) { u_int n1, n2, n3, n4, n5, n6; char buff[256]; @@ -665,11 +631,11 @@ so_rcv->sb_rptr += m->m_len; m->m_data[m->m_len] = 0; /* NULL terminate */ if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n')) { - if (sscanf(so_rcv->sb_data, "%d%*[ ,]%d", &n1, &n2) == 2) { + if (sscanf(so_rcv->sb_data, "%u%*[ ,]%u", &n1, &n2) == 2) { HTONS(n1); HTONS(n2); /* n2 is the one on our host */ - for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) { + for (tmpso = s->tcb.so_next; tmpso != &s->tcb; tmpso = tmpso->so_next) { if (tmpso->so_laddr.s_addr == so->so_laddr.s_addr && tmpso->so_lport == n2 && tmpso->so_faddr.s_addr == so->so_faddr.s_addr && @@ -685,7 +651,7 @@ so_rcv->sb_rptr = so_rcv->sb_data; so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc; } - m_free(m); + m_free(s, m); return 0; } @@ -841,8 +807,8 @@ ns->so_fport=htons(IPPORT_RESERVED-1); /* Use a fake port. */ if (ns->so_faddr.s_addr == 0 || - ns->so_faddr.s_addr == loopback_addr.s_addr) - ns->so_faddr = alias_addr; + ns->so_faddr.s_addr == s->loopback_addr.s_addr) + ns->so_faddr = s->alias_addr; ns->so_iptos = tcp_tos(ns); tp = sototcpcb(ns); @@ -857,12 +823,12 @@ /*soisfconnecting(ns);*/ - tcpstat.tcps_connattempt++; + STAT(s->tcpstat.tcps_connattempt++); tp->t_state = TCPS_SYN_SENT; tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; - tp->iss = tcp_iss; - tcp_iss += TCP_ISSINCR/2; + tp->iss = s->tcp_iss; + s->tcp_iss += TCP_ISSINCR / 2; tcp_sendseqinit(tp); tcp_output(tp); so->extra=ns; @@ -931,11 +897,13 @@ * because in linemode, the line is already echoed * XXX two or more control connections won't work */ - if (do_echo == -1) { - if (m->m_len == 1) do_echo = 1; - else do_echo = 0; + if (s->do_echo == -1) { + if (m->m_len == 1) + s->do_echo = 1; + else + s->do_echo = 0; } - if (do_echo) { + if (s->do_echo) { sbappendsb(so_snd, m); m_free(m); tcp_output(sototcpcb(so)); /* XXX */ @@ -991,7 +959,7 @@ /* * Need to emulate the PORT command */ - x = sscanf(bptr, "ORT %d,%d,%d,%d,%d,%d\r\n%256[^\177]", + x = sscanf(bptr, "ORT %u,%u,%u,%u,%u,%u\r\n%256[^\177]", &n1, &n2, &n3, &n4, &n5, &n6, buff); if (x < 6) return 1; @@ -999,7 +967,7 @@ laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4)); lport = htons((n5 << 8) | (n6)); - if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL) + if ((so = solisten(s, 0, laddr, lport, SS_FACCEPTONCE)) == NULL) return 1; n6 = ntohs(so->so_fport); @@ -1022,7 +990,7 @@ /* * Need to emulate the PASV response */ - x = sscanf(bptr, "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%256[^\177]", + x = sscanf(bptr, "27 Entering Passive Mode (%u,%u,%u,%u,%u,%u)\r\n%256[^\177]", &n1, &n2, &n3, &n4, &n5, &n6, buff); if (x < 6) return 1; @@ -1030,7 +998,7 @@ laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4)); lport = htons((n5 << 8) | (n6)); - if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL) + if ((so = solisten(s, 0, laddr, lport, SS_FACCEPTONCE)) == NULL) return 1; n6 = ntohs(so->so_fport); @@ -1069,7 +1037,7 @@ lport += m->m_data[i] - '0'; } if (m->m_data[m->m_len-1] == '\0' && lport != 0 && - (so = solisten(0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL) + (so = solisten(s, 0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL) m->m_len = sprintf(m->m_data, "%d", ntohs(so->so_fport))+1; return 1; @@ -1083,7 +1051,7 @@ /* The %256s is for the broken mIRC */ if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3) { - if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL) + if ((so = solisten(s, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL) return 1; m->m_len = bptr - m->m_data; /* Adjust length */ @@ -1091,7 +1059,7 @@ (unsigned long)ntohl(so->so_faddr.s_addr), ntohs(so->so_fport), 1); } else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) { - if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL) + if ((so = solisten(s, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL) return 1; m->m_len = bptr - m->m_data; /* Adjust length */ @@ -1099,7 +1067,7 @@ buff, (unsigned long)ntohl(so->so_faddr.s_addr), ntohs(so->so_fport), n1, 1); } else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) { - if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL) + if ((so = solisten(s, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL) return 1; m->m_len = bptr - m->m_data; /* Adjust length */ @@ -1109,6 +1077,11 @@ } return 1; +#if 1 +//def VBOX + /** @todo Disabled EMU_REALAUDIO, because it uses a static variable. + * This is not legal when more than one slirp instance is active. */ +#else /* !VBOX */ case EMU_REALAUDIO: /* * RealAudio emulation - JP. We must try to parse the incoming @@ -1234,6 +1207,7 @@ ra++; } return 1; +#endif /* !VBOX */ default: /* Ooops, not emulated, won't call tcp_emu again */ @@ -1248,8 +1222,7 @@ * return 2 if this is a command-line connection */ int -tcp_ctl(so) - struct socket *so; +tcp_ctl(slirp_state_t *s, struct socket *so) { struct sbuf *sb = &so->so_snd; int command; @@ -1278,7 +1251,7 @@ /* * Check if it's pty_exec */ - for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { + for (ex_ptr = s->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { if (ex_ptr->ex_fport == so->so_fport && command == ex_ptr->ex_addr) { do_pty = ex_ptr->ex_pty; @@ -1300,11 +1273,11 @@ do_exec: DEBUG_MISC((dfd, " executing %s \n",ex_ptr->ex_exec)); - return(fork_exec(so, ex_ptr->ex_exec, do_pty)); + return(fork_exec(s, so, ex_ptr->ex_exec, do_pty)); #if 0 case CTL_CMD: - for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) { + for (tmpso = s->tcb.so_next; tmpso != &s->tcb; tmpso = tmpso->so_next) { if (tmpso->so_emu == EMU_CTL && !(tmpso->so_tcpcb? (tmpso->so_tcpcb->t_state & (TCPS_TIME_WAIT|TCPS_LAST_ACK)) @@ -1319,7 +1292,7 @@ ctl_password_ok = 0; sb->sb_cc = sprintf(sb->sb_wptr, "Slirp command-line ready (type \"help\" for help).\r\nSlirp> "); sb->sb_wptr += sb->sb_cc; - do_echo=-1; + s->do_echo = -1; return(2); #endif } Index: qemu/slirp/tcp_timer.c =================================================================== --- qemu.orig/slirp/tcp_timer.c 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/tcp_timer.c 2007-10-22 18:49:01.000000000 +0000 @@ -36,34 +36,29 @@ #include <slirp.h> -int tcp_keepidle = TCPTV_KEEP_IDLE; -int tcp_keepintvl = TCPTV_KEEPINTVL; -int tcp_maxidle; -int so_options = DO_KEEPALIVE; - -struct tcpstat tcpstat; /* tcp statistics */ -u_int32_t tcp_now; /* for RFC 1323 timestamps */ +static struct tcpcb *tcp_timers(slirp_state_t *s, register struct tcpcb *tp, + int timer); /* * Fast timeout routine for processing delayed acks */ void -tcp_fasttimo() +tcp_fasttimo(slirp_state_t *s) { register struct socket *so; register struct tcpcb *tp; DEBUG_CALL("tcp_fasttimo"); - so = tcb.so_next; + so = s->tcb.so_next; if (so) - for (; so != &tcb; so = so->so_next) + for (; so != &s->tcb; so = so->so_next) if ((tp = (struct tcpcb *)so->so_tcpcb) && (tp->t_flags & TF_DELACK)) { tp->t_flags &= ~TF_DELACK; tp->t_flags |= TF_ACKNOW; - tcpstat.tcps_delack++; - (void) tcp_output(tp); + STAT(s->tcpstat.tcps_delack++); + (void) tcp_output(s, tp); } } @@ -73,7 +68,7 @@ * causes finite state machine actions if timers expire. */ void -tcp_slowtimo() +tcp_slowtimo(slirp_state_t *s) { register struct socket *ip, *ipnxt; register struct tcpcb *tp; @@ -81,21 +76,20 @@ DEBUG_CALL("tcp_slowtimo"); - tcp_maxidle = TCPTV_KEEPCNT * tcp_keepintvl; /* * Search through tcb's and update active timers. */ - ip = tcb.so_next; + ip = s->tcb.so_next; if (ip == 0) return; - for (; ip != &tcb; ip = ipnxt) { + for (; ip != &s->tcb; ip = ipnxt) { ipnxt = ip->so_next; tp = sototcpcb(ip); if (tp == 0) continue; for (i = 0; i < TCPT_NTIMERS; i++) { if (tp->t_timer[i] && --tp->t_timer[i] == 0) { - tcp_timers(tp,i); + tcp_timers(s, tp, i); if (ipnxt->so_prev != ip) goto tpgone; } @@ -106,20 +100,19 @@ tpgone: ; } - tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ + s->tcp_iss += TCP_ISSINCR / PR_SLOWHZ; /* increment iss */ #ifdef TCP_COMPAT_42 - if ((int)tcp_iss < 0) - tcp_iss = 0; /* XXX */ + if ((int)s->tcp_iss < 0) + s->tcp_iss = 0; /* XXX */ #endif - tcp_now++; /* for timestamps */ + s->tcp_now++; /* for timestamps */ } /* * Cancel all timers for TCP tp. */ void -tcp_canceltimers(tp) - struct tcpcb *tp; +tcp_canceltimers(struct tcpcb *tp) { register int i; @@ -127,16 +120,14 @@ tp->t_timer[i] = 0; } -int tcp_backoff[TCP_MAXRXTSHIFT + 1] = +const int tcp_backoff[TCP_MAXRXTSHIFT + 1] = { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 }; /* * TCP timer processing. */ -struct tcpcb * -tcp_timers(tp, timer) - register struct tcpcb *tp; - int timer; +static struct tcpcb * +tcp_timers(slirp_state_t *s, register struct tcpcb *tp, int timer) { register int rexmt; @@ -152,10 +143,10 @@ */ case TCPT_2MSL: if (tp->t_state != TCPS_TIME_WAIT && - tp->t_idle <= tcp_maxidle) - tp->t_timer[TCPT_2MSL] = tcp_keepintvl; + tp->t_idle <= TCP_MAXIDLE) + tp->t_timer[TCPT_2MSL] = TCPTV_KEEPINTVL; else - tp = tcp_close(tp); + tp = tcp_close(s, tp); break; /* @@ -192,8 +183,8 @@ * We tried our best, now the connection must die! */ tp->t_rxtshift = TCP_MAXRXTSHIFT; - tcpstat.tcps_timeoutdrop++; - tp = tcp_drop(tp, tp->t_softerror); + STAT(s->tcpstat.tcps_timeoutdrop++); + tp = tcp_drop(s, tp, tp->t_softerror); /* tp->t_softerror : ETIMEDOUT); */ /* XXX */ return (tp); /* XXX */ } @@ -204,7 +195,7 @@ */ tp->t_rxtshift = 6; } - tcpstat.tcps_rexmttimeo++; + STAT(s->tcpstat.tcps_rexmttimeo++); rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift]; TCPT_RANGESET(tp->t_rxtcur, rexmt, (short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */ @@ -259,7 +250,7 @@ tp->snd_ssthresh = win * tp->t_maxseg; tp->t_dupacks = 0; } - (void) tcp_output(tp); + (void) tcp_output(s, tp); break; /* @@ -267,10 +258,10 @@ * Force a byte to be output, if possible. */ case TCPT_PERSIST: - tcpstat.tcps_persisttimeo++; + STAT(s->tcpstat.tcps_persisttimeo++); tcp_setpersist(tp); tp->t_force = 1; - (void) tcp_output(tp); + (void) tcp_output(s, tp); tp->t_force = 0; break; @@ -279,13 +270,13 @@ * or drop connection if idle for too long. */ case TCPT_KEEP: - tcpstat.tcps_keeptimeo++; + STAT(s->tcpstat.tcps_keeptimeo++); if (tp->t_state < TCPS_ESTABLISHED) goto dropit; /* if (tp->t_socket->so_options & SO_KEEPALIVE && */ - if ((so_options) && tp->t_state <= TCPS_CLOSE_WAIT) { - if (tp->t_idle >= tcp_keepidle + tcp_maxidle) + if ((SO_OPTIONS) && tp->t_state <= TCPS_CLOSE_WAIT) { + if (tp->t_idle >= TCPTV_KEEP_IDLE + TCP_MAXIDLE) goto dropit; /* * Send a packet designed to force a response @@ -299,7 +290,7 @@ * by the protocol spec, this requires the * correspondent TCP to respond. */ - tcpstat.tcps_keepprobe++; + STAT(s->tcpstat.tcps_keepprobe++); #ifdef TCP_COMPAT_42 /* * The keepalive packet must have nonzero length @@ -308,17 +299,17 @@ tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL, tp->rcv_nxt - 1, tp->snd_una - 1, 0); #else - tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL, + tcp_respond(s, tp, &tp->t_template, (struct mbuf *)NULL, tp->rcv_nxt, tp->snd_una - 1, 0); #endif - tp->t_timer[TCPT_KEEP] = tcp_keepintvl; + tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL; } else - tp->t_timer[TCPT_KEEP] = tcp_keepidle; + tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE; break; dropit: - tcpstat.tcps_keepdrops++; - tp = tcp_drop(tp, 0); /* ETIMEDOUT); */ + STAT(s->tcpstat.tcps_keepdrops++); + tp = tcp_drop(s, tp, 0); /* ETIMEDOUT); */ break; } Index: qemu/slirp/tcp_timer.h =================================================================== --- qemu.orig/slirp/tcp_timer.h 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/tcp_timer.h 2007-10-21 18:47:11.000000000 +0000 @@ -108,6 +108,9 @@ #define TCP_LINGERTIME 120 /* linger at most 2 minutes */ #define TCP_MAXRXTSHIFT 12 /* maximum retransmits */ +/** Maximum idle time before timing out a connection. */ +#define TCP_MAXIDLE (TCPTV_KEEPCNT * TCPTV_KEEPINTVL) + #ifdef TCPTIMERS @@ -126,17 +129,12 @@ (tv) = (tvmax); \ } -extern int tcp_keepidle; /* time before keepalive probes begin */ -extern int tcp_keepintvl; /* time between keepalive probes */ -extern int tcp_maxidle; /* time to drop after starting probes */ -extern int tcp_ttl; /* time to live for TCP segs */ -extern int tcp_backoff[]; +extern const int tcp_backoff[]; struct tcpcb; -void tcp_fasttimo _P((void)); -void tcp_slowtimo _P((void)); +void tcp_fasttimo(slirp_state_t *s); +void tcp_slowtimo(slirp_state_t *s); void tcp_canceltimers _P((struct tcpcb *)); -struct tcpcb * tcp_timers _P((register struct tcpcb *, int)); #endif Index: qemu/slirp/tcp_var.h =================================================================== --- qemu.orig/slirp/tcp_var.h 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/tcp_var.h 2007-10-22 19:03:56.000000000 +0000 @@ -45,13 +45,12 @@ #else typedef u_int32_t tcpiphdrp_32; #endif - /* * Tcp control block, one per tcp; fields: */ struct tcpcb { - tcpiphdrp_32 seg_next; /* sequencing queue */ - tcpiphdrp_32 seg_prev; + tcpiphdrp_32 t_seg_next; /* sequencing queue */ + tcpiphdrp_32 t_seg_prev; short t_state; /* state of this connection */ short t_timer[TCPT_NTIMERS]; /* tcp timers */ short t_rxtshift; /* log(2) of rexmt exp. backoff */ @@ -138,6 +137,21 @@ }; +static inline struct tcpcb *tcpcb_get_next(struct tcpcb *tcpcb) +{ + return (struct tcpcb *)(unsigned long)tcpcb->t_seg_next; +} + +static inline void tcpcb_set_next(struct tcpcb *tcpcb, struct tcpcb *next) +{ + tcpcb->t_seg_next = (tcpiphdrp_32)(unsigned long)next; +} + +static inline void tcpcb_set_prev(struct tcpcb *tcpcb, struct tcpcb *prev) +{ + tcpcb->t_seg_prev = (tcpiphdrp_32)(unsigned long)prev; +} + #define sototcpcb(so) ((so)->so_tcpcb) /* @@ -170,21 +184,6 @@ #define TCP_REXMTVAL(tp) \ (((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar) -/* XXX - * We want to avoid doing m_pullup on incoming packets but that - * means avoiding dtom on the tcp reassembly code. That in turn means - * keeping an mbuf pointer in the reassembly queue (since we might - * have a cluster). As a quick hack, the source & destination - * port numbers (which are no longer needed once we've located the - * tcpcb) are overlayed with an mbuf pointer. - */ -#if SIZEOF_CHAR_P == 4 -typedef struct mbuf *mbufp_32; -#else -typedef u_int32_t mbufp_32; -#endif -#define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t)) - /* * TCP statistics. * Many of these should be kept per connection, @@ -246,7 +245,5 @@ u_long tcps_didnuttin; /* Times tcp_output didn't do anything XXX */ }; -extern struct tcpstat tcpstat; /* tcp statistics */ -extern u_int32_t tcp_now; /* for RFC 1323 timestamps */ #endif Index: qemu/slirp/tcpip.h =================================================================== --- qemu.orig/slirp/tcpip.h 2007-10-21 18:47:03.000000000 +0000 +++ qemu/slirp/tcpip.h 2007-10-22 15:39:29.000000000 +0000 @@ -37,6 +37,8 @@ #ifndef _TCPIP_H_ #define _TCPIP_H_ +#include "mbuf.h" + /* * Tcp+ip header, after ip options removed. */ @@ -44,8 +46,54 @@ struct ipovly ti_i; /* overlaid ip structure */ struct tcphdr ti_t; /* tcp header */ }; -#define ti_next ti_i.ih_next -#define ti_prev ti_i.ih_prev + +static inline struct tcpiphdr *ti_get_next(slirp_state_t *s, struct tcpiphdr *ti) +{ + return (struct tcpiphdr *)ih_get_next(s, &ti->ti_i); +} + +static inline struct tcpiphdr *ti_get_prev(slirp_state_t *s, struct tcpiphdr *ti) +{ + return (struct tcpiphdr *)ih_get_prev(s, &ti->ti_i); +} + +static inline void ti_set_next(slirp_state_t *s, struct tcpiphdr *ti, struct tcpiphdr *next) +{ + ih_set_next(s, &ti->ti_i, (struct ipovly *)next); +} + +static inline void ti_set_prev(slirp_state_t *s, struct tcpiphdr *ti, struct tcpiphdr *prev) +{ + ih_set_prev(s, &ti->ti_i, (struct ipovly *)prev); +} + +/* XXX + * We want to avoid doing m_pullup on incoming packets but that + * means avoiding dtom on the tcp reassembly code. That in turn means + * keeping an mbuf pointer in the reassembly queue (since we might + * have a cluster). As a quick hack, the source & destination + * port numbers (which are no longer needed once we've located the + * tcpcb) are overlayed with an mbuf pointer. + */ +#if 0 +#if SIZEOF_CHAR_P == 4 +typedef struct mbuf *mbufp_32; +#else +typedef u_int32_t mbufp_32; +#endif +#endif + +static inline struct mbuf *ti_get_mbuf(slirp_state_t *s, struct tcpiphdr *ti) +{ + return dtom(s, ti); + //return (struct mbuf *)(unsigned long)(*(mbufp_32 *)&(ti->ti_t)); +} + +static inline void ti_set_mbuf(struct tcpiphdr *ti, struct mbuf *m) +{ + //*(mbufp_32 *)&((ti)->ti_t) = (mbufp_32)(unsigned long)m; +} + #define ti_x1 ti_i.ih_x1 #define ti_pr ti_i.ih_pr #define ti_len ti_i.ih_len Index: qemu/slirp/tftp.c =================================================================== --- qemu.orig/slirp/tftp.c 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/tftp.c 2007-10-22 19:35:09.000000000 +0000 @@ -24,23 +24,10 @@ #include <slirp.h> -struct tftp_session { - int in_use; - unsigned char filename[TFTP_FILENAME_MAX]; - struct in_addr client_ip; - u_int16_t client_port; - - int timestamp; -}; - -struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX]; - -const char *tftp_prefix; - -static void tftp_session_update(struct tftp_session *spt) +static void tftp_session_update(slirp_state_t *s, struct tftp_session *spt) { - spt->timestamp = curtime; + spt->timestamp = s->curtime; spt->in_use = 1; } @@ -49,19 +36,19 @@ spt->in_use = 0; } -static int tftp_session_allocate(struct tftp_t *tp) +static int tftp_session_allocate(slirp_state_t *s, struct tftp_t *tp) { struct tftp_session *spt; int k; for (k = 0; k < TFTP_SESSIONS_MAX; k++) { - spt = &tftp_sessions[k]; + spt = &s->tftp_sessions[k]; if (!spt->in_use) goto found; /* sessions time out after 5 inactive seconds */ - if ((int)(curtime - spt->timestamp) > 5000) + if ((int)(s->curtime - spt->timestamp) > 5000) goto found; } @@ -72,18 +59,18 @@ memcpy(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip)); spt->client_port = tp->udp.uh_sport; - tftp_session_update(spt); + tftp_session_update(s, spt); return k; } -static int tftp_session_find(struct tftp_t *tp) +static int tftp_session_find(slirp_state_t *s, struct tftp_t *tp) { struct tftp_session *spt; int k; for (k = 0; k < TFTP_SESSIONS_MAX; k++) { - spt = &tftp_sessions[k]; + spt = &s->tftp_sessions[k]; if (spt->in_use) { if (!memcmp(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip))) { @@ -97,7 +84,7 @@ return -1; } -static int tftp_read_data(struct tftp_session *spt, u_int16_t block_nr, +static int tftp_read_data(slirp_state_t *s, struct tftp_session *spt, u_int16_t block_nr, u_int8_t *buf, int len) { int fd; @@ -106,7 +93,7 @@ int n; n = snprintf(buffer, sizeof(buffer), "%s/%s", - tftp_prefix, spt->filename); + s->tftp_prefix, spt->filename); if (n >= sizeof(buffer)) return -1; @@ -127,7 +114,8 @@ return bytes_read; } -static int tftp_send_oack(struct tftp_session *spt, +static int tftp_send_oack(slirp_state_t *s, + struct tftp_session *spt, const char *key, uint32_t value, struct tftp_t *recv_tp) { @@ -136,14 +124,14 @@ struct tftp_t *tp; int n = 0; - m = m_get(); + m = m_get(s); if (!m) return -1; memset(m->m_data, 0, m->m_size); - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; tp = (void *)m->m_data; m->m_data += sizeof(struct udpiphdr); @@ -159,14 +147,15 @@ m->m_len = sizeof(struct tftp_t) - 514 + n - sizeof(struct ip) - sizeof(struct udphdr); - udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); + udp_output2(s, NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); return 0; } -static int tftp_send_error(struct tftp_session *spt, +static int tftp_send_error(slirp_state_t *s, + struct tftp_session *spt, u_int16_t errorcode, const char *msg, struct tftp_t *recv_tp) { @@ -175,7 +164,7 @@ struct tftp_t *tp; int nobytes; - m = m_get(); + m = m_get(s); if (!m) { return -1; @@ -183,7 +172,7 @@ memset(m->m_data, 0, m->m_size); - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; tp = (void *)m->m_data; m->m_data += sizeof(struct udpiphdr); @@ -202,14 +191,15 @@ m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg) - sizeof(struct ip) - sizeof(struct udphdr); - udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); + udp_output2(s, NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); tftp_session_terminate(spt); return 0; } -static int tftp_send_data(struct tftp_session *spt, +static int tftp_send_data(slirp_state_t *s, + struct tftp_session *spt, u_int16_t block_nr, struct tftp_t *recv_tp) { @@ -222,7 +212,7 @@ return -1; } - m = m_get(); + m = m_get(s); if (!m) { return -1; @@ -230,7 +220,7 @@ memset(m->m_data, 0, m->m_size); - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; tp = (void *)m->m_data; m->m_data += sizeof(struct udpiphdr); @@ -243,14 +233,14 @@ daddr.sin_addr = spt->client_ip; daddr.sin_port = spt->client_port; - nobytes = tftp_read_data(spt, block_nr - 1, tp->x.tp_data.tp_buf, 512); + nobytes = tftp_read_data(s, spt, block_nr - 1, tp->x.tp_data.tp_buf, 512); if (nobytes < 0) { - m_free(m); + m_free(s, m); /* send "file not found" error back */ - tftp_send_error(spt, 1, "File not found", tp); + tftp_send_error(s, spt, 1, "File not found", tp); return -1; } @@ -258,10 +248,10 @@ m->m_len = sizeof(struct tftp_t) - (512 - nobytes) - sizeof(struct ip) - sizeof(struct udphdr); - udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); + udp_output2(s, NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); if (nobytes == 512) { - tftp_session_update(spt); + tftp_session_update(s, spt); } else { tftp_session_terminate(spt); @@ -270,19 +260,19 @@ return 0; } -static void tftp_handle_rrq(struct tftp_t *tp, int pktlen) +static void tftp_handle_rrq(slirp_state_t *s, struct tftp_t *tp, int pktlen) { struct tftp_session *spt; - int s, k, n; + int session, k, n; u_int8_t *src, *dst; - s = tftp_session_allocate(tp); + session = tftp_session_allocate(s, tp); - if (s < 0) { + if (session < 0) { return; } - spt = &tftp_sessions[s]; + spt = &s->tftp_sessions[session]; src = tp->x.tp_buf; dst = spt->filename; @@ -315,7 +305,7 @@ } if (memcmp(&src[k], "octet\0", 6) != 0) { - tftp_send_error(spt, 4, "Unsupported transfer mode", tp); + tftp_send_error(s, spt, 4, "Unsupported transfer mode", tp); return; } @@ -326,26 +316,26 @@ if ((spt->filename[0] != '/') || (spt->filename[strlen(spt->filename) - 1] == '/') || strstr(spt->filename, "/../")) { - tftp_send_error(spt, 2, "Access violation", tp); + tftp_send_error(s, spt, 2, "Access violation", tp); return; } /* only allow exported prefixes */ - if (!tftp_prefix) { - tftp_send_error(spt, 2, "Access violation", tp); + if (!s->tftp_prefix) { + tftp_send_error(s, spt, 2, "Access violation", tp); return; } /* check if the file exists */ - if (tftp_read_data(spt, 0, spt->filename, 0) < 0) { - tftp_send_error(spt, 1, "File not found", tp); + if (tftp_read_data(s, spt, 0, spt->filename, 0) < 0) { + tftp_send_error(s, spt, 1, "File not found", tp); return; } if (src[n - 1] != 0) { - tftp_send_error(spt, 2, "Access violation", tp); + tftp_send_error(s, spt, 2, "Access violation", tp); return; } @@ -356,7 +346,7 @@ k += strlen(key) + 1; if (k >= n) { - tftp_send_error(spt, 2, "Access violation", tp); + tftp_send_error(s, spt, 2, "Access violation", tp); return; } @@ -367,56 +357,56 @@ int tsize = atoi(value); struct stat stat_p; - if (tsize == 0 && tftp_prefix) { + if (tsize == 0 && s->tftp_prefix) { char buffer[1024]; int len; len = snprintf(buffer, sizeof(buffer), "%s/%s", - tftp_prefix, spt->filename); + s->tftp_prefix, spt->filename); if (stat(buffer, &stat_p) == 0) tsize = stat_p.st_size; else { - tftp_send_error(spt, 1, "File not found", tp); + tftp_send_error(s, spt, 1, "File not found", tp); return; } } - tftp_send_oack(spt, "tsize", tsize, tp); + tftp_send_oack(s, spt, "tsize", tsize, tp); } } - tftp_send_data(spt, 1, tp); + tftp_send_data(s, spt, 1, tp); } -static void tftp_handle_ack(struct tftp_t *tp, int pktlen) +static void tftp_handle_ack(slirp_state_t *s, struct tftp_t *tp, int pktlen) { - int s; + int session; - s = tftp_session_find(tp); + session = tftp_session_find(s, tp); - if (s < 0) { + if (session < 0) { return; } - if (tftp_send_data(&tftp_sessions[s], + if (tftp_send_data(s, &s->tftp_sessions[session], ntohs(tp->x.tp_data.tp_block_nr) + 1, tp) < 0) { return; } } -void tftp_input(struct mbuf *m) +void tftp_input(slirp_state_t *s, struct mbuf *m) { struct tftp_t *tp = (struct tftp_t *)m->m_data; switch(ntohs(tp->tp_op)) { case TFTP_RRQ: - tftp_handle_rrq(tp, m->m_len); + tftp_handle_rrq(s, tp, m->m_len); break; case TFTP_ACK: - tftp_handle_ack(tp, m->m_len); + tftp_handle_ack(s, tp, m->m_len); break; } } Index: qemu/slirp/tftp.h =================================================================== --- qemu.orig/slirp/tftp.h 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/tftp.h 2007-10-21 18:47:11.000000000 +0000 @@ -30,4 +30,4 @@ } x; }; -void tftp_input(struct mbuf *m); +void tftp_input(slirp_state_t *s, struct mbuf *m); Index: qemu/slirp/udp.c =================================================================== --- qemu.orig/slirp/udp.c 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/udp.c 2007-10-22 18:51:57.000000000 +0000 @@ -45,38 +45,32 @@ #include <slirp.h> #include "ip_icmp.h" -struct udpstat udpstat; - -struct socket udb; +static u_int8_t udp_tos(struct socket *so); +static void udp_emu(slirp_state_t *s, struct socket *so, struct mbuf *m); /* * UDP protocol implementation. * Per RFC 768, August, 1980. */ -#ifndef COMPAT_42 -int udpcksum = 1; -#else -int udpcksum = 0; /* XXX */ -#endif - -struct socket *udp_last_so = &udb; +#define udpcksum 1 void -udp_init() +udp_init(slirp_state_t *s) { - udb.so_next = udb.so_prev = &udb; + s->udp_last_so = &s->udb; + s->udb.so_next = s->udb.so_prev = &s->udb; } + /* m->m_data points at ip packet header * m->m_len length ip packet * ip->ip_len length data (IPDU) */ void -udp_input(m, iphlen) - register struct mbuf *m; - int iphlen; +udp_input(slirp_state_t *s, register struct mbuf *m, int iphlen) { register struct ip *ip; register struct udphdr *uh; + struct ipovly *ih; /* struct mbuf *opts = 0;*/ int len; struct ip save_ip; @@ -86,7 +80,7 @@ DEBUG_ARG("m = %lx", (long)m); DEBUG_ARG("iphlen = %d", iphlen); - udpstat.udps_ipackets++; + STAT(s->udpstat.udps_ipackets++); /* * Strip IP options, if any; should skip this, @@ -113,7 +107,7 @@ if (ip->ip_len != len) { if (len > ip->ip_len) { - udpstat.udps_badlen++; + STAT(s->udpstat.udps_badlen++); goto bad; } m_adj(m, len - ip->ip_len); @@ -130,17 +124,18 @@ /* * Checksum extended UDP header and data. */ + ih = (struct ipovly *)ip; if (udpcksum && uh->uh_sum) { - ((struct ipovly *)ip)->ih_next = 0; - ((struct ipovly *)ip)->ih_prev = 0; - ((struct ipovly *)ip)->ih_x1 = 0; - ((struct ipovly *)ip)->ih_len = uh->uh_ulen; + ih_set_next(s, ih, 0); + ih_set_prev(s, ih, 0); + ih->ih_x1 = 0; + ih->ih_len = uh->uh_ulen; /* keep uh_sum for ICMP reply * uh->uh_sum = cksum(m, len + sizeof (struct ip)); * if (uh->uh_sum) { */ if(cksum(m, len + sizeof(struct ip))) { - udpstat.udps_badsum++; + STAT(s->udpstat.udps_badsum++); goto bad; } } @@ -149,7 +144,7 @@ * handle DHCP/BOOTP */ if (ntohs(uh->uh_dport) == BOOTP_SERVER) { - bootp_input(m); + bootp_input(s, m); goto bad; } @@ -157,19 +152,19 @@ * handle TFTP */ if (ntohs(uh->uh_dport) == TFTP_SERVER) { - tftp_input(m); + tftp_input(s, m); goto bad; } /* * Locate pcb for datagram. */ - so = udp_last_so; + so = s->udp_last_so; if (so->so_lport != uh->uh_sport || so->so_laddr.s_addr != ip->ip_src.s_addr) { struct socket *tmp; - for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) { + for (tmp = s->udb.so_next; tmp != &s->udb; tmp = tmp->so_next) { if (tmp->so_lport == uh->uh_sport && tmp->so_laddr.s_addr == ip->ip_src.s_addr) { tmp->so_faddr.s_addr = ip->ip_dst.s_addr; @@ -178,11 +173,11 @@ break; } } - if (tmp == &udb) { + if (tmp == &s->udb) { so = NULL; } else { - udpstat.udpps_pcbcachemiss++; - udp_last_so = so; + STAT(s->udpstat.udpps_pcbcachemiss++); + s->udp_last_so = so; } } @@ -192,10 +187,10 @@ * create one */ if ((so = socreate()) == NULL) goto bad; - if(udp_attach(so) == -1) { + if(udp_attach(s, so) == -1) { DEBUG_MISC((dfd," udp_attach errno = %d-%s\n", errno,strerror(errno))); - sofree(so); + sofree(s, so); goto bad; } @@ -226,17 +221,17 @@ * Now we sendto() the packet. */ if (so->so_emu) - udp_emu(so, m); + udp_emu(s, so, m); - if(sosendto(so,m) == -1) { + if(sosendto(s, so,m) == -1) { m->m_len += iphlen; m->m_data -= iphlen; *ip=save_ip; DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno))); - icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); + icmp_error(s, m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); } - m_free(so->so_m); /* used for ICMP if error on sorecvfrom */ + m_free(s, so->so_m); /* used for ICMP if error on sorecvfrom */ /* restore the orig mbuf packet */ m->m_len += iphlen; @@ -246,12 +241,12 @@ return; bad: - m_freem(m); + m_freem(s, m); /* if (opts) m_freem(opts); */ return; } -int udp_output2(struct socket *so, struct mbuf *m, +int udp_output2(slirp_state_t *s, struct socket *so, struct mbuf *m, struct sockaddr_in *saddr, struct sockaddr_in *daddr, int iptos) { @@ -275,7 +270,8 @@ * and addresses and length put into network format. */ ui = mtod(m, struct udpiphdr *); - ui->ui_next = ui->ui_prev = 0; + ui_set_next(s, ui, NULL); + ui_set_prev(s, ui, NULL); ui->ui_x1 = 0; ui->ui_pr = IPPROTO_UDP; ui->ui_len = htons(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */ @@ -296,37 +292,35 @@ } ((struct ip *)ui)->ip_len = m->m_len; - ((struct ip *)ui)->ip_ttl = ip_defttl; + ((struct ip *)ui)->ip_ttl = IPDEFTTL; ((struct ip *)ui)->ip_tos = iptos; - udpstat.udps_opackets++; + STAT(s->udpstat.udps_opackets++); - error = ip_output(so, m); + error = ip_output(s, so, m); return (error); } -int udp_output(struct socket *so, struct mbuf *m, +int udp_output(slirp_state_t *s, struct socket *so, struct mbuf *m, struct sockaddr_in *addr) - { struct sockaddr_in saddr, daddr; saddr = *addr; - if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) { + if ((so->so_faddr.s_addr & htonl(0xffffff00)) == s->special_addr.s_addr) { saddr.sin_addr.s_addr = so->so_faddr.s_addr; if ((so->so_faddr.s_addr & htonl(0x000000ff)) == htonl(0xff)) - saddr.sin_addr.s_addr = alias_addr.s_addr; + saddr.sin_addr.s_addr = s->alias_addr.s_addr; } daddr.sin_addr = so->so_laddr; daddr.sin_port = so->so_lport; - return udp_output2(so, m, &saddr, &daddr, so->so_iptos); + return udp_output2(s, so, m, &saddr, &daddr, so->so_iptos); } int -udp_attach(so) - struct socket *so; +udp_attach(slirp_state_t *s, struct socket *so) { struct sockaddr_in addr; @@ -349,25 +343,30 @@ errno=lasterrno; #endif } else { + int opt = 1; /* success, insert in queue */ - so->so_expire = curtime + SO_EXPIRE; - insque(so,&udb); + so->so_expire = s->curtime + SO_EXPIRE; + /* enable broadcast for later use */ + setsockopt(so->s, SOL_SOCKET, SO_BROADCAST, (const char *)&opt, sizeof(opt)); + insque(s, so, &s->udb); } } return(so->s); } void -udp_detach(so) - struct socket *so; +udp_detach(slirp_state_t *s, struct socket *so) { + /* Correctly update list if detaching last socket in list. */ + if (so == s->udp_last_so) + s->udp_last_so = &s->udb; closesocket(so->s); /* if (so->so_m) m_free(so->so_m); done by sofree */ - sofree(so); + sofree(s, so); } -struct tos_t udptos[] = { +static const struct tos_t udptos[] = { {0, 53, IPTOS_LOWDELAY, 0}, /* DNS */ {517, 517, IPTOS_LOWDELAY, EMU_TALK}, /* talk */ {518, 518, IPTOS_LOWDELAY, EMU_NTALK}, /* ntalk */ @@ -375,9 +374,8 @@ {0, 0, 0, 0} }; -u_int8_t -udp_tos(so) - struct socket *so; +static u_int8_t +udp_tos(struct socket *so) { int i = 0; @@ -400,10 +398,8 @@ /* * Here, talk/ytalk/ntalk requests must be emulated */ -void -udp_emu(so, m) - struct socket *so; - struct mbuf *m; +static void +udp_emu(slirp_state_t *s, struct socket *so, struct mbuf *m) { struct sockaddr_in addr; int addrlen = sizeof(addr); @@ -470,14 +466,14 @@ nmsg = (CTL_MSG *) buff; type = omsg->type; OTOSIN(omsg, ctl_addr)->sin_port = addr.sin_port; - OTOSIN(omsg, ctl_addr)->sin_addr = our_addr; + OTOSIN(omsg, ctl_addr)->sin_addr = s->our_addr; strncpy(omsg->l_name, getlogin(), NAME_SIZE_OLD); } else { /* new talk */ omsg = (CTL_MSG_OLD *) buff; nmsg = mtod(m, CTL_MSG *); type = nmsg->type; OTOSIN(nmsg, ctl_addr)->sin_port = addr.sin_port; - OTOSIN(nmsg, ctl_addr)->sin_addr = our_addr; + OTOSIN(nmsg, ctl_addr)->sin_addr = s->our_addr; strncpy(nmsg->l_name, getlogin(), NAME_SIZE_OLD); } @@ -530,9 +526,9 @@ (struct sockaddr *) &addr, &addrlen); OTOSIN(omsg, addr)->sin_port = addr.sin_port; - OTOSIN(omsg, addr)->sin_addr = our_addr; + OTOSIN(omsg, addr)->sin_addr = s->our_addr; OTOSIN(nmsg, addr)->sin_port = addr.sin_port; - OTOSIN(nmsg, addr)->sin_addr = our_addr; + OTOSIN(nmsg, addr)->sin_addr = s->our_addr; /* send LEAVE_INVITEs */ temp_port = OTOSIN(omsg, ctl_addr)->sin_port; @@ -541,7 +537,7 @@ omsg->type = nmsg->type = LEAVE_INVITE; s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); - addr.sin_addr = our_addr; + addr.sin_addr = s->our_addr; addr.sin_family = AF_INET; addr.sin_port = htons(517); sendto(s, (char *)omsg, sizeof(*omsg), 0, @@ -572,7 +568,7 @@ OTOSIN(nmsg, ctl_addr)->sin_port = 0; s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); - addr.sin_addr = our_addr; + addr.sin_addr = s->our_addr; addr.sin_family = AF_INET; addr.sin_port = htons(517); sendto(s, (char *)omsg, sizeof(*omsg), 0, @@ -621,7 +617,7 @@ return; cu_head = mtod(m, struct cu_header *); cu_head->s_port = addr.sin_port; - cu_head->so_addr = our_addr.s_addr; + cu_head->so_addr = s->our_addr.s_addr; } return; @@ -629,11 +625,8 @@ } struct socket * -udp_listen(port, laddr, lport, flags) - u_int port; - u_int32_t laddr; - u_int lport; - int flags; +udp_listen(slirp_state_t *s, u_int port, u_int32_t laddr, u_int lport, + int flags) { struct sockaddr_in addr; struct socket *so; @@ -644,15 +637,15 @@ return NULL; } so->s = socket(AF_INET,SOCK_DGRAM,0); - so->so_expire = curtime + SO_EXPIRE; - insque(so,&udb); + so->so_expire = s->curtime + SO_EXPIRE; + insque(s, so, &s->udb); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = port; if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) { - udp_detach(so); + udp_detach(s, so); return NULL; } setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)); @@ -660,8 +653,8 @@ getsockname(so->s,(struct sockaddr *)&addr,&addrlen); so->so_fport = addr.sin_port; - if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) - so->so_faddr = alias_addr; + if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == s->loopback_addr.s_addr) + so->so_faddr = s->alias_addr; else so->so_faddr = addr.sin_addr; Index: qemu/slirp/udp.h =================================================================== --- qemu.orig/slirp/udp.h 2007-10-21 18:47:08.000000000 +0000 +++ qemu/slirp/udp.h 2007-10-22 15:39:59.000000000 +0000 @@ -40,8 +40,6 @@ #define UDP_TTL 0x60 #define UDP_UDPDATALEN 16192 -extern struct socket *udp_last_so; - /* * Udp protocol header. * Per RFC 768, September, 1981. @@ -60,8 +58,17 @@ struct ipovly ui_i; /* overlaid ip structure */ struct udphdr ui_u; /* udp header */ }; -#define ui_next ui_i.ih_next -#define ui_prev ui_i.ih_prev + +static inline void ui_set_next(slirp_state_t *s, struct udpiphdr *ui, struct udpiphdr *next) +{ + ih_set_next(s, &ui->ui_i, (struct ipovly *)next); +} + +static inline void ui_set_prev(slirp_state_t *s, struct udpiphdr *ui, struct udpiphdr *prev) +{ + ih_set_prev(s, &ui->ui_i, (struct ipovly *)prev); +} + #define ui_x1 ui_i.ih_x1 #define ui_pr ui_i.ih_pr #define ui_len ui_i.ih_len @@ -92,19 +99,17 @@ #define UDPCTL_CHECKSUM 1 /* checksum UDP packets */ #define UDPCTL_MAXID 2 -extern struct udpstat udpstat; -extern struct socket udb; struct mbuf; -void udp_init _P((void)); -void udp_input _P((register struct mbuf *, int)); -int udp_output _P((struct socket *, struct mbuf *, struct sockaddr_in *)); -int udp_attach _P((struct socket *)); -void udp_detach _P((struct socket *)); -u_int8_t udp_tos _P((struct socket *)); -void udp_emu _P((struct socket *, struct mbuf *)); -struct socket * udp_listen _P((u_int, u_int32_t, u_int, int)); -int udp_output2(struct socket *so, struct mbuf *m, +void udp_init(slirp_state_t *s); +void udp_input(slirp_state_t *s, register struct mbuf *m, int iphlen); +int udp_output(slirp_state_t *s, struct socket *so, struct mbuf *m, + struct sockaddr_in *addr); +int udp_attach(slirp_state_t *s, struct socket *so); +void udp_detach(slirp_state_t *s, struct socket *so); +struct socket *udp_listen(slirp_state_t *s, u_int port, u_int32_t laddr, + u_int lport, int flags); +int udp_output2(slirp_state_t *s, struct socket *so, struct mbuf *m, struct sockaddr_in *saddr, struct sockaddr_in *daddr, int iptos); #endif Index: qemu/vl.c =================================================================== --- qemu.orig/vl.c 2007-10-21 18:47:08.000000000 +0000 +++ qemu/vl.c 2007-10-21 18:47:11.000000000 +0000 @@ -3608,13 +3608,28 @@ static int slirp_inited; static VLANClientState *slirp_vc; +static const char *tftp_prefix; +static const char *bootp_filename; +static const char *slirp_hostname; +static void *slirp_opaque; +static char slirp_network[32]; -int slirp_can_output(void) +void slirp_maybe_init(void) +{ + if (!slirp_inited) { + slirp_inited = 1; + sprintf(slirp_network, "10.0.%d.0", slirp_vc->vlan->id + 2); + slirp_opaque = slirp_init(slirp_vc, slirp_hostname, tftp_prefix, + slirp_network); + } +} + +int slirp_can_output(void *user) { return !slirp_vc || qemu_can_send_packet(slirp_vc); } -void slirp_output(const uint8_t *pkt, int pkt_len) +void slirp_output(void *user, const uint8_t *pkt, int pkt_len) { #if 0 printf("slirp output:\n"); @@ -3631,17 +3646,13 @@ printf("slirp input:\n"); hex_dump(stdout, buf, size); #endif - slirp_input(buf, size); + slirp_input(slirp_opaque, buf, size); } static int net_slirp_init(VLANState *vlan) { - if (!slirp_inited) { - slirp_inited = 1; - slirp_init(); - } - slirp_vc = qemu_new_vlan_client(vlan, - slirp_receive, NULL, NULL); + slirp_vc = qemu_new_vlan_client(vlan, slirp_receive, NULL, NULL); + slirp_maybe_init(); snprintf(slirp_vc->info_str, sizeof(slirp_vc->info_str), "user redirector"); return 0; } @@ -3654,11 +3665,7 @@ struct in_addr guest_addr; int host_port, guest_port; - if (!slirp_inited) { - slirp_inited = 1; - slirp_init(); - } - + slirp_maybe_init(); p = redir_str; if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) goto fail; @@ -3688,7 +3695,8 @@ if (r == p) goto fail; - if (slirp_redir(is_udp, host_port, guest_addr, guest_port) < 0) { + if (slirp_redir(slirp_opaque, is_udp, host_port, guest_addr, + guest_port) < 0) { fprintf(stderr, "qemu: could not set up redirection\n"); exit(1); } @@ -3732,11 +3740,7 @@ char smb_cmdline[1024]; FILE *f; - if (!slirp_inited) { - slirp_inited = 1; - slirp_init(); - } - + slirp_maybe_init(); /* XXX: better tmp dir construction */ snprintf(smb_dir, sizeof(smb_dir), "/tmp/qemu-smb.%d", getpid()); if (mkdir(smb_dir, 0700) < 0) { @@ -3777,10 +3781,14 @@ snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s", SMBD_COMMAND, smb_conf); - slirp_add_exec(0, smb_cmdline, 4, 139); + slirp_add_exec(slirp_opaque, 0, smb_cmdline, 4, 139); } #endif /* !defined(_WIN32) */ +void do_info_slirp(void) +{ + slirp_stats(slirp_opaque); +} #endif /* CONFIG_SLIRP */ @@ -4600,8 +4608,8 @@ } else #ifdef CONFIG_SLIRP if (!strcmp(device, "user")) { - if (get_param_value(buf, sizeof(buf), "hostname", p)) { - pstrcpy(slirp_hostname, sizeof(slirp_hostname), buf); + if (get_param_value(buf, sizeof(buf), "hostname", p) <= 0) { + slirp_hostname = strdup(buf); } vlan->nb_host_devs++; ret = net_slirp_init(vlan); @@ -6823,7 +6831,7 @@ #endif #if defined(CONFIG_SLIRP) if (slirp_inited) { - slirp_select_fill(&nfds, &rfds, &wfds, &xfds); + slirp_select_fill(slirp_opaque, &nfds, &rfds, &wfds, &xfds); } #endif ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv); @@ -6857,7 +6865,7 @@ FD_ZERO(&wfds); FD_ZERO(&xfds); } - slirp_select_poll(&rfds, &wfds, &xfds); + slirp_select_poll(slirp_opaque, &rfds, &wfds, &xfds); } #endif qemu_aio_poll(); Index: qemu/vl.h =================================================================== --- qemu.orig/vl.h 2007-10-21 18:47:08.000000000 +0000 +++ qemu/vl.h 2007-10-21 18:47:11.000000000 +0000 @@ -183,7 +183,6 @@ extern int semihosting_enabled; extern int autostart; extern int old_param; -extern const char *bootp_filename; #define MAX_OPTION_ROMS 16 extern const char *option_rom[MAX_OPTION_ROMS]; @@ -439,6 +438,9 @@ extern int nb_nics; extern NICInfo nd_table[MAX_NICS]; +/* SLIRP */ +void do_info_slirp(void); + /* timers */ typedef struct QEMUClock QEMUClock; ^ permalink raw reply [flat|nested] 4+ messages in thread
* [Qemu-devel] Re: PATCH, RFC: Slirp improvements @ 2007-10-23 20:39 Fabrice Bellard 2007-10-24 20:04 ` Blue Swirl 0 siblings, 1 reply; 4+ messages in thread From: Fabrice Bellard @ 2007-10-23 20:39 UTC (permalink / raw) To: Blue Swirl; +Cc: qemu-devel > I tried harder to change the SLIRP queue stuff to something saner by > hiding the pointer access inside inlined functions. Still when I > changed the 32 bit pointers to native 64 bit (or moved the pointers > outside the packet), qemu crashes. Must be some devilishly hidden > access somewhere. I already fixed one, which involved recycling port > number fields for buffer pointers. IMHO there should be some kind of > corporeal punishments mandated by law for writing this kind of mess. > Maybe it would even be easier to create a new userland IP stack based > on Linux from scratch instead of fixing this. > > I think I'll just commit in the log part, unless there are objections. IMHO you should add a context in the 'struct socket' structure so that you can avoid adding a context in all the functions manipulating this structure. The same holds for mbuf. Regards, Fabrice. ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] Re: PATCH, RFC: Slirp improvements 2007-10-23 20:39 Fabrice Bellard @ 2007-10-24 20:04 ` Blue Swirl 0 siblings, 0 replies; 4+ messages in thread From: Blue Swirl @ 2007-10-24 20:04 UTC (permalink / raw) To: Fabrice Bellard; +Cc: qemu-devel [-- Attachment #1: Type: text/plain, Size: 1158 bytes --] On 10/23/07, Fabrice Bellard <fabrice@bellard.org> wrote: > > I tried harder to change the SLIRP queue stuff to something saner by > > hiding the pointer access inside inlined functions. Still when I > > changed the 32 bit pointers to native 64 bit (or moved the pointers > > outside the packet), qemu crashes. Must be some devilishly hidden > > access somewhere. I already fixed one, which involved recycling port > > number fields for buffer pointers. IMHO there should be some kind of > > corporeal punishments mandated by law for writing this kind of mess. > > Maybe it would even be easier to create a new userland IP stack based > > on Linux from scratch instead of fixing this. > > > > I think I'll just commit in the log part, unless there are objections. > > IMHO you should add a context in the 'struct socket' structure so that > you can avoid adding a context in all the functions manipulating this > structure. The same holds for mbuf. That way some changes could be avoided, maybe gain some performance. Somehow I feel this reverses the hierarchy, though. I extracted the logging parts and safest fixes into two patches. Comments? [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: slirp_const_etc.diff --] [-- Type: text/x-diff; name=slirp_const_etc.diff, Size: 36098 bytes --] Index: qemu/slirp/bootp.c =================================================================== --- qemu.orig/slirp/bootp.c 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/bootp.c 2007-10-24 19:42:40.000000000 +0000 @@ -149,7 +149,7 @@ if ((m = m_get()) == NULL) return; - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; rbp = (struct bootp_t *)m->m_data; m->m_data += sizeof(struct udpiphdr); memset(rbp, 0, sizeof(struct bootp_t)); Index: qemu/slirp/debug.c =================================================================== --- qemu.orig/slirp/debug.c 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/debug.c 2007-10-24 19:42:40.000000000 +0000 @@ -92,9 +92,9 @@ lprint(" \r\n"); - if (if_comp & IF_COMPRESS) + if (IF_COMP & IF_COMPRESS) strcpy(buff, "on"); - else if (if_comp & IF_NOCOMPRESS) + else if (IF_COMP & IF_NOCOMPRESS) strcpy(buff, "off"); else strcpy(buff, "off (for now)"); Index: qemu/slirp/if.c =================================================================== --- qemu.orig/slirp/if.c 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/if.c 2007-10-24 19:42:40.000000000 +0000 @@ -7,9 +7,6 @@ #include <slirp.h> -int if_mtu, if_mru; -int if_comp; -int if_maxlinkhdr; int if_queued = 0; /* Number of packets queued so far */ int if_thresh = 10; /* Number of packets queued before we start sending * (to prevent allocing too many mbufs) */ @@ -41,23 +38,6 @@ void if_init() { -#if 0 - /* - * Set if_maxlinkhdr to 48 because it's 40 bytes for TCP/IP, - * and 8 bytes for PPP, but need to have it on an 8byte boundary - */ -#ifdef USE_PPP - if_maxlinkhdr = 48; -#else - if_maxlinkhdr = 40; -#endif -#else - /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */ - if_maxlinkhdr = 2 + 14 + 40; -#endif - if_mtu = 1500; - if_mru = 1500; - if_comp = IF_AUTOCOMP; if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq; if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq; // sl_compress_init(&comp_s); Index: qemu/slirp/if.h =================================================================== --- qemu.orig/slirp/if.h 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/if.h 2007-10-24 19:42:40.000000000 +0000 @@ -13,12 +13,25 @@ #define IF_AUTOCOMP 0x04 /* Autodetect (default) */ #define IF_NOCIDCOMP 0x08 /* CID compression */ -/* Needed for FreeBSD */ -#undef if_mtu -extern int if_mtu; -extern int if_mru; /* MTU and MRU */ -extern int if_comp; /* Flags for compression */ -extern int if_maxlinkhdr; +#define IF_MTU 1500 +#define IF_MRU 1500 +#define IF_COMP IF_AUTOCOMP /* Flags for compression */ + +#if 0 +/* + * Set if_maxlinkhdr to 48 because it's 40 bytes for TCP/IP, + * and 8 bytes for PPP, but need to have it on an 8byte boundary + */ +#ifdef USE_PPP +#define IF_MAXLINKHDR 48 +#else +#define IF_MAXLINKHDR 40 +#endif +#else + /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */ +#define IF_MAXLINKHDR (2 + 14 + 40) +#endif + extern int if_queued; /* Number of packets queued so far */ extern int if_thresh; /* Number of packets queued before we start sending * (to prevent allocing too many mbufs) */ Index: qemu/slirp/ip_icmp.c =================================================================== --- qemu.orig/slirp/ip_icmp.c 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/ip_icmp.c 2007-10-24 19:42:40.000000000 +0000 @@ -46,7 +46,7 @@ char icmp_ping_msg[] = "This is a psuedo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n"; /* list of actions for icmp_error() on RX of an icmp message */ -static int icmp_flush[19] = { +static const int icmp_flush[19] = { /* ECHO REPLY (0) */ 0, 1, 1, Index: qemu/slirp/ip_input.c =================================================================== --- qemu.orig/slirp/ip_input.c 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/ip_input.c 2007-10-24 19:42:40.000000000 +0000 @@ -45,14 +45,19 @@ #include <slirp.h> #include "ip_icmp.h" -int ip_defttl; - #ifdef LOG_ENABLED struct ipstat ipstat; #endif struct ipq ipq; +static struct ip *ip_reass(register struct ipasfrag *ip, + register struct ipq *fp); +static void ip_freef(struct ipq *fp); +static void ip_enq(register struct ipasfrag *p, + register struct ipasfrag *prev); +static void ip_deq(register struct ipasfrag *p); + /* * IP initialization: fill in IP protocol switch table. * All protocols not implemented in kernel go to raw IP protocol handler. @@ -64,7 +69,6 @@ ip_id = tt.tv_sec & 0xffff; udp_init(); tcp_init(); - ip_defttl = IPDEFTTL; } /* @@ -239,10 +243,8 @@ * reassembly of this datagram already exists, then it * is given as fp; otherwise have to make a chain. */ -struct ip * -ip_reass(ip, fp) - register struct ipasfrag *ip; - register struct ipq *fp; +static struct ip * +ip_reass(register struct ipasfrag *ip, register struct ipq *fp) { register struct mbuf *m = dtom(ip); register struct ipasfrag *q; @@ -398,9 +400,8 @@ * Free a fragment reassembly header and all * associated datagrams. */ -void -ip_freef(fp) - struct ipq *fp; +static void +ip_freef(struct ipq *fp) { register struct ipasfrag *q, *p; @@ -418,9 +419,8 @@ * Put an ip fragment on a reassembly chain. * Like insque, but pointers in middle of structure. */ -void -ip_enq(p, prev) - register struct ipasfrag *p, *prev; +static void +ip_enq(register struct ipasfrag *p, register struct ipasfrag *prev) { DEBUG_CALL("ip_enq"); DEBUG_ARG("prev = %lx", (long)prev); @@ -433,9 +433,8 @@ /* * To ip_enq as remque is to insque. */ -void -ip_deq(p) - register struct ipasfrag *p; +static void +ip_deq(register struct ipasfrag *p) { ((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next; ((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev; Index: qemu/slirp/ip_output.c =================================================================== --- qemu.orig/slirp/ip_output.c 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/ip_output.c 2007-10-24 19:42:40.000000000 +0000 @@ -96,7 +96,7 @@ /* * If small enough for interface, can just send directly. */ - if ((u_int16_t)ip->ip_len <= if_mtu) { + if ((u_int16_t)ip->ip_len <= IF_MTU) { ip->ip_len = htons((u_int16_t)ip->ip_len); ip->ip_off = htons((u_int16_t)ip->ip_off); ip->ip_sum = 0; @@ -116,7 +116,7 @@ goto bad; } - len = (if_mtu - hlen) &~ 7; /* ip databytes per packet */ + len = (IF_MTU - hlen) &~ 7; /* ip databytes per packet */ if (len < 8) { error = -1; goto bad; @@ -140,7 +140,7 @@ STAT(ipstat.ips_odropped++); goto sendorfree; } - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; mhip = mtod(m, struct ip *); *mhip = *ip; Index: qemu/slirp/main.h =================================================================== --- qemu.orig/slirp/main.h 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/main.h 2007-10-24 19:42:40.000000000 +0000 @@ -42,7 +42,6 @@ extern char *socket_path; extern int towrite_max; extern int ppp_exit; -extern int so_options; extern int tcp_keepintvl; extern uint8_t client_ethaddr[6]; Index: qemu/slirp/mbuf.c =================================================================== --- qemu.orig/slirp/mbuf.c 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/mbuf.c 2007-10-24 19:42:40.000000000 +0000 @@ -21,27 +21,20 @@ char *mclrefcnt; int mbuf_alloced = 0; struct mbuf m_freelist, m_usedlist; -int mbuf_thresh = 30; +#define MBUF_THRESH 30 int mbuf_max = 0; -int msize; + +/* + * Find a nice value for msize + * XXX if_maxlinkhdr already in mtu + */ +#define MSIZE (IF_MTU + IF_MAXLINKHDR + sizeof(struct m_hdr ) + 6) void m_init() { m_freelist.m_next = m_freelist.m_prev = &m_freelist; m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist; - msize_init(); -} - -void -msize_init() -{ - /* - * Find a nice value for msize - * XXX if_maxlinkhdr already in mtu - */ - msize = (if_mtu>if_mru?if_mtu:if_mru) + - if_maxlinkhdr + sizeof(struct m_hdr ) + 6; } /* @@ -61,10 +54,10 @@ DEBUG_CALL("m_get"); if (m_freelist.m_next == &m_freelist) { - m = (struct mbuf *)malloc(msize); + m = (struct mbuf *)malloc(MSIZE); if (m == NULL) goto end_error; mbuf_alloced++; - if (mbuf_alloced > mbuf_thresh) + if (mbuf_alloced > MBUF_THRESH) flags = M_DOFREE; if (mbuf_alloced > mbuf_max) mbuf_max = mbuf_alloced; @@ -78,7 +71,7 @@ m->m_flags = (flags | M_USEDLIST); /* Initialise it */ - m->m_size = msize - sizeof(struct m_hdr); + m->m_size = MSIZE - sizeof(struct m_hdr); m->m_data = m->m_dat; m->m_len = 0; m->m_nextpkt = 0; Index: qemu/slirp/mbuf.h =================================================================== --- qemu.orig/slirp/mbuf.h 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/mbuf.h 2007-10-24 19:42:40.000000000 +0000 @@ -135,7 +135,6 @@ extern int mbuf_max; void m_init _P((void)); -void msize_init _P((void)); struct mbuf * m_get _P((void)); void m_free _P((struct mbuf *)); void m_cat _P((register struct mbuf *, register struct mbuf *)); Index: qemu/slirp/misc.c =================================================================== --- qemu.orig/slirp/misc.c 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/misc.c 2007-10-24 19:42:40.000000000 +0000 @@ -8,8 +8,7 @@ #define WANT_SYS_IOCTL_H #include <slirp.h> -u_int curtime, time_fasttimo, last_slowtimo, detach_time; -u_int detach_wait = 600000; /* 10 minutes */ +u_int curtime, time_fasttimo, last_slowtimo; #if 0 int x_port = -1; @@ -214,10 +213,7 @@ #ifdef _WIN32 int -fork_exec(so, ex, do_pty) - struct socket *so; - char *ex; - int do_pty; +fork_exec(struct socket *so, const char *ex, int do_pty) { /* not implemented */ return 0; @@ -225,6 +221,7 @@ #else +#ifndef CONFIG_QEMU int slirp_openpty(amaster, aslave) int *amaster, *aslave; @@ -289,6 +286,7 @@ return (-1); #endif } +#endif /* * XXX This is ugly @@ -302,23 +300,20 @@ * do_ptr = 2 Fork/exec using pty */ int -fork_exec(so, ex, do_pty) - struct socket *so; - char *ex; - int do_pty; +fork_exec(struct socket *so, const char *ex, int do_pty) { int s; struct sockaddr_in addr; int addrlen = sizeof(addr); int opt; - int master; + int master = -1; char *argv[256]; #if 0 char buff[256]; #endif /* don't want to clobber the original */ char *bptr; - char *curarg; + const char *curarg; int c, i, ret; DEBUG_CALL("fork_exec"); @@ -327,10 +322,12 @@ DEBUG_ARG("do_pty = %lx", (long)do_pty); if (do_pty == 2) { +#if 0 if (slirp_openpty(&master, &s) == -1) { lprint("Error: openpty failed: %s\n", strerror(errno)); return 0; } +#endif } else { addr.sin_family = AF_INET; addr.sin_port = 0; @@ -390,7 +387,7 @@ dup2(s, 0); dup2(s, 1); dup2(s, 2); - for (s = 3; s <= 255; s++) + for (s = getdtablesize() - 1; s >= 3; s--) close(s); i = 0; Index: qemu/slirp/misc.h =================================================================== --- qemu.orig/slirp/misc.h 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/misc.h 2007-10-24 19:42:40.000000000 +0000 @@ -12,12 +12,12 @@ int ex_pty; /* Do we want a pty? */ int ex_addr; /* The last byte of the address */ int ex_fport; /* Port to telnet to */ - char *ex_exec; /* Command line of what to exec */ + const char *ex_exec; /* Command line of what to exec */ struct ex_list *ex_next; }; extern struct ex_list *exec_list; -extern u_int curtime, time_fasttimo, last_slowtimo, detach_time, detach_wait; +extern u_int curtime, time_fasttimo, last_slowtimo; extern int (*lprint_print) _P((void *, const char *, va_list)); extern char *lprint_ptr, *lprint_ptr2, **lprint_arg; @@ -74,7 +74,7 @@ inline void slirp_remque _P((void *)); int add_exec _P((struct ex_list **, int, char *, int, int)); int slirp_openpty _P((int *, int *)); -int fork_exec _P((struct socket *, char *, int)); +int fork_exec(struct socket *so, const char *ex, int do_pty); void snooze_hup _P((int)); void snooze _P((void)); void relay _P((int)); Index: qemu/slirp/sbuf.c =================================================================== --- qemu.orig/slirp/sbuf.c 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/sbuf.c 2007-10-24 19:42:40.000000000 +0000 @@ -7,6 +7,8 @@ #include <slirp.h> +static void sbappendsb(struct sbuf *sb, struct mbuf *m); + /* Done as a macro in socket.h */ /* int * sbspace(struct sockbuff *sb) @@ -133,10 +135,8 @@ * Copy the data from m into sb * The caller is responsible to make sure there's enough room */ -void -sbappendsb(sb, m) - struct sbuf *sb; - struct mbuf *m; +static void +sbappendsb(struct sbuf *sb, struct mbuf *m) { int len, n, nn; Index: qemu/slirp/sbuf.h =================================================================== --- qemu.orig/slirp/sbuf.h 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/sbuf.h 2007-10-24 19:42:40.000000000 +0000 @@ -25,7 +25,6 @@ void sbdrop _P((struct sbuf *, int)); void sbreserve _P((struct sbuf *, int)); void sbappend _P((struct socket *, struct mbuf *)); -void sbappendsb _P((struct sbuf *, struct mbuf *)); void sbcopy _P((struct sbuf *, int, int, char *)); #endif Index: qemu/slirp/slirp.c =================================================================== --- qemu.orig/slirp/slirp.c 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/slirp.c 2007-10-24 19:42:40.000000000 +0000 @@ -12,7 +12,7 @@ /* virtual address alias for host */ struct in_addr alias_addr; -const uint8_t special_ethaddr[6] = { +static const uint8_t special_ethaddr[6] = { 0x52, 0x54, 0x00, 0x12, 0x35, 0x00 }; @@ -93,7 +93,9 @@ if (!f) return -1; +#ifdef DEBUG lprint("IP address of your DNS(s): "); +#endif while (fgets(buff, 512, f) != NULL) { if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) { if (!inet_aton(buff2, &tmp_addr)) @@ -103,13 +105,20 @@ /* If it's the first one, set it to dns_addr */ if (!found) *pdns_addr = tmp_addr; +#ifdef DEBUG else lprint(", "); +#endif if (++found > 3) { +#ifdef DEBUG lprint("(more)"); +#endif break; - } else + } +#ifdef DEBUG + else lprint("%s", inet_ntoa(tmp_addr)); +#endif } } fclose(f); @@ -121,7 +130,7 @@ #endif #ifdef _WIN32 -void slirp_cleanup(void) +static void slirp_cleanup(void) { WSACleanup(); } Index: qemu/slirp/slirp.h =================================================================== --- qemu.orig/slirp/slirp.h 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/slirp.h 2007-10-24 19:42:40.000000000 +0000 @@ -6,7 +6,7 @@ //#define DEBUG 1 // Uncomment the following line to enable SLIRP statistics printing in Qemu -//#define LOG_ENABLED +#define LOG_ENABLED #ifdef LOG_ENABLED #define STAT(expr) expr @@ -292,6 +292,9 @@ #define DEFAULT_BAUD 115200 +#define SO_OPTIONS DO_KEEPALIVE +#define TCP_MAXIDLE (TCPTV_KEEPCNT * TCPTV_KEEPINTVL) + /* cksum.c */ int cksum(struct mbuf *m, int len); @@ -302,10 +305,6 @@ /* ip_input.c */ void ip_init _P((void)); void ip_input _P((struct mbuf *)); -struct ip * ip_reass _P((register struct ipasfrag *, register struct ipq *)); -void ip_freef _P((struct ipq *)); -void ip_enq _P((register struct ipasfrag *, register struct ipasfrag *)); -void ip_deq _P((register struct ipasfrag *)); void ip_slowtimo _P((void)); void ip_stripoptions _P((register struct mbuf *, struct mbuf *)); @@ -313,10 +312,7 @@ int ip_output _P((struct socket *, struct mbuf *)); /* tcp_input.c */ -int tcp_reass _P((register struct tcpcb *, register struct tcpiphdr *, struct mbuf *)); void tcp_input _P((register struct mbuf *, int, struct socket *)); -void tcp_dooptions _P((struct tcpcb *, u_char *, int, struct tcpiphdr *)); -void tcp_xmit_timer _P((register struct tcpcb *, int)); int tcp_mss _P((register struct tcpcb *, u_int)); /* tcp_output.c */ @@ -329,7 +325,6 @@ void tcp_respond _P((struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int)); struct tcpcb * tcp_newtcpcb _P((struct socket *)); struct tcpcb * tcp_close _P((register struct tcpcb *)); -void tcp_drain _P((void)); void tcp_sockclosed _P((struct tcpcb *)); int tcp_fconnect _P((struct socket *)); void tcp_connect _P((struct socket *)); Index: qemu/slirp/socket.c =================================================================== --- qemu.orig/slirp/socket.c 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/socket.c 2007-10-24 19:42:40.000000000 +0000 @@ -13,12 +13,16 @@ #include <sys/filio.h> #endif -void +static void sofcantrcvmore(struct socket *so); +static void sofcantsendmore(struct socket *so); + +#if 0 +static void so_init() { /* Nothing yet */ } - +#endif struct socket * solookup(head, laddr, lport, faddr, fport) @@ -421,7 +425,7 @@ int len, n; if (!(m = m_get())) return; - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; /* * XXX Shouldn't FIONREAD packets destined for port 53, @@ -604,12 +608,13 @@ return so; } +#if 0 /* * Data is available in so_rcv * Just write() the data to the socket * XXX not yet... */ -void +static void sorwakeup(so) struct socket *so; { @@ -622,12 +627,13 @@ * We have room for a read() if we want to * For now, don't read, it'll be done in the main loop */ -void +static void sowwakeup(so) struct socket *so; { /* Nothing, yet */ } +#endif /* * Various session state calls @@ -652,9 +658,8 @@ so->so_state |= SS_ISFCONNECTED; /* Clobber other states */ } -void -sofcantrcvmore(so) - struct socket *so; +static void +sofcantrcvmore(struct socket *so) { if ((so->so_state & SS_NOFDREF) == 0) { shutdown(so->s,0); @@ -669,9 +674,8 @@ so->so_state |= SS_FCANTRCVMORE; } -void -sofcantsendmore(so) - struct socket *so; +static void +sofcantsendmore(struct socket *so) { if ((so->so_state & SS_NOFDREF) == 0) { shutdown(so->s,1); /* send FIN to fhost */ Index: qemu/slirp/socket.h =================================================================== --- qemu.orig/slirp/socket.h 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/socket.h 2007-10-24 19:42:40.000000000 +0000 @@ -81,7 +81,6 @@ }; #endif -void so_init _P((void)); struct socket * solookup _P((struct socket *, struct in_addr, u_int, struct in_addr, u_int)); struct socket * socreate _P((void)); void sofree _P((struct socket *)); @@ -92,12 +91,8 @@ void sorecvfrom _P((struct socket *)); int sosendto _P((struct socket *, struct mbuf *)); struct socket * solisten _P((u_int, u_int32_t, u_int, int)); -void sorwakeup _P((struct socket *)); -void sowwakeup _P((struct socket *)); void soisfconnecting _P((register struct socket *)); void soisfconnected _P((register struct socket *)); -void sofcantrcvmore _P((struct socket *)); -void sofcantsendmore _P((struct socket *)); void soisfdisconnected _P((struct socket *)); void sofwdrain _P((struct socket *)); Index: qemu/slirp/tcp.h =================================================================== --- qemu.orig/slirp/tcp.h 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/tcp.h 2007-10-24 19:42:40.000000000 +0000 @@ -42,8 +42,6 @@ #define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */ #define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */ -extern int tcp_rcvspace; -extern int tcp_sndspace; extern struct socket *tcp_last_so; #define TCP_SNDSPACE 8192 @@ -172,6 +170,6 @@ extern tcp_seq tcp_iss; /* tcp initial send seq # */ -extern char *tcpstates[]; +extern const char * const tcpstates[]; #endif Index: qemu/slirp/tcp_input.c =================================================================== --- qemu.orig/slirp/tcp_input.c 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/tcp_input.c 2007-10-24 19:42:40.000000000 +0000 @@ -47,7 +47,7 @@ struct socket tcb; -int tcprexmtthresh = 3; +#define TCPREXMTTHRESH 3 struct socket *tcp_last_so = &tcb; tcp_seq tcp_iss; /* tcp initial send seq # */ @@ -112,12 +112,13 @@ } \ } #endif - -int -tcp_reass(tp, ti, m) - register struct tcpcb *tp; - register struct tcpiphdr *ti; - struct mbuf *m; +static void tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, + struct tcpiphdr *ti); +static void tcp_xmit_timer(register struct tcpcb *tp, int rtt); + +static int +tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti, + struct mbuf *m) { register struct tcpiphdr *q; struct socket *so = tp->t_socket; @@ -402,8 +403,8 @@ goto dropwithreset; } - sbreserve(&so->so_snd, tcp_sndspace); - sbreserve(&so->so_rcv, tcp_rcvspace); + sbreserve(&so->so_snd, TCP_SNDSPACE); + sbreserve(&so->so_rcv, TCP_RCVSPACE); /* tcp_last_so = so; */ /* XXX ? */ /* tp = sototcpcb(so); */ @@ -448,10 +449,10 @@ * Reset idle time and keep-alive timer. */ tp->t_idle = 0; - if (so_options) - tp->t_timer[TCPT_KEEP] = tcp_keepintvl; + if (SO_OPTIONS) + tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL; else - tp->t_timer[TCPT_KEEP] = tcp_keepidle; + tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE; /* * Process options if not in LISTEN state, @@ -1102,7 +1103,7 @@ if (tp->t_timer[TCPT_REXMT] == 0 || ti->ti_ack != tp->snd_una) tp->t_dupacks = 0; - else if (++tp->t_dupacks == tcprexmtthresh) { + else if (++tp->t_dupacks == TCPREXMTTHRESH) { tcp_seq onxt = tp->snd_nxt; u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / @@ -1121,7 +1122,7 @@ if (SEQ_GT(onxt, tp->snd_nxt)) tp->snd_nxt = onxt; goto drop; - } else if (tp->t_dupacks > tcprexmtthresh) { + } else if (tp->t_dupacks > TCPREXMTTHRESH) { tp->snd_cwnd += tp->t_maxseg; (void) tcp_output(tp); goto drop; @@ -1135,7 +1136,7 @@ * If the congestion window was inflated to account * for the other side's cached packets, retract it. */ - if (tp->t_dupacks > tcprexmtthresh && + if (tp->t_dupacks > TCPREXMTTHRESH && tp->snd_cwnd > tp->snd_ssthresh) tp->snd_cwnd = tp->snd_ssthresh; tp->t_dupacks = 0; @@ -1227,7 +1228,7 @@ */ if (so->so_state & SS_FCANTRCVMORE) { soisfdisconnected(so); - tp->t_timer[TCPT_2MSL] = tcp_maxidle; + tp->t_timer[TCPT_2MSL] = TCP_MAXIDLE; } tp->t_state = TCPS_FIN_WAIT_2; } @@ -1490,12 +1491,8 @@ /* int *ts_present; * u_int32_t *ts_val, *ts_ecr; */ -void -tcp_dooptions(tp, cp, cnt, ti) - struct tcpcb *tp; - u_char *cp; - int cnt; - struct tcpiphdr *ti; +static void +tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti) { u_int16_t mss; int opt, optlen; @@ -1605,10 +1602,8 @@ * and update averages and current timeout. */ -void -tcp_xmit_timer(tp, rtt) - register struct tcpcb *tp; - int rtt; +static void +tcp_xmit_timer(register struct tcpcb *tp, int rtt) { register short delta; @@ -1707,7 +1702,7 @@ DEBUG_ARG("tp = %lx", (long)tp); DEBUG_ARG("offer = %d", offer); - mss = min(if_mtu, if_mru) - sizeof(struct tcpiphdr); + mss = min(IF_MTU, IF_MRU) - sizeof(struct tcpiphdr); if (offer) mss = min(mss, offer); mss = max(mss, 32); @@ -1716,8 +1711,12 @@ tp->snd_cwnd = mss; - sbreserve(&so->so_snd, tcp_sndspace+((tcp_sndspace%mss)?(mss-(tcp_sndspace%mss)):0)); - sbreserve(&so->so_rcv, tcp_rcvspace+((tcp_rcvspace%mss)?(mss-(tcp_rcvspace%mss)):0)); + sbreserve(&so->so_snd, TCP_SNDSPACE + ((TCP_SNDSPACE % mss) ? + (mss - (TCP_SNDSPACE % mss)) : + 0)); + sbreserve(&so->so_rcv, TCP_RCVSPACE + ((TCP_RCVSPACE % mss) ? + (mss - (TCP_RCVSPACE % mss)) : + 0)); DEBUG_MISC((dfd, " returning mss = %d\n", mss)); Index: qemu/slirp/tcp_output.c =================================================================== --- qemu.orig/slirp/tcp_output.c 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/tcp_output.c 2007-10-24 19:42:40.000000000 +0000 @@ -48,14 +48,14 @@ * Since this is only used in "stats socket", we give meaning * names instead of the REAL names */ -char *tcpstates[] = { +const char * const tcpstates[] = { /* "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", */ "REDIRECT", "LISTEN", "SYN_SENT", "SYN_RCVD", "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING", "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT", }; -u_char tcp_outflags[TCP_NSTATES] = { +static const u_char tcp_outflags[TCP_NSTATES] = { TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK, TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK, TH_ACK, TH_ACK, @@ -354,7 +354,7 @@ error = 1; goto out; } - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; m->m_len = hdrlen; /* @@ -396,7 +396,7 @@ error = 1; goto out; } - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; m->m_len = hdrlen; } @@ -536,7 +536,7 @@ ((struct ip *)ti)->ip_len = m->m_len; - ((struct ip *)ti)->ip_ttl = ip_defttl; + ((struct ip *)ti)->ip_ttl = IPDEFTTL; ((struct ip *)ti)->ip_tos = so->so_iptos; /* #if BSD >= 43 */ Index: qemu/slirp/tcp_subr.c =================================================================== --- qemu.orig/slirp/tcp_subr.c 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/tcp_subr.c 2007-10-24 19:42:40.000000000 +0000 @@ -46,11 +46,8 @@ #include <slirp.h> /* patchable/settable parameters for tcp */ -int tcp_mssdflt = TCP_MSS; -int tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ; -int tcp_do_rfc1323 = 0; /* Don't do rfc1323 performance enhancements */ -int tcp_rcvspace; /* You may want to change this */ -int tcp_sndspace; /* Keep small if you have an error prone link */ +/* Don't do rfc1323 performance enhancements */ +#define TCP_DO_RFC1323 0 /* * Tcp initialization @@ -60,14 +57,6 @@ { tcp_iss = 1; /* wrong */ tcb.so_next = tcb.so_prev = &tcb; - - /* tcp_rcvspace = our Window we advertise to the remote */ - tcp_rcvspace = TCP_RCVSPACE; - tcp_sndspace = TCP_SNDSPACE; - - /* Make sure tcp_sndspace is at least 2*MSS */ - if (tcp_sndspace < 2*(min(if_mtu, if_mru) - sizeof(struct tcpiphdr))) - tcp_sndspace = 2*(min(if_mtu, if_mru) - sizeof(struct tcpiphdr)); } /* @@ -145,7 +134,7 @@ #else tlen = 0; #endif - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; *mtod(m, struct tcpiphdr *) = *ti; ti = mtod(m, struct tcpiphdr *); flags = TH_ACK; @@ -186,7 +175,7 @@ if(flags & TH_RST) ((struct ip *)ti)->ip_ttl = MAXTTL; else - ((struct ip *)ti)->ip_ttl = ip_defttl; + ((struct ip *)ti)->ip_ttl = IPDEFTTL; (void) ip_output((struct socket *)0, m); } @@ -208,9 +197,9 @@ memset((char *) tp, 0, sizeof(struct tcpcb)); tp->seg_next = tp->seg_prev = (tcpiphdrp_32)tp; - tp->t_maxseg = tcp_mssdflt; + tp->t_maxseg = TCP_MSS; - tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0; + tp->t_flags = TCP_DO_RFC1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0; tp->t_socket = so; /* @@ -219,7 +208,7 @@ * reasonable initial retransmit time. */ tp->t_srtt = TCPTV_SRTTBASE; - tp->t_rttvar = tcp_rttdflt * PR_SLOWHZ << 2; + tp->t_rttvar = TCPTV_SRTTDFLT << 2; tp->t_rttmin = TCPTV_MIN; TCPT_RANGESET(tp->t_rxtcur, @@ -309,6 +298,7 @@ return ((struct tcpcb *)0); } +#ifdef notdef void tcp_drain() { @@ -319,9 +309,6 @@ * When a source quench is received, close congestion window * to one segment. We will gradually open it again as we proceed. */ - -#ifdef notdef - void tcp_quench(i, errno) @@ -556,7 +543,7 @@ /* * Set the socket's type of service field */ -struct tos_t tcptos[] = { +static const struct tos_t tcptos[] = { {0, 20, IPTOS_THROUGHPUT, 0}, /* ftp data */ {21, 21, IPTOS_LOWDELAY, EMU_FTP}, /* ftp control */ {0, 23, IPTOS_LOWDELAY, 0}, /* telnet */ @@ -572,7 +559,7 @@ {0, 0, 0, 0} }; -struct emu_t *tcpemu = 0; +static struct emu_t *tcpemu = 0; /* * Return TOS according to the above table @@ -665,7 +652,7 @@ so_rcv->sb_rptr += m->m_len; m->m_data[m->m_len] = 0; /* NULL terminate */ if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n')) { - if (sscanf(so_rcv->sb_data, "%d%*[ ,]%d", &n1, &n2) == 2) { + if (sscanf(so_rcv->sb_data, "%u%*[ ,]%u", &n1, &n2) == 2) { HTONS(n1); HTONS(n2); /* n2 is the one on our host */ @@ -991,7 +978,7 @@ /* * Need to emulate the PORT command */ - x = sscanf(bptr, "ORT %d,%d,%d,%d,%d,%d\r\n%256[^\177]", + x = sscanf(bptr, "ORT %u,%u,%u,%u,%u,%u\r\n%256[^\177]", &n1, &n2, &n3, &n4, &n5, &n6, buff); if (x < 6) return 1; @@ -1022,7 +1009,7 @@ /* * Need to emulate the PASV response */ - x = sscanf(bptr, "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%256[^\177]", + x = sscanf(bptr, "27 Entering Passive Mode (%u,%u,%u,%u,%u,%u)\r\n%256[^\177]", &n1, &n2, &n3, &n4, &n5, &n6, buff); if (x < 6) return 1; Index: qemu/slirp/tcp_timer.c =================================================================== --- qemu.orig/slirp/tcp_timer.c 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/tcp_timer.c 2007-10-24 19:42:40.000000000 +0000 @@ -36,17 +36,14 @@ #include <slirp.h> -int tcp_keepidle = TCPTV_KEEP_IDLE; -int tcp_keepintvl = TCPTV_KEEPINTVL; -int tcp_maxidle; -int so_options = DO_KEEPALIVE; - #ifdef LOG_ENABLED struct tcpstat tcpstat; /* tcp statistics */ #endif u_int32_t tcp_now; /* for RFC 1323 timestamps */ +static struct tcpcb *tcp_timers(register struct tcpcb *tp, int timer); + /* * Fast timeout routine for processing delayed acks */ @@ -84,7 +81,6 @@ DEBUG_CALL("tcp_slowtimo"); - tcp_maxidle = TCPTV_KEEPCNT * tcp_keepintvl; /* * Search through tcb's and update active timers. */ @@ -130,16 +126,14 @@ tp->t_timer[i] = 0; } -int tcp_backoff[TCP_MAXRXTSHIFT + 1] = +const int tcp_backoff[TCP_MAXRXTSHIFT + 1] = { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 }; /* * TCP timer processing. */ -struct tcpcb * -tcp_timers(tp, timer) - register struct tcpcb *tp; - int timer; +static struct tcpcb * +tcp_timers(register struct tcpcb *tp, int timer) { register int rexmt; @@ -155,8 +149,8 @@ */ case TCPT_2MSL: if (tp->t_state != TCPS_TIME_WAIT && - tp->t_idle <= tcp_maxidle) - tp->t_timer[TCPT_2MSL] = tcp_keepintvl; + tp->t_idle <= TCP_MAXIDLE) + tp->t_timer[TCPT_2MSL] = TCPTV_KEEPINTVL; else tp = tcp_close(tp); break; @@ -287,8 +281,8 @@ goto dropit; /* if (tp->t_socket->so_options & SO_KEEPALIVE && */ - if ((so_options) && tp->t_state <= TCPS_CLOSE_WAIT) { - if (tp->t_idle >= tcp_keepidle + tcp_maxidle) + if ((SO_OPTIONS) && tp->t_state <= TCPS_CLOSE_WAIT) { + if (tp->t_idle >= TCPTV_KEEP_IDLE + TCP_MAXIDLE) goto dropit; /* * Send a packet designed to force a response @@ -314,9 +308,9 @@ tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL, tp->rcv_nxt, tp->snd_una - 1, 0); #endif - tp->t_timer[TCPT_KEEP] = tcp_keepintvl; + tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL; } else - tp->t_timer[TCPT_KEEP] = tcp_keepidle; + tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE; break; dropit: Index: qemu/slirp/tcp_timer.h =================================================================== --- qemu.orig/slirp/tcp_timer.h 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/tcp_timer.h 2007-10-24 19:42:40.000000000 +0000 @@ -126,17 +126,12 @@ (tv) = (tvmax); \ } -extern int tcp_keepidle; /* time before keepalive probes begin */ -extern int tcp_keepintvl; /* time between keepalive probes */ -extern int tcp_maxidle; /* time to drop after starting probes */ -extern int tcp_ttl; /* time to live for TCP segs */ -extern int tcp_backoff[]; +extern const int tcp_backoff[]; struct tcpcb; void tcp_fasttimo _P((void)); void tcp_slowtimo _P((void)); void tcp_canceltimers _P((struct tcpcb *)); -struct tcpcb * tcp_timers _P((register struct tcpcb *, int)); #endif Index: qemu/slirp/tftp.c =================================================================== --- qemu.orig/slirp/tftp.c 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/tftp.c 2007-10-24 19:42:40.000000000 +0000 @@ -34,7 +34,7 @@ int timestamp; }; -struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX]; +static struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX]; const char *tftp_prefix; @@ -143,7 +143,7 @@ memset(m->m_data, 0, m->m_size); - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; tp = (void *)m->m_data; m->m_data += sizeof(struct udpiphdr); @@ -183,7 +183,7 @@ memset(m->m_data, 0, m->m_size); - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; tp = (void *)m->m_data; m->m_data += sizeof(struct udpiphdr); @@ -230,7 +230,7 @@ memset(m->m_data, 0, m->m_size); - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; tp = (void *)m->m_data; m->m_data += sizeof(struct udpiphdr); Index: qemu/slirp/udp.h =================================================================== --- qemu.orig/slirp/udp.h 2007-10-24 19:38:20.000000000 +0000 +++ qemu/slirp/udp.h 2007-10-24 19:42:40.000000000 +0000 @@ -106,8 +106,6 @@ int udp_output _P((struct socket *, struct mbuf *, struct sockaddr_in *)); int udp_attach _P((struct socket *)); void udp_detach _P((struct socket *)); -u_int8_t udp_tos _P((struct socket *)); -void udp_emu _P((struct socket *, struct mbuf *)); struct socket * udp_listen _P((u_int, u_int32_t, u_int, int)); int udp_output2(struct socket *so, struct mbuf *m, struct sockaddr_in *saddr, struct sockaddr_in *daddr, Index: qemu/slirp/udp.c =================================================================== --- qemu.orig/slirp/udp.c 2007-10-24 19:42:58.000000000 +0000 +++ qemu/slirp/udp.c 2007-10-24 19:49:44.000000000 +0000 @@ -51,14 +51,17 @@ struct socket udb; +static u_int8_t udp_tos(struct socket *so); +static void udp_emu(struct socket *so, struct mbuf *m); + /* * UDP protocol implementation. * Per RFC 768, August, 1980. */ #ifndef COMPAT_42 -int udpcksum = 1; +#define UDPCKSUM 1 #else -int udpcksum = 0; /* XXX */ +#define UDPCKSUM 0 /* XXX */ #endif struct socket *udp_last_so = &udb; @@ -132,7 +135,7 @@ /* * Checksum extended UDP header and data. */ - if (udpcksum && uh->uh_sum) { + if (UDPCKSUM && uh->uh_sum) { ((struct ipovly *)ip)->ih_next = 0; ((struct ipovly *)ip)->ih_prev = 0; ((struct ipovly *)ip)->ih_x1 = 0; @@ -292,13 +295,13 @@ * Stuff checksum and output datagram. */ ui->ui_sum = 0; - if (udpcksum) { + if (UDPCKSUM) { if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0) ui->ui_sum = 0xffff; } ((struct ip *)ui)->ip_len = m->m_len; - ((struct ip *)ui)->ip_ttl = ip_defttl; + ((struct ip *)ui)->ip_ttl = IPDEFTTL; ((struct ip *)ui)->ip_tos = iptos; STAT(udpstat.udps_opackets++); @@ -369,7 +372,7 @@ sofree(so); } -struct tos_t udptos[] = { +static const struct tos_t udptos[] = { {0, 53, IPTOS_LOWDELAY, 0}, /* DNS */ {517, 517, IPTOS_LOWDELAY, EMU_TALK}, /* talk */ {518, 518, IPTOS_LOWDELAY, EMU_NTALK}, /* ntalk */ @@ -377,9 +380,8 @@ {0, 0, 0, 0} }; -u_int8_t -udp_tos(so) - struct socket *so; +static u_int8_t +udp_tos(struct socket *so) { int i = 0; @@ -402,10 +404,8 @@ /* * Here, talk/ytalk/ntalk requests must be emulated */ -void -udp_emu(so, m) - struct socket *so; - struct mbuf *m; +static void +udp_emu(struct socket *so, struct mbuf *m) { struct sockaddr_in addr; int addrlen = sizeof(addr); [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #3: slirp_debug.diff --] [-- Type: text/x-diff; name=slirp_debug.diff, Size: 28389 bytes --] Index: qemu/slirp/debug.c =================================================================== --- qemu.orig/slirp/debug.c 2007-10-24 18:23:09.000000000 +0000 +++ qemu/slirp/debug.c 2007-10-24 19:38:20.000000000 +0000 @@ -20,6 +20,7 @@ /* Carry over one item from main.c so that the tty's restored. * Only done when the tty being used is /dev/tty --RedWolf */ +#ifndef CONFIG_QEMU extern struct termios slirp_tty_settings; extern int slirp_tty_restore; @@ -70,7 +71,9 @@ } } #endif +#endif +#ifdef LOG_ENABLED #if 0 /* * Statistic routines @@ -80,7 +83,7 @@ * the link as well. */ -void +static void ttystats(ttyp) struct ttys *ttyp; { @@ -119,8 +122,8 @@ lprint(" %6d bad input packets\r\n", is->in_mbad); } -void -allttystats() +static void +allttystats(void) { struct ttys *ttyp; @@ -129,8 +132,8 @@ } #endif -void -ipstats() +static void +ipstats(void) { lprint(" \r\n"); @@ -153,9 +156,9 @@ lprint(" %6d total packets delivered\r\n", ipstat.ips_delivered); } -#if 0 -void -vjstats() +#ifndef CONFIG_QEMU +static void +vjstats(void) { lprint(" \r\n"); @@ -172,8 +175,8 @@ } #endif -void -tcpstats() +static void +tcpstats(void) { lprint(" \r\n"); @@ -240,8 +243,8 @@ } -void -udpstats() +static void +udpstats(void) { lprint(" \r\n"); @@ -254,8 +257,8 @@ lprint(" %6d datagrams sent\r\n", udpstat.udps_opackets); } -void -icmpstats() +static void +icmpstats(void) { lprint(" \r\n"); lprint("ICMP stats:\r\n"); @@ -267,8 +270,8 @@ lprint(" %6d ICMP packets sent in reply\r\n", icmpstat.icps_reflect); } -void -mbufstats() +static void +mbufstats(void) { struct mbuf *m; int i; @@ -291,8 +294,8 @@ lprint(" %6d mbufs queued as packets\r\n\r\n", if_queued); } -void -sockstats() +static void +sockstats(void) { char buff[256]; int n; @@ -331,8 +334,9 @@ so->so_rcv.sb_cc, so->so_snd.sb_cc); } } +#endif -#if 0 +#ifndef CONFIG_QEMU void slirp_exit(exit_status) int exit_status; @@ -374,3 +378,18 @@ exit(exit_status); } #endif + +void +slirp_stats(void) +{ +#ifdef LOG_ENABLED + ipstats(); + tcpstats(); + udpstats(); + icmpstats(); + mbufstats(); + sockstats(); +#else + lprint("SLIRP statistics not compiled\n"); +#endif +} Index: qemu/slirp/debug.h =================================================================== --- qemu.orig/slirp/debug.h 2007-10-24 18:23:09.000000000 +0000 +++ qemu/slirp/debug.h 2007-10-24 18:45:42.000000000 +0000 @@ -37,14 +37,4 @@ #endif void debug_init _P((char *, int)); -//void ttystats _P((struct ttys *)); -void allttystats _P((void)); -void ipstats _P((void)); -void vjstats _P((void)); -void tcpstats _P((void)); -void udpstats _P((void)); -void icmpstats _P((void)); -void mbufstats _P((void)); -void sockstats _P((void)); -void slirp_exit _P((int)); Index: qemu/slirp/icmp_var.h =================================================================== --- qemu.orig/slirp/icmp_var.h 2007-10-24 18:23:09.000000000 +0000 +++ qemu/slirp/icmp_var.h 2007-10-24 18:45:42.000000000 +0000 @@ -64,6 +64,8 @@ { "stats", CTLTYPE_STRUCT }, \ } +#ifdef LOG_ENABLED extern struct icmpstat icmpstat; +#endif #endif Index: qemu/slirp/ip.h =================================================================== --- qemu.orig/slirp/ip.h 2007-10-24 18:23:09.000000000 +0000 +++ qemu/slirp/ip.h 2007-10-24 18:51:06.000000000 +0000 @@ -272,6 +272,7 @@ int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */ }; +#ifdef LOG_ENABLED /* * Structure attached to inpcb.ip_moptions and * passed to ip_output when IP multicast options are in use. @@ -306,8 +307,9 @@ }; extern struct ipstat ipstat; +#endif + extern struct ipq ipq; /* ip reass. queue */ extern u_int16_t ip_id; /* ip packet ctr, for ids */ -extern int ip_defttl; /* default IP ttl */ #endif Index: qemu/slirp/ip_icmp.c =================================================================== --- qemu.orig/slirp/ip_icmp.c 2007-10-24 18:23:09.000000000 +0000 +++ qemu/slirp/ip_icmp.c 2007-10-24 19:38:20.000000000 +0000 @@ -37,7 +37,9 @@ #include "slirp.h" #include "ip_icmp.h" +#ifdef LOG_ENABLED struct icmpstat icmpstat; +#endif /* The message sent when emulating PING */ /* Be nice and tell them it's just a psuedo-ping packet */ @@ -83,14 +85,14 @@ DEBUG_ARG("m = %lx", (long )m); DEBUG_ARG("m_len = %d", m->m_len); - icmpstat.icps_received++; + STAT(icmpstat.icps_received++); /* * Locate icmp structure in mbuf, and check * that its not corrupted and of at least minimum length. */ if (icmplen < ICMP_MINLEN) { /* min 8 bytes payload */ - icmpstat.icps_tooshort++; + STAT(icmpstat.icps_tooshort++); freeit: m_freem(m); goto end_error; @@ -100,7 +102,7 @@ m->m_data += hlen; icp = mtod(m, struct icmp *); if (cksum(m, icmplen)) { - icmpstat.icps_checksum++; + STAT(icmpstat.icps_checksum++); goto freeit; } m->m_len += hlen; @@ -170,12 +172,12 @@ case ICMP_TSTAMP: case ICMP_MASKREQ: case ICMP_REDIRECT: - icmpstat.icps_notsupp++; + STAT(icmpstat.icps_notsupp++); m_freem(m); break; default: - icmpstat.icps_badtype++; + STAT(icmpstat.icps_badtype++); m_freem(m); } /* swith */ @@ -314,7 +316,7 @@ (void ) ip_output((struct socket *)NULL, m); - icmpstat.icps_reflect++; + STAT(icmpstat.icps_reflect++); end_error: return; @@ -371,5 +373,5 @@ (void ) ip_output((struct socket *)NULL, m); - icmpstat.icps_reflect++; + STAT(icmpstat.icps_reflect++); } Index: qemu/slirp/ip_input.c =================================================================== --- qemu.orig/slirp/ip_input.c 2007-10-24 18:23:09.000000000 +0000 +++ qemu/slirp/ip_input.c 2007-10-24 19:38:20.000000000 +0000 @@ -46,7 +46,11 @@ #include "ip_icmp.h" int ip_defttl; + +#ifdef LOG_ENABLED struct ipstat ipstat; +#endif + struct ipq ipq; /* @@ -78,23 +82,23 @@ DEBUG_ARG("m = %lx", (long)m); DEBUG_ARG("m_len = %d", m->m_len); - ipstat.ips_total++; + STAT(ipstat.ips_total++); if (m->m_len < sizeof (struct ip)) { - ipstat.ips_toosmall++; + STAT(ipstat.ips_toosmall++); return; } ip = mtod(m, struct ip *); if (ip->ip_v != IPVERSION) { - ipstat.ips_badvers++; + STAT(ipstat.ips_badvers++); goto bad; } hlen = ip->ip_hl << 2; if (hlen<sizeof(struct ip ) || hlen>m->m_len) {/* min header length */ - ipstat.ips_badhlen++; /* or packet too short */ + STAT(ipstat.ips_badhlen++); /* or packet too short */ goto bad; } @@ -103,7 +107,7 @@ * if (ip->ip_sum) { */ if(cksum(m,hlen)) { - ipstat.ips_badsum++; + STAT(ipstat.ips_badsum++); goto bad; } @@ -112,7 +116,7 @@ */ NTOHS(ip->ip_len); if (ip->ip_len < hlen) { - ipstat.ips_badlen++; + STAT(ipstat.ips_badlen++); goto bad; } NTOHS(ip->ip_id); @@ -125,7 +129,7 @@ * Drop packet if shorter than we expect. */ if (m->m_len < ip->ip_len) { - ipstat.ips_tooshort++; + STAT(ipstat.ips_tooshort++); goto bad; } /* Should drop packet if mbuf too long? hmmm... */ @@ -192,11 +196,11 @@ * attempt reassembly; if it succeeds, proceed. */ if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) { - ipstat.ips_fragments++; + STAT(ipstat.ips_fragments++); ip = ip_reass((struct ipasfrag *)ip, fp); if (ip == 0) return; - ipstat.ips_reassembled++; + STAT(ipstat.ips_reassembled++); m = dtom(ip); } else if (fp) @@ -208,7 +212,7 @@ /* * Switch out to protocol's input routine. */ - ipstat.ips_delivered++; + STAT(ipstat.ips_delivered++); switch (ip->ip_p) { case IPPROTO_TCP: tcp_input(m, hlen, (struct socket *)NULL); @@ -220,7 +224,7 @@ icmp_input(m, hlen); break; default: - ipstat.ips_noproto++; + STAT(ipstat.ips_noproto++); m_free(m); } return; @@ -385,7 +389,7 @@ return ((struct ip *)ip); dropfrag: - ipstat.ips_fragdropped++; + STAT(ipstat.ips_fragdropped++); m_freem(m); return (0); } @@ -457,7 +461,7 @@ --fp->ipq_ttl; fp = (struct ipq *) fp->next; if (((struct ipq *)(fp->prev))->ipq_ttl == 0) { - ipstat.ips_fragtimeout++; + STAT(ipstat.ips_fragtimeout++); ip_freef((struct ipq *) fp->prev); } } @@ -664,7 +668,7 @@ /* Not yet */ icmp_error(m, type, code, 0, 0); - ipstat.ips_badoptions++; + STAT(ipstat.ips_badoptions++); return (1); } Index: qemu/slirp/ip_output.c =================================================================== --- qemu.orig/slirp/ip_output.c 2007-10-24 18:23:09.000000000 +0000 +++ qemu/slirp/ip_output.c 2007-10-24 19:38:20.000000000 +0000 @@ -80,7 +80,7 @@ ip->ip_off &= IP_DF; ip->ip_id = htons(ip_id++); ip->ip_hl = hlen >> 2; - ipstat.ips_localout++; + STAT(ipstat.ips_localout++); /* * Verify that we have any chance at all of being able to queue @@ -112,7 +112,7 @@ */ if (ip->ip_off & IP_DF) { error = -1; - ipstat.ips_cantfrag++; + STAT(ipstat.ips_cantfrag++); goto bad; } @@ -137,7 +137,7 @@ m = m_get(); if (m == 0) { error = -1; - ipstat.ips_odropped++; + STAT(ipstat.ips_odropped++); goto sendorfree; } m->m_data += if_maxlinkhdr; @@ -170,7 +170,7 @@ mhip->ip_sum = cksum(m, mhlen); *mnext = m; mnext = &m->m_nextpkt; - ipstat.ips_ofragments++; + STAT(ipstat.ips_ofragments++); } /* * Update first fragment by trimming what's been copied out @@ -193,7 +193,7 @@ } if (error == 0) - ipstat.ips_fragmented++; + STAT(ipstat.ips_fragmented++); } done: Index: qemu/slirp/misc.c =================================================================== --- qemu.orig/slirp/misc.c 2007-10-24 18:23:09.000000000 +0000 +++ qemu/slirp/misc.c 2007-10-24 19:38:20.000000000 +0000 @@ -603,6 +603,7 @@ } #endif +#ifndef CONFIG_QEMU int (*lprint_print) _P((void *, const char *, va_list)); char *lprint_ptr, *lprint_ptr2, **lprint_arg; @@ -754,6 +755,7 @@ lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport); } +#endif #ifdef BAD_SPRINTF Index: qemu/slirp/slirp.h =================================================================== --- qemu.orig/slirp/slirp.h 2007-10-24 18:23:09.000000000 +0000 +++ qemu/slirp/slirp.h 2007-10-24 19:38:20.000000000 +0000 @@ -3,7 +3,16 @@ #define CONFIG_QEMU -#define DEBUG 1 +//#define DEBUG 1 + +// Uncomment the following line to enable SLIRP statistics printing in Qemu +//#define LOG_ENABLED + +#ifdef LOG_ENABLED +#define STAT(expr) expr +#else +#define STAT(expr) do { } while(0) +#endif #ifndef CONFIG_QEMU #include "version.h" @@ -253,7 +262,19 @@ long gethostid _P((void)); #endif +#ifdef CONFIG_QEMU +static inline void lprint(const char *format, ...) +{ +#ifdef LOG_ENABLED + va_list args; + va_start(args, format); + term_vprintf(format, args); + va_end(args); +#endif +} +#else void lprint _P((const char *, ...)); +#endif extern int do_echo; Index: qemu/slirp/tcp_input.c =================================================================== --- qemu.orig/slirp/tcp_input.c 2007-10-24 18:23:09.000000000 +0000 +++ qemu/slirp/tcp_input.c 2007-10-24 19:38:20.000000000 +0000 @@ -79,8 +79,8 @@ tp->t_flags |= TF_DELACK; \ (tp)->rcv_nxt += (ti)->ti_len; \ flags = (ti)->ti_flags & TH_FIN; \ - tcpstat.tcps_rcvpack++;\ - tcpstat.tcps_rcvbyte += (ti)->ti_len;\ + STAT(tcpstat.tcps_rcvpack++); \ + STAT(tcpstat.tcps_rcvbyte += (ti)->ti_len); \ if (so->so_emu) { \ if (tcp_emu((so),(m))) sbappend((so), (m)); \ } else \ @@ -99,8 +99,8 @@ tp->t_flags |= TF_DELACK; \ (tp)->rcv_nxt += (ti)->ti_len; \ flags = (ti)->ti_flags & TH_FIN; \ - tcpstat.tcps_rcvpack++;\ - tcpstat.tcps_rcvbyte += (ti)->ti_len;\ + STAT(tcpstat.tcps_rcvpack++); \ + STAT(tcpstat.tcps_rcvbyte += (ti)->ti_len); \ if (so->so_emu) { \ if (tcp_emu((so),(m))) sbappend(so, (m)); \ } else \ @@ -150,8 +150,8 @@ i = q->ti_seq + q->ti_len - ti->ti_seq; if (i > 0) { if (i >= ti->ti_len) { - tcpstat.tcps_rcvduppack++; - tcpstat.tcps_rcvdupbyte += ti->ti_len; + STAT(tcpstat.tcps_rcvduppack++); + STAT(tcpstat.tcps_rcvdupbyte += ti->ti_len); m_freem(m); /* * Try to present any queued data @@ -167,8 +167,8 @@ } q = (struct tcpiphdr *)(q->ti_next); } - tcpstat.tcps_rcvoopack++; - tcpstat.tcps_rcvoobyte += ti->ti_len; + STAT(tcpstat.tcps_rcvoopack++); + STAT(tcpstat.tcps_rcvoobyte += ti->ti_len); REASS_MBUF(ti) = (mbufp_32) m; /* XXX */ /* @@ -275,7 +275,7 @@ } - tcpstat.tcps_rcvtotal++; + STAT(tcpstat.tcps_rcvtotal++); /* * Get IP and TCP header together in first mbuf. * Note: IP leaves IP header in first mbuf. @@ -308,7 +308,7 @@ * ti->ti_sum = cksum(m, len); * if (ti->ti_sum) { */ if(cksum(m, len)) { - tcpstat.tcps_rcvbadsum++; + STAT(tcpstat.tcps_rcvbadsum++); goto drop; } @@ -318,7 +318,7 @@ */ off = ti->ti_off << 2; if (off < sizeof (struct tcphdr) || off > tlen) { - tcpstat.tcps_rcvbadoff++; + STAT(tcpstat.tcps_rcvbadoff++); goto drop; } tlen -= off; @@ -375,7 +375,7 @@ ti->ti_dst, ti->ti_dport); if (so) tcp_last_so = so; - ++tcpstat.tcps_socachemiss; + STAT(tcpstat.tcps_socachemiss++); } /* @@ -503,7 +503,7 @@ /* * this is a pure ack for outstanding data. */ - ++tcpstat.tcps_predack; + STAT(tcpstat.tcps_predack++); /* if (ts_present) * tcp_xmit_timer(tp, tcp_now-ts_ecr+1); * else @@ -511,8 +511,8 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) tcp_xmit_timer(tp, tp->t_rtt); acked = ti->ti_ack - tp->snd_una; - tcpstat.tcps_rcvackpack++; - tcpstat.tcps_rcvackbyte += acked; + STAT(tcpstat.tcps_rcvackpack++); + STAT(tcpstat.tcps_rcvackbyte += acked); sbdrop(&so->so_snd, acked); tp->snd_una = ti->ti_ack; m_freem(m); @@ -556,10 +556,10 @@ * with nothing on the reassembly queue and * we have enough buffer space to take it. */ - ++tcpstat.tcps_preddat; + STAT(tcpstat.tcps_preddat++); tp->rcv_nxt += ti->ti_len; - tcpstat.tcps_rcvpack++; - tcpstat.tcps_rcvbyte += ti->ti_len; + STAT(tcpstat.tcps_rcvpack++); + STAT(tcpstat.tcps_rcvbyte += ti->ti_len); /* * Add data to socket buffer. */ @@ -726,7 +726,7 @@ tp->t_flags |= TF_ACKNOW; tp->t_state = TCPS_SYN_RECEIVED; tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; - tcpstat.tcps_accepts++; + STAT(tcpstat.tcps_accepts++); goto trimthenstep6; } /* case TCPS_LISTEN */ @@ -767,7 +767,7 @@ tcp_rcvseqinit(tp); tp->t_flags |= TF_ACKNOW; if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) { - tcpstat.tcps_connects++; + STAT(tcpstat.tcps_connects++); soisfconnected(so); tp->t_state = TCPS_ESTABLISHED; @@ -801,8 +801,8 @@ m_adj(m, -todrop); ti->ti_len = tp->rcv_wnd; tiflags &= ~TH_FIN; - tcpstat.tcps_rcvpackafterwin++; - tcpstat.tcps_rcvbyteafterwin += todrop; + STAT(tcpstat.tcps_rcvpackafterwin++); + STAT(tcpstat.tcps_rcvbyteafterwin += todrop); } tp->snd_wl1 = ti->ti_seq - 1; tp->rcv_up = ti->ti_seq; @@ -873,11 +873,11 @@ */ tp->t_flags |= TF_ACKNOW; todrop = ti->ti_len; - tcpstat.tcps_rcvduppack++; - tcpstat.tcps_rcvdupbyte += todrop; + STAT(tcpstat.tcps_rcvduppack++); + STAT(tcpstat.tcps_rcvdupbyte += todrop); } else { - tcpstat.tcps_rcvpartduppack++; - tcpstat.tcps_rcvpartdupbyte += todrop; + STAT(tcpstat.tcps_rcvpartduppack++); + STAT(tcpstat.tcps_rcvpartdupbyte += todrop); } m_adj(m, todrop); ti->ti_seq += todrop; @@ -896,7 +896,7 @@ if ((so->so_state & SS_NOFDREF) && tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) { tp = tcp_close(tp); - tcpstat.tcps_rcvafterclose++; + STAT(tcpstat.tcps_rcvafterclose++); goto dropwithreset; } @@ -906,9 +906,9 @@ */ todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd); if (todrop > 0) { - tcpstat.tcps_rcvpackafterwin++; + STAT(tcpstat.tcps_rcvpackafterwin++); if (todrop >= ti->ti_len) { - tcpstat.tcps_rcvbyteafterwin += ti->ti_len; + STAT(tcpstat.tcps_rcvbyteafterwin += ti->ti_len); /* * If a new connection request is received * while in TIME_WAIT, drop the old connection @@ -931,11 +931,11 @@ */ if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) { tp->t_flags |= TF_ACKNOW; - tcpstat.tcps_rcvwinprobe++; + STAT(tcpstat.tcps_rcvwinprobe++); } else goto dropafterack; } else - tcpstat.tcps_rcvbyteafterwin += todrop; + STAT(tcpstat.tcps_rcvbyteafterwin += todrop); m_adj(m, -todrop); ti->ti_len -= todrop; tiflags &= ~(TH_PUSH|TH_FIN); @@ -976,7 +976,7 @@ /* so->so_error = ECONNRESET; */ close: tp->t_state = TCPS_CLOSED; - tcpstat.tcps_drops++; + STAT(tcpstat.tcps_drops++); tp = tcp_close(tp); goto drop; @@ -1015,7 +1015,7 @@ if (SEQ_GT(tp->snd_una, ti->ti_ack) || SEQ_GT(ti->ti_ack, tp->snd_max)) goto dropwithreset; - tcpstat.tcps_connects++; + STAT(tcpstat.tcps_connects++); tp->t_state = TCPS_ESTABLISHED; /* * The sent SYN is ack'ed with our sequence number +1 @@ -1072,7 +1072,7 @@ if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) { if (ti->ti_len == 0 && tiwin == tp->snd_wnd) { - tcpstat.tcps_rcvdupack++; + STAT(tcpstat.tcps_rcvdupack++); DEBUG_MISC((dfd," dup ack m = %lx so = %lx \n", (long )m, (long )so)); /* @@ -1140,12 +1140,12 @@ tp->snd_cwnd = tp->snd_ssthresh; tp->t_dupacks = 0; if (SEQ_GT(ti->ti_ack, tp->snd_max)) { - tcpstat.tcps_rcvacktoomuch++; + STAT(tcpstat.tcps_rcvacktoomuch++); goto dropafterack; } acked = ti->ti_ack - tp->snd_una; - tcpstat.tcps_rcvackpack++; - tcpstat.tcps_rcvackbyte += acked; + STAT(tcpstat.tcps_rcvackpack++); + STAT(tcpstat.tcps_rcvackbyte += acked); /* * If we have a timestamp reply, update smoothed @@ -1284,7 +1284,7 @@ /* keep track of pure window updates */ if (ti->ti_len == 0 && tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd) - tcpstat.tcps_rcvwinupd++; + STAT(tcpstat.tcps_rcvwinupd++); tp->snd_wnd = tiwin; tp->snd_wl1 = ti->ti_seq; tp->snd_wl2 = ti->ti_ack; @@ -1616,7 +1616,7 @@ DEBUG_ARG("tp = %lx", (long)tp); DEBUG_ARG("rtt = %d", rtt); - tcpstat.tcps_rttupdated++; + STAT(tcpstat.tcps_rttupdated++); if (tp->t_srtt != 0) { /* * srtt is stored as fixed point with 3 bits after the Index: qemu/slirp/tcp_output.c =================================================================== --- qemu.orig/slirp/tcp_output.c 2007-10-24 18:23:09.000000000 +0000 +++ qemu/slirp/tcp_output.c 2007-10-24 19:38:20.000000000 +0000 @@ -263,7 +263,7 @@ /* * No reason to send a segment, just return. */ - tcpstat.tcps_didnuttin++; + STAT(tcpstat.tcps_didnuttin++); return (0); @@ -339,13 +339,13 @@ */ if (len) { if (tp->t_force && len == 1) - tcpstat.tcps_sndprobe++; + STAT(tcpstat.tcps_sndprobe++); else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) { - tcpstat.tcps_sndrexmitpack++; - tcpstat.tcps_sndrexmitbyte += len; + STAT(tcpstat.tcps_sndrexmitpack++); + STAT(tcpstat.tcps_sndrexmitbyte += len); } else { - tcpstat.tcps_sndpack++; - tcpstat.tcps_sndbyte += len; + STAT(tcpstat.tcps_sndpack++); + STAT(tcpstat.tcps_sndbyte += len); } m = m_get(); @@ -382,13 +382,13 @@ flags |= TH_PUSH; } else { if (tp->t_flags & TF_ACKNOW) - tcpstat.tcps_sndacks++; + STAT(tcpstat.tcps_sndacks++); else if (flags & (TH_SYN|TH_FIN|TH_RST)) - tcpstat.tcps_sndctrl++; + STAT(tcpstat.tcps_sndctrl++); else if (SEQ_GT(tp->snd_up, tp->snd_una)) - tcpstat.tcps_sndurg++; + STAT(tcpstat.tcps_sndurg++); else - tcpstat.tcps_sndwinup++; + STAT(tcpstat.tcps_sndwinup++); m = m_get(); if (m == NULL) { @@ -500,7 +500,7 @@ if (tp->t_rtt == 0) { tp->t_rtt = 1; tp->t_rtseq = startseq; - tcpstat.tcps_segstimed++; + STAT(tcpstat.tcps_segstimed++); } } @@ -567,7 +567,7 @@ */ return (error); } - tcpstat.tcps_sndtotal++; + STAT(tcpstat.tcps_sndtotal++); /* * Data sent (as far as we can tell). Index: qemu/slirp/tcp_subr.c =================================================================== --- qemu.orig/slirp/tcp_subr.c 2007-10-24 18:23:09.000000000 +0000 +++ qemu/slirp/tcp_subr.c 2007-10-24 19:38:20.000000000 +0000 @@ -255,9 +255,9 @@ if (TCPS_HAVERCVDSYN(tp->t_state)) { tp->t_state = TCPS_CLOSED; (void) tcp_output(tp); - tcpstat.tcps_drops++; + STAT(tcpstat.tcps_drops++); } else - tcpstat.tcps_conndrops++; + STAT(tcpstat.tcps_conndrops++); /* if (errno == ETIMEDOUT && tp->t_softerror) * errno = tp->t_softerror; */ @@ -305,7 +305,7 @@ sbfree(&so->so_rcv); sbfree(&so->so_snd); sofree(so); - tcpstat.tcps_closed++; + STAT(tcpstat.tcps_closed++); return ((struct tcpcb *)0); } @@ -528,7 +528,7 @@ */ /* soisconnecting(so); */ /* NOFDREF used instead */ - tcpstat.tcps_connattempt++; + STAT(tcpstat.tcps_connattempt++); tp->t_state = TCPS_SYN_SENT; tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; @@ -857,7 +857,7 @@ /*soisfconnecting(ns);*/ - tcpstat.tcps_connattempt++; + STAT(tcpstat.tcps_connattempt++); tp->t_state = TCPS_SYN_SENT; tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; Index: qemu/slirp/if.h =================================================================== --- qemu.orig/slirp/if.h 2007-10-24 18:23:09.000000000 +0000 +++ qemu/slirp/if.h 2007-10-24 19:38:20.000000000 +0000 @@ -29,6 +29,7 @@ #define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm)) +#ifdef LOG_ENABLED /* Interface statistics */ struct slirp_ifstats { u_int out_pkts; /* Output packets */ @@ -46,5 +47,6 @@ u_int in_mbad; /* Bad incoming packets */ }; +#endif #endif Index: qemu/slirp/tcp_timer.c =================================================================== --- qemu.orig/slirp/tcp_timer.c 2007-10-24 18:23:09.000000000 +0000 +++ qemu/slirp/tcp_timer.c 2007-10-24 19:38:20.000000000 +0000 @@ -41,7 +41,10 @@ int tcp_maxidle; int so_options = DO_KEEPALIVE; +#ifdef LOG_ENABLED struct tcpstat tcpstat; /* tcp statistics */ +#endif + u_int32_t tcp_now; /* for RFC 1323 timestamps */ /* @@ -62,7 +65,7 @@ (tp->t_flags & TF_DELACK)) { tp->t_flags &= ~TF_DELACK; tp->t_flags |= TF_ACKNOW; - tcpstat.tcps_delack++; + STAT(tcpstat.tcps_delack++); (void) tcp_output(tp); } } @@ -192,7 +195,7 @@ * We tried our best, now the connection must die! */ tp->t_rxtshift = TCP_MAXRXTSHIFT; - tcpstat.tcps_timeoutdrop++; + STAT(tcpstat.tcps_timeoutdrop++); tp = tcp_drop(tp, tp->t_softerror); /* tp->t_softerror : ETIMEDOUT); */ /* XXX */ return (tp); /* XXX */ @@ -204,7 +207,7 @@ */ tp->t_rxtshift = 6; } - tcpstat.tcps_rexmttimeo++; + STAT(tcpstat.tcps_rexmttimeo++); rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift]; TCPT_RANGESET(tp->t_rxtcur, rexmt, (short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */ @@ -267,7 +270,7 @@ * Force a byte to be output, if possible. */ case TCPT_PERSIST: - tcpstat.tcps_persisttimeo++; + STAT(tcpstat.tcps_persisttimeo++); tcp_setpersist(tp); tp->t_force = 1; (void) tcp_output(tp); @@ -279,7 +282,7 @@ * or drop connection if idle for too long. */ case TCPT_KEEP: - tcpstat.tcps_keeptimeo++; + STAT(tcpstat.tcps_keeptimeo++); if (tp->t_state < TCPS_ESTABLISHED) goto dropit; @@ -299,7 +302,7 @@ * by the protocol spec, this requires the * correspondent TCP to respond. */ - tcpstat.tcps_keepprobe++; + STAT(tcpstat.tcps_keepprobe++); #ifdef TCP_COMPAT_42 /* * The keepalive packet must have nonzero length @@ -317,7 +320,7 @@ break; dropit: - tcpstat.tcps_keepdrops++; + STAT(tcpstat.tcps_keepdrops++); tp = tcp_drop(tp, 0); /* ETIMEDOUT); */ break; } Index: qemu/slirp/tcp_var.h =================================================================== --- qemu.orig/slirp/tcp_var.h 2007-10-24 18:23:09.000000000 +0000 +++ qemu/slirp/tcp_var.h 2007-10-24 18:45:42.000000000 +0000 @@ -185,6 +185,7 @@ #endif #define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t)) +#ifdef LOG_ENABLED /* * TCP statistics. * Many of these should be kept per connection, @@ -247,6 +248,8 @@ }; extern struct tcpstat tcpstat; /* tcp statistics */ +#endif + extern u_int32_t tcp_now; /* for RFC 1323 timestamps */ #endif Index: qemu/slirp/udp.h =================================================================== --- qemu.orig/slirp/udp.h 2007-10-24 18:23:09.000000000 +0000 +++ qemu/slirp/udp.h 2007-10-24 19:38:20.000000000 +0000 @@ -72,6 +72,7 @@ #define ui_ulen ui_u.uh_ulen #define ui_sum ui_u.uh_sum +#ifdef LOG_ENABLED struct udpstat { /* input statistics: */ u_long udps_ipackets; /* total input packets */ @@ -85,6 +86,7 @@ /* output statistics: */ u_long udps_opackets; /* total output packets */ }; +#endif /* * Names for UDP sysctl objects @@ -92,7 +94,10 @@ #define UDPCTL_CHECKSUM 1 /* checksum UDP packets */ #define UDPCTL_MAXID 2 +#ifdef LOG_ENABLED extern struct udpstat udpstat; +#endif + extern struct socket udb; struct mbuf; Index: qemu/slirp/udp.c =================================================================== --- qemu.orig/slirp/udp.c 2007-10-24 18:23:09.000000000 +0000 +++ qemu/slirp/udp.c 2007-10-24 19:42:14.000000000 +0000 @@ -45,7 +45,9 @@ #include <slirp.h> #include "ip_icmp.h" +#ifdef LOG_ENABLED struct udpstat udpstat; +#endif struct socket udb; @@ -86,7 +88,7 @@ DEBUG_ARG("m = %lx", (long)m); DEBUG_ARG("iphlen = %d", iphlen); - udpstat.udps_ipackets++; + STAT(udpstat.udps_ipackets++); /* * Strip IP options, if any; should skip this, @@ -113,7 +115,7 @@ if (ip->ip_len != len) { if (len > ip->ip_len) { - udpstat.udps_badlen++; + STAT(udpstat.udps_badlen++); goto bad; } m_adj(m, len - ip->ip_len); @@ -140,7 +142,7 @@ * if (uh->uh_sum) { */ if(cksum(m, len + sizeof(struct ip))) { - udpstat.udps_badsum++; + STAT(udpstat.udps_badsum++); goto bad; } } @@ -181,7 +183,7 @@ if (tmp == &udb) { so = NULL; } else { - udpstat.udpps_pcbcachemiss++; + STAT(udpstat.udpps_pcbcachemiss++); udp_last_so = so; } } @@ -299,7 +301,7 @@ ((struct ip *)ui)->ip_ttl = ip_defttl; ((struct ip *)ui)->ip_tos = iptos; - udpstat.udps_opackets++; + STAT(udpstat.udps_opackets++); error = ip_output(so, m); Index: qemu/monitor.c =================================================================== --- qemu.orig/monitor.c 2007-10-24 18:23:09.000000000 +0000 +++ qemu/monitor.c 2007-10-24 18:45:42.000000000 +0000 @@ -1365,6 +1365,10 @@ { "cpustats", "", do_info_cpu_stats, "", "show CPU statistics", }, #endif +#if defined(CONFIG_SLIRP) + { "slirp", "", do_info_slirp, + "", "show SLIRP statistics", }, +#endif { NULL, NULL, }, }; Index: qemu/slirp/libslirp.h =================================================================== --- qemu.orig/slirp/libslirp.h 2007-10-24 18:23:09.000000000 +0000 +++ qemu/slirp/libslirp.h 2007-10-24 18:45:42.000000000 +0000 @@ -26,6 +26,8 @@ extern const char *tftp_prefix; extern char slirp_hostname[33]; +void slirp_stats(void); + #ifdef __cplusplus } #endif Index: qemu/vl.c =================================================================== --- qemu.orig/vl.c 2007-10-24 18:23:09.000000000 +0000 +++ qemu/vl.c 2007-10-24 18:45:42.000000000 +0000 @@ -3781,6 +3781,10 @@ } #endif /* !defined(_WIN32) */ +void do_info_slirp(void) +{ + slirp_stats(); +} #endif /* CONFIG_SLIRP */ Index: qemu/vl.h =================================================================== --- qemu.orig/vl.h 2007-10-24 18:23:09.000000000 +0000 +++ qemu/vl.h 2007-10-24 18:45:42.000000000 +0000 @@ -439,6 +439,9 @@ extern int nb_nics; extern NICInfo nd_table[MAX_NICS]; +/* SLIRP */ +void do_info_slirp(void); + /* timers */ typedef struct QEMUClock QEMUClock; ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2007-10-24 20:04 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2007-10-20 18:42 [Qemu-devel] PATCH, RFC: Slirp improvements Blue Swirl 2007-10-23 17:42 ` [Qemu-devel] " Blue Swirl -- strict thread matches above, loose matches on Subject: below -- 2007-10-23 20:39 Fabrice Bellard 2007-10-24 20:04 ` Blue Swirl
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).