diff options
-rw-r--r-- | bootp.c | 81 | ||||
-rw-r--r-- | bootp.h | 7 | ||||
-rw-r--r-- | if.c | 50 | ||||
-rw-r--r-- | if.h | 6 | ||||
-rw-r--r-- | ip.h | 3 | ||||
-rw-r--r-- | ip_icmp.c | 20 | ||||
-rw-r--r-- | ip_input.c | 76 | ||||
-rw-r--r-- | ip_output.c | 7 | ||||
-rw-r--r-- | libslirp.h | 3 | ||||
-rw-r--r-- | main.h | 12 | ||||
-rw-r--r-- | mbuf.c | 29 | ||||
-rw-r--r-- | mbuf.h | 9 | ||||
-rw-r--r-- | misc.c | 5 | ||||
-rw-r--r-- | misc.h | 2 | ||||
-rw-r--r-- | slirp.c | 180 | ||||
-rw-r--r-- | slirp.h | 65 | ||||
-rw-r--r-- | socket.c | 36 | ||||
-rw-r--r-- | socket.h | 9 | ||||
-rw-r--r-- | tcp.h | 4 | ||||
-rw-r--r-- | tcp_input.c | 36 | ||||
-rw-r--r-- | tcp_output.c | 4 | ||||
-rw-r--r-- | tcp_subr.c | 79 | ||||
-rw-r--r-- | tcp_timer.c | 18 | ||||
-rw-r--r-- | tcp_timer.h | 4 | ||||
-rw-r--r-- | tcp_var.h | 2 | ||||
-rw-r--r-- | tftp.c | 65 | ||||
-rw-r--r-- | tftp.h | 10 | ||||
-rw-r--r-- | udp.c | 52 | ||||
-rw-r--r-- | udp.h | 8 |
29 files changed, 467 insertions, 415 deletions
@@ -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 @@ -52,33 +41,34 @@ static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE }; #define dprintf(fmt, ...) #endif -static BOOTPClient *get_new_addr(struct in_addr *paddr, const uint8_t *macaddr) +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]; + if (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; @@ -87,20 +77,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; } @@ -151,7 +142,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; @@ -175,10 +166,12 @@ static void bootp_reply(const struct bootp_t *bp) if (dhcp_msg_type != DHCPDISCOVER && dhcp_msg_type != DHCPREQUEST) return; /* XXX: this is a hack to get the client mac address */ - memcpy(client_ethaddr, bp->bp_hwaddr, 6); + memcpy(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); @@ -186,30 +179,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) */ @@ -217,7 +210,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); @@ -250,9 +243,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; @@ -261,10 +254,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); @@ -272,7 +265,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; } @@ -282,11 +275,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 { @@ -318,6 +311,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); } } @@ -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); @@ -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 ifs_insque(struct mbuf *ifm, struct mbuf *ifmhead) @@ -29,11 +23,11 @@ static void ifs_remque(struct mbuf *ifm) ifm->ifs_next->ifs_prev = ifm->ifs_prev; } -void if_init(void) +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; } /* @@ -51,6 +45,7 @@ void if_init(void) */ void if_output(struct socket *so, struct mbuf *ifm) { + Slirp *slirp = ifm->slirp; struct mbuf *ifq; int on_fastq = 1; @@ -76,7 +71,8 @@ void if_output(struct socket *so, struct mbuf *ifm) * 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; @@ -87,7 +83,7 @@ void 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 @@ -99,7 +95,7 @@ void 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; @@ -107,7 +103,7 @@ void if_output(struct socket *so, struct mbuf *ifm) insque(ifm, ifq); diddit: - ++if_queued; + slirp->if_queued++; if (so) { /* Update *_queued */ @@ -126,7 +122,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); } } @@ -134,7 +130,7 @@ diddit: /* * This prevents us from malloc()ing too many mbufs */ - if_start(); + if_start(ifm->slirp); #endif } @@ -150,13 +146,13 @@ diddit: * from the second session, then one packet from the third, then back * to the first, etc. etc. */ -void if_start(void) +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: @@ -168,22 +164,22 @@ again: * 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) { @@ -199,10 +195,10 @@ again: } /* 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; } @@ -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 @@ -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 @@ -70,6 +70,7 @@ void 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); @@ -99,12 +100,12 @@ void 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) + if ((so = socreate(slirp)) == NULL) goto freeit; if (udp_attach(so) == -1) { DEBUG_MISC((dfd, "icmp_input udp_attach errno = %d-%s\n", errno, @@ -124,10 +125,10 @@ void 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; @@ -228,8 +229,11 @@ void 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 = @@ -297,7 +301,7 @@ void 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); @@ -42,10 +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); @@ -53,11 +51,11 @@ static void ip_deq(register struct ipasfrag *p); * IP initialization: fill in IP protocol switch table. * All protocols not implemented in kernel go to raw IP protocol handler. */ -void ip_init(void) +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); } /* @@ -66,6 +64,7 @@ void ip_init(void) */ void ip_input(struct mbuf *m) { + Slirp *slirp = m->slirp; register struct ip *ip; int hlen; @@ -116,19 +115,19 @@ void 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; @@ -163,7 +162,8 @@ void 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 && @@ -193,12 +193,12 @@ void 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; @@ -233,9 +233,9 @@ bad: * reassembly of this datagram already exists, then it * is given as fp; otherwise have to make a chain. */ -static struct ip *ip_reass(register struct ip *ip, register struct ipq *fp) +static struct ip *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; @@ -257,11 +257,13 @@ static struct ip *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) + 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; @@ -291,7 +293,7 @@ static struct ip *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; } @@ -307,11 +309,11 @@ static struct ip *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); } @@ -335,11 +337,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); } @@ -370,7 +372,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); @@ -385,7 +387,7 @@ dropfrag: * Free a fragment reassembly header and all * associated datagrams. */ -static void ip_freef(struct ipq *fp) +static void ip_freef(Slirp *slirp, struct ipq *fp) { register struct ipasfrag *q, *p; @@ -393,10 +395,10 @@ static void ip_freef(struct ipq *fp) 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)); } /* @@ -427,22 +429,22 @@ static void ip_deq(register struct ipasfrag *p) * if a timer expires on a reassembly * queue, discard it. */ -void ip_slowtimo(void) +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/ip_output.c b/ip_output.c index 865a807..1f07540 100644 --- a/ip_output.c +++ b/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 @@ -54,6 +52,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); @@ -69,7 +68,7 @@ int 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; /* @@ -112,7 +111,7 @@ int 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; @@ -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, @@ -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); @@ -17,8 +17,6 @@ #include <slirp.h> -static int mbuf_alloced; -struct mbuf m_freelist, m_usedlist; #define MBUF_THRESH 30 /* @@ -27,10 +25,10 @@ struct mbuf m_freelist, m_usedlist; */ #define SLIRP_MSIZE (IF_MTU + IF_MAXLINKHDR + sizeof(struct m_hdr) + 6) -void m_init(void) +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; } /* @@ -41,27 +39,28 @@ void m_init(void) * free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE, * which tells m_free to actually free() it */ -struct mbuf *m_get(void) +struct mbuf *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 */ @@ -94,9 +93,9 @@ void 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) */ @@ -185,7 +184,7 @@ int m_copy(struct mbuf *n, struct mbuf *m, int off, int len) * XXX This is a kludge, I should eliminate the need for it * Fortunately, it's not used often */ -struct mbuf *dtom(void *dat) +struct mbuf *dtom(Slirp *slirp, void *dat) { struct mbuf *m; @@ -193,7 +192,7 @@ struct mbuf *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; @@ -83,6 +83,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 { 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 @@ -369,6 +369,7 @@ void slirp_connection_info(Monitor *mon) [TCPS_LAST_ACK] = "LAST_ACK", [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; @@ -381,7 +382,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) { @@ -410,7 +411,7 @@ void slirp_connection_info(Monitor *mon) ntohs(dst_port), 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); @@ -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 @@ -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) \ @@ -273,6 +263,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; @@ -295,9 +286,10 @@ void slirp_select_fill(int *pnfds, fd_set *readfds, fd_set *writefds, * *_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; /* @@ -355,7 +347,7 @@ void slirp_select_fill(int *pnfds, fd_set *readfds, fd_set *writefds, /* * 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; /* @@ -391,6 +383,7 @@ void slirp_select_fill(int *pnfds, fd_set *readfds, fd_set *writefds, 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; @@ -409,12 +402,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; } @@ -425,7 +418,7 @@ 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; /* @@ -541,7 +534,7 @@ 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)) { @@ -553,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 @@ -597,7 +591,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); @@ -610,18 +604,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); @@ -643,9 +638,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: @@ -655,6 +650,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; @@ -664,10 +660,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 */ @@ -688,7 +684,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; @@ -696,7 +692,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); @@ -709,7 +705,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); @@ -718,20 +714,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); @@ -741,8 +737,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 +761,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 +781,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)); } @@ -805,12 +807,12 @@ ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags) return send(so->s, buf, len, flags); } -static struct socket *slirp_find_ctl_socket(struct in_addr guest_addr, - int guest_port) +static struct socket * +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 +823,11 @@ static struct socket *slirp_find_ctl_socket(struct in_addr guest_addr, 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 +841,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,13 +932,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; @@ -943,7 +948,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) @@ -1042,12 +1047,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; @@ -1057,11 +1063,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) { @@ -1075,7 +1081,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; @@ -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,66 @@ 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 +310,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 +331,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)); @@ -36,7 +36,7 @@ struct socket *solookup(struct socket *head, struct in_addr laddr, u_int lport, * It is the responsibility of the caller to * insque() it into the correct linked-list */ -struct socket *socreate(void) +struct socket *socreate(Slirp *slirp) { struct socket *so; @@ -45,6 +45,7 @@ struct socket *socreate(void) memset(so, 0, sizeof(struct socket)); so->so_state = SS_NOFDREF; so->s = -1; + so->slirp = slirp; } return (so); } @@ -54,15 +55,17 @@ struct socket *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) @@ -477,8 +480,10 @@ void sorecvfrom(struct socket *so) int n; #endif - if (!(m = m_get())) + m = m_get(so->slirp); + if (!m) { return; + } m->m_data += IF_MAXLINKHDR; /* @@ -539,6 +544,7 @@ void sorecvfrom(struct socket *so) */ int sosendto(struct socket *so, struct mbuf *m) { + Slirp *slirp = so->slirp; int ret; struct sockaddr_in addr; @@ -547,9 +553,10 @@ int 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; @@ -582,8 +589,8 @@ int 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) +struct socket *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; @@ -597,7 +604,8 @@ struct socket *tcp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, DEBUG_ARG("lport = %d", lport); DEBUG_ARG("flags = %x", flags); - if ((so = socreate()) == NULL) { + so = socreate(slirp); + if (!so) { return NULL; } @@ -606,7 +614,7 @@ struct socket *tcp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, free(so); return NULL; } - insque(so, &tcb); + insque(so, &slirp->tcb); /* * SS_FACCEPTONCE sockets must time out. @@ -646,7 +654,7 @@ struct socket *tcp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, 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; @@ -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 @@ -79,11 +81,9 @@ struct socket { #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 *)); @@ -91,7 +91,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 *)); @@ -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/tcp_input.c b/tcp_input.c index 21e8b0a..97a247e 100644 --- a/tcp_input.c +++ b/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) @@ -234,6 +229,7 @@ void 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", (long)m, iphlen, @@ -244,6 +240,7 @@ void 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); @@ -255,6 +252,7 @@ void 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. @@ -319,8 +317,8 @@ void 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; @@ -333,13 +331,14 @@ void 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, ti->ti_dst, ti->ti_dport); + 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; } /* @@ -359,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) */ @@ -551,12 +550,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 +631,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/tcp_output.c b/tcp_output.c index 1791002..39d84d1 100644 --- a/tcp_output.c +++ b/tcp_output.c @@ -289,7 +289,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; @@ -309,7 +309,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; @@ -47,10 +47,11 @@ /* * Tcp initialization */ -void tcp_init(void) +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; } /* @@ -113,7 +114,7 @@ void 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; @@ -238,6 +239,7 @@ struct tcpcb *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"); @@ -254,8 +256,8 @@ struct tcpcb *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); @@ -315,6 +317,7 @@ void tcp_sockclosed(struct tcpcb *tp) */ int tcp_fconnect(struct socket *so) { + Slirp *slirp = so->slirp; int ret = 0; DEBUG_CALL("tcp_fconnect"); @@ -331,10 +334,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; @@ -374,6 +377,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); @@ -391,7 +395,7 @@ void 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; @@ -422,7 +426,7 @@ void 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) { @@ -442,8 +446,8 @@ void 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 +460,7 @@ int 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; } @@ -537,6 +541,7 @@ u_int8_t 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; @@ -570,7 +575,7 @@ int 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; + 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 && @@ -606,10 +611,10 @@ int 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; @@ -641,10 +646,10 @@ int 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; @@ -683,8 +688,8 @@ int 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; @@ -700,10 +705,10 @@ int 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", @@ -711,10 +716,10 @@ int tcp_emu(struct socket *so, struct mbuf *m) 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", @@ -722,10 +727,10 @@ int tcp_emu(struct socket *so, struct mbuf *m) 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", @@ -837,8 +842,9 @@ int 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, htons(p), so->so_laddr.s_addr, - htons(lport), SS_FACCEPTONCE)) { + if (udp_listen(slirp, INADDR_ANY, htons(p), + so->so_laddr.s_addr, htons(lport), + SS_FACCEPTONCE)) { break; } } @@ -871,6 +877,7 @@ int 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; @@ -878,9 +885,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/tcp_timer.c b/tcp_timer.c index a90f08d..de1c3e2 100644 --- a/tcp_timer.c +++ b/tcp_timer.c @@ -32,23 +32,21 @@ #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) +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; @@ -62,7 +60,7 @@ void tcp_fasttimo(void) * Updates the timers in all active tcb's and * causes finite state machine actions if timers expire. */ -void tcp_slowtimo(void) +void tcp_slowtimo(Slirp *slirp) { register struct socket *ip, *ipnxt; register struct tcpcb *tp; @@ -73,10 +71,10 @@ void 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) @@ -93,8 +91,8 @@ void tcp_slowtimo(void) tp->t_rtt++; 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/tcp_timer.h b/tcp_timer.h index 5713df5..2ff1dfd 100644 --- a/tcp_timer.h +++ b/tcp_timer.h @@ -122,8 +122,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 @@ -157,6 +157,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 @@ -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; + 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 @@ found: 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) { @@ -133,7 +124,7 @@ static int tftp_send_oack(struct tftp_session *spt, const char *key, struct tftp_t *tp; int n = 0; - m = m_get(); + m = m_get(spt->slirp); if (!m) return -1; @@ -173,7 +164,7 @@ static void tftp_send_error(struct tftp_session *spt, u_int16_t errorcode, 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, u_int16_t block_nr, return -1; } - m = m_get(); + m = m_get(spt->slirp); if (!m) { return -1; @@ -265,23 +256,23 @@ static int tftp_send_data(struct tftp_session *spt, u_int16_t block_nr, 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; } @@ -291,9 +282,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; @@ -374,18 +365,18 @@ 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], ntohs(tp->x.tp_data.tp_block_nr) + 1, - tp) < 0) { + if (tftp_send_data(&slirp->tftp_sessions[s], + ntohs(tp->x.tp_data.tp_block_nr) + 1, tp) < 0) { return; } } @@ -396,11 +387,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; } } @@ -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); @@ -41,16 +41,13 @@ #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) +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 @@ -58,6 +55,7 @@ void 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; @@ -126,8 +124,9 @@ void udp_input(register struct mbuf *m, int iphlen) goto bad; } - if (slirp_restrict) + if (slirp->restricted) { goto bad; + } /* * handle TFTP @@ -140,22 +139,22 @@ void 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; } } @@ -164,8 +163,10 @@ void udp_input(register struct mbuf *m, int iphlen) * If there's no socket for this packet, * create one */ - if ((so = socreate()) == NULL) + so = socreate(slirp); + if (!so) { goto bad; + } if (udp_attach(so) == -1) { DEBUG_MISC( (dfd, " udp_attach errno = %d-%s\n", errno, strerror(errno))); @@ -277,15 +278,18 @@ int udp_output2(struct socket *so, struct mbuf *m, struct sockaddr_in *saddr, 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; } } @@ -320,7 +324,7 @@ int 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); @@ -587,20 +591,20 @@ static void udp_emu(struct socket *so, struct mbuf *m) } } -struct socket *udp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, - u_int lport, int flags) +struct socket *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); + 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; @@ -616,7 +620,7 @@ struct socket *udp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, 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; } @@ -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); #endif |