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 -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 #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 (hlenm->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 -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 -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 -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 +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 #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 #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 #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 -/* 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 -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 -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 #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 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, }, };