diff options
-rw-r--r-- | slirp/bootp.c | 80 | ||||
-rw-r--r-- | slirp/bootp.h | 7 | ||||
-rw-r--r-- | slirp/if.c | 50 | ||||
-rw-r--r-- | slirp/if.h | 6 | ||||
-rw-r--r-- | slirp/ip.h | 3 | ||||
-rw-r--r-- | slirp/ip_icmp.c | 19 | ||||
-rw-r--r-- | slirp/ip_input.c | 80 | ||||
-rw-r--r-- | slirp/ip_output.c | 7 | ||||
-rw-r--r-- | slirp/libslirp.h | 3 | ||||
-rw-r--r-- | slirp/main.h | 12 | ||||
-rw-r--r-- | slirp/mbuf.c | 30 | ||||
-rw-r--r-- | slirp/mbuf.h | 9 | ||||
-rw-r--r-- | slirp/misc.c | 5 | ||||
-rw-r--r-- | slirp/misc.h | 2 | ||||
-rw-r--r-- | slirp/slirp.c | 182 | ||||
-rw-r--r-- | slirp/slirp.h | 66 | ||||
-rw-r--r-- | slirp/socket.c | 37 | ||||
-rw-r--r-- | slirp/socket.h | 9 | ||||
-rw-r--r-- | slirp/tcp.h | 4 | ||||
-rw-r--r-- | slirp/tcp_input.c | 35 | ||||
-rw-r--r-- | slirp/tcp_output.c | 4 | ||||
-rw-r--r-- | slirp/tcp_subr.c | 74 | ||||
-rw-r--r-- | slirp/tcp_timer.c | 18 | ||||
-rw-r--r-- | slirp/tcp_timer.h | 4 | ||||
-rw-r--r-- | slirp/tcp_var.h | 2 | ||||
-rw-r--r-- | slirp/tftp.c | 65 | ||||
-rw-r--r-- | slirp/tftp.h | 10 | ||||
-rw-r--r-- | slirp/udp.c | 56 | ||||
-rw-r--r-- | 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 <slirp.h> -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 <osdep.h> #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 <slirp.h> -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 <slirp.h> -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 <slirp.h> #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 <slirp.h> -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 <slirp.h> #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 <slirp.h> #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); |