slirp: Factor out internal state structure

The essence of this patch is to stuff (almost) all global variables of
the slirp stack into the structure Slirp. In this step, we still keep
the structure as global variable, directly accessible by the whole
stack. Changes to the external interface of slirp will be applied in
the following patches.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Jan Kiszka 2009-06-24 14:42:31 +02:00 committed by Anthony Liguori
parent b5302e1a9d
commit 460fec67ee
29 changed files with 479 additions and 408 deletions

View File

@ -25,19 +25,8 @@
/* XXX: only DHCP is supported */ /* XXX: only DHCP is supported */
#define NB_ADDR 16
#define LEASE_TIME (24 * 3600) #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 }; static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
#ifdef DEBUG #ifdef DEBUG
@ -47,35 +36,35 @@ do if (slirp_debug & DBG_CALL) { fprintf(dfd, fmt, ## __VA_ARGS__); fflush(dfd)
#define dprintf(fmt, ...) #define dprintf(fmt, ...)
#endif #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) const uint8_t *macaddr)
{ {
BOOTPClient *bc; BOOTPClient *bc;
int i; int i;
for(i = 0; i < NB_ADDR; i++) { for(i = 0; i < NB_BOOTP_CLIENTS; i++) {
bc = &bootp_clients[i]; bc = &slirp->bootp_clients[i];
if (!bc->allocated || !memcmp(macaddr, bc->macaddr, 6)) if (!bc->allocated || !memcmp(macaddr, bc->macaddr, 6))
goto found; goto found;
} }
return NULL; return NULL;
found: found:
bc = &bootp_clients[i]; bc = &slirp->bootp_clients[i];
bc->allocated = 1; bc->allocated = 1;
paddr->s_addr = vdhcp_startaddr.s_addr + htonl(i); paddr->s_addr = slirp->vdhcp_startaddr.s_addr + htonl(i);
return bc; 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) const uint8_t *macaddr)
{ {
uint32_t req_addr = ntohl(paddr->s_addr); 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; BOOTPClient *bc;
if (req_addr >= dhcp_addr && if (req_addr >= dhcp_addr &&
req_addr < (dhcp_addr + NB_ADDR)) { req_addr < (dhcp_addr + NB_BOOTP_CLIENTS)) {
bc = &bootp_clients[req_addr - dhcp_addr]; bc = &slirp->bootp_clients[req_addr - dhcp_addr];
if (!bc->allocated || !memcmp(macaddr, bc->macaddr, 6)) { if (!bc->allocated || !memcmp(macaddr, bc->macaddr, 6)) {
bc->allocated = 1; bc->allocated = 1;
return bc; return bc;
@ -84,20 +73,21 @@ static BOOTPClient *request_addr(const struct in_addr *paddr,
return NULL; 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; BOOTPClient *bc;
int i; int i;
for(i = 0; i < NB_ADDR; i++) { for(i = 0; i < NB_BOOTP_CLIENTS; i++) {
if (!memcmp(macaddr, bootp_clients[i].macaddr, 6)) if (!memcmp(macaddr, slirp->bootp_clients[i].macaddr, 6))
goto found; goto found;
} }
return NULL; return NULL;
found: found:
bc = &bootp_clients[i]; bc = &slirp->bootp_clients[i];
bc->allocated = 1; bc->allocated = 1;
paddr->s_addr = vdhcp_startaddr.s_addr + htonl(i); paddr->s_addr = slirp->vdhcp_startaddr.s_addr + htonl(i);
return bc; 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; BOOTPClient *bc = NULL;
struct mbuf *m; struct mbuf *m;
@ -173,10 +163,12 @@ static void bootp_reply(const struct bootp_t *bp)
dhcp_msg_type != DHCPREQUEST) dhcp_msg_type != DHCPREQUEST)
return; return;
/* XXX: this is a hack to get the client mac address */ /* 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; return;
}
m->m_data += IF_MAXLINKHDR; m->m_data += IF_MAXLINKHDR;
rbp = (struct bootp_t *)m->m_data; rbp = (struct bootp_t *)m->m_data;
m->m_data += sizeof(struct udpiphdr); 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 (dhcp_msg_type == DHCPDISCOVER) {
if (preq_addr) { if (preq_addr) {
bc = request_addr(preq_addr, client_ethaddr); bc = request_addr(slirp, preq_addr, slirp->client_ethaddr);
if (bc) { if (bc) {
daddr.sin_addr = *preq_addr; daddr.sin_addr = *preq_addr;
} }
} }
if (!bc) { if (!bc) {
new_addr: new_addr:
bc = get_new_addr(&daddr.sin_addr, client_ethaddr); bc = get_new_addr(slirp, &daddr.sin_addr, slirp->client_ethaddr);
if (!bc) { if (!bc) {
dprintf("no address left\n"); dprintf("no address left\n");
return; return;
} }
} }
memcpy(bc->macaddr, client_ethaddr, 6); memcpy(bc->macaddr, slirp->client_ethaddr, 6);
} else if (preq_addr) { } else if (preq_addr) {
bc = request_addr(preq_addr, client_ethaddr); bc = request_addr(slirp, preq_addr, slirp->client_ethaddr);
if (bc) { if (bc) {
daddr.sin_addr = *preq_addr; daddr.sin_addr = *preq_addr;
memcpy(bc->macaddr, client_ethaddr, 6); memcpy(bc->macaddr, slirp->client_ethaddr, 6);
} else { } else {
daddr.sin_addr.s_addr = 0; daddr.sin_addr.s_addr = 0;
} }
} else { } else {
bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr); bc = find_addr(slirp, &daddr.sin_addr, bp->bp_hwaddr);
if (!bc) { if (!bc) {
/* if never assigned, behaves as if it was already /* if never assigned, behaves as if it was already
assigned (windows fix because it remembers its address) */ 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); saddr.sin_port = htons(BOOTP_SERVER);
daddr.sin_port = htons(BOOTP_CLIENT); daddr.sin_port = htons(BOOTP_CLIENT);
@ -248,9 +240,9 @@ static void bootp_reply(const struct bootp_t *bp)
*q++ = DHCPACK; *q++ = DHCPACK;
} }
if (bootp_filename) if (slirp->bootp_filename)
snprintf((char *)rbp->bp_file, sizeof(rbp->bp_file), "%s", snprintf((char *)rbp->bp_file, sizeof(rbp->bp_file), "%s",
bootp_filename); slirp->bootp_filename);
*q++ = RFC2132_SRV_ID; *q++ = RFC2132_SRV_ID;
*q++ = 4; *q++ = 4;
@ -259,10 +251,10 @@ static void bootp_reply(const struct bootp_t *bp)
*q++ = RFC1533_NETMASK; *q++ = RFC1533_NETMASK;
*q++ = 4; *q++ = 4;
memcpy(q, &vnetwork_mask, 4); memcpy(q, &slirp->vnetwork_mask, 4);
q += 4; q += 4;
if (!slirp_restrict) { if (!slirp->restricted) {
*q++ = RFC1533_GATEWAY; *q++ = RFC1533_GATEWAY;
*q++ = 4; *q++ = 4;
memcpy(q, &saddr.sin_addr, 4); memcpy(q, &saddr.sin_addr, 4);
@ -270,7 +262,7 @@ static void bootp_reply(const struct bootp_t *bp)
*q++ = RFC1533_DNS; *q++ = RFC1533_DNS;
*q++ = 4; *q++ = 4;
memcpy(q, &vnameserver_addr, 4); memcpy(q, &slirp->vnameserver_addr, 4);
q += 4; q += 4;
} }
@ -280,11 +272,11 @@ static void bootp_reply(const struct bootp_t *bp)
memcpy(q, &val, 4); memcpy(q, &val, 4);
q += 4; q += 4;
if (*slirp_hostname) { if (*slirp->client_hostname) {
val = strlen(slirp_hostname); val = strlen(slirp->client_hostname);
*q++ = RFC1533_HOSTNAME; *q++ = RFC1533_HOSTNAME;
*q++ = val; *q++ = val;
memcpy(q, slirp_hostname, val); memcpy(q, slirp->client_hostname, val);
q += val; q += val;
} }
} else { } else {
@ -315,6 +307,6 @@ void bootp_input(struct mbuf *m)
struct bootp_t *bp = mtod(m, struct bootp_t *); struct bootp_t *bp = mtod(m, struct bootp_t *);
if (bp->bp_op == BOOTP_REQUEST) { if (bp->bp_op == BOOTP_REQUEST) {
bootp_reply(bp); bootp_reply(m->slirp, bp);
} }
} }

View File

@ -112,4 +112,11 @@ struct bootp_t {
uint8_t bp_vend[DHCP_OPT_LEN]; 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); void bootp_input(struct mbuf *m);

View File

@ -7,12 +7,6 @@
#include <slirp.h> #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)) #define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
static void static void
@ -32,11 +26,11 @@ ifs_remque(struct mbuf *ifm)
} }
void void
if_init(void) if_init(Slirp *slirp)
{ {
if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq; slirp->if_fastq.ifq_next = slirp->if_fastq.ifq_prev = &slirp->if_fastq;
if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq; slirp->if_batchq.ifq_next = slirp->if_batchq.ifq_prev = &slirp->if_batchq;
next_m = &if_batchq; slirp->next_m = &slirp->if_batchq;
} }
/* /*
@ -55,6 +49,7 @@ if_init(void)
void void
if_output(struct socket *so, struct mbuf *ifm) if_output(struct socket *so, struct mbuf *ifm)
{ {
Slirp *slirp = ifm->slirp;
struct mbuf *ifq; struct mbuf *ifq;
int on_fastq = 1; 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) * We mustn't put this packet back on the fastq (or we'll send it out of order)
* XXX add cache here? * 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) { if (so == ifq->ifq_so) {
/* A match! */ /* A match! */
ifm->ifq_so = so; 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 */ /* No match, check which queue to put it on */
if (so && (so->so_iptos & IPTOS_LOWDELAY)) { if (so && (so->so_iptos & IPTOS_LOWDELAY)) {
ifq = if_fastq.ifq_prev; ifq = slirp->if_fastq.ifq_prev;
on_fastq = 1; on_fastq = 1;
/* /*
* Check if this packet is a part of the last * Check if this packet is a part of the last
@ -102,7 +98,7 @@ if_output(struct socket *so, struct mbuf *ifm)
goto diddit; goto diddit;
} }
} else } else
ifq = if_batchq.ifq_prev; ifq = slirp->if_batchq.ifq_prev;
/* Create a new doubly linked list for this session */ /* Create a new doubly linked list for this session */
ifm->ifq_so = so; ifm->ifq_so = so;
@ -110,7 +106,7 @@ if_output(struct socket *so, struct mbuf *ifm)
insque(ifm, ifq); insque(ifm, ifq);
diddit: diddit:
++if_queued; slirp->if_queued++;
if (so) { if (so) {
/* Update *_queued */ /* Update *_queued */
@ -130,7 +126,7 @@ diddit:
remque(ifm->ifs_next); remque(ifm->ifs_next);
/* ...And insert in the new. That'll teach ya! */ /* ...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 * This prevents us from malloc()ing too many mbufs
*/ */
if_start(); if_start(ifm->slirp);
#endif #endif
} }
@ -155,13 +151,13 @@ diddit:
* to the first, etc. etc. * to the first, etc. etc.
*/ */
void void
if_start(void) if_start(Slirp *slirp)
{ {
struct mbuf *ifm, *ifqt; struct mbuf *ifm, *ifqt;
DEBUG_CALL("if_start"); DEBUG_CALL("if_start");
if (if_queued == 0) if (slirp->if_queued == 0)
return; /* Nothing to do */ return; /* Nothing to do */
again: again:
@ -173,22 +169,22 @@ if_start(void)
* See which queue to get next packet from * See which queue to get next packet from
* If there's something in the fastq, select it immediately * If there's something in the fastq, select it immediately
*/ */
if (if_fastq.ifq_next != &if_fastq) { if (slirp->if_fastq.ifq_next != &slirp->if_fastq) {
ifm = if_fastq.ifq_next; ifm = slirp->if_fastq.ifq_next;
} else { } else {
/* Nothing on fastq, see if next_m is valid */ /* Nothing on fastq, see if next_m is valid */
if (next_m != &if_batchq) if (slirp->next_m != &slirp->if_batchq)
ifm = next_m; ifm = slirp->next_m;
else else
ifm = if_batchq.ifq_next; ifm = slirp->if_batchq.ifq_next;
/* Set which packet to send on next iteration */ /* Set which packet to send on next iteration */
next_m = ifm->ifq_next; slirp->next_m = ifm->ifq_next;
} }
/* Remove it from the queue */ /* Remove it from the queue */
ifqt = ifm->ifq_prev; ifqt = ifm->ifq_prev;
remque(ifm); remque(ifm);
--if_queued; slirp->if_queued--;
/* If there are more packets for this session, re-queue them */ /* If there are more packets for this session, re-queue them */
if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) { if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) {
@ -204,10 +200,10 @@ if_start(void)
} }
/* Encapsulate the packet for sending */ /* 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); m_free(ifm);
if (if_queued) if (slirp->if_queued)
goto again; goto again;
} }

View File

@ -20,12 +20,6 @@
/* 2 for alignment, 14 for ethernet, 40 for TCP/IP */ /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */
#define IF_MAXLINKHDR (2 + 14 + 40) #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)) #define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
#endif #endif

View File

@ -250,7 +250,4 @@ struct ipoption {
int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */ 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 #endif

View File

@ -69,6 +69,7 @@ icmp_input(struct mbuf *m, int hlen)
register struct icmp *icp; register struct icmp *icp;
register struct ip *ip=mtod(m, struct ip *); register struct ip *ip=mtod(m, struct ip *);
int icmplen=ip->ip_len; int icmplen=ip->ip_len;
Slirp *slirp = m->slirp;
DEBUG_CALL("icmp_input"); DEBUG_CALL("icmp_input");
DEBUG_ARG("m = %lx", (long )m); DEBUG_ARG("m = %lx", (long )m);
@ -98,12 +99,12 @@ icmp_input(struct mbuf *m, int hlen)
case ICMP_ECHO: case ICMP_ECHO:
icp->icmp_type = ICMP_ECHOREPLY; icp->icmp_type = ICMP_ECHOREPLY;
ip->ip_len += hlen; /* since ip_input subtracts this */ 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); icmp_reflect(m);
} else { } else {
struct socket *so; struct socket *so;
struct sockaddr_in addr; struct sockaddr_in addr;
if ((so = socreate()) == NULL) goto freeit; if ((so = socreate(slirp)) == NULL) goto freeit;
if(udp_attach(so) == -1) { if(udp_attach(so) == -1) {
DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n", DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n",
errno,strerror(errno))); errno,strerror(errno)));
@ -122,10 +123,10 @@ icmp_input(struct mbuf *m, int hlen)
/* Send the packet */ /* Send the packet */
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) == if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
vnetwork_addr.s_addr) { slirp->vnetwork_addr.s_addr) {
/* It's an alias */ /* 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; addr.sin_addr = dns_addr;
} else { } else {
addr.sin_addr = loopback_addr; 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 */ /* 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; { int new_m_size;
new_m_size=sizeof(struct ip )+ICMP_MINLEN+msrc->m_len+ICMP_MAXDATALEN; new_m_size=sizeof(struct ip )+ICMP_MINLEN+msrc->m_len+ICMP_MAXDATALEN;
if(new_m_size>m->m_size) m_inc(m, new_m_size); if(new_m_size>m->m_size) m_inc(m, new_m_size);
@ -285,7 +290,7 @@ icmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
ip->ip_ttl = MAXTTL; ip->ip_ttl = MAXTTL;
ip->ip_p = IPPROTO_ICMP; ip->ip_p = IPPROTO_ICMP;
ip->ip_dst = ip->ip_src; /* ip adresses */ 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); (void ) ip_output((struct socket *)NULL, m);

View File

@ -42,11 +42,8 @@
#include <osdep.h> #include <osdep.h>
#include "ip_icmp.h" #include "ip_icmp.h"
struct ipq ipq; static struct ip *ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp);
static void ip_freef(Slirp *slirp, struct ipq *fp);
static struct ip *ip_reass(register struct ip *ip,
register struct ipq *fp);
static void ip_freef(struct ipq *fp);
static void ip_enq(register struct ipasfrag *p, static void ip_enq(register struct ipasfrag *p,
register struct ipasfrag *prev); register struct ipasfrag *prev);
static void ip_deq(register struct ipasfrag *p); 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. * All protocols not implemented in kernel go to raw IP protocol handler.
*/ */
void void
ip_init(void) ip_init(Slirp *slirp)
{ {
ipq.ip_link.next = ipq.ip_link.prev = &ipq.ip_link; slirp->ipq.ip_link.next = slirp->ipq.ip_link.prev = &slirp->ipq.ip_link;
udp_init(); udp_init(slirp);
tcp_init(); tcp_init(slirp);
} }
/* /*
@ -70,6 +67,7 @@ ip_init(void)
void void
ip_input(struct mbuf *m) ip_input(struct mbuf *m)
{ {
Slirp *slirp = m->slirp;
register struct ip *ip; register struct ip *ip;
int hlen; int hlen;
@ -120,19 +118,19 @@ ip_input(struct mbuf *m)
goto bad; goto bad;
} }
if (slirp_restrict) { if (slirp->restricted) {
if ((ip->ip_dst.s_addr & vnetwork_mask.s_addr) == if ((ip->ip_dst.s_addr & slirp->vnetwork_mask.s_addr) ==
vnetwork_addr.s_addr) { slirp->vnetwork_addr.s_addr) {
if (ip->ip_dst.s_addr == 0xffffffff && ip->ip_p != IPPROTO_UDP) if (ip->ip_dst.s_addr == 0xffffffff && ip->ip_p != IPPROTO_UDP)
goto bad; goto bad;
} else { } else {
uint32_t inv_mask = ~slirp->vnetwork_mask.s_addr;
struct ex_list *ex_ptr; struct ex_list *ex_ptr;
if ((ip->ip_dst.s_addr & ~vnetwork_mask.s_addr) == if ((ip->ip_dst.s_addr & inv_mask) == inv_mask) {
~vnetwork_mask.s_addr)
goto bad; 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) if (ex_ptr->ex_addr.s_addr == ip->ip_dst.s_addr)
break; break;
@ -167,7 +165,8 @@ ip_input(struct mbuf *m)
* Look for queue of fragments * Look for queue of fragments
* of this datagram. * 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); fp = container_of(l, struct ipq, ip_link);
if (ip->ip_id == fp->ipq_id && if (ip->ip_id == fp->ipq_id &&
ip->ip_src.s_addr == fp->ipq_src.s_addr && 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. * attempt reassembly; if it succeeds, proceed.
*/ */
if (ip->ip_tos & 1 || ip->ip_off) { if (ip->ip_tos & 1 || ip->ip_off) {
ip = ip_reass(ip, fp); ip = ip_reass(slirp, ip, fp);
if (ip == NULL) if (ip == NULL)
return; return;
m = dtom(ip); m = dtom(slirp, ip);
} else } else
if (fp) if (fp)
ip_freef(fp); ip_freef(slirp, fp);
} else } else
ip->ip_len -= hlen; ip->ip_len -= hlen;
@ -239,9 +238,9 @@ bad:
* is given as fp; otherwise have to make a chain. * is given as fp; otherwise have to make a chain.
*/ */
static struct ip * 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; register struct ipasfrag *q;
int hlen = ip->ip_hl << 2; int hlen = ip->ip_hl << 2;
int i, next; 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 first fragment to arrive, create a reassembly queue.
*/ */
if (fp == NULL) { if (fp == NULL) {
struct mbuf *t; struct mbuf *t = m_get(slirp);
if ((t = m_get()) == NULL) goto dropfrag;
if (t == NULL) {
goto dropfrag;
}
fp = mtod(t, struct ipq *); 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_ttl = IPFRAGTTL;
fp->ipq_p = ip->ip_p; fp->ipq_p = ip->ip_p;
fp->ipq_id = ip->ip_id; 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 > 0) {
if (i >= ip->ip_len) if (i >= ip->ip_len)
goto dropfrag; goto dropfrag;
m_adj(dtom(ip), i); m_adj(dtom(slirp, ip), i);
ip->ip_off += i; ip->ip_off += i;
ip->ip_len -= i; ip->ip_len -= i;
} }
@ -312,11 +314,11 @@ ip_reass(register struct ip *ip, register struct ipq *fp)
if (i < q->ipf_len) { if (i < q->ipf_len) {
q->ipf_len -= i; q->ipf_len -= i;
q->ipf_off += i; q->ipf_off += i;
m_adj(dtom(q), i); m_adj(dtom(slirp, q), i);
break; break;
} }
q = q->ipf_next; q = q->ipf_next;
m_freem(dtom(q->ipf_prev)); m_freem(dtom(slirp, q->ipf_prev));
ip_deq(q->ipf_prev); ip_deq(q->ipf_prev);
} }
@ -340,11 +342,11 @@ insert:
* Reassembly is complete; concatenate fragments. * Reassembly is complete; concatenate fragments.
*/ */
q = fp->frag_link.next; q = fp->frag_link.next;
m = dtom(q); m = dtom(slirp, q);
q = (struct ipasfrag *) q->ipf_next; q = (struct ipasfrag *) q->ipf_next;
while (q != (struct ipasfrag*)&fp->frag_link) { while (q != (struct ipasfrag*)&fp->frag_link) {
struct mbuf *t = dtom(q); struct mbuf *t = dtom(slirp, q);
q = (struct ipasfrag *) q->ipf_next; q = (struct ipasfrag *) q->ipf_next;
m_cat(m, t); m_cat(m, t);
} }
@ -375,7 +377,7 @@ insert:
ip->ip_src = fp->ipq_src; ip->ip_src = fp->ipq_src;
ip->ip_dst = fp->ipq_dst; ip->ip_dst = fp->ipq_dst;
remque(&fp->ip_link); remque(&fp->ip_link);
(void) m_free(dtom(fp)); (void) m_free(dtom(slirp, fp));
m->m_len += (ip->ip_hl << 2); m->m_len += (ip->ip_hl << 2);
m->m_data -= (ip->ip_hl << 2); m->m_data -= (ip->ip_hl << 2);
@ -391,17 +393,17 @@ dropfrag:
* associated datagrams. * associated datagrams.
*/ */
static void static void
ip_freef(struct ipq *fp) ip_freef(Slirp *slirp, struct ipq *fp)
{ {
register struct ipasfrag *q, *p; register struct ipasfrag *q, *p;
for (q = fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link; q = p) { for (q = fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link; q = p) {
p = q->ipf_next; p = q->ipf_next;
ip_deq(q); ip_deq(q);
m_freem(dtom(q)); m_freem(dtom(slirp, q));
} }
remque(&fp->ip_link); 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. * queue, discard it.
*/ */
void void
ip_slowtimo(void) ip_slowtimo(Slirp *slirp)
{ {
struct qlink *l; struct qlink *l;
DEBUG_CALL("ip_slowtimo"); DEBUG_CALL("ip_slowtimo");
l = ipq.ip_link.next; l = slirp->ipq.ip_link.next;
if (l == NULL) if (l == NULL)
return; return;
while (l != &ipq.ip_link) { while (l != &slirp->ipq.ip_link) {
struct ipq *fp = container_of(l, struct ipq, ip_link); struct ipq *fp = container_of(l, struct ipq, ip_link);
l = l->next; l = l->next;
if (--fp->ipq_ttl == 0) { if (--fp->ipq_ttl == 0) {
ip_freef(fp); ip_freef(slirp, fp);
} }
} }
} }
/* /*

View File

@ -40,8 +40,6 @@
#include <slirp.h> #include <slirp.h>
u_int16_t ip_id;
/* Number of packets queued before we start sending /* Number of packets queued before we start sending
* (to prevent allocing too many mbufs) */ * (to prevent allocing too many mbufs) */
#define IF_THRESH 10 #define IF_THRESH 10
@ -55,6 +53,7 @@ u_int16_t ip_id;
int int
ip_output(struct socket *so, struct mbuf *m0) ip_output(struct socket *so, struct mbuf *m0)
{ {
Slirp *slirp = m0->slirp;
register struct ip *ip; register struct ip *ip;
register struct mbuf *m = m0; register struct mbuf *m = m0;
register int hlen = sizeof(struct ip ); register int hlen = sizeof(struct ip );
@ -70,7 +69,7 @@ ip_output(struct socket *so, struct mbuf *m0)
*/ */
ip->ip_v = IPVERSION; ip->ip_v = IPVERSION;
ip->ip_off &= IP_DF; ip->ip_off &= IP_DF;
ip->ip_id = htons(ip_id++); ip->ip_id = htons(slirp->ip_id++);
ip->ip_hl = hlen >> 2; ip->ip_hl = hlen >> 2;
/* /*
@ -113,7 +112,7 @@ ip_output(struct socket *so, struct mbuf *m0)
mhlen = sizeof (struct ip); mhlen = sizeof (struct ip);
for (off = hlen + len; off < (u_int16_t)ip->ip_len; off += len) { for (off = hlen + len; off < (u_int16_t)ip->ip_len; off += len) {
register struct ip *mhip; register struct ip *mhip;
m = m_get(); m = m_get(slirp);
if (m == NULL) { if (m == NULL) {
error = -1; error = -1;
goto sendorfree; goto sendorfree;

View File

@ -5,6 +5,9 @@
#ifdef CONFIG_SLIRP #ifdef CONFIG_SLIRP
struct Slirp;
typedef struct Slirp Slirp;
void slirp_init(int restricted, struct in_addr vnetwork, void slirp_init(int restricted, struct in_addr vnetwork,
struct in_addr vnetmask, struct in_addr vhost, struct in_addr vnetmask, struct in_addr vhost,
const char *vhostname, const char *tftp_path, const char *vhostname, const char *tftp_path,

View File

@ -31,11 +31,6 @@ extern char *slirp_tty;
extern char *exec_shell; extern char *exec_shell;
extern u_int curtime; extern u_int curtime;
extern fd_set *global_readfds, *global_writefds, *global_xfds; 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 our_addr;
extern struct in_addr loopback_addr; extern struct in_addr loopback_addr;
extern struct in_addr dns_addr; extern struct in_addr dns_addr;
@ -44,16 +39,11 @@ extern char *socket_path;
extern int towrite_max; extern int towrite_max;
extern int ppp_exit; extern int ppp_exit;
extern int tcp_keepintvl; 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 #define PROTO_SLIP 0x1
#ifdef USE_PPP #ifdef USE_PPP
#define PROTO_PPP 0x2 #define PROTO_PPP 0x2
#endif #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); ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags);

View File

@ -17,8 +17,6 @@
#include <slirp.h> #include <slirp.h>
static int mbuf_alloced;
struct mbuf m_freelist, m_usedlist;
#define MBUF_THRESH 30 #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) #define SLIRP_MSIZE (IF_MTU + IF_MAXLINKHDR + sizeof(struct m_hdr ) + 6)
void void
m_init(void) m_init(Slirp *slirp)
{ {
m_freelist.m_next = m_freelist.m_prev = &m_freelist; slirp->m_freelist.m_next = slirp->m_freelist.m_prev = &slirp->m_freelist;
m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist; 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 * which tells m_free to actually free() it
*/ */
struct mbuf * struct mbuf *
m_get(void) m_get(Slirp *slirp)
{ {
register struct mbuf *m; register struct mbuf *m;
int flags = 0; int flags = 0;
DEBUG_CALL("m_get"); 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); m = (struct mbuf *)malloc(SLIRP_MSIZE);
if (m == NULL) goto end_error; if (m == NULL) goto end_error;
mbuf_alloced++; slirp->mbuf_alloced++;
if (mbuf_alloced > MBUF_THRESH) if (slirp->mbuf_alloced > MBUF_THRESH)
flags = M_DOFREE; flags = M_DOFREE;
m->slirp = slirp;
} else { } else {
m = m_freelist.m_next; m = slirp->m_freelist.m_next;
remque(m); remque(m);
} }
/* Insert it in the used list */ /* Insert it in the used list */
insque(m,&m_usedlist); insque(m,&slirp->m_usedlist);
m->m_flags = (flags | M_USEDLIST); m->m_flags = (flags | M_USEDLIST);
/* Initialise it */ /* Initialise it */
@ -97,9 +96,9 @@ m_free(struct mbuf *m)
*/ */
if (m->m_flags & M_DOFREE) { if (m->m_flags & M_DOFREE) {
free(m); free(m);
mbuf_alloced--; m->slirp->mbuf_alloced--;
} else if ((m->m_flags & M_FREELIST) == 0) { } 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 */ m->m_flags = M_FREELIST; /* Clobber other flags */
} }
} /* if(m) */ } /* if(m) */
@ -194,7 +193,7 @@ m_copy(struct mbuf *n, struct mbuf *m, int off, int len)
* Fortunately, it's not used often * Fortunately, it's not used often
*/ */
struct mbuf * struct mbuf *
dtom(void *dat) dtom(Slirp *slirp, void *dat)
{ {
struct mbuf *m; struct mbuf *m;
@ -202,7 +201,8 @@ dtom(void *dat)
DEBUG_ARG("dat = %lx", (long )dat); DEBUG_ARG("dat = %lx", (long )dat);
/* bug corrected for M_EXT buffers */ /* 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 (m->m_flags & M_EXT) {
if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) ) if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) )
return m; return m;

View File

@ -84,6 +84,7 @@ struct m_hdr {
struct mbuf { struct mbuf {
struct m_hdr m_hdr; struct m_hdr m_hdr;
Slirp *slirp;
union M_dat { union M_dat {
char m_dat_[1]; /* ANSI don't like 0 sized arrays */ char m_dat_[1]; /* ANSI don't like 0 sized arrays */
char *m_ext_; char *m_ext_;
@ -114,15 +115,13 @@ struct mbuf {
#define M_DOFREE 0x08 /* when m_free is called on the mbuf, free() #define M_DOFREE 0x08 /* when m_free is called on the mbuf, free()
* it rather than putting it on the free list */ * it rather than putting it on the free list */
extern struct mbuf m_freelist, m_usedlist; void m_init _P((Slirp *));
struct mbuf * m_get _P((Slirp *));
void m_init _P((void));
struct mbuf * m_get _P((void));
void m_free _P((struct mbuf *)); void m_free _P((struct mbuf *));
void m_cat _P((register struct mbuf *, register struct mbuf *)); void m_cat _P((register struct mbuf *, register struct mbuf *));
void m_inc _P((struct mbuf *, int)); void m_inc _P((struct mbuf *, int));
void m_adj _P((struct mbuf *, int)); void m_adj _P((struct mbuf *, int));
int m_copy _P((struct mbuf *, struct mbuf *, int, int)); int m_copy _P((struct mbuf *, struct mbuf *, int, int));
struct mbuf * dtom _P((void *)); struct mbuf * dtom _P((Slirp *, void *));
#endif #endif

View File

@ -385,6 +385,7 @@ void slirp_connection_info(Monitor *mon)
[TCPS_FIN_WAIT_2] = "FIN_WAIT_2", [TCPS_FIN_WAIT_2] = "FIN_WAIT_2",
[TCPS_TIME_WAIT] = "TIME_WAIT", [TCPS_TIME_WAIT] = "TIME_WAIT",
}; };
Slirp *slirp = &slirp_instance;
struct in_addr dst_addr; struct in_addr dst_addr;
struct sockaddr_in src; struct sockaddr_in src;
socklen_t src_len; socklen_t src_len;
@ -397,7 +398,7 @@ void slirp_connection_info(Monitor *mon)
monitor_printf(mon, " Protocol[State] FD Source Address Port " monitor_printf(mon, " Protocol[State] FD Source Address Port "
"Dest. Address Port RecvQ SendQ\n"); "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) { if (so->so_state & SS_HOSTFWD) {
state = "HOST_FORWARD"; state = "HOST_FORWARD";
} else if (so->so_tcpcb) { } 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); 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) { if (so->so_state & SS_HOSTFWD) {
n = snprintf(buf, sizeof(buf), " UDP[HOST_FORWARD]"); n = snprintf(buf, sizeof(buf), " UDP[HOST_FORWARD]");
src_len = sizeof(src); src_len = sizeof(src);

View File

@ -16,8 +16,6 @@ struct ex_list {
struct ex_list *ex_next; struct ex_list *ex_next;
}; };
extern struct ex_list *exec_list;
#ifndef HAVE_STRDUP #ifndef HAVE_STRDUP
char *strdup _P((const char *)); char *strdup _P((const char *));
#endif #endif

View File

@ -33,27 +33,14 @@ struct in_addr dns_addr;
/* host loopback address */ /* host loopback address */
struct in_addr loopback_addr; 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 */ /* emulated hosts use the MAC addr 52:55:IP:IP:IP:IP */
static const uint8_t special_ethaddr[6] = { static const uint8_t special_ethaddr[6] = {
0x52, 0x55, 0x00, 0x00, 0x00, 0x00 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 }; static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
int slirp_restrict; int link_up; // FIXME: kill this
int link_up;
struct ex_list *exec_list;
/* XXX: suppress those select globals */ /* XXX: suppress those select globals */
fd_set *global_readfds, *global_writefds, *global_xfds; fd_set *global_readfds, *global_writefds, *global_xfds;
@ -62,7 +49,7 @@ u_int curtime;
static u_int time_fasttimo, last_slowtimo; static u_int time_fasttimo, last_slowtimo;
static int do_slowtimo; static int do_slowtimo;
char slirp_hostname[33]; Slirp slirp_instance;
#ifdef _WIN32 #ifdef _WIN32
@ -206,37 +193,40 @@ void slirp_init(int restricted, struct in_addr vnetwork,
const char *bootfile, struct in_addr vdhcp_start, const char *bootfile, struct in_addr vdhcp_start,
struct in_addr vnameserver) struct in_addr vnameserver)
{ {
Slirp *slirp = &slirp_instance;
slirp_init_once(); slirp_init_once();
link_up = 1; link_up = 1;
slirp_restrict = restricted; slirp->restricted = restricted;
if_init(); if_init(slirp);
ip_init(); ip_init(slirp);
/* Initialise mbufs *after* setting the MTU */ /* Initialise mbufs *after* setting the MTU */
m_init(); m_init(slirp);
vnetwork_addr = vnetwork; slirp->vnetwork_addr = vnetwork;
vnetwork_mask = vnetmask; slirp->vnetwork_mask = vnetmask;
vhost_addr = vhost; slirp->vhost_addr = vhost;
if (vhostname) { if (vhostname) {
pstrcpy(slirp_hostname, sizeof(slirp_hostname), vhostname); pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname),
vhostname);
} }
qemu_free(tftp_prefix); qemu_free(slirp->tftp_prefix);
tftp_prefix = NULL; slirp->tftp_prefix = NULL;
if (tftp_path) { if (tftp_path) {
tftp_prefix = qemu_strdup(tftp_path); slirp->tftp_prefix = qemu_strdup(tftp_path);
} }
qemu_free(bootp_filename); qemu_free(slirp->bootp_filename);
bootp_filename = NULL; slirp->bootp_filename = NULL;
if (bootfile) { if (bootfile) {
bootp_filename = qemu_strdup(bootfile); slirp->bootp_filename = qemu_strdup(bootfile);
} }
vdhcp_startaddr = vdhcp_start; slirp->vdhcp_startaddr = vdhcp_start;
vnameserver_addr = vnameserver; 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) #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, void slirp_select_fill(int *pnfds,
fd_set *readfds, fd_set *writefds, fd_set *xfds) fd_set *readfds, fd_set *writefds, fd_set *xfds)
{ {
Slirp *slirp = &slirp_instance;
struct socket *so, *so_next; struct socket *so, *so_next;
int nfds; int nfds;
@ -291,10 +282,11 @@ void slirp_select_fill(int *pnfds,
* *_slowtimo needs calling if there are IP fragments * *_slowtimo needs calling if there are IP fragments
* in the fragment queue, or there are TCP connections active * in the fragment queue, or there are TCP connections active
*/ */
do_slowtimo = ((tcb.so_next != &tcb) || do_slowtimo = ((slirp->tcb.so_next != &slirp->tcb) ||
(&ipq.ip_link != ipq.ip_link.next)); (&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; so_next = so->so_next;
/* /*
@ -351,7 +343,8 @@ void slirp_select_fill(int *pnfds,
/* /*
* UDP sockets * 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; 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, void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
int select_error) int select_error)
{ {
Slirp *slirp = &slirp_instance;
struct socket *so, *so_next; struct socket *so, *so_next;
int ret; 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 * See if anything has timed out
*/ */
if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) { if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
tcp_fasttimo(); tcp_fasttimo(slirp);
time_fasttimo = 0; time_fasttimo = 0;
} }
if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) { if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
ip_slowtimo(); ip_slowtimo(slirp);
tcp_slowtimo(); tcp_slowtimo(slirp);
last_slowtimo = curtime; last_slowtimo = curtime;
} }
@ -421,7 +415,8 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
/* /*
* Check TCP sockets * 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; 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 packets are sent straight away, they're not buffered.
* Incoming UDP data isn't buffered either. * 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; so_next = so->so_next;
if (so->s != -1 && FD_ISSET(so->s, readfds)) { 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 * See if we can start outputting
*/ */
if (if_queued) if (slirp->if_queued) {
if_start(); if_start(slirp);
}
/* clear global file descriptor sets. /* clear global file descriptor sets.
* these reside on the stack in vl.c * these reside on the stack in vl.c
@ -596,7 +593,7 @@ struct arphdr
uint32_t ar_tip ; /* target IP address */ uint32_t ar_tip ; /* target IP address */
} __attribute__((packed)); } __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 ethhdr *eh = (struct ethhdr *)pkt;
struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN); 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); ar_op = ntohs(ah->ar_op);
switch(ar_op) { switch(ar_op) {
case ARPOP_REQUEST: case ARPOP_REQUEST:
if ((ah->ar_tip & vnetwork_mask.s_addr) == vnetwork_addr.s_addr) { if ((ah->ar_tip & slirp->vnetwork_mask.s_addr) ==
if (ah->ar_tip == vnameserver_addr.s_addr || slirp->vnetwork_addr.s_addr) {
ah->ar_tip == vhost_addr.s_addr) if (ah->ar_tip == slirp->vnameserver_addr.s_addr ||
ah->ar_tip == slirp->vhost_addr.s_addr)
goto arp_ok; 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) if (ex_ptr->ex_addr.s_addr == ah->ar_tip)
goto arp_ok; goto arp_ok;
} }
return; return;
arp_ok: arp_ok:
/* XXX: make an ARP request to have the client address */ /* 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 */ /* ARP request for alias/dns mac address */
memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN); 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; break;
case ARPOP_REPLY: case ARPOP_REPLY:
/* reply to request of client mac address ? */ /* reply to request of client mac address ? */
if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN) && if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN) &&
ah->ar_sip == client_ipaddr.s_addr) { ah->ar_sip == slirp->client_ipaddr.s_addr) {
memcpy(client_ethaddr, ah->ar_sha, ETH_ALEN); memcpy(slirp->client_ethaddr, ah->ar_sha, ETH_ALEN);
} }
break; break;
default: 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) void slirp_input(const uint8_t *pkt, int pkt_len)
{ {
Slirp *slirp = &slirp_instance;
struct mbuf *m; struct mbuf *m;
int proto; int proto;
@ -663,10 +662,10 @@ void slirp_input(const uint8_t *pkt, int pkt_len)
proto = ntohs(*(uint16_t *)(pkt + 12)); proto = ntohs(*(uint16_t *)(pkt + 12));
switch(proto) { switch(proto) {
case ETH_P_ARP: case ETH_P_ARP:
arp_input(pkt, pkt_len); arp_input(slirp, pkt, pkt_len);
break; break;
case ETH_P_IP: case ETH_P_IP:
m = m_get(); m = m_get(slirp);
if (!m) if (!m)
return; return;
/* Note: we add to align the IP header */ /* 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 */ /* 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]; uint8_t buf[1600];
struct ethhdr *eh = (struct ethhdr *)buf; 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)) if (ip_data_len + ETH_HLEN > sizeof(buf))
return; 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)]; uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];
struct ethhdr *reh = (struct ethhdr *)arp_req; struct ethhdr *reh = (struct ethhdr *)arp_req;
struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN); 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. */ will retry sending its packet. */
memset(reh->h_dest, 0xff, ETH_ALEN); memset(reh->h_dest, 0xff, ETH_ALEN);
memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4); 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); reh->h_proto = htons(ETH_P_ARP);
rah->ar_hrd = htons(1); rah->ar_hrd = htons(1);
rah->ar_pro = htons(ETH_P_IP); 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); rah->ar_op = htons(ARPOP_REQUEST);
/* source hw addr */ /* source hw addr */
memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 4); 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 */ /* source IP */
rah->ar_sip = vhost_addr.s_addr; rah->ar_sip = slirp->vhost_addr.s_addr;
/* target hw addr (none) */ /* target hw addr (none) */
memset(rah->ar_tha, 0, ETH_ALEN); memset(rah->ar_tha, 0, ETH_ALEN);
/* target IP */ /* target IP */
rah->ar_tip = iph->ip_dst.s_addr; 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)); slirp_output(arp_req, sizeof(arp_req));
} else { } 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); memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4);
/* XXX: not correct */ /* 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); eh->h_proto = htons(ETH_P_IP);
memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len); memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
slirp_output(buf, ip_data_len + ETH_HLEN); 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. */ /* Drop host forwarding rule, return 0 if found. */
int slirp_remove_hostfwd(int is_udp, struct in_addr host_addr, int host_port) int slirp_remove_hostfwd(int is_udp, struct in_addr host_addr, int host_port)
{ {
Slirp *slirp = &slirp_instance;
struct socket *so; struct socket *so;
struct socket *head = (is_udp ? &udb : &tcb); struct socket *head = (is_udp ? &slirp->udb : &slirp->tcb);
struct sockaddr_in addr; struct sockaddr_in addr;
int port = htons(host_port); int port = htons(host_port);
socklen_t addr_len; 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, int slirp_add_hostfwd(int is_udp, struct in_addr host_addr, int host_port,
struct in_addr guest_addr, int guest_port) struct in_addr guest_addr, int guest_port)
{ {
Slirp *slirp = &slirp_instance;
if (!guest_addr.s_addr) { if (!guest_addr.s_addr) {
guest_addr = vdhcp_startaddr; guest_addr = slirp->vdhcp_startaddr;
} }
if (is_udp) { if (is_udp) {
if (!udp_listen(host_addr.s_addr, htons(host_port), guest_addr.s_addr, if (!udp_listen(slirp, host_addr.s_addr, htons(host_port),
htons(guest_port), SS_HOSTFWD)) guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))
return -1; return -1;
} else { } else {
if (!tcp_listen(host_addr.s_addr, htons(host_port), guest_addr.s_addr, if (!tcp_listen(slirp, host_addr.s_addr, htons(host_port),
htons(guest_port), SS_HOSTFWD)) guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))
return -1; return -1;
} }
return 0; 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 slirp_add_exec(int do_pty, const void *args, struct in_addr guest_addr,
int guest_port) int guest_port)
{ {
Slirp *slirp = &slirp_instance;
if (!guest_addr.s_addr) { if (!guest_addr.s_addr) {
guest_addr.s_addr = guest_addr.s_addr = slirp->vnetwork_addr.s_addr |
vnetwork_addr.s_addr | (htonl(0x0204) & ~vnetwork_mask.s_addr); (htonl(0x0204) & ~slirp->vnetwork_mask.s_addr);
} }
if ((guest_addr.s_addr & vnetwork_mask.s_addr) != vnetwork_addr.s_addr || if ((guest_addr.s_addr & slirp->vnetwork_mask.s_addr) !=
guest_addr.s_addr == vhost_addr.s_addr || slirp->vnetwork_addr.s_addr ||
guest_addr.s_addr == vnameserver_addr.s_addr) { guest_addr.s_addr == slirp->vhost_addr.s_addr ||
guest_addr.s_addr == slirp->vnameserver_addr.s_addr) {
return -1; 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)); 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 * 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; 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 && if (so->so_faddr.s_addr == guest_addr.s_addr &&
htons(so->so_fport) == guest_port) { htons(so->so_fport) == guest_port) {
return so; 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) size_t slirp_socket_can_recv(struct in_addr guest_addr, int guest_port)
{ {
Slirp *slirp = &slirp_instance;
struct iovec iov[2]; struct iovec iov[2];
struct socket *so; 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) if (!so || so->so_state & SS_NOFDREF)
return 0; 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, void slirp_socket_recv(struct in_addr guest_addr, int guest_port,
const uint8_t *buf, int size) const uint8_t *buf, int size)
{ {
Slirp *slirp = &slirp_instance;
int ret; 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) if (!so)
return; return;
@ -928,12 +935,14 @@ static void slirp_socket_save(QEMUFile *f, struct socket *so)
static void slirp_state_save(QEMUFile *f, void *opaque) static void slirp_state_save(QEMUFile *f, void *opaque)
{ {
Slirp *slirp = opaque;
struct ex_list *ex_ptr; 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) { if (ex_ptr->ex_pty == 3) {
struct socket *so; 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) if (!so)
continue; continue;
@ -942,7 +951,7 @@ static void slirp_state_save(QEMUFile *f, void *opaque)
} }
qemu_put_byte(f, 0); 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) 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) static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
{ {
Slirp *slirp = opaque;
struct ex_list *ex_ptr; struct ex_list *ex_ptr;
int r; int r;
while ((r = qemu_get_byte(f))) { while ((r = qemu_get_byte(f))) {
int ret; int ret;
struct socket *so = socreate(); struct socket *so = socreate(slirp);
if (!so) if (!so)
return -ENOMEM; return -ENOMEM;
@ -1056,11 +1066,11 @@ static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
if (ret < 0) if (ret < 0)
return ret; return ret;
if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) != if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) !=
vnetwork_addr.s_addr) { slirp->vnetwork_addr.s_addr) {
return -EINVAL; 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 && if (ex_ptr->ex_pty == 3 &&
so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr && so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr &&
so->so_fport == ex_ptr->ex_fport) { 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) { if (version_id >= 2) {
ip_id = qemu_get_be16(f); slirp->ip_id = qemu_get_be16(f);
} }
return 0; return 0;

View File

@ -185,6 +185,7 @@ int inet_aton _P((const char *cp, struct in_addr *ia));
#include "debug.h" #include "debug.h"
#include "libslirp.h"
#include "ip.h" #include "ip.h"
#include "tcp.h" #include "tcp.h"
#include "tcp_timer.h" #include "tcp_timer.h"
@ -204,14 +205,67 @@ int inet_aton _P((const char *cp, struct in_addr *ia));
#include "bootp.h" #include "bootp.h"
#include "tftp.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 #ifndef NULL
#define NULL (void *)0 #define NULL (void *)0
#endif #endif
#ifndef FULL_BOLT #ifndef FULL_BOLT
void if_start _P((void)); void if_start _P((Slirp *));
#else #else
void if_start _P((struct ttys *)); void if_start _P((struct ttys *));
#endif #endif
@ -257,13 +311,13 @@ void lprint _P((const char *, ...));
int cksum(struct mbuf *m, int len); int cksum(struct mbuf *m, int len);
/* if.c */ /* if.c */
void if_init _P((void)); void if_init _P((Slirp *));
void if_output _P((struct socket *, struct mbuf *)); void if_output _P((struct socket *, struct mbuf *));
/* ip_input.c */ /* ip_input.c */
void ip_init _P((void)); void ip_init _P((Slirp *));
void ip_input _P((struct mbuf *)); 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 *)); void ip_stripoptions _P((register struct mbuf *, struct mbuf *));
/* ip_output.c */ /* ip_output.c */
@ -278,7 +332,7 @@ int tcp_output _P((register struct tcpcb *));
void tcp_setpersist _P((register struct tcpcb *)); void tcp_setpersist _P((register struct tcpcb *));
/* tcp_subr.c */ /* tcp_subr.c */
void tcp_init _P((void)); void tcp_init _P((Slirp *));
void tcp_template _P((struct tcpcb *)); void tcp_template _P((struct tcpcb *));
void tcp_respond _P((struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int)); void tcp_respond _P((struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int));
struct tcpcb * tcp_newtcpcb _P((struct socket *)); struct tcpcb * tcp_newtcpcb _P((struct socket *));

View File

@ -41,7 +41,7 @@ solookup(struct socket *head, struct in_addr laddr, u_int lport,
* insque() it into the correct linked-list * insque() it into the correct linked-list
*/ */
struct socket * struct socket *
socreate(void) socreate(Slirp *slirp)
{ {
struct socket *so; struct socket *so;
@ -50,6 +50,7 @@ socreate(void)
memset(so, 0, sizeof(struct socket)); memset(so, 0, sizeof(struct socket));
so->so_state = SS_NOFDREF; so->so_state = SS_NOFDREF;
so->s = -1; so->s = -1;
so->slirp = slirp;
} }
return(so); return(so);
} }
@ -60,15 +61,17 @@ socreate(void)
void void
sofree(struct socket *so) sofree(struct socket *so)
{ {
Slirp *slirp = so->slirp;
if (so->so_emu==EMU_RSH && so->extra) { if (so->so_emu==EMU_RSH && so->extra) {
sofree(so->extra); sofree(so->extra);
so->extra=NULL; so->extra=NULL;
} }
if (so == tcp_last_so) if (so == slirp->tcp_last_so) {
tcp_last_so = &tcb; slirp->tcp_last_so = &slirp->tcb;
else if (so == udp_last_so) } else if (so == slirp->udp_last_so) {
udp_last_so = &udb; slirp->udp_last_so = &slirp->udb;
}
m_free(so->so_m); m_free(so->so_m);
if(so->so_next && so->so_prev) if(so->so_next && so->so_prev)
@ -473,7 +476,10 @@ sorecvfrom(struct socket *so)
int n; int n;
#endif #endif
if (!(m = m_get())) return; m = m_get(so->slirp);
if (!m) {
return;
}
m->m_data += IF_MAXLINKHDR; m->m_data += IF_MAXLINKHDR;
/* /*
@ -533,6 +539,7 @@ sorecvfrom(struct socket *so)
int int
sosendto(struct socket *so, struct mbuf *m) sosendto(struct socket *so, struct mbuf *m)
{ {
Slirp *slirp = so->slirp;
int ret; int ret;
struct sockaddr_in addr; struct sockaddr_in addr;
@ -541,10 +548,10 @@ sosendto(struct socket *so, struct mbuf *m)
DEBUG_ARG("m = %lx", (long)m); DEBUG_ARG("m = %lx", (long)m);
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) == if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
vnetwork_addr.s_addr) { slirp->vnetwork_addr.s_addr) {
/* It's an alias */ /* 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; addr.sin_addr = dns_addr;
} else { } else {
addr.sin_addr = loopback_addr; addr.sin_addr = loopback_addr;
@ -576,7 +583,8 @@ sosendto(struct socket *so, struct mbuf *m)
* Listen for incoming TCP connections * Listen for incoming TCP connections
*/ */
struct socket * 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 sockaddr_in addr;
struct socket *so; 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("lport = %d", lport);
DEBUG_ARG("flags = %x", flags); DEBUG_ARG("flags = %x", flags);
if ((so = socreate()) == NULL) { so = socreate(slirp);
if (!so) {
return NULL; 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); free(so);
return NULL; return NULL;
} }
insque(so,&tcb); insque(so, &slirp->tcb);
/* /*
* SS_FACCEPTONCE sockets must time out. * 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); getsockname(s,(struct sockaddr *)&addr,&addrlen);
so->so_fport = addr.sin_port; so->so_fport = addr.sin_port;
if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) 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 else
so->so_faddr = addr.sin_addr; so->so_faddr = addr.sin_addr;

View File

@ -20,6 +20,8 @@ struct socket {
int s; /* The actual socket */ int s; /* The actual socket */
Slirp *slirp; /* managing slirp instance */
/* XXX union these with not-yet-used sbuf params */ /* XXX union these with not-yet-used sbuf params */
struct mbuf *so_m; /* Pointer to the original SYN packet, struct mbuf *so_m; /* Pointer to the original SYN packet,
* for non-blocking connect()'s, and * for non-blocking connect()'s, and
@ -72,10 +74,8 @@ struct socket {
#define SS_HOSTFWD 0x1000 /* Socket describes host->guest forwarding */ #define SS_HOSTFWD 0x1000 /* Socket describes host->guest forwarding */
#define SS_INCOMING 0x2000 /* Connection was initiated by a host on the internet */ #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 * 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 *)); void sofree _P((struct socket *));
int soread _P((struct socket *)); int soread _P((struct socket *));
void sorecvoob _P((struct socket *)); void sorecvoob _P((struct socket *));
@ -83,7 +83,8 @@ int sosendoob _P((struct socket *));
int sowrite _P((struct socket *)); int sowrite _P((struct socket *));
void sorecvfrom _P((struct socket *)); void sorecvfrom _P((struct socket *));
int sosendto _P((struct socket *, struct mbuf *)); 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 soisfconnecting _P((register struct socket *));
void soisfconnected _P((register struct socket *)); void soisfconnected _P((register struct socket *));
void sofwdrain _P((struct socket *)); void sofwdrain _P((struct socket *));

View File

@ -38,8 +38,6 @@ typedef u_int32_t tcp_seq;
#define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */ #define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */
#define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */ #define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */
extern struct socket *tcp_last_so;
#define TCP_SNDSPACE 8192 #define TCP_SNDSPACE 8192
#define TCP_RCVSPACE 8192 #define TCP_RCVSPACE 8192
@ -163,6 +161,4 @@ struct tcphdr {
#define TCP_ISSINCR (125*1024) /* increment for tcp_iss each second */ #define TCP_ISSINCR (125*1024) /* increment for tcp_iss each second */
extern tcp_seq tcp_iss; /* tcp initial send seq # */
#endif #endif

View File

@ -41,12 +41,7 @@
#include <slirp.h> #include <slirp.h>
#include "ip_icmp.h" #include "ip_icmp.h"
struct socket tcb;
#define TCPREXMTTHRESH 3 #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) #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; u_long tiwin;
int ret; int ret;
struct ex_list *ex_ptr; struct ex_list *ex_ptr;
Slirp *slirp;
DEBUG_CALL("tcp_input"); DEBUG_CALL("tcp_input");
DEBUG_ARGS((dfd," m = %8lx iphlen = %2d inso = %lx\n", 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) { if (m == NULL) {
so = inso; so = inso;
slirp = so->slirp;
/* Re-set a few variables */ /* Re-set a few variables */
tp = sototcpcb(so); tp = sototcpcb(so);
@ -254,6 +251,7 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
goto cont_conn; goto cont_conn;
} }
slirp = m->slirp;
/* /*
* Get IP and TCP header together in first mbuf. * 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_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
m->m_len -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); m->m_len -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
if (slirp_restrict) { if (slirp->restricted) {
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 == ti->ti_dport && if (ex_ptr->ex_fport == ti->ti_dport &&
ti->ti_dst.s_addr == ex_ptr->ex_addr.s_addr) { ti->ti_dst.s_addr == ex_ptr->ex_addr.s_addr) {
break; break;
@ -332,15 +330,15 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
* Locate pcb for segment. * Locate pcb for segment.
*/ */
findso: findso:
so = tcp_last_so; so = slirp->tcp_last_so;
if (so->so_fport != ti->ti_dport || if (so->so_fport != ti->ti_dport ||
so->so_lport != ti->ti_sport || so->so_lport != ti->ti_sport ||
so->so_laddr.s_addr != ti->ti_src.s_addr || so->so_laddr.s_addr != ti->ti_src.s_addr ||
so->so_faddr.s_addr != ti->ti_dst.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); ti->ti_dst, ti->ti_dport);
if (so) 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) if ((tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) != TH_SYN)
goto dropwithreset; goto dropwithreset;
if ((so = socreate()) == NULL) if ((so = socreate(slirp)) == NULL)
goto dropwithreset; goto dropwithreset;
if (tcp_attach(so) < 0) { if (tcp_attach(so) < 0) {
free(so); /* Not sofree (if it failed, it's not insqued) */ 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 * If this is destined for the control address, then flag to
* tcp_ctl once connected, otherwise connect * tcp_ctl once connected, otherwise connect
*/ */
if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) == if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
vnetwork_addr.s_addr) { slirp->vnetwork_addr.s_addr) {
if (so->so_faddr.s_addr != vhost_addr.s_addr && if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr &&
so->so_faddr.s_addr != vnameserver_addr.s_addr) { so->so_faddr.s_addr != slirp->vnameserver_addr.s_addr) {
/* May be an add exec */ /* 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 && if(ex_ptr->ex_fport == so->so_fport &&
so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) { so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {
so->so_state |= SS_CTL; so->so_state |= SS_CTL;
@ -631,8 +630,8 @@ findso:
if (iss) if (iss)
tp->iss = iss; tp->iss = iss;
else else
tp->iss = tcp_iss; tp->iss = slirp->tcp_iss;
tcp_iss += TCP_ISSINCR/2; slirp->tcp_iss += TCP_ISSINCR/2;
tp->irs = ti->ti_seq; tp->irs = ti->ti_seq;
tcp_sendseqinit(tp); tcp_sendseqinit(tp);
tcp_rcvseqinit(tp); tcp_rcvseqinit(tp);

View File

@ -290,7 +290,7 @@ send:
* the template for sends on this connection. * the template for sends on this connection.
*/ */
if (len) { if (len) {
m = m_get(); m = m_get(so->slirp);
if (m == NULL) { if (m == NULL) {
error = 1; error = 1;
goto out; goto out;
@ -310,7 +310,7 @@ send:
if (off + len == so->so_snd.sb_cc) if (off + len == so->so_snd.sb_cc)
flags |= TH_PUSH; flags |= TH_PUSH;
} else { } else {
m = m_get(); m = m_get(so->slirp);
if (m == NULL) { if (m == NULL) {
error = 1; error = 1;
goto out; goto out;

View File

@ -48,10 +48,11 @@
* Tcp initialization * Tcp initialization
*/ */
void void
tcp_init(void) tcp_init(Slirp *slirp)
{ {
tcp_iss = 1; /* wrong */ slirp->tcp_iss = 1; /* wrong */
tcb.so_next = tcb.so_prev = &tcb; 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) if (tp)
win = sbspace(&tp->t_socket->so_rcv); win = sbspace(&tp->t_socket->so_rcv);
if (m == NULL) { if (m == NULL) {
if ((m = m_get()) == NULL) if ((m = m_get(tp->t_socket->slirp)) == NULL)
return; return;
tlen = 0; tlen = 0;
m->m_data += IF_MAXLINKHDR; m->m_data += IF_MAXLINKHDR;
@ -237,6 +238,7 @@ tcp_close(struct tcpcb *tp)
{ {
register struct tcpiphdr *t; register struct tcpiphdr *t;
struct socket *so = tp->t_socket; struct socket *so = tp->t_socket;
Slirp *slirp = so->slirp;
register struct mbuf *m; register struct mbuf *m;
DEBUG_CALL("tcp_close"); DEBUG_CALL("tcp_close");
@ -253,8 +255,8 @@ tcp_close(struct tcpcb *tp)
free(tp); free(tp);
so->so_tcpcb = NULL; so->so_tcpcb = NULL;
/* clobber input socket cache if we're closing the cached connection */ /* clobber input socket cache if we're closing the cached connection */
if (so == tcp_last_so) if (so == slirp->tcp_last_so)
tcp_last_so = &tcb; slirp->tcp_last_so = &slirp->tcb;
closesocket(so->s); closesocket(so->s);
sbfree(&so->so_rcv); sbfree(&so->so_rcv);
sbfree(&so->so_snd); sbfree(&so->so_snd);
@ -317,6 +319,7 @@ tcp_sockclosed(struct tcpcb *tp)
*/ */
int tcp_fconnect(struct socket *so) int tcp_fconnect(struct socket *so)
{ {
Slirp *slirp = so->slirp;
int ret=0; int ret=0;
DEBUG_CALL("tcp_fconnect"); DEBUG_CALL("tcp_fconnect");
@ -333,9 +336,10 @@ int tcp_fconnect(struct socket *so)
setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(opt )); setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(opt ));
addr.sin_family = AF_INET; 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 */ /* 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; addr.sin_addr = dns_addr;
} else { } else {
addr.sin_addr = loopback_addr; addr.sin_addr = loopback_addr;
@ -375,6 +379,7 @@ int tcp_fconnect(struct socket *so)
void void
tcp_connect(struct socket *inso) tcp_connect(struct socket *inso)
{ {
Slirp *slirp = inso->slirp;
struct socket *so; struct socket *so;
struct sockaddr_in addr; struct sockaddr_in addr;
socklen_t addrlen = sizeof(struct sockaddr_in); socklen_t addrlen = sizeof(struct sockaddr_in);
@ -392,7 +397,7 @@ tcp_connect(struct socket *inso)
/* FACCEPTONCE already have a tcpcb */ /* FACCEPTONCE already have a tcpcb */
so = inso; so = inso;
} else { } else {
if ((so = socreate()) == NULL) { if ((so = socreate(slirp)) == NULL) {
/* If it failed, get rid of the pending connection */ /* If it failed, get rid of the pending connection */
closesocket(accept(inso->s,(struct sockaddr *)&addr,&addrlen)); closesocket(accept(inso->s,(struct sockaddr *)&addr,&addrlen));
return; return;
@ -423,7 +428,7 @@ tcp_connect(struct socket *inso)
so->so_faddr = addr.sin_addr; so->so_faddr = addr.sin_addr;
/* Translate connections from localhost to the real hostname */ /* Translate connections from localhost to the real hostname */
if (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == loopback_addr.s_addr) 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 */ /* Close the accept() socket, set right state */
if (inso->so_state & SS_FACCEPTONCE) { if (inso->so_state & SS_FACCEPTONCE) {
@ -441,8 +446,8 @@ tcp_connect(struct socket *inso)
tp->t_state = TCPS_SYN_SENT; tp->t_state = TCPS_SYN_SENT;
tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
tp->iss = tcp_iss; tp->iss = slirp->tcp_iss;
tcp_iss += TCP_ISSINCR/2; slirp->tcp_iss += TCP_ISSINCR/2;
tcp_sendseqinit(tp); tcp_sendseqinit(tp);
tcp_output(tp); tcp_output(tp);
} }
@ -456,7 +461,7 @@ tcp_attach(struct socket *so)
if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL)
return -1; return -1;
insque(so, &tcb); insque(so, &so->slirp->tcb);
return 0; return 0;
} }
@ -539,6 +544,7 @@ tcp_tos(struct socket *so)
int int
tcp_emu(struct socket *so, struct mbuf *m) tcp_emu(struct socket *so, struct mbuf *m)
{ {
Slirp *slirp = so->slirp;
u_int n1, n2, n3, n4, n5, n6; u_int n1, n2, n3, n4, n5, n6;
char buff[257]; char buff[257];
u_int32_t laddr; u_int32_t laddr;
@ -572,7 +578,9 @@ tcp_emu(struct socket *so, struct mbuf *m)
HTONS(n1); HTONS(n1);
HTONS(n2); HTONS(n2);
/* n2 is the one on our host */ /* 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 && if (tmpso->so_laddr.s_addr == so->so_laddr.s_addr &&
tmpso->so_lport == n2 && tmpso->so_lport == n2 &&
tmpso->so_faddr.s_addr == so->so_faddr.s_addr && 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)); laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
lport = htons((n5 << 8) | (n6)); 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; return 1;
}
n6 = ntohs(so->so_fport); n6 = ntohs(so->so_fport);
n5 = (n6 >> 8) & 0xff; 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)); laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
lport = htons((n5 << 8) | (n6)); 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; return 1;
}
n6 = ntohs(so->so_fport); n6 = ntohs(so->so_fport);
n5 = (n6 >> 8) & 0xff; n5 = (n6 >> 8) & 0xff;
@ -680,7 +690,8 @@ tcp_emu(struct socket *so, struct mbuf *m)
lport += m->m_data[i] - '0'; lport += m->m_data[i] - '0';
} }
if (m->m_data[m->m_len-1] == '\0' && lport != 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", m->m_len = snprintf(m->m_data, m->m_hdr.mh_size, "%d",
ntohs(so->so_fport)) + 1; ntohs(so->so_fport)) + 1;
return 1; return 1;
@ -695,27 +706,33 @@ tcp_emu(struct socket *so, struct mbuf *m)
/* The %256s is for the broken mIRC */ /* The %256s is for the broken mIRC */
if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3) { 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; return 1;
}
m->m_len = bptr - m->m_data; /* Adjust length */ m->m_len = bptr - m->m_data; /* Adjust length */
m->m_len += snprintf(bptr, m->m_hdr.mh_size, m->m_len += snprintf(bptr, m->m_hdr.mh_size,
"DCC CHAT chat %lu %u%c\n", "DCC CHAT chat %lu %u%c\n",
(unsigned long)ntohl(so->so_faddr.s_addr), (unsigned long)ntohl(so->so_faddr.s_addr),
ntohs(so->so_fport), 1); ntohs(so->so_fport), 1);
} else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) { } 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; return 1;
}
m->m_len = bptr - m->m_data; /* Adjust length */ m->m_len = bptr - m->m_data; /* Adjust length */
m->m_len += snprintf(bptr, m->m_hdr.mh_size, m->m_len += snprintf(bptr, m->m_hdr.mh_size,
"DCC SEND %s %lu %u %u%c\n", buff, "DCC SEND %s %lu %u %u%c\n", buff,
(unsigned long)ntohl(so->so_faddr.s_addr), (unsigned long)ntohl(so->so_faddr.s_addr),
ntohs(so->so_fport), n1, 1); ntohs(so->so_fport), n1, 1);
} else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) { } 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; return 1;
}
m->m_len = bptr - m->m_data; /* Adjust length */ m->m_len = bptr - m->m_data; /* Adjust length */
m->m_len += snprintf(bptr, m->m_hdr.mh_size, m->m_len += snprintf(bptr, m->m_hdr.mh_size,
"DCC MOVE %s %lu %u %u%c\n", buff, "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 */ /* try to get udp port between 6970 - 7170 */
for (p = 6970; p < 7071; p++) { for (p = 6970; p < 7071; p++) {
if (udp_listen(INADDR_ANY, if (udp_listen(slirp, INADDR_ANY,
htons(p), htons(p),
so->so_laddr.s_addr, so->so_laddr.s_addr,
htons(lport), htons(lport),
@ -865,6 +882,7 @@ tcp_emu(struct socket *so, struct mbuf *m)
*/ */
int tcp_ctl(struct socket *so) int tcp_ctl(struct socket *so)
{ {
Slirp *slirp = so->slirp;
struct sbuf *sb = &so->so_snd; struct sbuf *sb = &so->so_snd;
struct ex_list *ex_ptr; struct ex_list *ex_ptr;
int do_pty; int do_pty;
@ -872,9 +890,9 @@ int tcp_ctl(struct socket *so)
DEBUG_CALL("tcp_ctl"); DEBUG_CALL("tcp_ctl");
DEBUG_ARG("so = %lx", (long )so); 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 */ /* 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 && if (ex_ptr->ex_fport == so->so_fport &&
so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) { so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {
if (ex_ptr->ex_pty == 3) { if (ex_ptr->ex_pty == 3) {

View File

@ -32,24 +32,22 @@
#include <slirp.h> #include <slirp.h>
u_int32_t tcp_now; /* for RFC 1323 timestamps */
static struct tcpcb *tcp_timers(register struct tcpcb *tp, int timer); static struct tcpcb *tcp_timers(register struct tcpcb *tp, int timer);
/* /*
* Fast timeout routine for processing delayed acks * Fast timeout routine for processing delayed acks
*/ */
void void
tcp_fasttimo(void) tcp_fasttimo(Slirp *slirp)
{ {
register struct socket *so; register struct socket *so;
register struct tcpcb *tp; register struct tcpcb *tp;
DEBUG_CALL("tcp_fasttimo"); DEBUG_CALL("tcp_fasttimo");
so = tcb.so_next; so = slirp->tcb.so_next;
if (so) if (so)
for (; so != &tcb; so = so->so_next) for (; so != &slirp->tcb; so = so->so_next)
if ((tp = (struct tcpcb *)so->so_tcpcb) && if ((tp = (struct tcpcb *)so->so_tcpcb) &&
(tp->t_flags & TF_DELACK)) { (tp->t_flags & TF_DELACK)) {
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. * causes finite state machine actions if timers expire.
*/ */
void void
tcp_slowtimo(void) tcp_slowtimo(Slirp *slirp)
{ {
register struct socket *ip, *ipnxt; register struct socket *ip, *ipnxt;
register struct tcpcb *tp; register struct tcpcb *tp;
@ -75,10 +73,10 @@ tcp_slowtimo(void)
/* /*
* Search through tcb's and update active timers. * Search through tcb's and update active timers.
*/ */
ip = tcb.so_next; ip = slirp->tcb.so_next;
if (ip == 0) if (ip == 0)
return; return;
for (; ip != &tcb; ip = ipnxt) { for (; ip != &slirp->tcb; ip = ipnxt) {
ipnxt = ip->so_next; ipnxt = ip->so_next;
tp = sototcpcb(ip); tp = sototcpcb(ip);
if (tp == 0) if (tp == 0)
@ -96,8 +94,8 @@ tcp_slowtimo(void)
tpgone: tpgone:
; ;
} }
tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ slirp->tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */
tcp_now++; /* for timestamps */ slirp->tcp_now++; /* for timestamps */
} }
/* /*

View File

@ -120,8 +120,8 @@ extern const int tcp_backoff[];
struct tcpcb; struct tcpcb;
void tcp_fasttimo _P((void)); void tcp_fasttimo _P((Slirp *));
void tcp_slowtimo _P((void)); void tcp_slowtimo _P((Slirp *));
void tcp_canceltimers _P((struct tcpcb *)); void tcp_canceltimers _P((struct tcpcb *));
#endif #endif

View File

@ -158,6 +158,4 @@ struct tcpcb {
#define TCP_REXMTVAL(tp) \ #define TCP_REXMTVAL(tp) \
(((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar) (((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar)
extern u_int32_t tcp_now; /* for RFC 1323 timestamps */
#endif #endif

View File

@ -25,41 +25,31 @@
#include <slirp.h> #include <slirp.h>
#include "qemu-common.h" #include "qemu-common.h"
struct tftp_session { static inline int tftp_session_in_use(struct tftp_session *spt)
int in_use; {
char *filename; return (spt->slirp != NULL);
}
struct in_addr client_ip; static inline void tftp_session_update(struct tftp_session *spt)
u_int16_t client_port;
int timestamp;
};
static struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
char *tftp_prefix;
static void tftp_session_update(struct tftp_session *spt)
{ {
spt->timestamp = curtime; spt->timestamp = curtime;
spt->in_use = 1;
} }
static void tftp_session_terminate(struct tftp_session *spt) static void tftp_session_terminate(struct tftp_session *spt)
{ {
qemu_free(spt->filename); 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; struct tftp_session *spt;
int k; int k;
for (k = 0; k < TFTP_SESSIONS_MAX; 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; goto found;
/* sessions time out after 5 inactive seconds */ /* 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)); memset(spt, 0, sizeof(*spt));
memcpy(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip)); memcpy(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip));
spt->client_port = tp->udp.uh_sport; spt->client_port = tp->udp.uh_sport;
spt->slirp = slirp;
tftp_session_update(spt); tftp_session_update(spt);
return k; 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; struct tftp_session *spt;
int k; int k;
for (k = 0; k < TFTP_SESSIONS_MAX; 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 (!memcmp(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip))) {
if (spt->client_port == tp->udp.uh_sport) { if (spt->client_port == tp->udp.uh_sport) {
return k; return k;
@ -133,7 +124,7 @@ static int tftp_send_oack(struct tftp_session *spt,
struct tftp_t *tp; struct tftp_t *tp;
int n = 0; int n = 0;
m = m_get(); m = m_get(spt->slirp);
if (!m) if (!m)
return -1; return -1;
@ -172,7 +163,7 @@ static void tftp_send_error(struct tftp_session *spt,
struct tftp_t *tp; struct tftp_t *tp;
int nobytes; int nobytes;
m = m_get(); m = m_get(spt->slirp);
if (!m) { if (!m) {
goto out; goto out;
@ -218,7 +209,7 @@ static int tftp_send_data(struct tftp_session *spt,
return -1; return -1;
} }
m = m_get(); m = m_get(spt->slirp);
if (!m) { if (!m) {
return -1; return -1;
@ -266,23 +257,23 @@ static int tftp_send_data(struct tftp_session *spt,
return 0; 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; struct tftp_session *spt;
int s, k; int s, k;
size_t prefix_len; size_t prefix_len;
char *req_fname; char *req_fname;
s = tftp_session_allocate(tp); s = tftp_session_allocate(slirp, tp);
if (s < 0) { if (s < 0) {
return; return;
} }
spt = &tftp_sessions[s]; spt = &slirp->tftp_sessions[s];
/* unspecifed prefix means service disabled */ /* unspecifed prefix means service disabled */
if (!tftp_prefix) { if (!slirp->tftp_prefix) {
tftp_send_error(spt, 2, "Access violation", tp); tftp_send_error(spt, 2, "Access violation", tp);
return; 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); pktlen -= ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp);
/* prepend tftp_prefix */ /* prepend tftp_prefix */
prefix_len = strlen(tftp_prefix); prefix_len = strlen(slirp->tftp_prefix);
spt->filename = qemu_malloc(prefix_len + TFTP_FILENAME_MAX + 1); 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 */ /* get name */
req_fname = spt->filename + prefix_len; 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); 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; int s;
s = tftp_session_find(tp); s = tftp_session_find(slirp, tp);
if (s < 0) { if (s < 0) {
return; 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, ntohs(tp->x.tp_data.tp_block_nr) + 1,
tp) < 0) { tp) < 0) {
return; return;
@ -398,11 +389,11 @@ void tftp_input(struct mbuf *m)
switch(ntohs(tp->tp_op)) { switch(ntohs(tp->tp_op)) {
case TFTP_RRQ: case TFTP_RRQ:
tftp_handle_rrq(tp, m->m_len); tftp_handle_rrq(m->slirp, tp, m->m_len);
break; break;
case TFTP_ACK: case TFTP_ACK:
tftp_handle_ack(tp, m->m_len); tftp_handle_ack(m->slirp, tp, m->m_len);
break; break;
} }
} }

View File

@ -30,4 +30,14 @@ struct tftp_t {
} x; } 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); void tftp_input(struct mbuf *m);

View File

@ -41,17 +41,14 @@
#include <slirp.h> #include <slirp.h>
#include "ip_icmp.h" #include "ip_icmp.h"
struct socket udb;
static u_int8_t udp_tos(struct socket *so); static u_int8_t udp_tos(struct socket *so);
static void udp_emu(struct socket *so, struct mbuf *m); static void udp_emu(struct socket *so, struct mbuf *m);
struct socket *udp_last_so = &udb;
void 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_data points at ip packet header
* m->m_len length ip packet * m->m_len length ip packet
@ -60,6 +57,7 @@ udp_init(void)
void void
udp_input(register struct mbuf *m, int iphlen) udp_input(register struct mbuf *m, int iphlen)
{ {
Slirp *slirp = m->slirp;
register struct ip *ip; register struct ip *ip;
register struct udphdr *uh; register struct udphdr *uh;
int len; int len;
@ -128,8 +126,9 @@ udp_input(register struct mbuf *m, int iphlen)
goto bad; goto bad;
} }
if (slirp_restrict) if (slirp->restricted) {
goto bad; goto bad;
}
/* /*
* handle TFTP * handle TFTP
@ -142,22 +141,23 @@ udp_input(register struct mbuf *m, int iphlen)
/* /*
* Locate pcb for datagram. * Locate pcb for datagram.
*/ */
so = udp_last_so; so = slirp->udp_last_so;
if (so->so_lport != uh->uh_sport || if (so->so_lport != uh->uh_sport ||
so->so_laddr.s_addr != ip->ip_src.s_addr) { so->so_laddr.s_addr != ip->ip_src.s_addr) {
struct socket *tmp; 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 && if (tmp->so_lport == uh->uh_sport &&
tmp->so_laddr.s_addr == ip->ip_src.s_addr) { tmp->so_laddr.s_addr == ip->ip_src.s_addr) {
so = tmp; so = tmp;
break; break;
} }
} }
if (tmp == &udb) { if (tmp == &slirp->udb) {
so = NULL; so = NULL;
} else { } 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, * If there's no socket for this packet,
* create one * create one
*/ */
if ((so = socreate()) == NULL) goto bad; so = socreate(slirp);
if (!so) {
goto bad;
}
if(udp_attach(so) == -1) { if(udp_attach(so) == -1) {
DEBUG_MISC((dfd," udp_attach errno = %d-%s\n", DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",
errno,strerror(errno))); errno,strerror(errno)));
@ -279,15 +282,18 @@ int udp_output(struct socket *so, struct mbuf *m,
struct sockaddr_in *addr) struct sockaddr_in *addr)
{ {
Slirp *slirp = so->slirp;
struct sockaddr_in saddr, daddr; struct sockaddr_in saddr, daddr;
saddr = *addr; saddr = *addr;
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) ==
if ((so->so_faddr.s_addr & ~vnetwork_mask.s_addr) == slirp->vnetwork_addr.s_addr) {
~vnetwork_mask.s_addr) { uint32_t inv_mask = ~slirp->vnetwork_mask.s_addr;
saddr.sin_addr = vhost_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 || } 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; saddr.sin_addr = so->so_faddr;
} }
} }
@ -323,7 +329,7 @@ udp_attach(struct socket *so)
} else { } else {
/* success, insert in queue */ /* success, insert in queue */
so->so_expire = curtime + SO_EXPIRE; so->so_expire = curtime + SO_EXPIRE;
insque(so,&udb); insque(so, &so->slirp->udb);
} }
} }
return(so->s); return(so->s);
@ -595,20 +601,20 @@ struct cu_header {
} }
struct socket * struct socket *
udp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport, udp_listen(Slirp *slirp, u_int32_t haddr, u_int hport, u_int32_t laddr,
int flags) u_int lport, int flags)
{ {
struct sockaddr_in addr; struct sockaddr_in addr;
struct socket *so; struct socket *so;
socklen_t addrlen = sizeof(struct sockaddr_in), opt = 1; socklen_t addrlen = sizeof(struct sockaddr_in), opt = 1;
if ((so = socreate()) == NULL) { so = socreate(slirp);
free(so); if (!so) {
return NULL; return NULL;
} }
so->s = socket(AF_INET,SOCK_DGRAM,0); so->s = socket(AF_INET,SOCK_DGRAM,0);
so->so_expire = curtime + SO_EXPIRE; so->so_expire = curtime + SO_EXPIRE;
insque(so,&udb); insque(so, &slirp->udb);
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_addr.s_addr = haddr; 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; so->so_fport = addr.sin_port;
if (addr.sin_addr.s_addr == 0 || if (addr.sin_addr.s_addr == 0 ||
addr.sin_addr.s_addr == loopback_addr.s_addr) { addr.sin_addr.s_addr == loopback_addr.s_addr) {
so->so_faddr = vhost_addr; so->so_faddr = slirp->vhost_addr;
} else { } else {
so->so_faddr = addr.sin_addr; so->so_faddr = addr.sin_addr;
} }

View File

@ -36,8 +36,6 @@
#define UDP_TTL 0x60 #define UDP_TTL 0x60
#define UDP_UDPDATALEN 16192 #define UDP_UDPDATALEN 16192
extern struct socket *udp_last_so;
/* /*
* Udp protocol header. * Udp protocol header.
* Per RFC 768, September, 1981. * Per RFC 768, September, 1981.
@ -73,15 +71,15 @@ struct udpiphdr {
#define UDPCTL_CHECKSUM 1 /* checksum UDP packets */ #define UDPCTL_CHECKSUM 1 /* checksum UDP packets */
#define UDPCTL_MAXID 2 #define UDPCTL_MAXID 2
extern struct socket udb;
struct mbuf; struct mbuf;
void udp_init _P((void)); void udp_init _P((Slirp *));
void udp_input _P((register struct mbuf *, int)); void udp_input _P((register struct mbuf *, int));
int udp_output _P((struct socket *, struct mbuf *, struct sockaddr_in *)); int udp_output _P((struct socket *, struct mbuf *, struct sockaddr_in *));
int udp_attach _P((struct socket *)); int udp_attach _P((struct socket *));
void udp_detach _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, int udp_output2(struct socket *so, struct mbuf *m,
struct sockaddr_in *saddr, struct sockaddr_in *daddr, struct sockaddr_in *saddr, struct sockaddr_in *daddr,
int iptos); int iptos);