From 460fec67ee3807bb2eb189587ffe803a48f317e5 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Wed, 24 Jun 2009 14:42:31 +0200 Subject: [PATCH] slirp: Factor out internal state structure The essence of this patch is to stuff (almost) all global variables of the slirp stack into the structure Slirp. In this step, we still keep the structure as global variable, directly accessible by the whole stack. Changes to the external interface of slirp will be applied in the following patches. Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- slirp/bootp.c | 80 +++++++++++------------ slirp/bootp.h | 7 +++ slirp/if.c | 50 +++++++-------- slirp/if.h | 6 -- slirp/ip.h | 3 - slirp/ip_icmp.c | 19 +++--- slirp/ip_input.c | 80 +++++++++++------------ slirp/ip_output.c | 7 +-- slirp/libslirp.h | 3 + slirp/main.h | 12 +--- slirp/mbuf.c | 30 ++++----- slirp/mbuf.h | 9 ++- slirp/misc.c | 5 +- slirp/misc.h | 2 - slirp/slirp.c | 182 ++++++++++++++++++++++++++++------------------------- slirp/slirp.h | 66 +++++++++++++++++-- slirp/socket.c | 37 ++++++----- slirp/socket.h | 9 +-- slirp/tcp.h | 4 -- slirp/tcp_input.c | 35 +++++------ slirp/tcp_output.c | 4 +- slirp/tcp_subr.c | 74 +++++++++++++--------- slirp/tcp_timer.c | 18 +++--- slirp/tcp_timer.h | 4 +- slirp/tcp_var.h | 2 - slirp/tftp.c | 65 +++++++++---------- slirp/tftp.h | 10 +++ slirp/udp.c | 56 +++++++++-------- slirp/udp.h | 8 +-- 29 files changed, 479 insertions(+), 408 deletions(-) diff --git a/slirp/bootp.c b/slirp/bootp.c index fec52c0a84..911ec712c5 100644 --- a/slirp/bootp.c +++ b/slirp/bootp.c @@ -25,19 +25,8 @@ /* XXX: only DHCP is supported */ -#define NB_ADDR 16 - #define LEASE_TIME (24 * 3600) -typedef struct { - uint8_t allocated; - uint8_t macaddr[6]; -} BOOTPClient; - -static BOOTPClient bootp_clients[NB_ADDR]; - -char *bootp_filename; - static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE }; #ifdef DEBUG @@ -47,35 +36,35 @@ do if (slirp_debug & DBG_CALL) { fprintf(dfd, fmt, ## __VA_ARGS__); fflush(dfd) #define dprintf(fmt, ...) #endif -static BOOTPClient *get_new_addr(struct in_addr *paddr, +static BOOTPClient *get_new_addr(Slirp *slirp, struct in_addr *paddr, const uint8_t *macaddr) { BOOTPClient *bc; int i; - for(i = 0; i < NB_ADDR; i++) { - bc = &bootp_clients[i]; + for(i = 0; i < NB_BOOTP_CLIENTS; i++) { + bc = &slirp->bootp_clients[i]; if (!bc->allocated || !memcmp(macaddr, bc->macaddr, 6)) goto found; } return NULL; found: - bc = &bootp_clients[i]; + bc = &slirp->bootp_clients[i]; bc->allocated = 1; - paddr->s_addr = vdhcp_startaddr.s_addr + htonl(i); + paddr->s_addr = slirp->vdhcp_startaddr.s_addr + htonl(i); return bc; } -static BOOTPClient *request_addr(const struct in_addr *paddr, +static BOOTPClient *request_addr(Slirp *slirp, const struct in_addr *paddr, const uint8_t *macaddr) { uint32_t req_addr = ntohl(paddr->s_addr); - uint32_t dhcp_addr = ntohl(vdhcp_startaddr.s_addr); + uint32_t dhcp_addr = ntohl(slirp->vdhcp_startaddr.s_addr); BOOTPClient *bc; if (req_addr >= dhcp_addr && - req_addr < (dhcp_addr + NB_ADDR)) { - bc = &bootp_clients[req_addr - dhcp_addr]; + req_addr < (dhcp_addr + NB_BOOTP_CLIENTS)) { + bc = &slirp->bootp_clients[req_addr - dhcp_addr]; if (!bc->allocated || !memcmp(macaddr, bc->macaddr, 6)) { bc->allocated = 1; return bc; @@ -84,20 +73,21 @@ static BOOTPClient *request_addr(const struct in_addr *paddr, return NULL; } -static BOOTPClient *find_addr(struct in_addr *paddr, const uint8_t *macaddr) +static BOOTPClient *find_addr(Slirp *slirp, 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)) + for(i = 0; i < NB_BOOTP_CLIENTS; i++) { + if (!memcmp(macaddr, slirp->bootp_clients[i].macaddr, 6)) goto found; } return NULL; found: - bc = &bootp_clients[i]; + bc = &slirp->bootp_clients[i]; bc->allocated = 1; - paddr->s_addr = vdhcp_startaddr.s_addr + htonl(i); + paddr->s_addr = slirp->vdhcp_startaddr.s_addr + htonl(i); return bc; } @@ -148,7 +138,7 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type, } } -static void bootp_reply(const struct bootp_t *bp) +static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) { BOOTPClient *bc = NULL; struct mbuf *m; @@ -173,10 +163,12 @@ static void bootp_reply(const struct bootp_t *bp) dhcp_msg_type != DHCPREQUEST) return; /* XXX: this is a hack to get the client mac address */ - memcpy(client_ethaddr, bp->bp_hwaddr, 6); + memcpy(slirp->client_ethaddr, bp->bp_hwaddr, 6); - if ((m = m_get()) == NULL) + m = m_get(slirp); + if (!m) { return; + } m->m_data += IF_MAXLINKHDR; rbp = (struct bootp_t *)m->m_data; m->m_data += sizeof(struct udpiphdr); @@ -184,30 +176,30 @@ static void bootp_reply(const struct bootp_t *bp) if (dhcp_msg_type == DHCPDISCOVER) { if (preq_addr) { - bc = request_addr(preq_addr, client_ethaddr); + bc = request_addr(slirp, preq_addr, slirp->client_ethaddr); if (bc) { daddr.sin_addr = *preq_addr; } } if (!bc) { new_addr: - bc = get_new_addr(&daddr.sin_addr, client_ethaddr); + bc = get_new_addr(slirp, &daddr.sin_addr, slirp->client_ethaddr); if (!bc) { dprintf("no address left\n"); return; } } - memcpy(bc->macaddr, client_ethaddr, 6); + memcpy(bc->macaddr, slirp->client_ethaddr, 6); } else if (preq_addr) { - bc = request_addr(preq_addr, client_ethaddr); + bc = request_addr(slirp, preq_addr, slirp->client_ethaddr); if (bc) { daddr.sin_addr = *preq_addr; - memcpy(bc->macaddr, client_ethaddr, 6); + memcpy(bc->macaddr, slirp->client_ethaddr, 6); } else { daddr.sin_addr.s_addr = 0; } } else { - bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr); + bc = find_addr(slirp, &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) */ @@ -215,7 +207,7 @@ static void bootp_reply(const struct bootp_t *bp) } } - saddr.sin_addr = vhost_addr; + saddr.sin_addr = slirp->vhost_addr; saddr.sin_port = htons(BOOTP_SERVER); daddr.sin_port = htons(BOOTP_CLIENT); @@ -248,9 +240,9 @@ static void bootp_reply(const struct bootp_t *bp) *q++ = DHCPACK; } - if (bootp_filename) + if (slirp->bootp_filename) snprintf((char *)rbp->bp_file, sizeof(rbp->bp_file), "%s", - bootp_filename); + slirp->bootp_filename); *q++ = RFC2132_SRV_ID; *q++ = 4; @@ -259,10 +251,10 @@ static void bootp_reply(const struct bootp_t *bp) *q++ = RFC1533_NETMASK; *q++ = 4; - memcpy(q, &vnetwork_mask, 4); + memcpy(q, &slirp->vnetwork_mask, 4); q += 4; - if (!slirp_restrict) { + if (!slirp->restricted) { *q++ = RFC1533_GATEWAY; *q++ = 4; memcpy(q, &saddr.sin_addr, 4); @@ -270,7 +262,7 @@ static void bootp_reply(const struct bootp_t *bp) *q++ = RFC1533_DNS; *q++ = 4; - memcpy(q, &vnameserver_addr, 4); + memcpy(q, &slirp->vnameserver_addr, 4); q += 4; } @@ -280,11 +272,11 @@ static void bootp_reply(const struct bootp_t *bp) memcpy(q, &val, 4); q += 4; - if (*slirp_hostname) { - val = strlen(slirp_hostname); + if (*slirp->client_hostname) { + val = strlen(slirp->client_hostname); *q++ = RFC1533_HOSTNAME; *q++ = val; - memcpy(q, slirp_hostname, val); + memcpy(q, slirp->client_hostname, val); q += val; } } else { @@ -315,6 +307,6 @@ void bootp_input(struct mbuf *m) struct bootp_t *bp = mtod(m, struct bootp_t *); if (bp->bp_op == BOOTP_REQUEST) { - bootp_reply(bp); + bootp_reply(m->slirp, bp); } } diff --git a/slirp/bootp.h b/slirp/bootp.h index 3d80515c98..30c30ab863 100644 --- a/slirp/bootp.h +++ b/slirp/bootp.h @@ -112,4 +112,11 @@ struct bootp_t { uint8_t bp_vend[DHCP_OPT_LEN]; }; +typedef struct { + uint16_t allocated; + uint8_t macaddr[6]; +} BOOTPClient; + +#define NB_BOOTP_CLIENTS 16 + void bootp_input(struct mbuf *m); diff --git a/slirp/if.c b/slirp/if.c index 58ab4c7aca..75b15e400c 100644 --- a/slirp/if.c +++ b/slirp/if.c @@ -7,12 +7,6 @@ #include -int if_queued = 0; /* Number of packets queued so far */ - -struct mbuf if_fastq; /* fast queue (for interactive data) */ -struct mbuf if_batchq; /* queue for non-interactive data */ -struct mbuf *next_m; /* Pointer to next mbuf to output */ - #define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm)) static void @@ -32,11 +26,11 @@ ifs_remque(struct mbuf *ifm) } void -if_init(void) +if_init(Slirp *slirp) { - if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq; - if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq; - next_m = &if_batchq; + slirp->if_fastq.ifq_next = slirp->if_fastq.ifq_prev = &slirp->if_fastq; + slirp->if_batchq.ifq_next = slirp->if_batchq.ifq_prev = &slirp->if_batchq; + slirp->next_m = &slirp->if_batchq; } /* @@ -55,6 +49,7 @@ if_init(void) void if_output(struct socket *so, struct mbuf *ifm) { + Slirp *slirp = ifm->slirp; struct mbuf *ifq; int on_fastq = 1; @@ -79,7 +74,8 @@ if_output(struct socket *so, struct mbuf *ifm) * 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 = slirp->if_batchq.ifq_prev; ifq != &slirp->if_batchq; + ifq = ifq->ifq_prev) { if (so == ifq->ifq_so) { /* A match! */ ifm->ifq_so = so; @@ -90,7 +86,7 @@ if_output(struct socket *so, struct mbuf *ifm) /* No match, check which queue to put it on */ if (so && (so->so_iptos & IPTOS_LOWDELAY)) { - ifq = if_fastq.ifq_prev; + ifq = slirp->if_fastq.ifq_prev; on_fastq = 1; /* * Check if this packet is a part of the last @@ -102,7 +98,7 @@ if_output(struct socket *so, struct mbuf *ifm) goto diddit; } } else - ifq = if_batchq.ifq_prev; + ifq = slirp->if_batchq.ifq_prev; /* Create a new doubly linked list for this session */ ifm->ifq_so = so; @@ -110,7 +106,7 @@ if_output(struct socket *so, struct mbuf *ifm) insque(ifm, ifq); diddit: - ++if_queued; + slirp->if_queued++; if (so) { /* Update *_queued */ @@ -130,7 +126,7 @@ diddit: remque(ifm->ifs_next); /* ...And insert in the new. That'll teach ya! */ - insque(ifm->ifs_next, &if_batchq); + insque(ifm->ifs_next, &slirp->if_batchq); } } @@ -138,7 +134,7 @@ diddit: /* * This prevents us from malloc()ing too many mbufs */ - if_start(); + if_start(ifm->slirp); #endif } @@ -155,13 +151,13 @@ diddit: * to the first, etc. etc. */ void -if_start(void) +if_start(Slirp *slirp) { struct mbuf *ifm, *ifqt; DEBUG_CALL("if_start"); - if (if_queued == 0) + if (slirp->if_queued == 0) return; /* Nothing to do */ again: @@ -173,22 +169,22 @@ if_start(void) * 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 (slirp->if_fastq.ifq_next != &slirp->if_fastq) { + ifm = slirp->if_fastq.ifq_next; } else { /* Nothing on fastq, see if next_m is valid */ - if (next_m != &if_batchq) - ifm = next_m; + if (slirp->next_m != &slirp->if_batchq) + ifm = slirp->next_m; else - ifm = if_batchq.ifq_next; + ifm = slirp->if_batchq.ifq_next; /* Set which packet to send on next iteration */ - next_m = ifm->ifq_next; + slirp->next_m = ifm->ifq_next; } /* Remove it from the queue */ ifqt = ifm->ifq_prev; remque(ifm); - --if_queued; + slirp->if_queued--; /* If there are more packets for this session, re-queue them */ if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) { @@ -204,10 +200,10 @@ if_start(void) } /* Encapsulate the packet for sending */ - if_encap((uint8_t *)ifm->m_data, ifm->m_len); + if_encap(slirp, (uint8_t *)ifm->m_data, ifm->m_len); m_free(ifm); - if (if_queued) + if (slirp->if_queued) goto again; } diff --git a/slirp/if.h b/slirp/if.h index 2fdc354508..2dac1c7a10 100644 --- a/slirp/if.h +++ b/slirp/if.h @@ -20,12 +20,6 @@ /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */ #define IF_MAXLINKHDR (2 + 14 + 40) -extern int if_queued; /* Number of packets queued so far */ - -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)) #endif diff --git a/slirp/ip.h b/slirp/ip.h index e0d76748b2..574fc019ae 100644 --- a/slirp/ip.h +++ b/slirp/ip.h @@ -250,7 +250,4 @@ struct ipoption { int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */ }; -extern struct ipq ipq; /* ip reass. queue */ -extern u_int16_t ip_id; /* ip packet ctr, for ids */ - #endif diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c index 66b4d2351b..95a4b39a4e 100644 --- a/slirp/ip_icmp.c +++ b/slirp/ip_icmp.c @@ -69,6 +69,7 @@ icmp_input(struct mbuf *m, int hlen) register struct icmp *icp; register struct ip *ip=mtod(m, struct ip *); int icmplen=ip->ip_len; + Slirp *slirp = m->slirp; DEBUG_CALL("icmp_input"); DEBUG_ARG("m = %lx", (long )m); @@ -98,12 +99,12 @@ icmp_input(struct mbuf *m, int hlen) case ICMP_ECHO: icp->icmp_type = ICMP_ECHOREPLY; ip->ip_len += hlen; /* since ip_input subtracts this */ - if (ip->ip_dst.s_addr == vhost_addr.s_addr) { + if (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) { icmp_reflect(m); } else { struct socket *so; struct sockaddr_in addr; - if ((so = socreate()) == NULL) goto freeit; + if ((so = socreate(slirp)) == NULL) goto freeit; if(udp_attach(so) == -1) { DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n", errno,strerror(errno))); @@ -122,10 +123,10 @@ icmp_input(struct mbuf *m, int hlen) /* Send the packet */ addr.sin_family = AF_INET; - if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) == - vnetwork_addr.s_addr) { + if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) == + slirp->vnetwork_addr.s_addr) { /* It's an alias */ - if (so->so_faddr.s_addr == vnameserver_addr.s_addr) { + if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) { addr.sin_addr = dns_addr; } else { addr.sin_addr = loopback_addr; @@ -222,7 +223,11 @@ icmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize, } /* make a copy */ - if(!(m=m_get())) goto end_error; /* get mbuf */ + m = m_get(msrc->slirp); + if (!m) { + goto end_error; + } + { 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); @@ -285,7 +290,7 @@ icmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize, ip->ip_ttl = MAXTTL; ip->ip_p = IPPROTO_ICMP; ip->ip_dst = ip->ip_src; /* ip adresses */ - ip->ip_src = vhost_addr; + ip->ip_src = m->slirp->vhost_addr; (void ) ip_output((struct socket *)NULL, m); diff --git a/slirp/ip_input.c b/slirp/ip_input.c index b07d3d5d5d..35230f8d10 100644 --- a/slirp/ip_input.c +++ b/slirp/ip_input.c @@ -42,11 +42,8 @@ #include #include "ip_icmp.h" -struct ipq ipq; - -static struct ip *ip_reass(register struct ip *ip, - register struct ipq *fp); -static void ip_freef(struct ipq *fp); +static struct ip *ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp); +static void ip_freef(Slirp *slirp, struct ipq *fp); static void ip_enq(register struct ipasfrag *p, register struct ipasfrag *prev); static void ip_deq(register struct ipasfrag *p); @@ -56,11 +53,11 @@ static void ip_deq(register struct ipasfrag *p); * All protocols not implemented in kernel go to raw IP protocol handler. */ void -ip_init(void) +ip_init(Slirp *slirp) { - ipq.ip_link.next = ipq.ip_link.prev = &ipq.ip_link; - udp_init(); - tcp_init(); + slirp->ipq.ip_link.next = slirp->ipq.ip_link.prev = &slirp->ipq.ip_link; + udp_init(slirp); + tcp_init(slirp); } /* @@ -70,6 +67,7 @@ ip_init(void) void ip_input(struct mbuf *m) { + Slirp *slirp = m->slirp; register struct ip *ip; int hlen; @@ -120,19 +118,19 @@ ip_input(struct mbuf *m) goto bad; } - if (slirp_restrict) { - if ((ip->ip_dst.s_addr & vnetwork_mask.s_addr) == - vnetwork_addr.s_addr) { + if (slirp->restricted) { + if ((ip->ip_dst.s_addr & slirp->vnetwork_mask.s_addr) == + slirp->vnetwork_addr.s_addr) { if (ip->ip_dst.s_addr == 0xffffffff && ip->ip_p != IPPROTO_UDP) goto bad; } else { + uint32_t inv_mask = ~slirp->vnetwork_mask.s_addr; struct ex_list *ex_ptr; - if ((ip->ip_dst.s_addr & ~vnetwork_mask.s_addr) == - ~vnetwork_mask.s_addr) + if ((ip->ip_dst.s_addr & inv_mask) == inv_mask) { goto bad; - - for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) + } + for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) if (ex_ptr->ex_addr.s_addr == ip->ip_dst.s_addr) break; @@ -167,7 +165,8 @@ ip_input(struct mbuf *m) * Look for queue of fragments * of this datagram. */ - for (l = ipq.ip_link.next; l != &ipq.ip_link; l = l->next) { + for (l = slirp->ipq.ip_link.next; l != &slirp->ipq.ip_link; + l = l->next) { fp = container_of(l, struct ipq, ip_link); if (ip->ip_id == fp->ipq_id && ip->ip_src.s_addr == fp->ipq_src.s_addr && @@ -197,13 +196,13 @@ ip_input(struct mbuf *m) * attempt reassembly; if it succeeds, proceed. */ if (ip->ip_tos & 1 || ip->ip_off) { - ip = ip_reass(ip, fp); + ip = ip_reass(slirp, ip, fp); if (ip == NULL) return; - m = dtom(ip); + m = dtom(slirp, ip); } else if (fp) - ip_freef(fp); + ip_freef(slirp, fp); } else ip->ip_len -= hlen; @@ -239,9 +238,9 @@ bad: * is given as fp; otherwise have to make a chain. */ static struct ip * -ip_reass(register struct ip *ip, register struct ipq *fp) +ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp) { - register struct mbuf *m = dtom(ip); + register struct mbuf *m = dtom(slirp, ip); register struct ipasfrag *q; int hlen = ip->ip_hl << 2; int i, next; @@ -263,10 +262,13 @@ ip_reass(register struct ip *ip, register struct ipq *fp) * If first fragment to arrive, create a reassembly queue. */ if (fp == NULL) { - struct mbuf *t; - if ((t = m_get()) == NULL) goto dropfrag; + struct mbuf *t = m_get(slirp); + + if (t == NULL) { + goto dropfrag; + } fp = mtod(t, struct ipq *); - insque(&fp->ip_link, &ipq.ip_link); + insque(&fp->ip_link, &slirp->ipq.ip_link); fp->ipq_ttl = IPFRAGTTL; fp->ipq_p = ip->ip_p; fp->ipq_id = ip->ip_id; @@ -296,7 +298,7 @@ ip_reass(register struct ip *ip, register struct ipq *fp) if (i > 0) { if (i >= ip->ip_len) goto dropfrag; - m_adj(dtom(ip), i); + m_adj(dtom(slirp, ip), i); ip->ip_off += i; ip->ip_len -= i; } @@ -312,11 +314,11 @@ ip_reass(register struct ip *ip, register struct ipq *fp) if (i < q->ipf_len) { q->ipf_len -= i; q->ipf_off += i; - m_adj(dtom(q), i); + m_adj(dtom(slirp, q), i); break; } q = q->ipf_next; - m_freem(dtom(q->ipf_prev)); + m_freem(dtom(slirp, q->ipf_prev)); ip_deq(q->ipf_prev); } @@ -340,11 +342,11 @@ insert: * Reassembly is complete; concatenate fragments. */ q = fp->frag_link.next; - m = dtom(q); + m = dtom(slirp, q); q = (struct ipasfrag *) q->ipf_next; while (q != (struct ipasfrag*)&fp->frag_link) { - struct mbuf *t = dtom(q); + struct mbuf *t = dtom(slirp, q); q = (struct ipasfrag *) q->ipf_next; m_cat(m, t); } @@ -375,7 +377,7 @@ insert: ip->ip_src = fp->ipq_src; ip->ip_dst = fp->ipq_dst; remque(&fp->ip_link); - (void) m_free(dtom(fp)); + (void) m_free(dtom(slirp, fp)); m->m_len += (ip->ip_hl << 2); m->m_data -= (ip->ip_hl << 2); @@ -391,17 +393,17 @@ dropfrag: * associated datagrams. */ static void -ip_freef(struct ipq *fp) +ip_freef(Slirp *slirp, struct ipq *fp) { register struct ipasfrag *q, *p; for (q = fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link; q = p) { p = q->ipf_next; ip_deq(q); - m_freem(dtom(q)); + m_freem(dtom(slirp, q)); } remque(&fp->ip_link); - (void) m_free(dtom(fp)); + (void) m_free(dtom(slirp, fp)); } /* @@ -435,24 +437,24 @@ ip_deq(register struct ipasfrag *p) * queue, discard it. */ void -ip_slowtimo(void) +ip_slowtimo(Slirp *slirp) { struct qlink *l; DEBUG_CALL("ip_slowtimo"); - l = ipq.ip_link.next; + l = slirp->ipq.ip_link.next; if (l == NULL) return; - while (l != &ipq.ip_link) { + while (l != &slirp->ipq.ip_link) { struct ipq *fp = container_of(l, struct ipq, ip_link); l = l->next; if (--fp->ipq_ttl == 0) { - ip_freef(fp); + ip_freef(slirp, fp); } - } + } } /* diff --git a/slirp/ip_output.c b/slirp/ip_output.c index 3031f4d112..dba278478b 100644 --- a/slirp/ip_output.c +++ b/slirp/ip_output.c @@ -40,8 +40,6 @@ #include -u_int16_t ip_id; - /* Number of packets queued before we start sending * (to prevent allocing too many mbufs) */ #define IF_THRESH 10 @@ -55,6 +53,7 @@ u_int16_t ip_id; int ip_output(struct socket *so, struct mbuf *m0) { + Slirp *slirp = m0->slirp; register struct ip *ip; register struct mbuf *m = m0; register int hlen = sizeof(struct ip ); @@ -70,7 +69,7 @@ ip_output(struct socket *so, struct mbuf *m0) */ ip->ip_v = IPVERSION; ip->ip_off &= IP_DF; - ip->ip_id = htons(ip_id++); + ip->ip_id = htons(slirp->ip_id++); ip->ip_hl = hlen >> 2; /* @@ -113,7 +112,7 @@ ip_output(struct socket *so, struct mbuf *m0) 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(slirp); if (m == NULL) { error = -1; goto sendorfree; diff --git a/slirp/libslirp.h b/slirp/libslirp.h index b0496d546f..3bda69194e 100644 --- a/slirp/libslirp.h +++ b/slirp/libslirp.h @@ -5,6 +5,9 @@ #ifdef CONFIG_SLIRP +struct Slirp; +typedef struct Slirp Slirp; + void slirp_init(int restricted, struct in_addr vnetwork, struct in_addr vnetmask, struct in_addr vhost, const char *vhostname, const char *tftp_path, diff --git a/slirp/main.h b/slirp/main.h index 6fd38f9b62..90deb58b27 100644 --- a/slirp/main.h +++ b/slirp/main.h @@ -31,11 +31,6 @@ 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 vnetwork_addr; -extern struct in_addr vnetwork_mask; -extern struct in_addr vhost_addr; -extern struct in_addr vdhcp_startaddr; -extern struct in_addr vnameserver_addr; extern struct in_addr our_addr; extern struct in_addr loopback_addr; extern struct in_addr dns_addr; @@ -44,16 +39,11 @@ extern char *socket_path; extern int towrite_max; extern int ppp_exit; extern int tcp_keepintvl; -extern uint8_t client_ethaddr[6]; -extern int slirp_restrict; -extern char slirp_hostname[33]; -extern char *tftp_prefix; -extern char *bootp_filename; #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 *slirp, const uint8_t *ip_data, int ip_data_len); ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags); diff --git a/slirp/mbuf.c b/slirp/mbuf.c index 888de86e45..7652fea196 100644 --- a/slirp/mbuf.c +++ b/slirp/mbuf.c @@ -17,8 +17,6 @@ #include -static int mbuf_alloced; -struct mbuf m_freelist, m_usedlist; #define MBUF_THRESH 30 /* @@ -28,10 +26,10 @@ struct mbuf m_freelist, m_usedlist; #define SLIRP_MSIZE (IF_MTU + IF_MAXLINKHDR + sizeof(struct m_hdr ) + 6) void -m_init(void) +m_init(Slirp *slirp) { - m_freelist.m_next = m_freelist.m_prev = &m_freelist; - m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist; + slirp->m_freelist.m_next = slirp->m_freelist.m_prev = &slirp->m_freelist; + slirp->m_usedlist.m_next = slirp->m_usedlist.m_prev = &slirp->m_usedlist; } /* @@ -43,26 +41,27 @@ m_init(void) * which tells m_free to actually free() it */ struct mbuf * -m_get(void) +m_get(Slirp *slirp) { register struct mbuf *m; int flags = 0; DEBUG_CALL("m_get"); - if (m_freelist.m_next == &m_freelist) { + if (slirp->m_freelist.m_next == &slirp->m_freelist) { m = (struct mbuf *)malloc(SLIRP_MSIZE); if (m == NULL) goto end_error; - mbuf_alloced++; - if (mbuf_alloced > MBUF_THRESH) + slirp->mbuf_alloced++; + if (slirp->mbuf_alloced > MBUF_THRESH) flags = M_DOFREE; + m->slirp = slirp; } else { - m = m_freelist.m_next; + m = slirp->m_freelist.m_next; remque(m); } /* Insert it in the used list */ - insque(m,&m_usedlist); + insque(m,&slirp->m_usedlist); m->m_flags = (flags | M_USEDLIST); /* Initialise it */ @@ -97,9 +96,9 @@ m_free(struct mbuf *m) */ if (m->m_flags & M_DOFREE) { free(m); - mbuf_alloced--; + m->slirp->mbuf_alloced--; } else if ((m->m_flags & M_FREELIST) == 0) { - insque(m,&m_freelist); + insque(m,&m->slirp->m_freelist); m->m_flags = M_FREELIST; /* Clobber other flags */ } } /* if(m) */ @@ -194,7 +193,7 @@ m_copy(struct mbuf *n, struct mbuf *m, int off, int len) * Fortunately, it's not used often */ struct mbuf * -dtom(void *dat) +dtom(Slirp *slirp, void *dat) { struct mbuf *m; @@ -202,7 +201,8 @@ dtom(void *dat) 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 = slirp->m_usedlist.m_next; m != &slirp->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; diff --git a/slirp/mbuf.h b/slirp/mbuf.h index c482753fef..99fca43898 100644 --- a/slirp/mbuf.h +++ b/slirp/mbuf.h @@ -84,6 +84,7 @@ struct m_hdr { struct mbuf { struct m_hdr m_hdr; + Slirp *slirp; union M_dat { char m_dat_[1]; /* ANSI don't like 0 sized arrays */ char *m_ext_; @@ -114,15 +115,13 @@ struct mbuf { #define M_DOFREE 0x08 /* when m_free is called on the mbuf, free() * it rather than putting it on the free list */ -extern struct mbuf m_freelist, m_usedlist; - -void m_init _P((void)); -struct mbuf * m_get _P((void)); +void m_init _P((Slirp *)); +struct mbuf * m_get _P((Slirp *)); void m_free _P((struct mbuf *)); void m_cat _P((register struct mbuf *, register struct mbuf *)); 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 _P((Slirp *, void *)); #endif diff --git a/slirp/misc.c b/slirp/misc.c index ee14db5e38..c2b66fd967 100644 --- a/slirp/misc.c +++ b/slirp/misc.c @@ -385,6 +385,7 @@ void slirp_connection_info(Monitor *mon) [TCPS_FIN_WAIT_2] = "FIN_WAIT_2", [TCPS_TIME_WAIT] = "TIME_WAIT", }; + Slirp *slirp = &slirp_instance; struct in_addr dst_addr; struct sockaddr_in src; socklen_t src_len; @@ -397,7 +398,7 @@ void slirp_connection_info(Monitor *mon) monitor_printf(mon, " Protocol[State] FD Source Address Port " "Dest. Address Port RecvQ SendQ\n"); - for (so = tcb.so_next; so != &tcb; so = so->so_next) { + for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) { if (so->so_state & SS_HOSTFWD) { state = "HOST_FORWARD"; } else if (so->so_tcpcb) { @@ -427,7 +428,7 @@ void slirp_connection_info(Monitor *mon) so->so_rcv.sb_cc, so->so_snd.sb_cc); } - for (so = udb.so_next; so != &udb; so = so->so_next) { + for (so = slirp->udb.so_next; so != &slirp->udb; so = so->so_next) { if (so->so_state & SS_HOSTFWD) { n = snprintf(buf, sizeof(buf), " UDP[HOST_FORWARD]"); src_len = sizeof(src); diff --git a/slirp/misc.h b/slirp/misc.h index 2f478885de..e43519dcba 100644 --- a/slirp/misc.h +++ b/slirp/misc.h @@ -16,8 +16,6 @@ struct ex_list { struct ex_list *ex_next; }; -extern struct ex_list *exec_list; - #ifndef HAVE_STRDUP char *strdup _P((const char *)); #endif diff --git a/slirp/slirp.c b/slirp/slirp.c index 71f79a3630..25bc8a4c57 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -33,27 +33,14 @@ struct in_addr dns_addr; /* host loopback address */ struct in_addr loopback_addr; -/* virtual network configuration */ -struct in_addr vnetwork_addr; -struct in_addr vnetwork_mask; -struct in_addr vhost_addr; -struct in_addr vdhcp_startaddr; -struct in_addr vnameserver_addr; - /* emulated hosts use the MAC addr 52:55:IP:IP:IP:IP */ static const uint8_t special_ethaddr[6] = { 0x52, 0x55, 0x00, 0x00, 0x00, 0x00 }; -/* ARP cache for the guest IP addresses (XXX: allow many entries) */ -uint8_t client_ethaddr[6]; -static struct in_addr client_ipaddr; - static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 }; -int slirp_restrict; -int link_up; -struct ex_list *exec_list; +int link_up; // FIXME: kill this /* XXX: suppress those select globals */ fd_set *global_readfds, *global_writefds, *global_xfds; @@ -62,7 +49,7 @@ u_int curtime; static u_int time_fasttimo, last_slowtimo; static int do_slowtimo; -char slirp_hostname[33]; +Slirp slirp_instance; #ifdef _WIN32 @@ -206,37 +193,40 @@ void slirp_init(int restricted, struct in_addr vnetwork, const char *bootfile, struct in_addr vdhcp_start, struct in_addr vnameserver) { + Slirp *slirp = &slirp_instance; + slirp_init_once(); link_up = 1; - slirp_restrict = restricted; + slirp->restricted = restricted; - if_init(); - ip_init(); + if_init(slirp); + ip_init(slirp); /* Initialise mbufs *after* setting the MTU */ - m_init(); + m_init(slirp); - vnetwork_addr = vnetwork; - vnetwork_mask = vnetmask; - vhost_addr = vhost; + slirp->vnetwork_addr = vnetwork; + slirp->vnetwork_mask = vnetmask; + slirp->vhost_addr = vhost; if (vhostname) { - pstrcpy(slirp_hostname, sizeof(slirp_hostname), vhostname); + pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname), + vhostname); } - qemu_free(tftp_prefix); - tftp_prefix = NULL; + qemu_free(slirp->tftp_prefix); + slirp->tftp_prefix = NULL; if (tftp_path) { - tftp_prefix = qemu_strdup(tftp_path); + slirp->tftp_prefix = qemu_strdup(tftp_path); } - qemu_free(bootp_filename); - bootp_filename = NULL; + qemu_free(slirp->bootp_filename); + slirp->bootp_filename = NULL; if (bootfile) { - bootp_filename = qemu_strdup(bootfile); + slirp->bootp_filename = qemu_strdup(bootfile); } - vdhcp_startaddr = vdhcp_start; - vnameserver_addr = vnameserver; + slirp->vdhcp_startaddr = vdhcp_start; + slirp->vnameserver_addr = vnameserver; - register_savevm("slirp", 0, 2, slirp_state_save, slirp_state_load, NULL); + register_savevm("slirp", 0, 2, slirp_state_save, slirp_state_load, slirp); } #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED) @@ -269,6 +259,7 @@ static void updtime(void) void slirp_select_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds) { + Slirp *slirp = &slirp_instance; struct socket *so, *so_next; int nfds; @@ -291,10 +282,11 @@ void slirp_select_fill(int *pnfds, * *_slowtimo needs calling if there are IP fragments * in the fragment queue, or there are TCP connections active */ - do_slowtimo = ((tcb.so_next != &tcb) || - (&ipq.ip_link != ipq.ip_link.next)); + do_slowtimo = ((slirp->tcb.so_next != &slirp->tcb) || + (&slirp->ipq.ip_link != slirp->ipq.ip_link.next)); - for (so = tcb.so_next; so != &tcb; so = so_next) { + for (so = slirp->tcb.so_next; so != &slirp->tcb; + so = so_next) { so_next = so->so_next; /* @@ -351,7 +343,8 @@ void slirp_select_fill(int *pnfds, /* * UDP sockets */ - for (so = udb.so_next; so != &udb; so = so_next) { + for (so = slirp->udb.so_next; so != &slirp->udb; + so = so_next) { so_next = so->so_next; /* @@ -387,6 +380,7 @@ void slirp_select_fill(int *pnfds, void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int select_error) { + Slirp *slirp = &slirp_instance; struct socket *so, *so_next; int ret; @@ -405,12 +399,12 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, * See if anything has timed out */ if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) { - tcp_fasttimo(); + tcp_fasttimo(slirp); time_fasttimo = 0; } if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) { - ip_slowtimo(); - tcp_slowtimo(); + ip_slowtimo(slirp); + tcp_slowtimo(slirp); last_slowtimo = curtime; } @@ -421,7 +415,8 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, /* * Check TCP sockets */ - for (so = tcb.so_next; so != &tcb; so = so_next) { + for (so = slirp->tcb.so_next; so != &slirp->tcb; + so = so_next) { so_next = so->so_next; /* @@ -538,7 +533,8 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, * 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 = slirp->udb.so_next; so != &slirp->udb; + so = so_next) { so_next = so->so_next; if (so->s != -1 && FD_ISSET(so->s, readfds)) { @@ -550,8 +546,9 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, /* * See if we can start outputting */ - if (if_queued) - if_start(); + if (slirp->if_queued) { + if_start(slirp); + } /* clear global file descriptor sets. * these reside on the stack in vl.c @@ -596,7 +593,7 @@ struct arphdr uint32_t ar_tip ; /* target IP address */ } __attribute__((packed)); -static void arp_input(const uint8_t *pkt, int pkt_len) +static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len) { struct ethhdr *eh = (struct ethhdr *)pkt; struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN); @@ -609,18 +606,19 @@ static void arp_input(const uint8_t *pkt, int pkt_len) ar_op = ntohs(ah->ar_op); switch(ar_op) { case ARPOP_REQUEST: - if ((ah->ar_tip & vnetwork_mask.s_addr) == vnetwork_addr.s_addr) { - if (ah->ar_tip == vnameserver_addr.s_addr || - ah->ar_tip == vhost_addr.s_addr) + if ((ah->ar_tip & slirp->vnetwork_mask.s_addr) == + slirp->vnetwork_addr.s_addr) { + if (ah->ar_tip == slirp->vnameserver_addr.s_addr || + ah->ar_tip == slirp->vhost_addr.s_addr) goto arp_ok; - for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { + for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { if (ex_ptr->ex_addr.s_addr == ah->ar_tip) 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(slirp->client_ethaddr, eh->h_source, ETH_ALEN); /* ARP request for alias/dns mac address */ memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN); @@ -642,9 +640,9 @@ static void arp_input(const uint8_t *pkt, int pkt_len) break; case ARPOP_REPLY: /* reply to request of client mac address ? */ - if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN) && - ah->ar_sip == client_ipaddr.s_addr) { - memcpy(client_ethaddr, ah->ar_sha, ETH_ALEN); + if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN) && + ah->ar_sip == slirp->client_ipaddr.s_addr) { + memcpy(slirp->client_ethaddr, ah->ar_sha, ETH_ALEN); } break; default: @@ -654,6 +652,7 @@ static void arp_input(const uint8_t *pkt, int pkt_len) void slirp_input(const uint8_t *pkt, int pkt_len) { + Slirp *slirp = &slirp_instance; struct mbuf *m; int proto; @@ -663,10 +662,10 @@ void slirp_input(const uint8_t *pkt, int pkt_len) proto = ntohs(*(uint16_t *)(pkt + 12)); switch(proto) { case ETH_P_ARP: - arp_input(pkt, pkt_len); + arp_input(slirp, pkt, pkt_len); break; case ETH_P_IP: - m = m_get(); + m = m_get(slirp); if (!m) return; /* Note: we add to align the IP header */ @@ -687,7 +686,7 @@ void slirp_input(const uint8_t *pkt, int pkt_len) } /* output the IP packet to the ethernet device */ -void if_encap(const uint8_t *ip_data, int ip_data_len) +void if_encap(Slirp *slirp, const uint8_t *ip_data, int ip_data_len) { uint8_t buf[1600]; struct ethhdr *eh = (struct ethhdr *)buf; @@ -695,7 +694,7 @@ void if_encap(const uint8_t *ip_data, int ip_data_len) if (ip_data_len + ETH_HLEN > sizeof(buf)) return; - if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN)) { + if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN)) { uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)]; struct ethhdr *reh = (struct ethhdr *)arp_req; struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN); @@ -708,7 +707,7 @@ void if_encap(const uint8_t *ip_data, int ip_data_len) will retry sending its packet. */ memset(reh->h_dest, 0xff, ETH_ALEN); memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4); - memcpy(&reh->h_source[2], &vhost_addr, 4); + memcpy(&reh->h_source[2], &slirp->vhost_addr, 4); reh->h_proto = htons(ETH_P_ARP); rah->ar_hrd = htons(1); rah->ar_pro = htons(ETH_P_IP); @@ -717,20 +716,20 @@ void if_encap(const uint8_t *ip_data, int ip_data_len) rah->ar_op = htons(ARPOP_REQUEST); /* source hw addr */ memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 4); - memcpy(&rah->ar_sha[2], &vhost_addr, 4); + memcpy(&rah->ar_sha[2], &slirp->vhost_addr, 4); /* source IP */ - rah->ar_sip = vhost_addr.s_addr; + rah->ar_sip = slirp->vhost_addr.s_addr; /* target hw addr (none) */ memset(rah->ar_tha, 0, ETH_ALEN); /* target IP */ rah->ar_tip = iph->ip_dst.s_addr; - client_ipaddr = iph->ip_dst; + slirp->client_ipaddr = iph->ip_dst; slirp_output(arp_req, sizeof(arp_req)); } else { - memcpy(eh->h_dest, client_ethaddr, ETH_ALEN); + memcpy(eh->h_dest, slirp->client_ethaddr, ETH_ALEN); memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4); /* XXX: not correct */ - memcpy(&eh->h_source[2], &vhost_addr, 4); + memcpy(&eh->h_source[2], &slirp->vhost_addr, 4); 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); @@ -740,8 +739,9 @@ void if_encap(const uint8_t *ip_data, int ip_data_len) /* Drop host forwarding rule, return 0 if found. */ int slirp_remove_hostfwd(int is_udp, struct in_addr host_addr, int host_port) { + Slirp *slirp = &slirp_instance; struct socket *so; - struct socket *head = (is_udp ? &udb : &tcb); + struct socket *head = (is_udp ? &slirp->udb : &slirp->tcb); struct sockaddr_in addr; int port = htons(host_port); socklen_t addr_len; @@ -764,16 +764,18 @@ int slirp_remove_hostfwd(int is_udp, struct in_addr host_addr, int host_port) int slirp_add_hostfwd(int is_udp, struct in_addr host_addr, int host_port, struct in_addr guest_addr, int guest_port) { + Slirp *slirp = &slirp_instance; + if (!guest_addr.s_addr) { - guest_addr = vdhcp_startaddr; + guest_addr = slirp->vdhcp_startaddr; } if (is_udp) { - if (!udp_listen(host_addr.s_addr, htons(host_port), guest_addr.s_addr, - htons(guest_port), SS_HOSTFWD)) + if (!udp_listen(slirp, host_addr.s_addr, htons(host_port), + guest_addr.s_addr, htons(guest_port), SS_HOSTFWD)) return -1; } else { - if (!tcp_listen(host_addr.s_addr, htons(host_port), guest_addr.s_addr, - htons(guest_port), SS_HOSTFWD)) + if (!tcp_listen(slirp, host_addr.s_addr, htons(host_port), + guest_addr.s_addr, htons(guest_port), SS_HOSTFWD)) return -1; } return 0; @@ -782,16 +784,19 @@ int slirp_add_hostfwd(int is_udp, struct in_addr host_addr, int host_port, int slirp_add_exec(int do_pty, const void *args, struct in_addr guest_addr, int guest_port) { + Slirp *slirp = &slirp_instance; + if (!guest_addr.s_addr) { - guest_addr.s_addr = - vnetwork_addr.s_addr | (htonl(0x0204) & ~vnetwork_mask.s_addr); + guest_addr.s_addr = slirp->vnetwork_addr.s_addr | + (htonl(0x0204) & ~slirp->vnetwork_mask.s_addr); } - if ((guest_addr.s_addr & vnetwork_mask.s_addr) != vnetwork_addr.s_addr || - guest_addr.s_addr == vhost_addr.s_addr || - guest_addr.s_addr == vnameserver_addr.s_addr) { + if ((guest_addr.s_addr & slirp->vnetwork_mask.s_addr) != + slirp->vnetwork_addr.s_addr || + guest_addr.s_addr == slirp->vhost_addr.s_addr || + guest_addr.s_addr == slirp->vnameserver_addr.s_addr) { return -1; } - return add_exec(&exec_list, do_pty, (char *)args, guest_addr, + return add_exec(&slirp->exec_list, do_pty, (char *)args, guest_addr, htons(guest_port)); } @@ -806,11 +811,11 @@ ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags) } static struct socket * -slirp_find_ctl_socket(struct in_addr guest_addr, int guest_port) +slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, int guest_port) { struct socket *so; - for (so = tcb.so_next; so != &tcb; so = so->so_next) { + for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) { if (so->so_faddr.s_addr == guest_addr.s_addr && htons(so->so_fport) == guest_port) { return so; @@ -821,10 +826,11 @@ slirp_find_ctl_socket(struct in_addr guest_addr, int guest_port) size_t slirp_socket_can_recv(struct in_addr guest_addr, int guest_port) { + Slirp *slirp = &slirp_instance; struct iovec iov[2]; struct socket *so; - so = slirp_find_ctl_socket(guest_addr, guest_port); + so = slirp_find_ctl_socket(slirp, guest_addr, guest_port); if (!so || so->so_state & SS_NOFDREF) return 0; @@ -838,8 +844,9 @@ size_t slirp_socket_can_recv(struct in_addr guest_addr, int guest_port) void slirp_socket_recv(struct in_addr guest_addr, int guest_port, const uint8_t *buf, int size) { + Slirp *slirp = &slirp_instance; int ret; - struct socket *so = slirp_find_ctl_socket(guest_addr, guest_port); + struct socket *so = slirp_find_ctl_socket(slirp, guest_addr, guest_port); if (!so) return; @@ -928,12 +935,14 @@ static void slirp_socket_save(QEMUFile *f, struct socket *so) static void slirp_state_save(QEMUFile *f, void *opaque) { + Slirp *slirp = opaque; struct ex_list *ex_ptr; - for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) + for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) if (ex_ptr->ex_pty == 3) { struct socket *so; - so = slirp_find_ctl_socket(ex_ptr->ex_addr, ntohs(ex_ptr->ex_fport)); + so = slirp_find_ctl_socket(slirp, ex_ptr->ex_addr, + ntohs(ex_ptr->ex_fport)); if (!so) continue; @@ -942,7 +951,7 @@ static void slirp_state_save(QEMUFile *f, void *opaque) } qemu_put_byte(f, 0); - qemu_put_be16(f, ip_id); + qemu_put_be16(f, slirp->ip_id); } static void slirp_tcp_load(QEMUFile *f, struct tcpcb *tp) @@ -1041,12 +1050,13 @@ static int slirp_socket_load(QEMUFile *f, struct socket *so) static int slirp_state_load(QEMUFile *f, void *opaque, int version_id) { + Slirp *slirp = opaque; struct ex_list *ex_ptr; int r; while ((r = qemu_get_byte(f))) { int ret; - struct socket *so = socreate(); + struct socket *so = socreate(slirp); if (!so) return -ENOMEM; @@ -1056,11 +1066,11 @@ static int slirp_state_load(QEMUFile *f, void *opaque, int version_id) if (ret < 0) return ret; - if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) != - vnetwork_addr.s_addr) { + if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) != + slirp->vnetwork_addr.s_addr) { return -EINVAL; } - for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { + for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { if (ex_ptr->ex_pty == 3 && so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr && so->so_fport == ex_ptr->ex_fport) { @@ -1074,7 +1084,7 @@ static int slirp_state_load(QEMUFile *f, void *opaque, int version_id) } if (version_id >= 2) { - ip_id = qemu_get_be16(f); + slirp->ip_id = qemu_get_be16(f); } return 0; diff --git a/slirp/slirp.h b/slirp/slirp.h index 063e5f6c18..b1e8d4e6c6 100644 --- a/slirp/slirp.h +++ b/slirp/slirp.h @@ -185,6 +185,7 @@ int inet_aton _P((const char *cp, struct in_addr *ia)); #include "debug.h" +#include "libslirp.h" #include "ip.h" #include "tcp.h" #include "tcp_timer.h" @@ -204,14 +205,67 @@ int inet_aton _P((const char *cp, struct in_addr *ia)); #include "bootp.h" #include "tftp.h" -#include "libslirp.h" + +struct Slirp { + /* virtual network configuration */ + struct in_addr vnetwork_addr; + struct in_addr vnetwork_mask; + struct in_addr vhost_addr; + struct in_addr vdhcp_startaddr; + struct in_addr vnameserver_addr; + + /* ARP cache for the guest IP addresses (XXX: allow many entries) */ + uint8_t client_ethaddr[6]; + + struct in_addr client_ipaddr; + char client_hostname[33]; + + int restricted; + struct timeval tt; + struct ex_list *exec_list; + + /* mbuf states */ + struct mbuf m_freelist, m_usedlist; + int mbuf_alloced; + + /* if states */ + int if_queued; /* number of packets queued so far */ + 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 */ + + /* ip states */ + struct ipq ipq; /* ip reass. queue */ + u_int16_t ip_id; /* ip packet ctr, for ids */ + + /* bootp/dhcp states */ + BOOTPClient bootp_clients[NB_BOOTP_CLIENTS]; + char *bootp_filename; + + /* tcp states */ + struct socket tcb; + struct socket *tcp_last_so; + tcp_seq tcp_iss; /* tcp initial send seq # */ + u_int32_t tcp_now; /* for RFC 1323 timestamps */ + + /* udp states */ + struct socket udb; + struct socket *udp_last_so; + + /* tftp states */ + char *tftp_prefix; + struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX]; + +}; + +extern Slirp slirp_instance; #ifndef NULL #define NULL (void *)0 #endif #ifndef FULL_BOLT -void if_start _P((void)); +void if_start _P((Slirp *)); #else void if_start _P((struct ttys *)); #endif @@ -257,13 +311,13 @@ void lprint _P((const char *, ...)); int cksum(struct mbuf *m, int len); /* if.c */ -void if_init _P((void)); +void if_init _P((Slirp *)); void if_output _P((struct socket *, struct mbuf *)); /* ip_input.c */ -void ip_init _P((void)); +void ip_init _P((Slirp *)); void ip_input _P((struct mbuf *)); -void ip_slowtimo _P((void)); +void ip_slowtimo _P((Slirp *)); void ip_stripoptions _P((register struct mbuf *, struct mbuf *)); /* ip_output.c */ @@ -278,7 +332,7 @@ int tcp_output _P((register struct tcpcb *)); void tcp_setpersist _P((register struct tcpcb *)); /* tcp_subr.c */ -void tcp_init _P((void)); +void tcp_init _P((Slirp *)); 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 *)); diff --git a/slirp/socket.c b/slirp/socket.c index f7b212fba8..d8fbe89a74 100644 --- a/slirp/socket.c +++ b/slirp/socket.c @@ -41,7 +41,7 @@ solookup(struct socket *head, struct in_addr laddr, u_int lport, * insque() it into the correct linked-list */ struct socket * -socreate(void) +socreate(Slirp *slirp) { struct socket *so; @@ -50,6 +50,7 @@ socreate(void) memset(so, 0, sizeof(struct socket)); so->so_state = SS_NOFDREF; so->s = -1; + so->slirp = slirp; } return(so); } @@ -60,15 +61,17 @@ socreate(void) void sofree(struct socket *so) { + Slirp *slirp = so->slirp; + if (so->so_emu==EMU_RSH && so->extra) { sofree(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 == slirp->tcp_last_so) { + slirp->tcp_last_so = &slirp->tcb; + } else if (so == slirp->udp_last_so) { + slirp->udp_last_so = &slirp->udb; + } m_free(so->so_m); if(so->so_next && so->so_prev) @@ -473,7 +476,10 @@ sorecvfrom(struct socket *so) int n; #endif - if (!(m = m_get())) return; + m = m_get(so->slirp); + if (!m) { + return; + } m->m_data += IF_MAXLINKHDR; /* @@ -533,6 +539,7 @@ sorecvfrom(struct socket *so) int sosendto(struct socket *so, struct mbuf *m) { + Slirp *slirp = so->slirp; int ret; struct sockaddr_in addr; @@ -541,10 +548,10 @@ sosendto(struct socket *so, struct mbuf *m) DEBUG_ARG("m = %lx", (long)m); addr.sin_family = AF_INET; - if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) == - vnetwork_addr.s_addr) { + if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) == + slirp->vnetwork_addr.s_addr) { /* It's an alias */ - if (so->so_faddr.s_addr == vnameserver_addr.s_addr) { + if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) { addr.sin_addr = dns_addr; } else { addr.sin_addr = loopback_addr; @@ -576,7 +583,8 @@ sosendto(struct socket *so, struct mbuf *m) * Listen for incoming TCP connections */ struct socket * -tcp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport, int flags) +tcp_listen(Slirp *slirp, u_int32_t haddr, u_int hport, u_int32_t laddr, + u_int lport, int flags) { struct sockaddr_in addr; struct socket *so; @@ -590,7 +598,8 @@ tcp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport, int flags DEBUG_ARG("lport = %d", lport); DEBUG_ARG("flags = %x", flags); - if ((so = socreate()) == NULL) { + so = socreate(slirp); + if (!so) { return NULL; } @@ -599,7 +608,7 @@ tcp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport, int flags free(so); return NULL; } - insque(so,&tcb); + insque(so, &slirp->tcb); /* * SS_FACCEPTONCE sockets must time out. @@ -637,7 +646,7 @@ tcp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport, int flags getsockname(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 = vhost_addr; + so->so_faddr = slirp->vhost_addr; else so->so_faddr = addr.sin_addr; diff --git a/slirp/socket.h b/slirp/socket.h index 4db2147aa8..dcf27430b2 100644 --- a/slirp/socket.h +++ b/slirp/socket.h @@ -20,6 +20,8 @@ struct socket { int s; /* The actual socket */ + Slirp *slirp; /* managing slirp instance */ + /* XXX union these with not-yet-used sbuf params */ struct mbuf *so_m; /* Pointer to the original SYN packet, * for non-blocking connect()'s, and @@ -72,10 +74,8 @@ struct socket { #define SS_HOSTFWD 0x1000 /* Socket describes host->guest forwarding */ #define SS_INCOMING 0x2000 /* Connection was initiated by a host on the internet */ -extern struct socket tcb; - struct socket * solookup _P((struct socket *, struct in_addr, u_int, struct in_addr, u_int)); -struct socket * socreate _P((void)); +struct socket * socreate _P((Slirp *)); void sofree _P((struct socket *)); int soread _P((struct socket *)); void sorecvoob _P((struct socket *)); @@ -83,7 +83,8 @@ int sosendoob _P((struct socket *)); int sowrite _P((struct socket *)); void sorecvfrom _P((struct socket *)); int sosendto _P((struct socket *, struct mbuf *)); -struct socket * tcp_listen _P((u_int32_t, u_int, u_int32_t, u_int, int)); +struct socket * tcp_listen _P((Slirp *, u_int32_t, u_int, u_int32_t, u_int, + int)); void soisfconnecting _P((register struct socket *)); void soisfconnected _P((register struct socket *)); void sofwdrain _P((struct socket *)); diff --git a/slirp/tcp.h b/slirp/tcp.h index 4a18ed8821..c65ed43423 100644 --- a/slirp/tcp.h +++ b/slirp/tcp.h @@ -38,8 +38,6 @@ typedef u_int32_t tcp_seq; #define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */ #define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */ -extern struct socket *tcp_last_so; - #define TCP_SNDSPACE 8192 #define TCP_RCVSPACE 8192 @@ -163,6 +161,4 @@ struct tcphdr { #define TCP_ISSINCR (125*1024) /* increment for tcp_iss each second */ -extern tcp_seq tcp_iss; /* tcp initial send seq # */ - #endif diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c index b7a67e561f..47cf0ad8c7 100644 --- a/slirp/tcp_input.c +++ b/slirp/tcp_input.c @@ -41,12 +41,7 @@ #include #include "ip_icmp.h" -struct socket tcb; - #define 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) @@ -233,6 +228,7 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso) u_long tiwin; int ret; struct ex_list *ex_ptr; + Slirp *slirp; DEBUG_CALL("tcp_input"); DEBUG_ARGS((dfd," m = %8lx iphlen = %2d inso = %lx\n", @@ -243,6 +239,7 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso) */ if (m == NULL) { so = inso; + slirp = so->slirp; /* Re-set a few variables */ tp = sototcpcb(so); @@ -254,6 +251,7 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso) goto cont_conn; } + slirp = m->slirp; /* * Get IP and TCP header together in first mbuf. @@ -318,8 +316,8 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso) m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); m->m_len -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); - if (slirp_restrict) { - for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { + if (slirp->restricted) { + for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { if (ex_ptr->ex_fport == ti->ti_dport && ti->ti_dst.s_addr == ex_ptr->ex_addr.s_addr) { break; @@ -332,15 +330,15 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso) * Locate pcb for segment. */ findso: - so = tcp_last_so; + so = slirp->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(&slirp->tcb, ti->ti_src, ti->ti_sport, ti->ti_dst, ti->ti_dport); if (so) - tcp_last_so = so; + slirp->tcp_last_so = so; } /* @@ -360,7 +358,7 @@ findso: if ((tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) != TH_SYN) goto dropwithreset; - if ((so = socreate()) == NULL) + if ((so = socreate(slirp)) == NULL) goto dropwithreset; if (tcp_attach(so) < 0) { free(so); /* Not sofree (if it failed, it's not insqued) */ @@ -555,12 +553,13 @@ findso: * If this is destined for the control address, then flag to * tcp_ctl once connected, otherwise connect */ - if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) == - vnetwork_addr.s_addr) { - if (so->so_faddr.s_addr != vhost_addr.s_addr && - so->so_faddr.s_addr != vnameserver_addr.s_addr) { + if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) == + slirp->vnetwork_addr.s_addr) { + if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr && + so->so_faddr.s_addr != slirp->vnameserver_addr.s_addr) { /* May be an add exec */ - for(ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { + for (ex_ptr = slirp->exec_list; ex_ptr; + ex_ptr = ex_ptr->ex_next) { if(ex_ptr->ex_fport == so->so_fport && so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) { so->so_state |= SS_CTL; @@ -631,8 +630,8 @@ findso: if (iss) tp->iss = iss; else - tp->iss = tcp_iss; - tcp_iss += TCP_ISSINCR/2; + tp->iss = slirp->tcp_iss; + slirp->tcp_iss += TCP_ISSINCR/2; tp->irs = ti->ti_seq; tcp_sendseqinit(tp); tcp_rcvseqinit(tp); diff --git a/slirp/tcp_output.c b/slirp/tcp_output.c index 686e90dc0e..0d6011ac64 100644 --- a/slirp/tcp_output.c +++ b/slirp/tcp_output.c @@ -290,7 +290,7 @@ send: * the template for sends on this connection. */ if (len) { - m = m_get(); + m = m_get(so->slirp); if (m == NULL) { error = 1; goto out; @@ -310,7 +310,7 @@ send: if (off + len == so->so_snd.sb_cc) flags |= TH_PUSH; } else { - m = m_get(); + m = m_get(so->slirp); if (m == NULL) { error = 1; goto out; diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c index 868382a6c2..51b38344ef 100644 --- a/slirp/tcp_subr.c +++ b/slirp/tcp_subr.c @@ -48,10 +48,11 @@ * Tcp initialization */ void -tcp_init(void) +tcp_init(Slirp *slirp) { - tcp_iss = 1; /* wrong */ - tcb.so_next = tcb.so_prev = &tcb; + slirp->tcp_iss = 1; /* wrong */ + slirp->tcb.so_next = slirp->tcb.so_prev = &slirp->tcb; + slirp->tcp_last_so = &slirp->tcb; } /* @@ -116,7 +117,7 @@ tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m, if (tp) win = sbspace(&tp->t_socket->so_rcv); if (m == NULL) { - if ((m = m_get()) == NULL) + if ((m = m_get(tp->t_socket->slirp)) == NULL) return; tlen = 0; m->m_data += IF_MAXLINKHDR; @@ -237,6 +238,7 @@ tcp_close(struct tcpcb *tp) { register struct tcpiphdr *t; struct socket *so = tp->t_socket; + Slirp *slirp = so->slirp; register struct mbuf *m; DEBUG_CALL("tcp_close"); @@ -253,8 +255,8 @@ tcp_close(struct tcpcb *tp) free(tp); so->so_tcpcb = NULL; /* clobber input socket cache if we're closing the cached connection */ - if (so == tcp_last_so) - tcp_last_so = &tcb; + if (so == slirp->tcp_last_so) + slirp->tcp_last_so = &slirp->tcb; closesocket(so->s); sbfree(&so->so_rcv); sbfree(&so->so_snd); @@ -317,6 +319,7 @@ tcp_sockclosed(struct tcpcb *tp) */ int tcp_fconnect(struct socket *so) { + Slirp *slirp = so->slirp; int ret=0; DEBUG_CALL("tcp_fconnect"); @@ -333,9 +336,10 @@ int tcp_fconnect(struct socket *so) setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(opt )); addr.sin_family = AF_INET; - if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) == vnetwork_addr.s_addr) { + if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) == + slirp->vnetwork_addr.s_addr) { /* It's an alias */ - if (so->so_faddr.s_addr == vnameserver_addr.s_addr) { + if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) { addr.sin_addr = dns_addr; } else { addr.sin_addr = loopback_addr; @@ -375,6 +379,7 @@ int tcp_fconnect(struct socket *so) void tcp_connect(struct socket *inso) { + Slirp *slirp = inso->slirp; struct socket *so; struct sockaddr_in addr; socklen_t addrlen = sizeof(struct sockaddr_in); @@ -392,7 +397,7 @@ tcp_connect(struct socket *inso) /* FACCEPTONCE already have a tcpcb */ so = inso; } else { - if ((so = socreate()) == NULL) { + if ((so = socreate(slirp)) == NULL) { /* If it failed, get rid of the pending connection */ closesocket(accept(inso->s,(struct sockaddr *)&addr,&addrlen)); return; @@ -423,7 +428,7 @@ tcp_connect(struct socket *inso) 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 = vhost_addr; + so->so_faddr = slirp->vhost_addr; /* Close the accept() socket, set right state */ if (inso->so_state & SS_FACCEPTONCE) { @@ -441,8 +446,8 @@ tcp_connect(struct socket *inso) 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 = slirp->tcp_iss; + slirp->tcp_iss += TCP_ISSINCR/2; tcp_sendseqinit(tp); tcp_output(tp); } @@ -456,7 +461,7 @@ tcp_attach(struct socket *so) if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) return -1; - insque(so, &tcb); + insque(so, &so->slirp->tcb); return 0; } @@ -539,6 +544,7 @@ tcp_tos(struct socket *so) int tcp_emu(struct socket *so, struct mbuf *m) { + Slirp *slirp = so->slirp; u_int n1, n2, n3, n4, n5, n6; char buff[257]; u_int32_t laddr; @@ -572,7 +578,9 @@ tcp_emu(struct socket *so, struct mbuf *m) HTONS(n1); HTONS(n2); /* n2 is the one on our host */ - for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) { + for (tmpso = slirp->tcb.so_next; + tmpso != &slirp->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 && @@ -608,9 +616,10 @@ tcp_emu(struct socket *so, struct mbuf *m) laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4)); lport = htons((n5 << 8) | (n6)); - if ((so = tcp_listen(INADDR_ANY, 0, laddr, lport, SS_FACCEPTONCE)) == NULL) + if ((so = tcp_listen(slirp, INADDR_ANY, 0, laddr, + lport, SS_FACCEPTONCE)) == NULL) { return 1; - + } n6 = ntohs(so->so_fport); n5 = (n6 >> 8) & 0xff; @@ -640,9 +649,10 @@ tcp_emu(struct socket *so, struct mbuf *m) laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4)); lport = htons((n5 << 8) | (n6)); - if ((so = tcp_listen(INADDR_ANY, 0, laddr, lport, SS_FACCEPTONCE)) == NULL) + if ((so = tcp_listen(slirp, INADDR_ANY, 0, laddr, + lport, SS_FACCEPTONCE)) == NULL) { return 1; - + } n6 = ntohs(so->so_fport); n5 = (n6 >> 8) & 0xff; @@ -680,7 +690,8 @@ tcp_emu(struct socket *so, struct mbuf *m) lport += m->m_data[i] - '0'; } if (m->m_data[m->m_len-1] == '\0' && lport != 0 && - (so = tcp_listen(INADDR_ANY, 0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL) + (so = tcp_listen(slirp, INADDR_ANY, 0, so->so_laddr.s_addr, + htons(lport), SS_FACCEPTONCE)) != NULL) m->m_len = snprintf(m->m_data, m->m_hdr.mh_size, "%d", ntohs(so->so_fport)) + 1; return 1; @@ -695,27 +706,33 @@ tcp_emu(struct socket *so, struct mbuf *m) /* The %256s is for the broken mIRC */ if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3) { - if ((so = tcp_listen(INADDR_ANY, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL) + if ((so = tcp_listen(slirp, INADDR_ANY, 0, + htonl(laddr), htons(lport), + SS_FACCEPTONCE)) == NULL) { return 1; - + } m->m_len = bptr - m->m_data; /* Adjust length */ m->m_len += snprintf(bptr, m->m_hdr.mh_size, "DCC CHAT chat %lu %u%c\n", (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 = tcp_listen(INADDR_ANY, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL) + if ((so = tcp_listen(slirp, INADDR_ANY, 0, + htonl(laddr), htons(lport), + SS_FACCEPTONCE)) == NULL) { return 1; - + } m->m_len = bptr - m->m_data; /* Adjust length */ m->m_len += snprintf(bptr, m->m_hdr.mh_size, "DCC SEND %s %lu %u %u%c\n", 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 = tcp_listen(INADDR_ANY, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL) + if ((so = tcp_listen(slirp, INADDR_ANY, 0, + htonl(laddr), htons(lport), + SS_FACCEPTONCE)) == NULL) { return 1; - + } m->m_len = bptr - m->m_data; /* Adjust length */ m->m_len += snprintf(bptr, m->m_hdr.mh_size, "DCC MOVE %s %lu %u %u%c\n", buff, @@ -828,7 +845,7 @@ tcp_emu(struct socket *so, struct mbuf *m) /* try to get udp port between 6970 - 7170 */ for (p = 6970; p < 7071; p++) { - if (udp_listen(INADDR_ANY, + if (udp_listen(slirp, INADDR_ANY, htons(p), so->so_laddr.s_addr, htons(lport), @@ -865,6 +882,7 @@ tcp_emu(struct socket *so, struct mbuf *m) */ int tcp_ctl(struct socket *so) { + Slirp *slirp = so->slirp; struct sbuf *sb = &so->so_snd; struct ex_list *ex_ptr; int do_pty; @@ -872,9 +890,9 @@ int tcp_ctl(struct socket *so) DEBUG_CALL("tcp_ctl"); DEBUG_ARG("so = %lx", (long )so); - if (so->so_faddr.s_addr != vhost_addr.s_addr) { + if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr) { /* Check if it's pty_exec */ - for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { + for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { if (ex_ptr->ex_fport == so->so_fport && so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) { if (ex_ptr->ex_pty == 3) { diff --git a/slirp/tcp_timer.c b/slirp/tcp_timer.c index cd71572bbf..556e32eadd 100644 --- a/slirp/tcp_timer.c +++ b/slirp/tcp_timer.c @@ -32,24 +32,22 @@ #include -u_int32_t tcp_now; /* for RFC 1323 timestamps */ - static struct tcpcb *tcp_timers(register struct tcpcb *tp, int timer); /* * Fast timeout routine for processing delayed acks */ void -tcp_fasttimo(void) +tcp_fasttimo(Slirp *slirp) { register struct socket *so; register struct tcpcb *tp; DEBUG_CALL("tcp_fasttimo"); - so = tcb.so_next; + so = slirp->tcb.so_next; if (so) - for (; so != &tcb; so = so->so_next) + for (; so != &slirp->tcb; so = so->so_next) if ((tp = (struct tcpcb *)so->so_tcpcb) && (tp->t_flags & TF_DELACK)) { tp->t_flags &= ~TF_DELACK; @@ -64,7 +62,7 @@ tcp_fasttimo(void) * causes finite state machine actions if timers expire. */ void -tcp_slowtimo(void) +tcp_slowtimo(Slirp *slirp) { register struct socket *ip, *ipnxt; register struct tcpcb *tp; @@ -75,10 +73,10 @@ tcp_slowtimo(void) /* * Search through tcb's and update active timers. */ - ip = tcb.so_next; + ip = slirp->tcb.so_next; if (ip == 0) return; - for (; ip != &tcb; ip = ipnxt) { + for (; ip != &slirp->tcb; ip = ipnxt) { ipnxt = ip->so_next; tp = sototcpcb(ip); if (tp == 0) @@ -96,8 +94,8 @@ tcp_slowtimo(void) tpgone: ; } - tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ - tcp_now++; /* for timestamps */ + slirp->tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ + slirp->tcp_now++; /* for timestamps */ } /* diff --git a/slirp/tcp_timer.h b/slirp/tcp_timer.h index f648ed0de7..cfb06ffc87 100644 --- a/slirp/tcp_timer.h +++ b/slirp/tcp_timer.h @@ -120,8 +120,8 @@ extern const int tcp_backoff[]; struct tcpcb; -void tcp_fasttimo _P((void)); -void tcp_slowtimo _P((void)); +void tcp_fasttimo _P((Slirp *)); +void tcp_slowtimo _P((Slirp *)); void tcp_canceltimers _P((struct tcpcb *)); #endif diff --git a/slirp/tcp_var.h b/slirp/tcp_var.h index db0a9c986d..4ffbe04a18 100644 --- a/slirp/tcp_var.h +++ b/slirp/tcp_var.h @@ -158,6 +158,4 @@ struct tcpcb { #define TCP_REXMTVAL(tp) \ (((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar) -extern u_int32_t tcp_now; /* for RFC 1323 timestamps */ - #endif diff --git a/slirp/tftp.c b/slirp/tftp.c index 31a1e258cd..3b8643b8d8 100644 --- a/slirp/tftp.c +++ b/slirp/tftp.c @@ -25,41 +25,31 @@ #include #include "qemu-common.h" -struct tftp_session { - int in_use; - char *filename; - - struct in_addr client_ip; - u_int16_t client_port; - - int timestamp; -}; - -static struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX]; - -char *tftp_prefix; +static inline int tftp_session_in_use(struct tftp_session *spt) +{ + return (spt->slirp != NULL); +} -static void tftp_session_update(struct tftp_session *spt) +static inline void tftp_session_update(struct tftp_session *spt) { spt->timestamp = curtime; - spt->in_use = 1; } static void tftp_session_terminate(struct tftp_session *spt) { - qemu_free(spt->filename); - spt->in_use = 0; + qemu_free(spt->filename); + spt->slirp = NULL; } -static int tftp_session_allocate(struct tftp_t *tp) +static int tftp_session_allocate(Slirp *slirp, struct tftp_t *tp) { struct tftp_session *spt; int k; for (k = 0; k < TFTP_SESSIONS_MAX; k++) { - spt = &tftp_sessions[k]; + spt = &slirp->tftp_sessions[k]; - if (!spt->in_use) + if (!tftp_session_in_use(spt)) goto found; /* sessions time out after 5 inactive seconds */ @@ -75,21 +65,22 @@ static int tftp_session_allocate(struct tftp_t *tp) memset(spt, 0, sizeof(*spt)); memcpy(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip)); spt->client_port = tp->udp.uh_sport; + spt->slirp = slirp; tftp_session_update(spt); return k; } -static int tftp_session_find(struct tftp_t *tp) +static int tftp_session_find(Slirp *slirp, struct tftp_t *tp) { struct tftp_session *spt; int k; for (k = 0; k < TFTP_SESSIONS_MAX; k++) { - spt = &tftp_sessions[k]; + spt = &slirp->tftp_sessions[k]; - if (spt->in_use) { + if (tftp_session_in_use(spt)) { if (!memcmp(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip))) { if (spt->client_port == tp->udp.uh_sport) { return k; @@ -133,7 +124,7 @@ static int tftp_send_oack(struct tftp_session *spt, struct tftp_t *tp; int n = 0; - m = m_get(); + m = m_get(spt->slirp); if (!m) return -1; @@ -172,7 +163,7 @@ static void tftp_send_error(struct tftp_session *spt, struct tftp_t *tp; int nobytes; - m = m_get(); + m = m_get(spt->slirp); if (!m) { goto out; @@ -218,7 +209,7 @@ static int tftp_send_data(struct tftp_session *spt, return -1; } - m = m_get(); + m = m_get(spt->slirp); if (!m) { return -1; @@ -266,23 +257,23 @@ static int tftp_send_data(struct tftp_session *spt, return 0; } -static void tftp_handle_rrq(struct tftp_t *tp, int pktlen) +static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen) { struct tftp_session *spt; int s, k; size_t prefix_len; char *req_fname; - s = tftp_session_allocate(tp); + s = tftp_session_allocate(slirp, tp); if (s < 0) { return; } - spt = &tftp_sessions[s]; + spt = &slirp->tftp_sessions[s]; /* unspecifed prefix means service disabled */ - if (!tftp_prefix) { + if (!slirp->tftp_prefix) { tftp_send_error(spt, 2, "Access violation", tp); return; } @@ -292,9 +283,9 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen) pktlen -= ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp); /* prepend tftp_prefix */ - prefix_len = strlen(tftp_prefix); + prefix_len = strlen(slirp->tftp_prefix); spt->filename = qemu_malloc(prefix_len + TFTP_FILENAME_MAX + 1); - memcpy(spt->filename, tftp_prefix, prefix_len); + memcpy(spt->filename, slirp->tftp_prefix, prefix_len); /* get name */ req_fname = spt->filename + prefix_len; @@ -375,17 +366,17 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen) tftp_send_data(spt, 1, tp); } -static void tftp_handle_ack(struct tftp_t *tp, int pktlen) +static void tftp_handle_ack(Slirp *slirp, struct tftp_t *tp, int pktlen) { int s; - s = tftp_session_find(tp); + s = tftp_session_find(slirp, tp); if (s < 0) { return; } - if (tftp_send_data(&tftp_sessions[s], + if (tftp_send_data(&slirp->tftp_sessions[s], ntohs(tp->x.tp_data.tp_block_nr) + 1, tp) < 0) { return; @@ -398,11 +389,11 @@ void tftp_input(struct mbuf *m) switch(ntohs(tp->tp_op)) { case TFTP_RRQ: - tftp_handle_rrq(tp, m->m_len); + tftp_handle_rrq(m->slirp, tp, m->m_len); break; case TFTP_ACK: - tftp_handle_ack(tp, m->m_len); + tftp_handle_ack(m->slirp, tp, m->m_len); break; } } diff --git a/slirp/tftp.h b/slirp/tftp.h index 8f2675e077..1415c8527b 100644 --- a/slirp/tftp.h +++ b/slirp/tftp.h @@ -30,4 +30,14 @@ struct tftp_t { } x; }; +struct tftp_session { + Slirp *slirp; + char *filename; + + struct in_addr client_ip; + u_int16_t client_port; + + int timestamp; +}; + void tftp_input(struct mbuf *m); diff --git a/slirp/udp.c b/slirp/udp.c index 240e1bf38a..e0a669359b 100644 --- a/slirp/udp.c +++ b/slirp/udp.c @@ -41,17 +41,14 @@ #include #include "ip_icmp.h" -struct socket udb; - static u_int8_t udp_tos(struct socket *so); static void udp_emu(struct socket *so, struct mbuf *m); -struct socket *udp_last_so = &udb; - void -udp_init(void) +udp_init(Slirp *slirp) { - udb.so_next = udb.so_prev = &udb; + slirp->udb.so_next = slirp->udb.so_prev = &slirp->udb; + slirp->udp_last_so = &slirp->udb; } /* m->m_data points at ip packet header * m->m_len length ip packet @@ -60,6 +57,7 @@ udp_init(void) void udp_input(register struct mbuf *m, int iphlen) { + Slirp *slirp = m->slirp; register struct ip *ip; register struct udphdr *uh; int len; @@ -128,8 +126,9 @@ udp_input(register struct mbuf *m, int iphlen) goto bad; } - if (slirp_restrict) + if (slirp->restricted) { goto bad; + } /* * handle TFTP @@ -142,22 +141,23 @@ udp_input(register struct mbuf *m, int iphlen) /* * Locate pcb for datagram. */ - so = udp_last_so; + so = slirp->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 = slirp->udb.so_next; tmp != &slirp->udb; + tmp = tmp->so_next) { if (tmp->so_lport == uh->uh_sport && tmp->so_laddr.s_addr == ip->ip_src.s_addr) { so = tmp; break; } } - if (tmp == &udb) { + if (tmp == &slirp->udb) { so = NULL; } else { - udp_last_so = so; + slirp->udp_last_so = so; } } @@ -166,7 +166,10 @@ udp_input(register struct mbuf *m, int iphlen) * If there's no socket for this packet, * create one */ - if ((so = socreate()) == NULL) goto bad; + so = socreate(slirp); + if (!so) { + goto bad; + } if(udp_attach(so) == -1) { DEBUG_MISC((dfd," udp_attach errno = %d-%s\n", errno,strerror(errno))); @@ -279,15 +282,18 @@ int udp_output(struct socket *so, struct mbuf *m, struct sockaddr_in *addr) { + Slirp *slirp = so->slirp; struct sockaddr_in saddr, daddr; saddr = *addr; - if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) == vnetwork_addr.s_addr) { - if ((so->so_faddr.s_addr & ~vnetwork_mask.s_addr) == - ~vnetwork_mask.s_addr) { - saddr.sin_addr = vhost_addr; + if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) == + slirp->vnetwork_addr.s_addr) { + uint32_t inv_mask = ~slirp->vnetwork_mask.s_addr; + + if ((so->so_faddr.s_addr & inv_mask) == inv_mask) { + saddr.sin_addr = slirp->vhost_addr; } else if (addr->sin_addr.s_addr == loopback_addr.s_addr || - so->so_faddr.s_addr != vhost_addr.s_addr) { + so->so_faddr.s_addr != slirp->vhost_addr.s_addr) { saddr.sin_addr = so->so_faddr; } } @@ -323,7 +329,7 @@ udp_attach(struct socket *so) } else { /* success, insert in queue */ so->so_expire = curtime + SO_EXPIRE; - insque(so,&udb); + insque(so, &so->slirp->udb); } } return(so->s); @@ -595,20 +601,20 @@ struct cu_header { } struct socket * -udp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport, - int flags) +udp_listen(Slirp *slirp, u_int32_t haddr, u_int hport, u_int32_t laddr, + u_int lport, int flags) { struct sockaddr_in addr; struct socket *so; socklen_t addrlen = sizeof(struct sockaddr_in), opt = 1; - if ((so = socreate()) == NULL) { - free(so); - return NULL; + so = socreate(slirp); + if (!so) { + return NULL; } so->s = socket(AF_INET,SOCK_DGRAM,0); so->so_expire = curtime + SO_EXPIRE; - insque(so,&udb); + insque(so, &slirp->udb); addr.sin_family = AF_INET; addr.sin_addr.s_addr = haddr; @@ -624,7 +630,7 @@ udp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport, 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 = vhost_addr; + so->so_faddr = slirp->vhost_addr; } else { so->so_faddr = addr.sin_addr; } diff --git a/slirp/udp.h b/slirp/udp.h index 3eed14a677..cc814a3f48 100644 --- a/slirp/udp.h +++ b/slirp/udp.h @@ -36,8 +36,6 @@ #define UDP_TTL 0x60 #define UDP_UDPDATALEN 16192 -extern struct socket *udp_last_so; - /* * Udp protocol header. * Per RFC 768, September, 1981. @@ -73,15 +71,15 @@ struct udpiphdr { #define UDPCTL_CHECKSUM 1 /* checksum UDP packets */ #define UDPCTL_MAXID 2 -extern struct socket udb; struct mbuf; -void udp_init _P((void)); +void udp_init _P((Slirp *)); 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 *)); -struct socket * udp_listen _P((u_int32_t, u_int, u_int32_t, u_int, int)); +struct socket * udp_listen _P((Slirp *, u_int32_t, u_int, u_int32_t, u_int, + int)); int udp_output2(struct socket *so, struct mbuf *m, struct sockaddr_in *saddr, struct sockaddr_in *daddr, int iptos); -- 2.11.4.GIT