aboutsummaryrefslogtreecommitdiffstats
path: root/slirp
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commit55f4e4a5ec657a017e3bf75299ad71fd1c968dd3 (patch)
tree550ce922ea0e125ac6a9738210ce2939bf2fe901 /slirp
parent413f05aaf54fa08c0ae7e997327a4f4a473c0a8d (diff)
downloadexternal_qemu-55f4e4a5ec657a017e3bf75299ad71fd1c968dd3.zip
external_qemu-55f4e4a5ec657a017e3bf75299ad71fd1c968dd3.tar.gz
external_qemu-55f4e4a5ec657a017e3bf75299ad71fd1c968dd3.tar.bz2
Initial Contribution
Diffstat (limited to 'slirp')
-rw-r--r--slirp/bootp.c13
-rw-r--r--slirp/bootp.h2
-rw-r--r--slirp/cksum.c4
-rw-r--r--slirp/ctl.h3
-rw-r--r--slirp/debug.c26
-rw-r--r--slirp/if.c12
-rw-r--r--slirp/if.h2
-rw-r--r--slirp/ip_icmp.c83
-rw-r--r--slirp/ip_icmp.h6
-rw-r--r--slirp/ip_input.c54
-rw-r--r--slirp/ip_output.c20
-rw-r--r--slirp/libslirp.h12
-rw-r--r--slirp/main.h9
-rw-r--r--slirp/mbuf.c195
-rw-r--r--slirp/mbuf.h130
-rw-r--r--slirp/misc.c724
-rw-r--r--slirp/misc.h25
-rw-r--r--slirp/sbuf.c91
-rw-r--r--slirp/sbuf.h40
-rw-r--r--slirp/slirp.c540
-rw-r--r--slirp/slirp.h18
-rw-r--r--slirp/socket.c245
-rw-r--r--slirp/socket.h27
-rw-r--r--slirp/tcp.h4
-rw-r--r--slirp/tcp_input.c270
-rw-r--r--slirp/tcp_output.c16
-rw-r--r--slirp/tcp_subr.c680
-rw-r--r--slirp/tcp_timer.c4
-rw-r--r--slirp/tcp_var.h5
-rw-r--r--slirp/tftp.c149
-rw-r--r--slirp/tftp.h3
-rw-r--r--slirp/udp.c204
-rw-r--r--slirp/udp.h9
33 files changed, 1417 insertions, 2208 deletions
diff --git a/slirp/bootp.c b/slirp/bootp.c
index 62cbcfd..79f5f9f 100644
--- a/slirp/bootp.c
+++ b/slirp/bootp.c
@@ -38,6 +38,8 @@ typedef struct {
BOOTPClient bootp_clients[NB_ADDR];
+const char *bootp_filename;
+
static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
#ifdef DEBUG
@@ -125,7 +127,7 @@ static void dhcp_decode(const uint8_t *buf, int size,
static void bootp_reply(struct bootp_t *bp)
{
BOOTPClient *bc;
- struct mbuf *m;
+ MBuf m;
struct bootp_t *rbp;
struct sockaddr_in saddr, daddr;
struct in_addr dns_addr;
@@ -145,7 +147,7 @@ static void bootp_reply(struct bootp_t *bp)
/* XXX: this is a hack to get the client mac address */
memcpy(client_ethaddr, bp->bp_hwaddr, 6);
- if ((m = m_get()) == NULL)
+ if ((m = mbuf_alloc()) == NULL)
return;
m->m_data += if_maxlinkhdr;
rbp = (struct bootp_t *)m->m_data;
@@ -168,6 +170,9 @@ static void bootp_reply(struct bootp_t *bp)
goto new_addr;
}
}
+ if (bootp_filename)
+ snprintf((char*)rbp->bp_file, sizeof(rbp->bp_file), "%s", bootp_filename);
+
dprintf("offered addr=%08x\n", ntohl(daddr.sin_addr.s_addr));
saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS);
@@ -244,9 +249,9 @@ static void bootp_reply(struct bootp_t *bp)
udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
}
-void bootp_input(struct mbuf *m)
+void bootp_input(MBuf m)
{
- struct bootp_t *bp = mtod(m, struct bootp_t *);
+ struct bootp_t *bp = MBUF_TO(m, struct bootp_t *);
if (bp->bp_op == BOOTP_REQUEST) {
bootp_reply(bp);
diff --git a/slirp/bootp.h b/slirp/bootp.h
index e48f53f..1fb42fa 100644
--- a/slirp/bootp.h
+++ b/slirp/bootp.h
@@ -110,4 +110,4 @@ struct bootp_t {
uint8_t bp_vend[DHCP_OPT_LEN];
};
-void bootp_input(struct mbuf *m);
+void bootp_input(MBuf m);
diff --git a/slirp/cksum.c b/slirp/cksum.c
index f8f7512..9474b9e 100644
--- a/slirp/cksum.c
+++ b/slirp/cksum.c
@@ -48,7 +48,7 @@
#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
-int cksum(struct mbuf *m, int len)
+int cksum(MBuf m, int len)
{
register u_int16_t *w;
register int sum = 0;
@@ -66,7 +66,7 @@ int cksum(struct mbuf *m, int len)
if (m->m_len == 0)
goto cont;
- w = mtod(m, u_int16_t *);
+ w = MBUF_TO(m, u_int16_t *);
mlen = m->m_len;
diff --git a/slirp/ctl.h b/slirp/ctl.h
index 4a8576d..854ae9a 100644
--- a/slirp/ctl.h
+++ b/slirp/ctl.h
@@ -2,6 +2,9 @@
#define CTL_EXEC 1
#define CTL_ALIAS 2
#define CTL_DNS 3
+/* NOTE: DNS_ADDR_MAX addresses, starting from CTL_DNS, are reserved */
+
+#define CTL_IS_DNS(x) ((unsigned)((x)-CTL_DNS) < (unsigned)dns_addr_count)
#define CTL_SPECIAL "10.0.2.0"
#define CTL_LOCAL "10.0.2.15"
diff --git a/slirp/debug.c b/slirp/debug.c
index d3d8c57..a46626b 100644
--- a/slirp/debug.c
+++ b/slirp/debug.c
@@ -42,7 +42,7 @@ debug_init(file, dbg)
fflush(dfd);
slirp_debug = dbg;
} else {
- lprint("Error: Debugging file \"%s\" could not be opened: %s\r\n",
+ fprintf(stderr, "Error: Debugging file \"%s\" could not be opened: %s\r\n",
file, strerror(errno));
}
}
@@ -268,30 +268,6 @@ icmpstats()
}
void
-mbufstats()
-{
- struct mbuf *m;
- int i;
-
- lprint(" \r\n");
-
- lprint("Mbuf stats:\r\n");
-
- lprint(" %6d mbufs allocated (%d max)\r\n", mbuf_alloced, mbuf_max);
-
- i = 0;
- for (m = m_freelist.m_next; m != &m_freelist; m = m->m_next)
- i++;
- lprint(" %6d mbufs on free list\r\n", i);
-
- i = 0;
- for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next)
- i++;
- lprint(" %6d mbufs on used list\r\n", i);
- lprint(" %6d mbufs queued as packets\r\n\r\n", if_queued);
-}
-
-void
sockstats()
{
char buff[256];
diff --git a/slirp/if.c b/slirp/if.c
index 94132ca..b589c42 100644
--- a/slirp/if.c
+++ b/slirp/if.c
@@ -22,7 +22,7 @@ struct mbuf *next_m; /* Pointer to next mbuf to output */
void
ifs_insque(ifm, ifmhead)
- struct mbuf *ifm, *ifmhead;
+ MBuf ifm, ifmhead;
{
ifm->ifs_next = ifmhead->ifs_next;
ifmhead->ifs_next = ifm;
@@ -32,7 +32,7 @@ ifs_insque(ifm, ifmhead)
void
ifs_remque(ifm)
- struct mbuf *ifm;
+ MBuf ifm;
{
ifm->ifs_prev->ifs_next = ifm->ifs_next;
ifm->ifs_next->ifs_prev = ifm->ifs_prev;
@@ -159,9 +159,9 @@ if_input(ttyp)
void
if_output(so, ifm)
struct socket *so;
- struct mbuf *ifm;
+ MBuf ifm;
{
- struct mbuf *ifq;
+ MBuf ifq;
int on_fastq = 1;
DEBUG_CALL("if_output");
@@ -266,7 +266,7 @@ diddit:
void
if_start(void)
{
- struct mbuf *ifm, *ifqt;
+ MBuf ifm, *ifqt;
DEBUG_CALL("if_start");
@@ -315,7 +315,7 @@ if_start(void)
/* Encapsulate the packet for sending */
if_encap(ifm->m_data, ifm->m_len);
- m_free(ifm);
+ mbuf_free(ifm);
if (if_queued)
goto again;
diff --git a/slirp/if.h b/slirp/if.h
index 5d96a90..f22f161 100644
--- a/slirp/if.h
+++ b/slirp/if.h
@@ -25,7 +25,7 @@ extern int if_thresh; /* Number of packets queued before we start sending
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;
+extern MBuf next_m;
#define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c
index b67a373..2d50629 100644
--- a/slirp/ip_icmp.c
+++ b/slirp/ip_icmp.c
@@ -63,7 +63,7 @@ static int icmp_flush[19] = {
/* INFO (15) */ 0,
/* INFO REPLY (16) */ 0,
/* ADDR MASK (17) */ 0,
-/* ADDR MASK REPLY (18) */ 0
+/* ADDR MASK REPLY (18) */ 0
};
/*
@@ -71,20 +71,20 @@ static int icmp_flush[19] = {
*/
void
icmp_input(m, hlen)
- struct mbuf *m;
+ MBuf m;
int hlen;
{
register struct icmp *icp;
- register struct ip *ip=mtod(m, struct ip *);
+ register struct ip *ip=MBUF_TO(m, struct ip *);
int icmplen=ip->ip_len;
/* int code; */
-
+
DEBUG_CALL("icmp_input");
DEBUG_ARG("m = %lx", (long )m);
DEBUG_ARG("m_len = %d", m->m_len);
icmpstat.icps_received++;
-
+
/*
* Locate icmp structure in mbuf, and check
* that its not corrupted and of at least minimum length.
@@ -92,20 +92,20 @@ icmp_input(m, hlen)
if (icmplen < ICMP_MINLEN) { /* min 8 bytes payload */
icmpstat.icps_tooshort++;
freeit:
- m_freem(m);
+ mbuf_free(m);
goto end_error;
}
m->m_len -= hlen;
m->m_data += hlen;
- icp = mtod(m, struct icmp *);
+ icp = MBUF_TO(m, struct icmp *);
if (cksum(m, icmplen)) {
icmpstat.icps_checksum++;
goto freeit;
}
m->m_len += hlen;
m->m_data -= hlen;
-
+
/* icmpstat.icps_inhist[icp->icmp_type]++; */
/* code = icp->icmp_code; */
@@ -121,10 +121,10 @@ icmp_input(m, hlen)
struct sockaddr_in addr;
if ((so = socreate()) == NULL) goto freeit;
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)));
sofree(so);
- m_free(m);
+ mbuf_free(m);
goto end_error;
}
so->so_m = m;
@@ -135,20 +135,17 @@ icmp_input(m, hlen)
so->so_iptos = ip->ip_tos;
so->so_type = IPPROTO_ICMP;
so->so_state = SS_ISFCONNECTED;
-
+
/* Send the packet */
addr.sin_family = AF_INET;
if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
/* It's an alias */
- switch(ntohl(so->so_faddr.s_addr) & 0xff) {
- case CTL_DNS:
- addr.sin_addr = dns_addr;
- break;
- case CTL_ALIAS:
- default:
- addr.sin_addr = loopback_addr;
- break;
- }
+ int low = ntohl(so->so_faddr.s_addr) & 0xff;
+
+ if (low >= CTL_DNS && low < CTL_DNS + dns_addr_count)
+ addr.sin_addr = dns_addr[low - CTL_DNS];
+ else
+ addr.sin_addr = loopback_addr;
} else {
addr.sin_addr = so->so_faddr;
}
@@ -157,7 +154,7 @@ icmp_input(m, hlen)
(struct sockaddr *)&addr, sizeof(addr)) == -1) {
DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n",
errno,strerror(errno)));
- icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
+ icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
udp_detach(so);
}
} /* if ip->ip_dst.s_addr == alias_addr.s_addr */
@@ -171,16 +168,16 @@ icmp_input(m, hlen)
case ICMP_MASKREQ:
case ICMP_REDIRECT:
icmpstat.icps_notsupp++;
- m_freem(m);
+ mbuf_free(m);
break;
-
+
default:
icmpstat.icps_badtype++;
- m_freem(m);
+ mbuf_free(m);
} /* swith */
end_error:
- /* m is m_free()'d xor put in a socket xor or given to ip_send */
+ /* m is mbuf_free()'d xor put in a socket xor or given to ip_send */
return;
}
@@ -196,17 +193,17 @@ end_error:
*/
/*
* Send ICMP_UNREACH back to the source regarding msrc.
- * mbuf *msrc is used as a template, but is NOT m_free()'d.
+ * mbuf *msrc is used as a template, but is NOT mbuf_free()'d.
* It is reported as the bad ip packet. The header should
* be fully correct and in host byte order.
- * ICMP fragmentation is illegal. All machines must accept 576 bytes in one
+ * ICMP fragmentation is illegal. All machines must accept 576 bytes in one
* packet. The maximum payload is 576-20(ip hdr)-8(icmp hdr)=548
*/
#define ICMP_MAXDATALEN (IP_MSS-28)
void
icmp_error(msrc, type, code, minsize, message)
- struct mbuf *msrc;
+ MBuf msrc;
u_char type;
u_char code;
int minsize;
@@ -215,7 +212,7 @@ icmp_error(msrc, type, code, minsize, message)
unsigned hlen, shlen, s_ip_len;
register struct ip *ip;
register struct icmp *icp;
- register struct mbuf *m;
+ register MBuf m;
DEBUG_CALL("icmp_error");
DEBUG_ARG("msrc = %lx", (long )msrc);
@@ -225,8 +222,8 @@ icmp_error(msrc, type, code, minsize, message)
/* check msrc */
if(!msrc) goto end_error;
- ip = mtod(msrc, struct ip *);
-#if DEBUG
+ ip = MBUF_TO(msrc, struct ip *);
+#if DEBUG
{ char bufa[20], bufb[20];
strcpy(bufa, inet_ntoa(ip->ip_src));
strcpy(bufb, inet_ntoa(ip->ip_dst));
@@ -247,29 +244,29 @@ icmp_error(msrc, type, code, minsize, message)
}
/* make a copy */
- if(!(m=m_get())) goto end_error; /* get mbuf */
+ if(!(m=mbuf_alloc())) goto end_error; /* get mbuf */
{ int new_m_size;
new_m_size=sizeof(struct ip )+ICMP_MINLEN+msrc->m_len+ICMP_MAXDATALEN;
- if(new_m_size>m->m_size) m_inc(m, new_m_size);
+ if(new_m_size>m->m_size) mbuf_ensure(m, new_m_size);
}
memcpy(m->m_data, msrc->m_data, msrc->m_len);
m->m_len = msrc->m_len; /* copy msrc to m */
/* make the header of the reply packet */
- ip = mtod(m, struct ip *);
+ ip = MBUF_TO(m, struct ip *);
hlen= sizeof(struct ip ); /* no options in reply */
-
+
/* fill in icmp */
- m->m_data += hlen;
+ m->m_data += hlen;
m->m_len -= hlen;
- icp = mtod(m, struct icmp *);
+ icp = MBUF_TO(m, struct icmp *);
if(minsize) s_ip_len=shlen+ICMP_MINLEN; /* return header+8b only */
else if(s_ip_len>ICMP_MAXDATALEN) /* maximum size */
s_ip_len=ICMP_MAXDATALEN;
- m->m_len=ICMP_MINLEN+s_ip_len; /* 8 bytes ICMP header */
+ m->m_len=ICMP_MINLEN+s_ip_len; /* 8 bytes ICMP header */
/* min. size = 8+sizeof(struct ip)+8 */
@@ -304,7 +301,7 @@ icmp_error(msrc, type, code, minsize, message)
/* fill in ip */
ip->ip_hl = hlen >> 2;
ip->ip_len = m->m_len;
-
+
ip->ip_tos=((ip->ip_tos & 0x1E) | 0xC0); /* high priority for errors */
ip->ip_ttl = MAXTTL;
@@ -313,7 +310,7 @@ icmp_error(msrc, type, code, minsize, message)
ip->ip_src = alias_addr;
(void ) ip_output((struct socket *)NULL, m);
-
+
icmpstat.icps_reflect++;
end_error:
@@ -326,9 +323,9 @@ end_error:
*/
void
icmp_reflect(m)
- struct mbuf *m;
+ MBuf m;
{
- register struct ip *ip = mtod(m, struct ip *);
+ register struct ip *ip = MBUF_TO(m, struct ip *);
int hlen = ip->ip_hl << 2;
int optlen = hlen - sizeof(struct ip );
register struct icmp *icp;
@@ -339,7 +336,7 @@ icmp_reflect(m)
*/
m->m_data += hlen;
m->m_len -= hlen;
- icp = mtod(m, struct icmp *);
+ icp = MBUF_TO(m, struct icmp *);
icp->icmp_cksum = 0;
icp->icmp_cksum = cksum(m, ip->ip_len - hlen);
diff --git a/slirp/ip_icmp.h b/slirp/ip_icmp.h
index 8c9b5a1..42740db 100644
--- a/slirp/ip_icmp.h
+++ b/slirp/ip_icmp.h
@@ -157,8 +157,8 @@ struct icmp {
(type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \
(type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
-void icmp_input _P((struct mbuf *, int));
-void icmp_error _P((struct mbuf *, u_char, u_char, int, char *));
-void icmp_reflect _P((struct mbuf *));
+void icmp_input _P((MBuf , int));
+void icmp_error _P((MBuf , u_char, u_char, int, char *));
+void icmp_reflect _P((MBuf ));
#endif
diff --git a/slirp/ip_input.c b/slirp/ip_input.c
index 4f5bfd9..cc320de 100644
--- a/slirp/ip_input.c
+++ b/slirp/ip_input.c
@@ -69,7 +69,7 @@ ip_init()
*/
void
ip_input(m)
- struct mbuf *m;
+ MBuf m;
{
register struct ip *ip;
int hlen;
@@ -85,7 +85,7 @@ ip_input(m)
return;
}
- ip = mtod(m, struct ip *);
+ ip = MBUF_TO(m, struct ip *);
if (ip->ip_v != IPVERSION) {
ipstat.ips_badvers++;
@@ -130,7 +130,7 @@ ip_input(m)
}
/* Should drop packet if mbuf too long? hmmm... */
if (m->m_len > ip->ip_len)
- m_adj(m, ip->ip_len - m->m_len);
+ mbuf_trim(m, ip->ip_len - m->m_len);
/* check ip_ttl for a correct ICMP reply */
if(ip->ip_ttl==0 || ip->ip_ttl==1) {
@@ -197,7 +197,7 @@ ip_input(m)
if (ip == 0)
return;
ipstat.ips_reassembled++;
- m = dtom(ip);
+ m = MBUF_FROM(ip);
} else
if (fp)
ip_freef(fp);
@@ -221,11 +221,11 @@ ip_input(m)
break;
default:
ipstat.ips_noproto++;
- m_free(m);
+ mbuf_free(m);
}
return;
bad:
- m_freem(m);
+ mbuf_free(m);
return;
}
@@ -240,7 +240,7 @@ ip_reass(ip, fp)
register struct ipasfrag *ip;
register struct ipq *fp;
{
- register struct mbuf *m = dtom(ip);
+ register MBuf m = MBUF_FROM(ip);
register struct ipasfrag *q;
int hlen = ip->ip_hl << 2;
int i, next;
@@ -262,9 +262,9 @@ ip_reass(ip, fp)
* If first fragment to arrive, create a reassembly queue.
*/
if (fp == 0) {
- struct mbuf *t;
- if ((t = m_get()) == NULL) goto dropfrag;
- fp = mtod(t, struct ipq *);
+ MBuf t;
+ if ((t = mbuf_alloc()) == NULL) goto dropfrag;
+ fp = MBUF_TO(t, struct ipq *);
insque_32(fp, &ipq);
fp->ipq_ttl = IPFRAGTTL;
fp->ipq_p = ip->ip_p;
@@ -295,7 +295,7 @@ ip_reass(ip, fp)
if (i > 0) {
if (i >= ip->ip_len)
goto dropfrag;
- m_adj(dtom(ip), i);
+ mbuf_trim(MBUF_FROM(ip), i);
ip->ip_off += i;
ip->ip_len -= i;
}
@@ -310,11 +310,11 @@ ip_reass(ip, fp)
if (i < q->ip_len) {
q->ip_len -= i;
q->ip_off += i;
- m_adj(dtom(q), i);
+ mbuf_trim(MBUF_FROM(q), i);
break;
}
q = (struct ipasfrag *) q->ipf_next;
- m_freem(dtom((struct ipasfrag *) q->ipf_prev));
+ mbuf_free(MBUF_FROM((struct ipasfrag *) q->ipf_prev));
ip_deq((struct ipasfrag *) q->ipf_prev);
}
@@ -338,14 +338,14 @@ insert:
* Reassembly is complete; concatenate fragments.
*/
q = (struct ipasfrag *) fp->ipq_next;
- m = dtom(q);
+ m = MBUF_FROM(q);
q = (struct ipasfrag *) q->ipf_next;
while (q != (struct ipasfrag *)fp) {
- struct mbuf *t;
- t = dtom(q);
+ MBuf t;
+ t = MBUF_FROM(q);
q = (struct ipasfrag *) q->ipf_next;
- m_cat(m, t);
+ mbuf_append(m, t);
}
/*
@@ -377,8 +377,8 @@ insert:
((struct ip *)ip)->ip_src = fp->ipq_src;
((struct ip *)ip)->ip_dst = fp->ipq_dst;
remque_32(fp);
- (void) m_free(dtom(fp));
- m = dtom(ip);
+ (void) mbuf_free(MBUF_FROM(fp));
+ m = MBUF_FROM(ip);
m->m_len += (ip->ip_hl << 2);
m->m_data -= (ip->ip_hl << 2);
@@ -386,7 +386,7 @@ insert:
dropfrag:
ipstat.ips_fragdropped++;
- m_freem(m);
+ mbuf_free(m);
return (0);
}
@@ -404,10 +404,10 @@ ip_freef(fp)
q = p) {
p = (struct ipasfrag *) q->ipf_next;
ip_deq(q);
- m_freem(dtom(q));
+ mbuf_free(MBUF_FROM(q));
}
remque_32(fp);
- (void) m_free(dtom(fp));
+ (void) mbuf_free(MBUF_FROM(fp));
}
/*
@@ -475,9 +475,9 @@ ip_slowtimo()
int
ip_dooptions(m)
- struct mbuf *m;
+ MBuf m;
{
- register struct ip *ip = mtod(m, struct ip *);
+ register struct ip *ip = MBUF_TO(m, struct ip *);
register u_char *cp;
register struct ip_timestamp *ipt;
register struct in_ifaddr *ia;
@@ -679,11 +679,11 @@ bad:
*/
void
ip_stripoptions(m, mopt)
- register struct mbuf *m;
- struct mbuf *mopt;
+ register MBuf m;
+ MBuf mopt;
{
register int i;
- struct ip *ip = mtod(m, struct ip *);
+ struct ip *ip = MBUF_TO(m, struct ip *);
register caddr_t opts;
int olen;
diff --git a/slirp/ip_output.c b/slirp/ip_output.c
index f3dc9b7..42d789c 100644
--- a/slirp/ip_output.c
+++ b/slirp/ip_output.c
@@ -55,10 +55,10 @@ u_int16_t ip_id;
int
ip_output(so, m0)
struct socket *so;
- struct mbuf *m0;
+ MBuf m0;
{
register struct ip *ip;
- register struct mbuf *m = m0;
+ register MBuf m = m0;
register int hlen = sizeof(struct ip );
int len, off, error = 0;
@@ -72,7 +72,7 @@ ip_output(so, m0)
* hlen = len;
* }
*/
- ip = mtod(m, struct ip *);
+ ip = MBUF_TO(m, struct ip *);
/*
* Fill in IP header.
*/
@@ -124,7 +124,7 @@ ip_output(so, m0)
{
int mhlen, firstlen = len;
- struct mbuf **mnext = &m->m_nextpkt;
+ MBuf *mnext = &m->m_nextpkt;
/*
* Loop through length of segment after first fragment,
@@ -134,14 +134,14 @@ ip_output(so, m0)
mhlen = sizeof (struct ip);
for (off = hlen + len; off < (u_int16_t)ip->ip_len; off += len) {
register struct ip *mhip;
- m = m_get();
+ m = mbuf_alloc();
if (m == 0) {
error = -1;
ipstat.ips_odropped++;
goto sendorfree;
}
m->m_data += if_maxlinkhdr;
- mhip = mtod(m, struct ip *);
+ mhip = MBUF_TO(m, struct ip *);
*mhip = *ip;
/* No options */
@@ -160,7 +160,7 @@ ip_output(so, m0)
mhip->ip_off |= IP_MF;
mhip->ip_len = htons((u_int16_t)(len + mhlen));
- if (m_copy(m, m0, off, len) < 0) {
+ if (mbuf_copy(m, m0, off, len) < 0) {
error = -1;
goto sendorfree;
}
@@ -177,7 +177,7 @@ ip_output(so, m0)
* and updating header, then send each fragment (in order).
*/
m = m0;
- m_adj(m, hlen + firstlen - (u_int16_t)ip->ip_len);
+ mbuf_trim(m, hlen + firstlen - (u_int16_t)ip->ip_len);
ip->ip_len = htons((u_int16_t)m->m_len);
ip->ip_off = htons((u_int16_t)(ip->ip_off | IP_MF));
ip->ip_sum = 0;
@@ -189,7 +189,7 @@ sendorfree:
if (error == 0)
if_output(so, m);
else
- m_freem(m);
+ mbuf_free(m);
}
if (error == 0)
@@ -200,6 +200,6 @@ done:
return (error);
bad:
- m_freem(m0);
+ mbuf_free(m0);
goto done;
}
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index a9260af..3ce34b7 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -1,6 +1,7 @@
#ifndef _LIBSLIRP_H
#define _LIBSLIRP_H
+#include <stdint.h>
#ifdef _WIN32
#include <winsock2.h>
int inet_aton(const char *cp, struct in_addr *ia);
@@ -15,7 +16,7 @@ extern "C" {
void slirp_init(void);
-void slirp_select_fill(int *pnfds,
+void slirp_select_fill(int *pnfds,
fd_set *readfds, fd_set *writefds, fd_set *xfds);
void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds);
@@ -26,10 +27,13 @@ void slirp_input(const uint8_t *pkt, int pkt_len);
int slirp_can_output(void);
void slirp_output(const uint8_t *pkt, int pkt_len);
-int slirp_redir(int is_udp, int host_port,
+int slirp_redir(int is_udp, int host_port,
struct in_addr guest_addr, int guest_port);
-int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
- int guest_port);
+
+int slirp_unredir(int is_udp, int host_port);
+
+int slirp_add_dns_server(struct in_addr dns_addr);
+int slirp_get_system_dns_servers(void);
extern const char *tftp_prefix;
extern char slirp_hostname[33];
diff --git a/slirp/main.h b/slirp/main.h
index 181b6ae..49dad00 100644
--- a/slirp/main.h
+++ b/slirp/main.h
@@ -1,7 +1,7 @@
/*
* Copyright (c) 1995 Danny Gasparovski.
- *
- * Please read the file COPYRIGHT for the
+ *
+ * Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
@@ -28,6 +28,8 @@ extern int ctty_closed;
*/
#define TIME_DIFF(x,y) (x)-(y) < 0 ? ~0-(y)+(x) : (x)-(y)
+#define DNS_ADDR_MAX 4
+
extern char *slirp_tty;
extern char *exec_shell;
extern u_int curtime;
@@ -37,7 +39,8 @@ extern struct in_addr special_addr;
extern struct in_addr alias_addr;
extern struct in_addr our_addr;
extern struct in_addr loopback_addr;
-extern struct in_addr dns_addr;
+extern struct in_addr dns_addr[DNS_ADDR_MAX];
+extern int dns_addr_count;
extern char *username;
extern char *socket_path;
extern int towrite_max;
diff --git a/slirp/mbuf.c b/slirp/mbuf.c
index 3769baf..efc8141 100644
--- a/slirp/mbuf.c
+++ b/slirp/mbuf.c
@@ -17,16 +17,28 @@
#include <slirp.h>
-struct mbuf *mbutl;
-char *mclrefcnt;
-int mbuf_alloced = 0;
-struct mbuf m_freelist, m_usedlist;
-int mbuf_thresh = 30;
-int mbuf_max = 0;
-int msize;
+static int mbuf_alloced = 0;
+static MBufRec m_freelist, m_usedlist;
+static int mbuf_thresh = 30;
+static int mbuf_max = 0;
+static int msize;
+
+/*
+ * How much room is in the mbuf, from m_data to the end of the mbuf
+ */
+#define M_ROOM(m) ((m->m_flags & M_EXT)? \
+ (((m)->m_ext + (m)->m_size) - (m)->m_data) \
+ : \
+ (((m)->m_dat + (m)->m_size) - (m)->m_data))
+
+/*
+ * How much free room there is
+ */
+#define M_FREEROOM(m) (M_ROOM(m) - (m)->m_len)
+
void
-m_init()
+mbuf_init()
{
m_freelist.m_next = m_freelist.m_prev = &m_freelist;
m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist;
@@ -40,10 +52,27 @@ msize_init()
* Find a nice value for msize
* XXX if_maxlinkhdr already in mtu
*/
- msize = (if_mtu>if_mru?if_mtu:if_mru) +
+ msize = (if_mtu > if_mru ? if_mtu : if_mru) +
if_maxlinkhdr + sizeof(struct m_hdr ) + 6;
}
+static void
+mbuf_insque(MBuf m, MBuf head)
+{
+ m->m_next = head->m_next;
+ m->m_prev = head;
+ head->m_next = m;
+ m->m_next->m_prev = m;
+}
+
+static void
+mbuf_remque(MBuf m)
+{
+ m->m_prev->m_next = m->m_next;
+ m->m_next->m_prev = m->m_prev;
+ m->m_next = m->m_prev = m;
+}
+
/*
* Get an mbuf from the free list, if there are none
* malloc one
@@ -52,16 +81,16 @@ msize_init()
* free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE,
* which tells m_free to actually free() it
*/
-struct mbuf *
-m_get()
+MBuf
+mbuf_alloc(void)
{
- register struct mbuf *m;
+ register MBuf m;
int flags = 0;
- DEBUG_CALL("m_get");
+ DEBUG_CALL("mbuf_alloc");
if (m_freelist.m_next == &m_freelist) {
- m = (struct mbuf *)malloc(msize);
+ m = (MBuf) malloc(msize);
if (m == NULL) goto end_error;
mbuf_alloced++;
if (mbuf_alloced > mbuf_thresh)
@@ -70,36 +99,35 @@ m_get()
mbuf_max = mbuf_alloced;
} else {
m = m_freelist.m_next;
- remque(m);
+ mbuf_remque(m);
}
/* Insert it in the used list */
- insque(m,&m_usedlist);
+ mbuf_insque(m,&m_usedlist);
m->m_flags = (flags | M_USEDLIST);
/* Initialise it */
- m->m_size = msize - sizeof(struct m_hdr);
- m->m_data = m->m_dat;
- m->m_len = 0;
- m->m_nextpkt = 0;
- m->m_prevpkt = 0;
+ m->m_size = msize - sizeof(struct m_hdr);
+ m->m_data = m->m_dat;
+ m->m_len = 0;
+ m->m_next2 = NULL;
+ m->m_prev2 = NULL;
end_error:
DEBUG_ARG("m = %lx", (long )m);
return m;
}
void
-m_free(m)
- struct mbuf *m;
+mbuf_free(MBuf m)
{
- DEBUG_CALL("m_free");
+ DEBUG_CALL("mbuf_free");
DEBUG_ARG("m = %lx", (long )m);
if(m) {
/* Remove from m_usedlist */
if (m->m_flags & M_USEDLIST)
- remque(m);
+ mbuf_remque(m);
/* If it's M_EXT, free() it */
if (m->m_flags & M_EXT)
@@ -112,7 +140,7 @@ m_free(m)
free(m);
mbuf_alloced--;
} else if ((m->m_flags & M_FREELIST) == 0) {
- insque(m,&m_freelist);
+ mbuf_insque(m,&m_freelist);
m->m_flags = M_FREELIST; /* Clobber other flags */
}
} /* if(m) */
@@ -124,74 +152,62 @@ m_free(m)
* an M_EXT data segment
*/
void
-m_cat(m, n)
- register struct mbuf *m, *n;
+mbuf_append(MBuf m, MBuf n)
{
/*
* If there's no room, realloc
*/
if (M_FREEROOM(m) < n->m_len)
- m_inc(m,m->m_size+MINCSIZE);
+ mbuf_ensure(m, m->m_size+MINCSIZE);
memcpy(m->m_data+m->m_len, n->m_data, n->m_len);
m->m_len += n->m_len;
- m_free(n);
+ mbuf_free(n);
}
/* make m size bytes large */
void
-m_inc(m, size)
- struct mbuf *m;
- int size;
+mbuf_ensure(MBuf m, int size)
{
int datasize;
/* some compiles throw up on gotos. This one we can fake. */
- if(m->m_size>size) return;
-
- if (m->m_flags & M_EXT) {
- datasize = m->m_data - m->m_ext;
- m->m_ext = (char *)realloc(m->m_ext,size);
-/* if (m->m_ext == NULL)
- * return (struct mbuf *)NULL;
- */
- m->m_data = m->m_ext + datasize;
- } else {
- char *dat;
- datasize = m->m_data - m->m_dat;
- dat = (char *)malloc(size);
-/* if (dat == NULL)
- * return (struct mbuf *)NULL;
- */
- memcpy(dat, m->m_dat, m->m_size);
-
- m->m_ext = dat;
- m->m_data = m->m_ext + datasize;
- m->m_flags |= M_EXT;
- }
-
- m->m_size = size;
+ if(m->m_size > size) return;
+
+ if (m->m_flags & M_EXT) {
+ datasize = m->m_data - m->m_ext;
+ m->m_ext = (char *)realloc(m->m_ext,size);
+ m->m_data = m->m_ext + datasize;
+ } else {
+ char *dat;
+ datasize = m->m_data - m->m_dat;
+ dat = (char *)malloc(size);
+ memcpy(dat, m->m_dat, m->m_size);
+ m->m_ext = dat;
+ m->m_data = m->m_ext + datasize;
+ m->m_flags |= M_EXT;
+ }
+
+ m->m_size = size;
}
void
-m_adj(m, len)
- struct mbuf *m;
- int len;
+mbuf_trim(MBuf m, int len)
{
if (m == NULL)
return;
if (len >= 0) {
/* Trim from head */
m->m_data += len;
- m->m_len -= len;
+ m->m_len -= len;
} else {
/* Trim from tail */
- len = -len;
+ len = -len;
m->m_len -= len;
}
}
@@ -201,9 +217,7 @@ m_adj(m, len)
* Copy len bytes from m, starting off bytes into n
*/
int
-m_copy(n, m, off, len)
- struct mbuf *n, *m;
- int off, len;
+mbuf_copy(MBuf n, MBuf m, int off, int len)
{
if (len > M_FREEROOM(n))
return -1;
@@ -213,34 +227,61 @@ m_copy(n, m, off, len)
return 0;
}
+int
+mbuf_freeroom( MBuf m )
+{
+ return M_FREEROOM(m);
+}
/*
* Given a pointer into an mbuf, return the mbuf
* XXX This is a kludge, I should eliminate the need for it
* Fortunately, it's not used often
*/
-struct mbuf *
-dtom(dat)
- void *dat;
+MBuf
+mbuf_from(void* dat)
{
- struct mbuf *m;
+ MBuf m;
- DEBUG_CALL("dtom");
+ DEBUG_CALL("mbuf_from");
DEBUG_ARG("dat = %lx", (long )dat);
/* bug corrected for M_EXT buffers */
for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next) {
if (m->m_flags & M_EXT) {
- if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) )
- return m;
+ if( (unsigned)((char*)dat - m->m_ext) < (unsigned)m->m_size )
+ goto Exit;
} else {
- if( (char *)dat >= m->m_dat && (char *)dat<(m->m_dat + m->m_size) )
- return m;
+ if( (unsigned)((char *)dat - m->m_dat) < (unsigned)m->m_size )
+ goto Exit;
}
}
+ m = NULL;
+ DEBUG_ERROR((dfd, "mbuf_from failed"));
+Exit:
+ return m;
+}
+
+void
+mbufstats()
+{
+ MBuf m;
+ int i;
- DEBUG_ERROR((dfd, "dtom failed"));
+ lprint(" \r\n");
- return (struct mbuf *)0;
-}
+ lprint("Mbuf stats:\r\n");
+ lprint(" %6d mbufs allocated (%d max)\r\n", mbuf_alloced, mbuf_max);
+
+ i = 0;
+ for (m = m_freelist.m_next; m != &m_freelist; m = m->m_next)
+ i++;
+ lprint(" %6d mbufs on free list\r\n", i);
+
+ i = 0;
+ for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next)
+ i++;
+ lprint(" %6d mbufs on used list\r\n", i);
+ lprint(" %6d mbufs queued as packets\r\n\r\n", if_queued);
+}
diff --git a/slirp/mbuf.h b/slirp/mbuf.h
index 8cc292b..ed83372 100644
--- a/slirp/mbuf.h
+++ b/slirp/mbuf.h
@@ -37,111 +37,85 @@
#ifndef _MBUF_H_
#define _MBUF_H_
-#define m_freem m_free
-
-
#define MINCSIZE 4096 /* Amount to increase mbuf if too small */
-/*
- * Macros for type conversion
- * mtod(m,t) - convert mbuf pointer to data pointer of correct type
- * dtom(x) - convert data pointer within mbuf to mbuf pointer (XXX)
- */
-#define mtod(m,t) ((t)(m)->m_data)
-/* #define dtom(x) ((struct mbuf *)((int)(x) & ~(M_SIZE-1))) */
+/* flags for the mh_flags field */
+#define M_EXT 0x01 /* m_ext points to more (malloced) data */
+#define M_FREELIST 0x02 /* mbuf is on free list */
+#define M_USEDLIST 0x04 /* XXX mbuf is on used list (for dtom()) */
+#define M_DOFREE 0x08 /* when mbuf_free is called on the mbuf, free()
+ * it rather than putting it on the free list */
+
/* XXX About mbufs for slirp:
* Only one mbuf is ever used in a chain, for each "cell" of data.
* m_nextpkt points to the next packet, if fragmented.
* If the data is too large, the M_EXT is used, and a larger block
- * is alloced. Therefore, m_free[m] must check for M_EXT and if set
+ * is alloced. Therefore, mbuf_free[m] must check for M_EXT and if set
* free the m_ext. This is inefficient memory-wise, but who cares.
*/
/* XXX should union some of these! */
/* header at beginning of each mbuf: */
-struct m_hdr {
- struct mbuf *mh_next; /* Linked list of mbufs */
- struct mbuf *mh_prev;
- struct mbuf *mh_nextpkt; /* Next packet in queue/record */
- struct mbuf *mh_prevpkt; /* Flags aren't used in the output queue */
- int mh_flags; /* Misc flags */
-
- int mh_size; /* Size of data */
- struct socket *mh_so;
-
- caddr_t mh_data; /* Location of data */
- int mh_len; /* Amount of data in this mbuf */
-};
-/*
- * How much room is in the mbuf, from m_data to the end of the mbuf
+/**
+ * m_next, m_prev :: used to place the MBuf in free/used linked lists
+ * m_next2, m_prev2 :: used to place the same MBuf in other linked lists
+ * m_flags :: bit flags describing this MBuf
+ * m_size :: total size of MBuf buffer
+ * m_so :: socket this MBuf is attached to
+ * m_data :: pointer to current cursor in MBuf buffer
+ * m_len :: amount of data recorded in this MBuf
*/
-#define M_ROOM(m) ((m->m_flags & M_EXT)? \
- (((m)->m_ext + (m)->m_size) - (m)->m_data) \
- : \
- (((m)->m_dat + (m)->m_size) - (m)->m_data))
+#define MBUF_HEADER \
+ struct mbuf* m_next; \
+ struct mbuf* m_prev; \
+ struct mbuf* m_next2; \
+ struct mbuf* m_prev2; \
+ int m_flags; \
+ int m_size; \
+ struct socket* m_so; \
+ caddr_t m_data; \
+ int m_len;
-/*
- * How much free room there is
- */
-#define M_FREEROOM(m) (M_ROOM(m) - (m)->m_len)
-#define M_TRAILINGSPACE M_FREEROOM
+struct m_hdr {
+ MBUF_HEADER
+};
-struct mbuf {
- struct m_hdr m_hdr;
+typedef struct mbuf {
+ MBUF_HEADER
union M_dat {
- char m_dat_[1]; /* ANSI don't like 0 sized arrays */
- char *m_ext_;
+ char m_dat_[1]; /* ANSI doesn't like 0 sized arrays */
+ char* m_ext_;
} M_dat;
-};
+} MBufRec, *MBuf;
-#define m_next m_hdr.mh_next
-#define m_prev m_hdr.mh_prev
-#define m_nextpkt m_hdr.mh_nextpkt
-#define m_prevpkt m_hdr.mh_prevpkt
-#define m_flags m_hdr.mh_flags
-#define m_len m_hdr.mh_len
-#define m_data m_hdr.mh_data
-#define m_size m_hdr.mh_size
+#define m_nextpkt m_next2
+#define m_prevpkt m_prev2
#define m_dat M_dat.m_dat_
#define m_ext M_dat.m_ext_
-#define m_so m_hdr.mh_so
#define ifq_prev m_prev
#define ifq_next m_next
-#define ifs_prev m_prevpkt
-#define ifs_next m_nextpkt
-#define ifq_so m_so
-#define M_EXT 0x01 /* m_ext points to more (malloced) data */
-#define M_FREELIST 0x02 /* mbuf is on free list */
-#define M_USEDLIST 0x04 /* XXX mbuf is on used list (for dtom()) */
-#define M_DOFREE 0x08 /* when m_free is called on the mbuf, free()
- * it rather than putting it on the free list */
+#define ifs_prev m_prev2
+#define ifs_next m_next2
-/*
- * Mbuf statistics. XXX
- */
+#define ifq_so m_so
-struct mbstat {
- int mbs_alloced; /* Number of mbufs allocated */
-
-};
+void mbuf_init (void);
+void msize_init (void);
+MBuf mbuf_alloc (void);
+void mbuf_free (MBuf m);
+void mbuf_append(MBuf m1, MBuf m2);
+void mbuf_ensure(MBuf m, int size);
+void mbuf_trim (MBuf m, int len);
+int mbuf_copy (MBuf m, MBuf n, int n_offset, int n_length);
+
+#define MBUF_TO(m,t) ((t)(m)->m_data)
+#define MBUF_FROM(d) mbuf_from(d)
+MBuf mbuf_from (void *);
-extern struct mbstat mbstat;
-extern int mbuf_alloced;
-extern struct mbuf m_freelist, m_usedlist;
-extern int mbuf_max;
-
-void m_init _P((void));
-void msize_init _P((void));
-struct mbuf * m_get _P((void));
-void m_free _P((struct mbuf *));
-void m_cat _P((register struct mbuf *, register struct mbuf *));
-void m_inc _P((struct mbuf *, int));
-void m_adj _P((struct mbuf *, int));
-int m_copy _P((struct mbuf *, struct mbuf *, int, int));
-struct mbuf * dtom _P((void *));
+int mbuf_freeroom( MBuf m );
#endif
diff --git a/slirp/misc.c b/slirp/misc.c
index 2c42fd1..beffeee 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -1,77 +1,22 @@
/*
* Copyright (c) 1995 Danny Gasparovski.
- *
+ *
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
#define WANT_SYS_IOCTL_H
#include <slirp.h>
+#define SLIRP_COMPILATION
+#include "sockets.h"
u_int curtime, time_fasttimo, last_slowtimo, detach_time;
u_int detach_wait = 600000; /* 10 minutes */
-
-#if 0
-int x_port = -1;
-int x_display = 0;
-int x_screen = 0;
-
-int
-show_x(buff, inso)
- char *buff;
- struct socket *inso;
-{
- if (x_port < 0) {
- lprint("X Redir: X not being redirected.\r\n");
- } else {
- lprint("X Redir: In sh/bash/zsh/etc. type: DISPLAY=%s:%d.%d; export DISPLAY\r\n",
- inet_ntoa(our_addr), x_port, x_screen);
- lprint("X Redir: In csh/tcsh/etc. type: setenv DISPLAY %s:%d.%d\r\n",
- inet_ntoa(our_addr), x_port, x_screen);
- if (x_display)
- lprint("X Redir: Redirecting to display %d\r\n", x_display);
- }
-
- return CFG_OK;
-}
-
-
-/*
- * XXX Allow more than one X redirection?
- */
-void
-redir_x(inaddr, start_port, display, screen)
- u_int32_t inaddr;
- int start_port;
- int display;
- int screen;
-{
- int i;
-
- if (x_port >= 0) {
- lprint("X Redir: X already being redirected.\r\n");
- show_x(0, 0);
- } else {
- for (i = 6001 + (start_port-1); i <= 6100; i++) {
- if (solisten(htons(i), inaddr, htons(6000 + display), 0)) {
- /* Success */
- x_port = i - 6000;
- x_display = display;
- x_screen = screen;
- show_x(0, 0);
- return;
- }
- }
- lprint("X Redir: Error: Couldn't redirect a port for X. Weird.\r\n");
- }
-}
-#endif
+struct emu_t *tcpemu;
#ifndef HAVE_INET_ATON
int
-inet_aton(cp, ia)
- const char *cp;
- struct in_addr *ia;
+inet_aton(const char* cp, struct in_addr* ia)
{
u_int32_t addr = inet_addr(cp);
if (addr == 0xffffffff)
@@ -89,7 +34,7 @@ getouraddr()
{
char buff[256];
struct hostent *he = NULL;
-
+
if (gethostname(buff,256) == 0)
he = gethostbyname(buff);
if (he)
@@ -106,9 +51,7 @@ struct quehead_32 {
};
inline void
-insque_32(a, b)
- void *a;
- void *b;
+insque_32(void* a, void* b)
{
register struct quehead_32 *element = (struct quehead_32 *) a;
register struct quehead_32 *head = (struct quehead_32 *) b;
@@ -120,8 +63,7 @@ insque_32(a, b)
}
inline void
-remque_32(a)
- void *a;
+remque_32(void* a)
{
register struct quehead_32 *element = (struct quehead_32 *) a;
((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink;
@@ -137,8 +79,7 @@ struct quehead {
};
inline void
-insque(a, b)
- void *a, *b;
+insque(void* a, void* b)
{
register struct quehead *element = (struct quehead *) a;
register struct quehead *head = (struct quehead *) b;
@@ -150,8 +91,7 @@ insque(a, b)
}
inline void
-remque(a)
- void *a;
+remque(void* a)
{
register struct quehead *element = (struct quehead *) a;
((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;
@@ -163,32 +103,6 @@ remque(a)
/* #endif */
-int
-add_exec(ex_ptr, do_pty, exec, addr, port)
- struct ex_list **ex_ptr;
- int do_pty;
- char *exec;
- int addr;
- int port;
-{
- struct ex_list *tmp_ptr;
-
- /* First, check if the port is "bound" */
- for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
- if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr)
- return -1;
- }
-
- tmp_ptr = *ex_ptr;
- *ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list));
- (*ex_ptr)->ex_fport = port;
- (*ex_ptr)->ex_addr = addr;
- (*ex_ptr)->ex_pty = do_pty;
- (*ex_ptr)->ex_exec = strdup(exec);
- (*ex_ptr)->ex_next = tmp_ptr;
- return 0;
-}
-
#ifndef HAVE_STRERROR
/*
@@ -199,8 +113,7 @@ extern int sys_nerr;
extern char *sys_errlist[];
char *
-strerror(error)
- int error;
+strerror(int error)
{
if (error < sys_nerr)
return sys_errlist[error];
@@ -211,453 +124,45 @@ strerror(error)
#endif
-#ifdef _WIN32
-
-int
-fork_exec(so, ex, do_pty)
- struct socket *so;
- char *ex;
- int do_pty;
-{
- /* not implemented */
- return 0;
-}
-
-#else
-
-int
-slirp_openpty(amaster, aslave)
- int *amaster, *aslave;
-{
- register int master, slave;
-
-#ifdef HAVE_GRANTPT
- char *ptr;
-
- if ((master = open("/dev/ptmx", O_RDWR)) < 0 ||
- grantpt(master) < 0 ||
- unlockpt(master) < 0 ||
- (ptr = ptsname(master)) == NULL) {
- close(master);
- return -1;
- }
-
- if ((slave = open(ptr, O_RDWR)) < 0 ||
- ioctl(slave, I_PUSH, "ptem") < 0 ||
- ioctl(slave, I_PUSH, "ldterm") < 0 ||
- ioctl(slave, I_PUSH, "ttcompat") < 0) {
- close(master);
- close(slave);
- return -1;
- }
-
- *amaster = master;
- *aslave = slave;
- return 0;
-
-#else
-
- static char line[] = "/dev/ptyXX";
- register const char *cp1, *cp2;
-
- for (cp1 = "pqrsPQRS"; *cp1; cp1++) {
- line[8] = *cp1;
- for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) {
- line[9] = *cp2;
- if ((master = open(line, O_RDWR, 0)) == -1) {
- if (errno == ENOENT)
- return (-1); /* out of ptys */
- } else {
- line[5] = 't';
- /* These will fail */
- (void) chown(line, getuid(), 0);
- (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP);
-#ifdef HAVE_REVOKE
- (void) revoke(line);
-#endif
- if ((slave = open(line, O_RDWR, 0)) != -1) {
- *amaster = master;
- *aslave = slave;
- return 0;
- }
- (void) close(master);
- line[5] = 'p';
- }
- }
- }
- errno = ENOENT; /* out of ptys */
- return (-1);
-#endif
-}
-
-/*
- * XXX This is ugly
- * We create and bind a socket, then fork off to another
- * process, which connects to this socket, after which we
- * exec the wanted program. If something (strange) happens,
- * the accept() call could block us forever.
- *
- * do_pty = 0 Fork/exec inetd style
- * do_pty = 1 Fork/exec using slirp.telnetd
- * do_ptr = 2 Fork/exec using pty
- */
-int
-fork_exec(so, ex, do_pty)
- struct socket *so;
- char *ex;
- int do_pty;
-{
- int s;
- struct sockaddr_in addr;
- int addrlen = sizeof(addr);
- int opt;
- int master;
- char *argv[256];
-#if 0
- char buff[256];
-#endif
- /* don't want to clobber the original */
- char *bptr;
- char *curarg;
- int c, i, ret;
-
- DEBUG_CALL("fork_exec");
- DEBUG_ARG("so = %lx", (long)so);
- DEBUG_ARG("ex = %lx", (long)ex);
- DEBUG_ARG("do_pty = %lx", (long)do_pty);
-
- if (do_pty == 2) {
- if (slirp_openpty(&master, &s) == -1) {
- lprint("Error: openpty failed: %s\n", strerror(errno));
- return 0;
- }
- } else {
- addr.sin_family = AF_INET;
- addr.sin_port = 0;
- addr.sin_addr.s_addr = INADDR_ANY;
-
- if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
- bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
- listen(s, 1) < 0) {
- lprint("Error: inet socket: %s\n", strerror(errno));
- closesocket(s);
-
- return 0;
- }
- }
-
- switch(fork()) {
- case -1:
- lprint("Error: fork failed: %s\n", strerror(errno));
- close(s);
- if (do_pty == 2)
- close(master);
- return 0;
-
- case 0:
- /* Set the DISPLAY */
- if (do_pty == 2) {
- (void) close(master);
-#ifdef TIOCSCTTY /* XXXXX */
- (void) setsid();
- ioctl(s, TIOCSCTTY, (char *)NULL);
-#endif
- } else {
- getsockname(s, (struct sockaddr *)&addr, &addrlen);
- close(s);
- /*
- * Connect to the socket
- * XXX If any of these fail, we're in trouble!
- */
- s = socket(AF_INET, SOCK_STREAM, 0);
- addr.sin_addr = loopback_addr;
- do {
- ret = connect(s, (struct sockaddr *)&addr, addrlen);
- } while (ret < 0 && errno == EINTR);
- }
-
-#if 0
- if (x_port >= 0) {
-#ifdef HAVE_SETENV
- sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
- setenv("DISPLAY", buff, 1);
-#else
- sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
- putenv(buff);
-#endif
- }
-#endif
- dup2(s, 0);
- dup2(s, 1);
- dup2(s, 2);
- for (s = 3; s <= 255; s++)
- close(s);
-
- i = 0;
- bptr = strdup(ex); /* No need to free() this */
- if (do_pty == 1) {
- /* Setup "slirp.telnetd -x" */
- argv[i++] = "slirp.telnetd";
- argv[i++] = "-x";
- argv[i++] = bptr;
- } else
- do {
- /* Change the string into argv[] */
- curarg = bptr;
- while (*bptr != ' ' && *bptr != (char)0)
- bptr++;
- c = *bptr;
- *bptr++ = (char)0;
- argv[i++] = strdup(curarg);
- } while (c);
-
- argv[i] = 0;
- execvp(argv[0], argv);
-
- /* Ooops, failed, let's tell the user why */
- {
- char buff[256];
-
- sprintf(buff, "Error: execvp of %s failed: %s\n",
- argv[0], strerror(errno));
- write(2, buff, strlen(buff)+1);
- }
- close(0); close(1); close(2); /* XXX */
- exit(1);
-
- default:
- if (do_pty == 2) {
- close(s);
- so->s = master;
- } else {
- /*
- * XXX this could block us...
- * XXX Should set a timer here, and if accept() doesn't
- * return after X seconds, declare it a failure
- * The only reason this will block forever is if socket()
- * of connect() fail in the child process
- */
- do {
- so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
- } while (so->s < 0 && errno == EINTR);
- closesocket(s);
- opt = 1;
- setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
- opt = 1;
- setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
- }
- fd_nonblock(so->s);
-
- /* Append the telnet options now */
- if (so->so_m != 0 && do_pty == 1) {
- sbappend(so, so->so_m);
- so->so_m = 0;
- }
-
- return 1;
- }
-}
-#endif
#ifndef HAVE_STRDUP
char *
-strdup(str)
- const char *str;
+strdup(const char* str)
{
char *bptr;
-
- bptr = (char *)malloc(strlen(str)+1);
- strcpy(bptr, str);
-
- return bptr;
-}
-#endif
+ int len = strlen(str);
-#if 0
-void
-snooze_hup(num)
- int num;
-{
- int s, ret;
-#ifndef NO_UNIX_SOCKETS
- struct sockaddr_un sock_un;
-#endif
- struct sockaddr_in sock_in;
- char buff[256];
-
- ret = -1;
- if (slirp_socket_passwd) {
- s = socket(AF_INET, SOCK_STREAM, 0);
- if (s < 0)
- slirp_exit(1);
- sock_in.sin_family = AF_INET;
- sock_in.sin_addr.s_addr = slirp_socket_addr;
- sock_in.sin_port = htons(slirp_socket_port);
- if (connect(s, (struct sockaddr *)&sock_in, sizeof(sock_in)) != 0)
- slirp_exit(1); /* just exit...*/
- sprintf(buff, "kill %s:%d", slirp_socket_passwd, slirp_socket_unit);
- write(s, buff, strlen(buff)+1);
- }
-#ifndef NO_UNIX_SOCKETS
- else {
- s = socket(AF_UNIX, SOCK_STREAM, 0);
- if (s < 0)
- slirp_exit(1);
- sock_un.sun_family = AF_UNIX;
- strcpy(sock_un.sun_path, socket_path);
- if (connect(s, (struct sockaddr *)&sock_un,
- sizeof(sock_un.sun_family) + sizeof(sock_un.sun_path)) != 0)
- slirp_exit(1);
- sprintf(buff, "kill none:%d", slirp_socket_unit);
- write(s, buff, strlen(buff)+1);
- }
-#endif
- slirp_exit(0);
-}
-
-
-void
-snooze()
-{
- sigset_t s;
- int i;
-
- /* Don't need our data anymore */
- /* XXX This makes SunOS barf */
-/* brk(0); */
-
- /* Close all fd's */
- for (i = 255; i >= 0; i--)
- close(i);
-
- signal(SIGQUIT, slirp_exit);
- signal(SIGHUP, snooze_hup);
- sigemptyset(&s);
-
- /* Wait for any signal */
- sigsuspend(&s);
-
- /* Just in case ... */
- exit(255);
-}
+ bptr = (char *)malloc(len+1);
+ memcpy(bptr, str, len+1);
-void
-relay(s)
- int s;
-{
- char buf[8192];
- int n;
- fd_set readfds;
- struct ttys *ttyp;
-
- /* Don't need our data anymore */
- /* XXX This makes SunOS barf */
-/* brk(0); */
-
- signal(SIGQUIT, slirp_exit);
- signal(SIGHUP, slirp_exit);
- signal(SIGINT, slirp_exit);
- signal(SIGTERM, slirp_exit);
-
- /* Fudge to get term_raw and term_restore to work */
- if (NULL == (ttyp = tty_attach (0, slirp_tty))) {
- lprint ("Error: tty_attach failed in misc.c:relay()\r\n");
- slirp_exit (1);
- }
- ttyp->fd = 0;
- ttyp->flags |= TTY_CTTY;
- term_raw(ttyp);
-
- while (1) {
- FD_ZERO(&readfds);
-
- FD_SET(0, &readfds);
- FD_SET(s, &readfds);
-
- n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
-
- if (n <= 0)
- slirp_exit(0);
-
- if (FD_ISSET(0, &readfds)) {
- n = read(0, buf, 8192);
- if (n <= 0)
- slirp_exit(0);
- n = writen(s, buf, n);
- if (n <= 0)
- slirp_exit(0);
- }
-
- if (FD_ISSET(s, &readfds)) {
- n = read(s, buf, 8192);
- if (n <= 0)
- slirp_exit(0);
- n = writen(0, buf, n);
- if (n <= 0)
- slirp_exit(0);
- }
- }
-
- /* Just in case.... */
- exit(1);
+ return bptr;
}
#endif
+
int (*lprint_print) _P((void *, const char *, va_list));
char *lprint_ptr, *lprint_ptr2, **lprint_arg;
void
-#ifdef __STDC__
lprint(const char *format, ...)
-#else
-lprint(va_alist) va_dcl
-#endif
{
va_list args;
-
-#ifdef __STDC__
- va_start(args, format);
-#else
- char *format;
- va_start(args);
- format = va_arg(args, char *);
-#endif
-#if 0
- /* If we're printing to an sbuf, make sure there's enough room */
- /* XXX +100? */
- if (lprint_sb) {
- if ((lprint_ptr - lprint_sb->sb_wptr) >=
- (lprint_sb->sb_datalen - (strlen(format) + 100))) {
- int deltaw = lprint_sb->sb_wptr - lprint_sb->sb_data;
- int deltar = lprint_sb->sb_rptr - lprint_sb->sb_data;
- int deltap = lprint_ptr - lprint_sb->sb_data;
-
- lprint_sb->sb_data = (char *)realloc(lprint_sb->sb_data,
- lprint_sb->sb_datalen + TCP_SNDSPACE);
-
- /* Adjust all values */
- lprint_sb->sb_wptr = lprint_sb->sb_data + deltaw;
- lprint_sb->sb_rptr = lprint_sb->sb_data + deltar;
- lprint_ptr = lprint_sb->sb_data + deltap;
-
- lprint_sb->sb_datalen += TCP_SNDSPACE;
- }
- }
-#endif
+
+ va_start(args, format);
if (lprint_print)
lprint_ptr += (*lprint_print)(*lprint_arg, format, args);
-
+
/* Check if they want output to be logged to file as well */
if (lfd) {
- /*
+ /*
* Remove \r's
* otherwise you'll get ^M all over the file
*/
int len = strlen(format);
char *bptr1, *bptr2;
-
+
bptr1 = bptr2 = strdup(format);
-
+
while (len--) {
if (*bptr1 == '\r')
memcpy(bptr1, bptr1+1, len+1);
@@ -671,8 +176,7 @@ lprint(va_alist) va_dcl
}
void
-add_emu(buff)
- char *buff;
+add_emu(char* buff)
{
u_int lport, fport;
u_int8_t tos = 0, emu = 0;
@@ -680,12 +184,12 @@ add_emu(buff)
char *buff3 = buff4;
struct emu_t *emup;
struct socket *so;
-
+
if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) {
lprint("Error: Bad arguments\r\n");
return;
}
-
+
if (sscanf(buff1, "%d:%d", &lport, &fport) != 2) {
lport = 0;
if (sscanf(buff1, "%d", &fport) != 1) {
@@ -693,7 +197,7 @@ add_emu(buff)
return;
}
}
-
+
if (sscanf(buff2, "%128[^:]:%128s", buff1, buff3) != 2) {
buff3 = 0;
if (sscanf(buff2, "%256s", buff1) != 1) {
@@ -701,7 +205,7 @@ add_emu(buff)
return;
}
}
-
+
if (buff3) {
if (strcmp(buff3, "lowdelay") == 0)
tos = IPTOS_LOWDELAY;
@@ -712,7 +216,7 @@ add_emu(buff)
return;
}
}
-
+
if (strcmp(buff1, "ftp") == 0)
emu = EMU_FTP;
else if (strcmp(buff1, "irc") == 0)
@@ -723,7 +227,7 @@ add_emu(buff)
lprint("Error: Unknown service\r\n");
return;
}
-
+
/* First, check that it isn't already emulated */
for (emup = tcpemu; emup; emup = emup->next) {
if (emup->lport == lport && emup->fport == fport) {
@@ -731,7 +235,7 @@ add_emu(buff)
return;
}
}
-
+
/* link it */
emup = (struct emu_t *)malloc(sizeof (struct emu_t));
emup->lport = (u_int16_t)lport;
@@ -740,7 +244,7 @@ add_emu(buff)
emup->emu = emu;
emup->next = tcpemu;
tcpemu = emup;
-
+
/* And finally, mark all current sessions, if any, as being emulated */
for (so = tcb.so_next; so != &tcb; so = so->so_next) {
if ((lport && lport == ntohs(so->so_lport)) ||
@@ -751,7 +255,7 @@ add_emu(buff)
so->so_iptos = tos;
}
}
-
+
lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport);
}
@@ -765,180 +269,20 @@ add_emu(buff)
*/
int
-vsprintf_len(string, format, args)
- char *string;
- const char *format;
- va_list args;
+vsprintf_len(char* string, const char* format, va_list args)
{
vsprintf(string, format, args);
return strlen(string);
}
int
-#ifdef __STDC__
sprintf_len(char *string, const char *format, ...)
-#else
-sprintf_len(va_alist) va_dcl
-#endif
{
va_list args;
-#ifdef __STDC__
va_start(args, format);
-#else
- char *string;
- char *format;
- va_start(args);
- string = va_arg(args, char *);
- format = va_arg(args, char *);
-#endif
vsprintf(string, format, args);
return strlen(string);
}
#endif
-void
-u_sleep(usec)
- int usec;
-{
- struct timeval t;
- fd_set fdset;
-
- FD_ZERO(&fdset);
-
- t.tv_sec = 0;
- t.tv_usec = usec * 1000;
-
- select(0, &fdset, &fdset, &fdset, &t);
-}
-
-/*
- * Set fd blocking and non-blocking
- */
-
-void
-fd_nonblock(fd)
- int fd;
-{
-#ifdef FIONBIO
- int opt = 1;
-
- ioctlsocket(fd, FIONBIO, &opt);
-#else
- int opt;
-
- opt = fcntl(fd, F_GETFL, 0);
- opt |= O_NONBLOCK;
- fcntl(fd, F_SETFL, opt);
-#endif
-}
-
-void
-fd_block(fd)
- int fd;
-{
-#ifdef FIONBIO
- int opt = 0;
-
- ioctlsocket(fd, FIONBIO, &opt);
-#else
- int opt;
-
- opt = fcntl(fd, F_GETFL, 0);
- opt &= ~O_NONBLOCK;
- fcntl(fd, F_SETFL, opt);
-#endif
-}
-
-
-#if 0
-/*
- * invoke RSH
- */
-int
-rsh_exec(so,ns, user, host, args)
- struct socket *so;
- struct socket *ns;
- char *user;
- char *host;
- char *args;
-{
- int fd[2];
- int fd0[2];
- int s;
- char buff[256];
-
- DEBUG_CALL("rsh_exec");
- DEBUG_ARG("so = %lx", (long)so);
-
- if (pipe(fd)<0) {
- lprint("Error: pipe failed: %s\n", strerror(errno));
- return 0;
- }
-/* #ifdef HAVE_SOCKETPAIR */
-#if 1
- if (socketpair(PF_UNIX,SOCK_STREAM,0, fd0) == -1) {
- close(fd[0]);
- close(fd[1]);
- lprint("Error: openpty failed: %s\n", strerror(errno));
- return 0;
- }
-#else
- if (slirp_openpty(&fd0[0], &fd0[1]) == -1) {
- close(fd[0]);
- close(fd[1]);
- lprint("Error: openpty failed: %s\n", strerror(errno));
- return 0;
- }
-#endif
-
- switch(fork()) {
- case -1:
- lprint("Error: fork failed: %s\n", strerror(errno));
- close(fd[0]);
- close(fd[1]);
- close(fd0[0]);
- close(fd0[1]);
- return 0;
-
- case 0:
- close(fd[0]);
- close(fd0[0]);
-
- /* Set the DISPLAY */
- if (x_port >= 0) {
-#ifdef HAVE_SETENV
- sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
- setenv("DISPLAY", buff, 1);
-#else
- sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
- putenv(buff);
-#endif
- }
-
- dup2(fd0[1], 0);
- dup2(fd0[1], 1);
- dup2(fd[1], 2);
- for (s = 3; s <= 255; s++)
- close(s);
-
- execlp("rsh","rsh","-l", user, host, args, NULL);
-
- /* Ooops, failed, let's tell the user why */
-
- sprintf(buff, "Error: execlp of %s failed: %s\n",
- "rsh", strerror(errno));
- write(2, buff, strlen(buff)+1);
- close(0); close(1); close(2); /* XXX */
- exit(1);
-
- default:
- close(fd[1]);
- close(fd0[1]);
- ns->s=fd[0];
- so->s=fd0[0];
-
- return 1;
- }
-}
-#endif
diff --git a/slirp/misc.h b/slirp/misc.h
index 8e6a606..aa4a0ce 100644
--- a/slirp/misc.h
+++ b/slirp/misc.h
@@ -8,20 +8,11 @@
#ifndef _MISC_H_
#define _MISC_H_
-struct ex_list {
- int ex_pty; /* Do we want a pty? */
- int ex_addr; /* The last byte of the address */
- int ex_fport; /* Port to telnet to */
- char *ex_exec; /* Command line of what to exec */
- struct ex_list *ex_next;
-};
-
-extern struct ex_list *exec_list;
extern u_int curtime, time_fasttimo, last_slowtimo, detach_time, detach_wait;
extern int (*lprint_print) _P((void *, const char *, va_list));
extern char *lprint_ptr, *lprint_ptr2, **lprint_arg;
-extern struct sbuf *lprint_sb;
+//extern SBuf lprint_sb;
#ifndef HAVE_STRDUP
char *strdup _P((const char *));
@@ -65,23 +56,9 @@ struct emu_t {
extern struct emu_t *tcpemu;
-extern int x_port, x_server, x_display;
-
-int show_x _P((char *, struct socket *));
-void redir_x _P((u_int32_t, int, int, int));
void getouraddr _P((void));
inline void slirp_insque _P((void *, void *));
inline void slirp_remque _P((void *));
-int add_exec _P((struct ex_list **, int, char *, int, int));
-int slirp_openpty _P((int *, int *));
-int fork_exec _P((struct socket *, char *, int));
-void snooze_hup _P((int));
-void snooze _P((void));
-void relay _P((int));
void add_emu _P((char *));
-void u_sleep _P((int));
-void fd_nonblock _P((int));
-void fd_block _P((int));
-int rsh_exec _P((struct socket *, struct socket *, char *, char *, char *));
#endif
diff --git a/slirp/sbuf.c b/slirp/sbuf.c
index d6726c9..3d975f8 100644
--- a/slirp/sbuf.c
+++ b/slirp/sbuf.c
@@ -6,26 +6,17 @@
*/
#include <slirp.h>
-
-/* Done as a macro in socket.h */
-/* int
- * sbspace(struct sockbuff *sb)
- * {
- * return SB_DATALEN - sb->sb_cc;
- * }
- */
+#define SLIRP_COMPILATION
+#include "sockets.h"
void
-sbfree(sb)
- struct sbuf *sb;
+sbuf_free(SBuf sb)
{
free(sb->sb_data);
}
void
-sbdrop(sb, num)
- struct sbuf *sb;
- int num;
+sbuf_drop(SBuf sb, int num)
{
/*
* We can only drop how much we have
@@ -41,28 +32,17 @@ sbdrop(sb, num)
}
void
-sbreserve(sb, size)
- struct sbuf *sb;
- int size;
+sbuf_reserve(SBuf sb, int size)
{
- if (sb->sb_data) {
- /* Already alloced, realloc if necessary */
- if (sb->sb_datalen != size) {
- sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)realloc(sb->sb_data, size);
- sb->sb_cc = 0;
- if (sb->sb_wptr)
- sb->sb_datalen = size;
- else
- sb->sb_datalen = 0;
- }
- } else {
- sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)malloc(size);
- sb->sb_cc = 0;
- if (sb->sb_wptr)
- sb->sb_datalen = size;
- else
- sb->sb_datalen = 0;
- }
+ if (sb->sb_datalen == size)
+ return;
+
+ sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)realloc(sb->sb_data, size);
+ sb->sb_cc = 0;
+ if (sb->sb_wptr)
+ sb->sb_datalen = size;
+ else
+ sb->sb_datalen = 0;
}
/*
@@ -72,20 +52,18 @@ sbreserve(sb, size)
* (the socket is non-blocking, so we won't hang)
*/
void
-sbappend(so, m)
- struct socket *so;
- struct mbuf *m;
+sbuf_append(struct socket *so, MBuf m)
{
int ret = 0;
-
- DEBUG_CALL("sbappend");
+
+ DEBUG_CALL("sbuf_append");
DEBUG_ARG("so = %lx", (long)so);
DEBUG_ARG("m = %lx", (long)m);
DEBUG_ARG("m->m_len = %d", m->m_len);
/* Shouldn't happen, but... e.g. foreign host closes connection */
if (m->m_len <= 0) {
- m_free(m);
+ mbuf_free(m);
return;
}
@@ -95,8 +73,8 @@ sbappend(so, m)
* (The rest of this function is just an optimisation)
*/
if (so->so_urgc) {
- sbappendsb(&so->so_rcv, m);
- m_free(m);
+ sbuf_appendsb(&so->so_rcv, m);
+ mbuf_free(m);
sosendoob(so);
return;
}
@@ -105,9 +83,12 @@ sbappend(so, m)
* We only write if there's nothing in the buffer,
* ottherwise it'll arrive out of order, and hence corrupt
*/
- if (!so->so_rcv.sb_cc)
- ret = send(so->s, m->m_data, m->m_len, 0);
-
+ if (!so->so_rcv.sb_cc) {
+ do {
+ ret = send(so->s, m->m_data, m->m_len, 0);
+ } while (ret == 0 && socket_errno == EINTR);
+ }
+
if (ret <= 0) {
/*
* Nothing was written
@@ -115,18 +96,18 @@ sbappend(so, m)
* we don't need to check because if it has closed,
* it will be detected in the normal way by soread()
*/
- sbappendsb(&so->so_rcv, m);
+ sbuf_appendsb(&so->so_rcv, m);
} else if (ret != m->m_len) {
/*
* Something was written, but not everything..
- * sbappendsb the rest
+ * sbuf_appendsb the rest
*/
m->m_len -= ret;
m->m_data += ret;
- sbappendsb(&so->so_rcv, m);
+ sbuf_appendsb(&so->so_rcv, m);
} /* else */
/* Whatever happened, we free the mbuf */
- m_free(m);
+ mbuf_free(m);
}
/*
@@ -134,9 +115,7 @@ sbappend(so, m)
* The caller is responsible to make sure there's enough room
*/
void
-sbappendsb(sb, m)
- struct sbuf *sb;
- struct mbuf *m;
+sbuf_appendsb(SBuf sb, MBuf m)
{
int len, n, nn;
@@ -161,7 +140,7 @@ sbappendsb(sb, m)
}
}
- sb->sb_cc += n;
+ sb->sb_cc += n;
sb->sb_wptr += n;
if (sb->sb_wptr >= sb->sb_data + sb->sb_datalen)
sb->sb_wptr -= sb->sb_datalen;
@@ -173,11 +152,7 @@ sbappendsb(sb, m)
* done in sbdrop when the data is acked
*/
void
-sbcopy(sb, off, len, to)
- struct sbuf *sb;
- int off;
- int len;
- char *to;
+sbuf_copy(SBuf sb, int off, int len, char* to)
{
char *from;
diff --git a/slirp/sbuf.h b/slirp/sbuf.h
index 161e0bb..05fa01a 100644
--- a/slirp/sbuf.h
+++ b/slirp/sbuf.h
@@ -8,24 +8,30 @@
#ifndef _SBUF_H_
#define _SBUF_H_
-#define sbflush(sb) sbdrop((sb),(sb)->sb_cc)
-#define sbspace(sb) ((sb)->sb_datalen - (sb)->sb_cc)
+#include "mbuf.h"
+#include <stddef.h>
-struct sbuf {
- u_int sb_cc; /* actual chars in buffer */
- u_int sb_datalen; /* Length of data */
- char *sb_wptr; /* write pointer. points to where the next
- * bytes should be written in the sbuf */
- char *sb_rptr; /* read pointer. points to where the next
- * byte should be read from the sbuf */
- char *sb_data; /* Actual data */
-};
+/* a SBuf is a simple circular buffer used to hold RX and TX data in a struct socket
+ */
+
+typedef struct sbuf {
+ unsigned sb_cc; /* actual chars in buffer */
+ unsigned sb_datalen; /* Length of data */
+ char* sb_wptr; /* write pointer. points to where the next
+ * bytes should be written in the sbuf */
+ char* sb_rptr; /* read pointer. points to where the next
+ * byte should be read from the sbuf */
+ char* sb_data; /* Actual data */
+} SBufRec, *SBuf;
+
+void sbuf_free (SBuf sb);
+void sbuf_drop (SBuf sb, int num);
+void sbuf_reserve (SBuf sb, int count);
+void sbuf_append (struct socket *so, MBuf m);
+void sbuf_appendsb(SBuf sb, MBuf m);
+void sbuf_copy (SBuf sb, int offset, int length, char *to);
-void sbfree _P((struct sbuf *));
-void sbdrop _P((struct sbuf *, int));
-void sbreserve _P((struct sbuf *, int));
-void sbappend _P((struct socket *, struct mbuf *));
-void sbappendsb _P((struct sbuf *, struct mbuf *));
-void sbcopy _P((struct sbuf *, int, int, char *));
+#define sbuf_flush(sb) sbuf_drop((sb),(sb)->sb_cc)
+#define sbuf_space(sb) ((sb)->sb_datalen - (sb)->sb_cc)
#endif
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 6ba753e..d6eaac4 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -1,9 +1,17 @@
#include "slirp.h"
+#include "proxy_common.h"
+#include "android_utils.h" /* for dprint */
+#include "android.h"
+
+#define D(...) VERBOSE_PRINT(slirp,__VA_ARGS__)
+#define DN(...) do { if (VERBOSE_CHECK(slirp)) dprintn(__VA_ARGS__); } while (0)
/* host address */
struct in_addr our_addr;
/* host dns address */
-struct in_addr dns_addr;
+struct in_addr dns_addr[DNS_ADDR_MAX];
+int dns_addr_count;
+
/* host loopback address */
struct in_addr loopback_addr;
@@ -12,36 +20,50 @@ struct in_addr special_addr;
/* virtual address alias for host */
struct in_addr alias_addr;
-const uint8_t special_ethaddr[6] = {
+const uint8_t special_ethaddr[6] = {
0x52, 0x54, 0x00, 0x12, 0x35, 0x00
};
-uint8_t client_ethaddr[6];
+uint8_t client_ethaddr[6] = {
+ 0x52, 0x54, 0x00, 0x12, 0x34, 0x56
+};
int do_slowtimo;
int link_up;
struct timeval tt;
FILE *lfd;
-struct ex_list *exec_list;
/* XXX: suppress those select globals */
fd_set *global_readfds, *global_writefds, *global_xfds;
char slirp_hostname[33];
+int slirp_add_dns_server(struct in_addr new_dns_addr)
+{
+ if (dns_addr_count >= DNS_ADDR_MAX)
+ return -1;
+
+ dns_addr[dns_addr_count++] = new_dns_addr;
+ return 0;
+}
+
+
#ifdef _WIN32
-static int get_dns_addr(struct in_addr *pdns_addr)
+int slirp_get_system_dns_servers()
{
FIXED_INFO *FixedInfo=NULL;
ULONG BufLen;
DWORD ret;
IP_ADDR_STRING *pIPAddr;
struct in_addr tmp_addr;
-
+
+ if (dns_addr_count > 0)
+ return dns_addr_count;
+
FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
BufLen = sizeof(FIXED_INFO);
-
+
if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
if (FixedInfo) {
GlobalFree(FixedInfo);
@@ -49,7 +71,7 @@ static int get_dns_addr(struct in_addr *pdns_addr)
}
FixedInfo = GlobalAlloc(GPTR, BufLen);
}
-
+
if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret );
if (FixedInfo) {
@@ -58,84 +80,114 @@ static int get_dns_addr(struct in_addr *pdns_addr)
}
return -1;
}
-
+
+ D( "DNS Servers:");
pIPAddr = &(FixedInfo->DnsServerList);
- inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
- *pdns_addr = tmp_addr;
-#if 0
- printf( "DNS Servers:\n" );
- printf( "DNS Addr:%s\n", pIPAddr->IpAddress.String );
-
- pIPAddr = FixedInfo -> DnsServerList.Next;
- while ( pIPAddr ) {
- printf( "DNS Addr:%s\n", pIPAddr ->IpAddress.String );
- pIPAddr = pIPAddr ->Next;
+ while (pIPAddr && dns_addr_count < DNS_ADDR_MAX) {
+ D( " %s", pIPAddr->IpAddress.String );
+ inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
+ if (tmp_addr.s_addr == loopback_addr.s_addr)
+ tmp_addr = our_addr;
+ if (dns_addr_count < DNS_ADDR_MAX)
+ dns_addr[dns_addr_count++] = tmp_addr;
+ pIPAddr = pIPAddr->Next;
}
-#endif
+
if (FixedInfo) {
GlobalFree(FixedInfo);
FixedInfo = NULL;
}
- return 0;
+ if (dns_addr_count <= 0)
+ return -1;
+
+ return dns_addr_count;
}
#else
-static int get_dns_addr(struct in_addr *pdns_addr)
+int slirp_get_system_dns_servers(void)
{
char buff[512];
char buff2[256];
FILE *f;
- int found = 0;
struct in_addr tmp_addr;
-
+
+ if (dns_addr_count > 0)
+ return dns_addr_count;
+
+#ifdef CONFIG_DARWIN
+ /* on Darwin /etc/resolv.conf is a symlink to /private/var/run/resolv.conf
+ * in some siutations, the symlink can be destroyed and the system will not
+ * re-create it. Darwin-aware applications will continue to run, but "legacy"
+ * Unix ones will not.
+ */
+ f = fopen("/private/var/run/resolv.conf", "r");
+ if (!f)
+ f = fopen("/etc/resolv.conf", "r"); /* desperate attempt to sanity */
+#else
f = fopen("/etc/resolv.conf", "r");
+#endif
if (!f)
return -1;
- lprint("IP address of your DNS(s): ");
+ DN("emulator: IP address of your DNS(s): ");
while (fgets(buff, 512, f) != NULL) {
if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
if (!inet_aton(buff2, &tmp_addr))
continue;
if (tmp_addr.s_addr == loopback_addr.s_addr)
tmp_addr = our_addr;
- /* If it's the first one, set it to dns_addr */
- if (!found)
- *pdns_addr = tmp_addr;
- else
- lprint(", ");
- if (++found > 3) {
- lprint("(more)");
+ if (dns_addr_count < DNS_ADDR_MAX) {
+ dns_addr[dns_addr_count++] = tmp_addr;
+ if (dns_addr_count > 1)
+ DN(", ");
+ DN("%s", inet_ntoa(tmp_addr));
+ } else {
+ DN("(more)");
break;
- } else
- lprint("%s", inet_ntoa(tmp_addr));
+ }
}
}
+ DN("\n");
fclose(f);
- if (!found)
+
+ if (!dns_addr_count)
return -1;
- return 0;
+
+ return dns_addr_count;
}
#endif
-#ifdef _WIN32
-void slirp_cleanup(void)
-{
- WSACleanup();
-}
-#endif
+extern void slirp_init_shapers();
void slirp_init(void)
{
- // debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
-
-#ifdef _WIN32
+#if DEBUG
+ int slirp_logmask = 0;
+ char slirp_logfile[512];
+
{
- WSADATA Data;
- WSAStartup(MAKEWORD(2,0), &Data);
- atexit(slirp_cleanup);
+ const char* env = getenv( "ANDROID_SLIRP_LOGMASK" );
+ if (env != NULL)
+ slirp_logmask = atoi(env);
+ else if (VERBOSE_CHECK(slirp))
+ slirp_logmask = DEBUG_DEFAULT;
+ }
+
+ {
+ char* p = slirp_logfile;
+ char* end = p + sizeof(slirp_logfile);
+
+ p = bufprint_temp_file( p, end, "slirp.log" );
+ if (p >= end) {
+ dprint( "cannot create slirp log file in temporary directory" );
+ slirp_logmask = 0;
+ }
+ }
+ if (slirp_logmask) {
+ dprint( "sending slirp logs with mask %x to %s", slirp_logmask, slirp_logfile );
+ debug_init( slirp_logfile, slirp_logmask );
}
#endif
@@ -145,19 +197,24 @@ void slirp_init(void)
ip_init();
/* Initialise mbufs *after* setting the MTU */
- m_init();
+ mbuf_init();
/* set default addresses */
inet_aton("127.0.0.1", &loopback_addr);
- if (get_dns_addr(&dns_addr) < 0) {
- dns_addr = loopback_addr;
- fprintf (stderr, "Warning: No DNS servers found\n");
+ if (dns_addr_count == 0) {
+ if (slirp_get_system_dns_servers() < 0) {
+ dns_addr[0] = loopback_addr;
+ dns_addr_count = 1;
+ fprintf (stderr, "Warning: No DNS servers found\n");
+ }
}
inet_aton(CTL_SPECIAL, &special_addr);
alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
getouraddr();
+
+ slirp_init_shapers();
}
#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
@@ -180,16 +237,16 @@ static void updtime(void)
static void updtime(void)
{
gettimeofday(&tt, 0);
-
+
curtime = (u_int)tt.tv_sec * (u_int)1000;
curtime += (u_int)tt.tv_usec / (u_int)1000;
-
+
if ((tt.tv_usec % 1000) >= 500)
curtime++;
}
#endif
-void slirp_select_fill(int *pnfds,
+void slirp_select_fill(int *pnfds,
fd_set *readfds, fd_set *writefds, fd_set *xfds)
{
struct socket *so, *so_next;
@@ -201,143 +258,158 @@ void slirp_select_fill(int *pnfds,
global_readfds = NULL;
global_writefds = NULL;
global_xfds = NULL;
-
+
nfds = *pnfds;
- /*
- * First, TCP sockets
- */
- do_slowtimo = 0;
- if (link_up) {
- /*
- * *_slowtimo needs calling if there are IP fragments
- * in the fragment queue, or there are TCP connections active
- */
- do_slowtimo = ((tcb.so_next != &tcb) ||
- ((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next));
-
- for (so = tcb.so_next; so != &tcb; so = so_next) {
- so_next = so->so_next;
-
- /*
- * See if we need a tcp_fasttimo
- */
- if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
- time_fasttimo = curtime; /* Flag when we want a fasttimo */
-
- /*
- * NOFDREF can include still connecting to local-host,
- * newly socreated() sockets etc. Don't want to select these.
- */
- if (so->so_state & SS_NOFDREF || so->s == -1)
- continue;
-
- /*
- * Set for reading sockets which are accepting
- */
- if (so->so_state & SS_FACCEPTCONN) {
+ /*
+ * First, TCP sockets
+ */
+ do_slowtimo = 0;
+ if (link_up) {
+ /*
+ * *_slowtimo needs calling if there are IP fragments
+ * in the fragment queue, or there are TCP connections active
+ */
+ do_slowtimo = ((tcb.so_next != &tcb) ||
+ ((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next));
+
+ for (so = tcb.so_next; so != &tcb; so = so_next) {
+ so_next = so->so_next;
+
+ /*
+ * See if we need a tcp_fasttimo
+ */
+ if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
+ time_fasttimo = curtime; /* Flag when we want a fasttimo */
+
+ /*
+ * NOFDREF can include still connecting to local-host,
+ * newly socreated() sockets etc. Don't want to select these.
+ */
+ if (so->so_state & SS_NOFDREF || so->s == -1)
+ continue;
+
+ /*
+ * don't register proxified socked connections here
+ */
+ if ((so->so_state & SS_PROXIFIED) != 0)
+ continue;
+
+ /*
+ * Set for reading sockets which are accepting
+ */
+ if (so->so_state & SS_FACCEPTCONN) {
FD_SET(so->s, readfds);
- UPD_NFDS(so->s);
- continue;
- }
-
- /*
- * Set for writing sockets which are connecting
- */
- if (so->so_state & SS_ISFCONNECTING) {
- FD_SET(so->s, writefds);
- UPD_NFDS(so->s);
- continue;
- }
-
- /*
- * Set for writing if we are connected, can send more, and
- * we have something to send
- */
- if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
- FD_SET(so->s, writefds);
- UPD_NFDS(so->s);
- }
-
- /*
- * Set for reading (and urgent data) if we are connected, can
- * receive more, and we have room for it XXX /2 ?
- */
- if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
- FD_SET(so->s, readfds);
- FD_SET(so->s, xfds);
- UPD_NFDS(so->s);
- }
- }
-
- /*
- * UDP sockets
- */
- for (so = udb.so_next; so != &udb; so = so_next) {
- so_next = so->so_next;
-
- /*
- * See if it's timed out
- */
- if (so->so_expire) {
- if (so->so_expire <= curtime) {
- udp_detach(so);
- continue;
- } else
- do_slowtimo = 1; /* Let socket expire */
- }
-
- /*
- * When UDP packets are received from over the
- * link, they're sendto()'d straight away, so
- * no need for setting for writing
- * Limit the number of packets queued by this session
- * to 4. Note that even though we try and limit this
- * to 4 packets, the session could have more queued
- * if the packets needed to be fragmented
- * (XXX <= 4 ?)
- */
- if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
- FD_SET(so->s, readfds);
- UPD_NFDS(so->s);
- }
- }
- }
-
- /*
- * Setup timeout to use minimum CPU usage, especially when idle
- */
-
- /*
- * First, see the timeout needed by *timo
- */
- timeout.tv_sec = 0;
- timeout.tv_usec = -1;
- /*
- * If a slowtimo is needed, set timeout to 500ms from the last
- * slow timeout. If a fast timeout is needed, set timeout within
- * 200ms of when it was requested.
- */
- if (do_slowtimo) {
- /* XXX + 10000 because some select()'s aren't that accurate */
- timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000;
- if (timeout.tv_usec < 0)
- timeout.tv_usec = 0;
- else if (timeout.tv_usec > 510000)
- timeout.tv_usec = 510000;
-
- /* Can only fasttimo if we also slowtimo */
- if (time_fasttimo) {
- tmp_time = (200 - (curtime - time_fasttimo)) * 1000;
- if (tmp_time < 0)
- tmp_time = 0;
-
- /* Choose the smallest of the 2 */
- if (tmp_time < timeout.tv_usec)
- timeout.tv_usec = (u_int)tmp_time;
- }
- }
+ UPD_NFDS(so->s);
+ continue;
+ }
+
+ /*
+ * Set for writing sockets which are connecting
+ */
+ if (so->so_state & SS_ISFCONNECTING) {
+ FD_SET(so->s, writefds);
+ UPD_NFDS(so->s);
+ continue;
+ }
+
+ /*
+ * Set for writing if we are connected, can send more, and
+ * we have something to send
+ */
+ if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
+ FD_SET(so->s, writefds);
+ UPD_NFDS(so->s);
+ }
+
+ /*
+ * Set for reading (and urgent data) if we are connected, can
+ * receive more, and we have room for it XXX /2 ?
+ */
+ if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
+ FD_SET(so->s, readfds);
+ FD_SET(so->s, xfds);
+ UPD_NFDS(so->s);
+ }
+ }
+
+ /*
+ * UDP sockets
+ */
+ for (so = udb.so_next; so != &udb; so = so_next) {
+ so_next = so->so_next;
+
+ if ((so->so_state & SS_PROXIFIED) != 0)
+ continue;
+
+ /*
+ * See if it's timed out
+ */
+ if (so->so_expire) {
+ if (so->so_expire <= curtime) {
+ udp_detach(so);
+ continue;
+ } else
+ do_slowtimo = 1; /* Let socket expire */
+ }
+
+ /*
+ * When UDP packets are received from over the
+ * link, they're sendto()'d straight away, so
+ * no need for setting for writing
+ * Limit the number of packets queued by this session
+ * to 4. Note that even though we try and limit this
+ * to 4 packets, the session could have more queued
+ * if the packets needed to be fragmented
+ * (XXX <= 4 ?)
+ */
+ if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
+ FD_SET(so->s, readfds);
+ UPD_NFDS(so->s);
+ }
+ }
+ }
+
+ /*
+ * Setup timeout to use minimum CPU usage, especially when idle
+ */
+
+ /*
+ * First, see the timeout needed by *timo
+ */
+ timeout.tv_sec = 0;
+ timeout.tv_usec = -1;
+ /*
+ * If a slowtimo is needed, set timeout to 500ms from the last
+ * slow timeout. If a fast timeout is needed, set timeout within
+ * 200ms of when it was requested.
+ */
+ if (do_slowtimo) {
+ /* XXX + 10000 because some select()'s aren't that accurate */
+ timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000;
+ if (timeout.tv_usec < 0)
+ timeout.tv_usec = 0;
+ else if (timeout.tv_usec > 510000)
+ timeout.tv_usec = 510000;
+
+ /* Can only fasttimo if we also slowtimo */
+ if (time_fasttimo) {
+ tmp_time = (200 - (curtime - time_fasttimo)) * 1000;
+ if (tmp_time < 0)
+ tmp_time = 0;
+
+ /* Choose the smallest of the 2 */
+ if (tmp_time < timeout.tv_usec)
+ timeout.tv_usec = (u_int)tmp_time;
+ }
+ }
+
+ /*
+ * now, the proxified sockets
+ */
+ proxy_manager_select_fill(&nfds, readfds, writefds, xfds);
+
*pnfds = nfds;
-}
+}
void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
{
@@ -350,9 +422,9 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
/* Update time */
updtime();
-
+
/*
- * See if anything has timed out
+ * See if anything has timed out
*/
if (link_up) {
if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
@@ -365,7 +437,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
last_slowtimo = curtime;
}
}
-
+
/*
* Check sockets
*/
@@ -375,14 +447,21 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
*/
for (so = tcb.so_next; so != &tcb; so = so_next) {
so_next = so->so_next;
-
+
/*
* FD_ISSET is meaningless on these sockets
* (and they can crash the program)
*/
if (so->so_state & SS_NOFDREF || so->s == -1)
continue;
-
+
+ /*
+ * proxified sockets are polled later in this
+ * function.
+ */
+ if ((so->so_state & SS_PROXIFIED) != 0)
+ continue;
+
/*
* Check for URG data
* This will soread as well, so no need to
@@ -402,12 +481,12 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
continue;
} /* else */
ret = soread(so);
-
+
/* Output it if we read something */
if (ret > 0)
tcp_output(sototcpcb(so));
}
-
+
/*
* Check sockets for writing
*/
@@ -418,34 +497,34 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
if (so->so_state & SS_ISFCONNECTING) {
/* Connected */
so->so_state &= ~SS_ISFCONNECTING;
-
- ret = send(so->s, &ret, 0, 0);
+
+ ret = send(so->s, (char*)&ret, 0, 0);
if (ret < 0) {
/* XXXXX Must fix, zero bytes is a NOP */
if (errno == EAGAIN || errno == EWOULDBLOCK ||
errno == EINPROGRESS || errno == ENOTCONN)
continue;
-
+
/* else failed */
so->so_state = SS_NOFDREF;
}
/* else so->so_state &= ~SS_ISFCONNECTING; */
-
+
/*
* Continue tcp_input
*/
- tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
+ tcp_input((MBuf )NULL, sizeof(struct ip), so);
/* continue; */
} else
ret = sowrite(so);
/*
- * XXXXX If we wrote something (a lot), there
+ * XXXXX If we wrote something (a lot), there
* could be a need for a window update.
* In the worst case, the remote will send
* a window probe to get things going again
*/
}
-
+
/*
* Probe a still-connecting, non-blocking socket
* to check if it's still alive
@@ -453,16 +532,16 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
#ifdef PROBE_CONN
if (so->so_state & SS_ISFCONNECTING) {
ret = recv(so->s, (char *)&ret, 0,0);
-
+
if (ret < 0) {
/* XXX */
if (errno == EAGAIN || errno == EWOULDBLOCK ||
errno == EINPROGRESS || errno == ENOTCONN)
continue; /* Still connecting, continue */
-
+
/* else failed */
so->so_state = SS_NOFDREF;
-
+
/* tcp_input will take care of it */
} else {
ret = send(so->s, &ret, 0,0);
@@ -475,13 +554,13 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
so->so_state = SS_NOFDREF;
} else
so->so_state &= ~SS_ISFCONNECTING;
-
+
}
- tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
+ tcp_input((MBuf )NULL, sizeof(struct ip),so);
} /* SS_ISFCONNECTING */
#endif
}
-
+
/*
* Now UDP sockets.
* Incoming packets are sent straight away, they're not buffered.
@@ -489,13 +568,21 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
*/
for (so = udb.so_next; so != &udb; so = so_next) {
so_next = so->so_next;
-
+
+ if ((so->so_state & SS_PROXIFIED) != 0)
+ continue;
+
if (so->s != -1 && FD_ISSET(so->s, readfds)) {
sorecvfrom(so);
}
}
}
-
+
+ /*
+ * Now the proxified sockets
+ */
+ proxy_manager_poll(readfds, writefds, xfds);
+
/*
* See if we can start outputting
*/
@@ -521,7 +608,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
#define ARPOP_REQUEST 1 /* ARP request */
#define ARPOP_REPLY 2 /* ARP reply */
-struct ethhdr
+struct ethhdr
{
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
unsigned char h_source[ETH_ALEN]; /* source ether addr */
@@ -553,18 +640,13 @@ void arp_input(const uint8_t *pkt, int pkt_len)
struct ethhdr *reh = (struct ethhdr *)arp_reply;
struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);
int ar_op;
- struct ex_list *ex_ptr;
ar_op = ntohs(ah->ar_op);
switch(ar_op) {
case ARPOP_REQUEST:
if (!memcmp(ah->ar_tip, &special_addr, 3)) {
- if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS)
+ if ( CTL_IS_DNS(ah->ar_tip[3]) || ah->ar_tip[3] == CTL_ALIAS)
goto arp_ok;
- for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
- if (ex_ptr->ex_addr == ah->ar_tip[3])
- goto arp_ok;
- }
return;
arp_ok:
/* XXX: make an ARP request to have the client address */
@@ -595,19 +677,19 @@ void arp_input(const uint8_t *pkt, int pkt_len)
void slirp_input(const uint8_t *pkt, int pkt_len)
{
- struct mbuf *m;
+ MBuf m;
int proto;
if (pkt_len < ETH_HLEN)
return;
-
+
proto = ntohs(*(uint16_t *)(pkt + 12));
switch(proto) {
case ETH_P_ARP:
arp_input(pkt, pkt_len);
break;
case ETH_P_IP:
- m = m_get();
+ m = mbuf_alloc();
if (!m)
return;
/* Note: we add to align the IP header */
@@ -642,24 +724,26 @@ void if_encap(const uint8_t *ip_data, int ip_data_len)
slirp_output(buf, ip_data_len + ETH_HLEN);
}
-int slirp_redir(int is_udp, int host_port,
+int slirp_redir(int is_udp, int host_port,
struct in_addr guest_addr, int guest_port)
{
if (is_udp) {
- if (!udp_listen(htons(host_port), guest_addr.s_addr,
+ if (!udp_listen(htons(host_port), guest_addr.s_addr,
htons(guest_port), 0))
return -1;
} else {
- if (!solisten(htons(host_port), guest_addr.s_addr,
+ if (!solisten(htons(host_port), guest_addr.s_addr,
htons(guest_port), 0))
return -1;
}
return 0;
}
-int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
- int guest_port)
+int slirp_unredir(int is_udp, int host_port)
{
- return add_exec(&exec_list, do_pty, (char *)args,
- addr_low_byte, htons(guest_port));
+ if (is_udp)
+ return udp_unlisten( host_port );
+ else
+ return sounlisten( host_port );
}
+
diff --git a/slirp/slirp.h b/slirp/slirp.h
index 1ff68cb..50c0a77 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -272,28 +272,28 @@ extern int do_echo;
#define DEFAULT_BAUD 115200
/* cksum.c */
-int cksum(struct mbuf *m, int len);
+int cksum(MBuf m, int len);
/* if.c */
void if_init _P((void));
-void if_output _P((struct socket *, struct mbuf *));
+void if_output _P((struct socket *, MBuf ));
/* ip_input.c */
void ip_init _P((void));
-void ip_input _P((struct mbuf *));
+void ip_input _P((MBuf ));
struct ip * ip_reass _P((register struct ipasfrag *, register struct ipq *));
void ip_freef _P((struct ipq *));
void ip_enq _P((register struct ipasfrag *, register struct ipasfrag *));
void ip_deq _P((register struct ipasfrag *));
void ip_slowtimo _P((void));
-void ip_stripoptions _P((register struct mbuf *, struct mbuf *));
+void ip_stripoptions _P((register MBuf , MBuf ));
/* ip_output.c */
-int ip_output _P((struct socket *, struct mbuf *));
+int ip_output _P((struct socket *, MBuf ));
/* tcp_input.c */
-int tcp_reass _P((register struct tcpcb *, register struct tcpiphdr *, struct mbuf *));
-void tcp_input _P((register struct mbuf *, int, struct socket *));
+int tcp_reass _P((register struct tcpcb *, register struct tcpiphdr *, MBuf ));
+void tcp_input _P((register MBuf , int, struct socket *));
void tcp_dooptions _P((struct tcpcb *, u_char *, int, struct tcpiphdr *));
void tcp_xmit_timer _P((register struct tcpcb *, int));
int tcp_mss _P((register struct tcpcb *, u_int));
@@ -305,7 +305,7 @@ void tcp_setpersist _P((register struct tcpcb *));
/* tcp_subr.c */
void tcp_init _P((void));
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 MBuf , tcp_seq, tcp_seq, int));
struct tcpcb * tcp_newtcpcb _P((struct socket *));
struct tcpcb * tcp_close _P((register struct tcpcb *));
void tcp_drain _P((void));
@@ -314,7 +314,7 @@ int tcp_fconnect _P((struct socket *));
void tcp_connect _P((struct socket *));
int tcp_attach _P((struct socket *));
u_int8_t tcp_tos _P((struct socket *));
-int tcp_emu _P((struct socket *, struct mbuf *));
+int tcp_emu _P((struct socket *, MBuf ));
int tcp_ctl _P((struct socket *));
struct tcpcb *tcp_drop(struct tcpcb *tp, int err);
diff --git a/slirp/socket.c b/slirp/socket.c
index 0ae1f87..8ddc95c 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 1995 Danny Gasparovski.
- *
- * Please read the file COPYRIGHT for the
+ *
+ * Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
@@ -12,6 +12,9 @@
#ifdef __sun__
#include <sys/filio.h>
#endif
+#define SLIRP_COMPILATION
+#include "sockets.h"
+#include "proxy_common.h"
void
so_init()
@@ -29,19 +32,19 @@ solookup(head, laddr, lport, faddr, fport)
u_int fport;
{
struct socket *so;
-
+
for (so = head->so_next; so != head; so = so->so_next) {
- if (so->so_lport == lport &&
+ if (so->so_lport == lport &&
so->so_laddr.s_addr == laddr.s_addr &&
so->so_faddr.s_addr == faddr.s_addr &&
so->so_fport == fport)
break;
}
-
+
if (so == head)
return (struct socket *)NULL;
return so;
-
+
}
/*
@@ -53,7 +56,7 @@ struct socket *
socreate()
{
struct socket *so;
-
+
so = (struct socket *)malloc(sizeof(struct socket));
if(so) {
memset(so, 0, sizeof(struct socket));
@@ -70,7 +73,10 @@ void
sofree(so)
struct socket *so;
{
- if (so->so_emu==EMU_RSH && so->extra) {
+ if (so->so_state & SS_PROXIFIED)
+ proxy_manager_del(so->s);
+
+ if (so->extra) {
sofree(so->extra);
so->extra=NULL;
}
@@ -78,10 +84,10 @@ sofree(so)
tcp_last_so = &tcb;
else if (so == udp_last_so)
udp_last_so = &udb;
-
- m_free(so->so_m);
-
- if(so->so_next && so->so_prev)
+
+ mbuf_free(so->so_m);
+
+ if(so->so_next && so->so_prev)
remque(so); /* crashes if so is not in a queue */
free(so);
@@ -97,21 +103,21 @@ soread(so)
struct socket *so;
{
int n, nn, lss, total;
- struct sbuf *sb = &so->so_snd;
- int len = sb->sb_datalen - sb->sb_cc;
+ SBuf sb = &so->so_snd;
+ int len = sb->sb_datalen - sb->sb_cc;
struct iovec iov[2];
int mss = so->so_tcpcb->t_maxseg;
-
+
DEBUG_CALL("soread");
DEBUG_ARG("so = %lx", (long )so);
-
- /*
+
+ /*
* No need to check if there's enough room to read.
* soread wouldn't have been called if there weren't
*/
-
+
len = sb->sb_datalen - sb->sb_cc;
-
+
iov[0].iov_base = sb->sb_wptr;
if (sb->sb_wptr < sb->sb_rptr) {
iov[0].iov_len = sb->sb_rptr - sb->sb_wptr;
@@ -150,13 +156,13 @@ soread(so)
n = 1;
}
}
-
+
#ifdef HAVE_READV
nn = readv(so->s, (struct iovec *)iov, n);
DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
#else
nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
-#endif
+#endif
if (nn <= 0) {
if (nn < 0 && (errno == EINTR || errno == EAGAIN))
return 0;
@@ -167,7 +173,7 @@ soread(so)
return -1;
}
}
-
+
#ifndef HAVE_READV
/*
* If there was no error, try and read the second time round
@@ -184,10 +190,10 @@ soread(so)
if (ret > 0)
nn += ret;
}
-
+
DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
#endif
-
+
/* Update fields */
sb->sb_cc += nn;
sb->sb_wptr += nn;
@@ -195,10 +201,10 @@ soread(so)
sb->sb_wptr -= sb->sb_datalen;
return nn;
}
-
+
/*
* Get urgent data
- *
+ *
* When the socket is created, we set it SO_OOBINLINE,
* so when OOB data arrives, we soread() it and everything
* in the send buffer is sent as urgent data
@@ -211,13 +217,13 @@ sorecvoob(so)
DEBUG_CALL("sorecvoob");
DEBUG_ARG("so = %lx", (long)so);
-
+
/*
* We take a guess at how much urgent data has arrived.
* In most situations, when urgent data arrives, the next
* read() should get all the urgent data. This guess will
* be wrong however if more data arrives just after the
- * urgent data, or the read() doesn't return all the
+ * urgent data, or the read() doesn't return all the
* urgent data.
*/
soread(so);
@@ -235,26 +241,25 @@ int
sosendoob(so)
struct socket *so;
{
- struct sbuf *sb = &so->so_rcv;
- char buff[2048]; /* XXX Shouldn't be sending more oob data than this */
-
- int n, len;
-
+ SBuf sb = &so->so_rcv;
+ char buff[2048]; /* XXX Shouldn't be sending more oob data than this */
+ int n, len;
+
DEBUG_CALL("sosendoob");
DEBUG_ARG("so = %lx", (long)so);
DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc);
-
+
if (so->so_urgc > 2048)
so->so_urgc = 2048; /* XXXX */
-
+
if (sb->sb_rptr < sb->sb_wptr) {
/* We can send it directly */
n = send(so->s, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */
so->so_urgc -= n;
-
+
DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
} else {
- /*
+ /*
* Since there's no sendv or sendtov like writev,
* we must copy all data to a linear buffer then
* send it all
@@ -274,34 +279,34 @@ sosendoob(so)
#ifdef DEBUG
if (n != len)
DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n"));
-#endif
+#endif
DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
}
-
+
sb->sb_cc -= n;
sb->sb_rptr += n;
if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
sb->sb_rptr -= sb->sb_datalen;
-
+
return n;
}
/*
- * Write data from so_rcv to so's socket,
+ * Write data from so_rcv to so's socket,
* updating all sbuf field as necessary
*/
int
sowrite(so)
struct socket *so;
{
- int n,nn;
- struct sbuf *sb = &so->so_rcv;
- int len = sb->sb_cc;
+ int n,nn;
+ SBuf sb = &so->so_rcv;
+ int len = sb->sb_cc;
struct iovec iov[2];
-
+
DEBUG_CALL("sowrite");
DEBUG_ARG("so = %lx", (long)so);
-
+
if (so->so_urgc) {
sosendoob(so);
if (sb->sb_cc == 0)
@@ -312,9 +317,9 @@ sowrite(so)
* No need to check if there's something to write,
* sowrite wouldn't have been called otherwise
*/
-
+
len = sb->sb_cc;
-
+
iov[0].iov_base = sb->sb_rptr;
if (sb->sb_rptr < sb->sb_wptr) {
iov[0].iov_len = sb->sb_wptr - sb->sb_rptr;
@@ -337,7 +342,7 @@ sowrite(so)
#ifdef HAVE_READV
nn = writev(so->s, (const struct iovec *)iov, n);
-
+
DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
#else
nn = send(so->s, iov[0].iov_base, iov[0].iov_len,0);
@@ -345,7 +350,7 @@ sowrite(so)
/* This should never happen, but people tell me it does *shrug* */
if (nn < 0 && (errno == EAGAIN || errno == EINTR))
return 0;
-
+
if (nn <= 0) {
DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n",
so->so_state, errno));
@@ -353,7 +358,7 @@ sowrite(so)
tcp_sockclosed(sototcpcb(so));
return -1;
}
-
+
#ifndef HAVE_READV
if (n == 2 && nn == iov[0].iov_len) {
int ret;
@@ -363,20 +368,20 @@ sowrite(so)
}
DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
#endif
-
+
/* Update sbuf */
sb->sb_cc -= nn;
sb->sb_rptr += nn;
if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
sb->sb_rptr -= sb->sb_datalen;
-
+
/*
* If in DRAIN mode, and there's no more data, set
* it CANTSENDMORE
*/
if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0)
sofcantsendmore(so);
-
+
return nn;
}
@@ -389,68 +394,68 @@ sorecvfrom(so)
{
struct sockaddr_in addr;
int addrlen = sizeof(struct sockaddr_in);
-
+
DEBUG_CALL("sorecvfrom");
DEBUG_ARG("so = %lx", (long)so);
-
+
if (so->so_type == IPPROTO_ICMP) { /* This is a "ping" reply */
char buff[256];
int len;
-
- len = recvfrom(so->s, buff, 256, 0,
+
+ len = recvfrom(so->s, buff, 256, 0,
(struct sockaddr *)&addr, &addrlen);
/* XXX Check if reply is "correct"? */
-
+
if(len == -1 || len == 0) {
u_char code=ICMP_UNREACH_PORT;
if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
-
+
DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n",
errno,strerror(errno)));
icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
} else {
icmp_reflect(so->so_m);
- so->so_m = 0; /* Don't m_free() it again! */
+ so->so_m = 0; /* Don't mbuf_free() it again! */
}
/* No need for this socket anymore, udp_detach it */
udp_detach(so);
} else { /* A "normal" UDP packet */
- struct mbuf *m;
+ MBuf m;
int len, n;
- if (!(m = m_get())) return;
+ if (!(m = mbuf_alloc())) return;
m->m_data += if_maxlinkhdr;
-
- /*
+
+ /*
* XXX Shouldn't FIONREAD packets destined for port 53,
* but I don't know the max packet size for DNS lookups
*/
- len = M_FREEROOM(m);
+ len = mbuf_freeroom(m);
/* if (so->so_fport != htons(53)) { */
ioctlsocket(so->s, FIONREAD, &n);
-
+
if (n > len) {
n = (m->m_data - m->m_dat) + m->m_len + n + 1;
- m_inc(m, n);
- len = M_FREEROOM(m);
+ mbuf_ensure(m, n);
+ len = mbuf_freeroom(m);
}
/* } */
-
+
m->m_len = recvfrom(so->s, m->m_data, len, 0,
(struct sockaddr *)&addr, &addrlen);
- DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n",
+ DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n",
m->m_len, errno,strerror(errno)));
if(m->m_len<0) {
u_char code=ICMP_UNREACH_PORT;
if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
-
+
DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));
icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
- m_free(m);
+ mbuf_free(m);
} else {
/*
* Hack: domain name lookup will be used the most for UDP,
@@ -466,12 +471,12 @@ sorecvfrom(so)
}
/* if (m->m_len == len) {
- * m_inc(m, MINCSIZE);
+ * mbuf_ensure(m, MINCSIZE);
* m->m_len = 0;
* }
*/
-
- /*
+
+ /*
* If this packet was destined for CTL_ADDR,
* make it look like that's where it came from, done by udp_output
*/
@@ -486,7 +491,7 @@ sorecvfrom(so)
int
sosendto(so, m)
struct socket *so;
- struct mbuf *m;
+ MBuf m;
{
int ret;
struct sockaddr_in addr;
@@ -494,31 +499,28 @@ sosendto(so, m)
DEBUG_CALL("sosendto");
DEBUG_ARG("so = %lx", (long)so);
DEBUG_ARG("m = %lx", (long)m);
-
+
addr.sin_family = AF_INET;
if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
/* It's an alias */
- switch(ntohl(so->so_faddr.s_addr) & 0xff) {
- case CTL_DNS:
- addr.sin_addr = dns_addr;
- break;
- case CTL_ALIAS:
- default:
- addr.sin_addr = loopback_addr;
- break;
- }
+ int low = ntohl(so->so_faddr.s_addr) & 0xff;
+
+ if ( CTL_IS_DNS(low) )
+ addr.sin_addr = dns_addr[low - CTL_DNS];
+ else
+ addr.sin_addr = loopback_addr;
} else
addr.sin_addr = so->so_faddr;
addr.sin_port = so->so_fport;
DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n", ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
-
+
/* Don't care what port we get */
ret = sendto(so->s, m->m_data, m->m_len, 0,
(struct sockaddr *)&addr, sizeof (struct sockaddr));
if (ret < 0)
return -1;
-
+
/*
* Kill the socket if there's no reply in 4 minutes,
* but only if it's an expirable socket
@@ -548,39 +550,47 @@ solisten(port, laddr, lport, flags)
DEBUG_ARG("laddr = %x", laddr);
DEBUG_ARG("lport = %d", lport);
DEBUG_ARG("flags = %x", flags);
-
+
if ((so = socreate()) == NULL) {
/* free(so); Not sofree() ??? free(NULL) == NOP */
return NULL;
}
-
+
/* Don't tcp_attach... we don't need so_snd nor so_rcv */
if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) {
free(so);
return NULL;
}
insque(so,&tcb);
-
- /*
+
+ /*
* SS_FACCEPTONCE sockets must time out.
*/
if (flags & SS_FACCEPTONCE)
so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;
-
+
so->so_state = (SS_FACCEPTCONN|flags);
so->so_lport = lport; /* Kept in network format */
+ so->so_hport = port;
so->so_laddr.s_addr = laddr; /* Ditto */
-
+
+ memset( &addr, 0, sizeof(addr) );
addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = INADDR_ANY;
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr.sin_port = port;
-
- if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) ||
- (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||
- (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||
+
+ if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) {
+ sofree(so);
+ return NULL;
+ }
+
+ socket_set_xreuseaddr(s);
+
+ if ((socket_set_xreuseaddr(s) < 0) ||
+ (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||
(listen(s,1) < 0)) {
int tmperrno = errno; /* Don't clobber the real reason we failed */
-
+
close(s);
sofree(so);
/* Restore the real errno */
@@ -591,8 +601,8 @@ solisten(port, laddr, lport, flags)
#endif
return NULL;
}
- setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
-
+ socket_set_oobinline(s);
+
getsockname(s,(struct sockaddr *)&addr,&addrlen);
so->so_fport = addr.sin_port;
if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
@@ -604,7 +614,32 @@ solisten(port, laddr, lport, flags)
return so;
}
-/*
+
+int
+sounlisten(u_int port)
+{
+ struct socket *so;
+
+ for (so = tcb.so_next; so != &tcb; so = so->so_next) {
+ if (so->so_hport == htons(port)) {
+ break;
+ }
+ }
+
+ if (so == &tcb) {
+ return -1;
+ }
+
+ sofcantrcvmore( so );
+ sofcantsendmore( so );
+ close( so->s );
+ so->s = -1;
+ sofree( so );
+ return 0;
+}
+
+
+/*
* Data is available in so_rcv
* Just write() the data to the socket
* XXX not yet...
@@ -616,7 +651,7 @@ sorwakeup(so)
/* sowrite(so); */
/* FD_CLR(so->s,&writefds); */
}
-
+
/*
* Data has been freed in so_snd
* We have room for a read() if we want to
diff --git a/slirp/socket.h b/slirp/socket.h
index d05354c..54cb21c 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -1,7 +1,7 @@
/*
* Copyright (c) 1995 Danny Gasparovski.
- *
- * Please read the file COPYRIGHT for the
+ *
+ * Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
@@ -23,7 +23,7 @@ struct socket {
int s; /* The actual socket */
/* XXX union these with not-yet-used sbuf params */
- struct mbuf *so_m; /* Pointer to the original SYN packet,
+ MBuf so_m; /* Pointer to the original SYN packet,
* for non-blocking connect()'s, and
* PING reply's */
struct tcpiphdr *so_ti; /* Pointer to the original ti within
@@ -33,23 +33,24 @@ struct socket {
struct in_addr so_laddr; /* local host table entry */
u_int16_t so_fport; /* foreign port */
u_int16_t so_lport; /* local port */
-
+ u_int16_t so_hport;
+
u_int8_t so_iptos; /* Type of service */
u_int8_t so_emu; /* Is the socket emulated? */
-
+
u_char so_type; /* Type of socket, UDP or TCP */
int so_state; /* internal state flags SS_*, below */
-
+
struct tcpcb *so_tcpcb; /* pointer to TCP protocol control block */
u_int so_expire; /* When the socket will expire */
-
+
int so_queued; /* Number of packets queued from this socket */
int so_nqueued; /* Number of packets queued in a row
* Used to determine when to "downgrade" a session
* from fastq to batchq */
-
- struct sbuf so_rcv; /* Receive buffer */
- struct sbuf so_snd; /* Send buffer */
+
+ SBufRec so_rcv; /* Receive buffer */
+ SBufRec so_snd; /* Send buffer */
void * extra; /* Extra pointer */
};
@@ -70,7 +71,8 @@ struct socket {
#define SS_CTL 0x080
#define SS_FACCEPTCONN 0x100 /* Socket is accepting connections from a host on the internet */
#define SS_FACCEPTONCE 0x200 /* If set, the SS_FACCEPTCONN socket will die after one accept */
-
+#define SS_PROXIFIED 0x400 /* Socket is trying to connect through a proxy, only makes sense
+ when SS_ISFCONNECTING is also set */
extern struct socket tcb;
@@ -90,8 +92,9 @@ void sorecvoob _P((struct socket *));
int sosendoob _P((struct socket *));
int sowrite _P((struct socket *));
void sorecvfrom _P((struct socket *));
-int sosendto _P((struct socket *, struct mbuf *));
+int sosendto _P((struct socket *, MBuf ));
struct socket * solisten _P((u_int, u_int32_t, u_int, int));
+int sounlisten _P((u_int port));
void sorwakeup _P((struct socket *));
void sowwakeup _P((struct socket *));
void soisfconnecting _P((register struct socket *));
diff --git a/slirp/tcp.h b/slirp/tcp.h
index cd7e891..769f364 100644
--- a/slirp/tcp.h
+++ b/slirp/tcp.h
@@ -112,7 +112,9 @@ struct tcphdr {
/*
* User-settable options (used with setsockopt).
*/
-/* #define TCP_NODELAY 0x01 */ /* don't delay send to coalesce packets */
+#undef TCP_NODELAY
+#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */
+#undef TCP_MAXSEG
/* #define TCP_MAXSEG 0x02 */ /* set maximum segment size */
/*
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index c015161..4621ca2 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -37,8 +37,8 @@
/*
* Changes and additions relating to SLiRP
* Copyright (c) 1995 Danny Gasparovski.
- *
- * Please read the file COPYRIGHT for the
+ *
+ * Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
@@ -82,9 +82,9 @@ tcp_seq tcp_iss; /* tcp initial send seq # */
tcpstat.tcps_rcvpack++;\
tcpstat.tcps_rcvbyte += (ti)->ti_len;\
if (so->so_emu) { \
- if (tcp_emu((so),(m))) sbappend((so), (m)); \
+ if (tcp_emu((so),(m))) sbuf_append((so), (m)); \
} else \
- sbappend((so), (m)); \
+ sbuf_append((so), (m)); \
/* sorwakeup(so); */ \
} else {\
(flags) = tcp_reass((tp), (ti), (m)); \
@@ -102,9 +102,9 @@ tcp_seq tcp_iss; /* tcp initial send seq # */
tcpstat.tcps_rcvpack++;\
tcpstat.tcps_rcvbyte += (ti)->ti_len;\
if (so->so_emu) { \
- if (tcp_emu((so),(m))) sbappend(so, (m)); \
+ if (tcp_emu((so),(m))) sbuf_append(so, (m)); \
} else \
- sbappend((so), (m)); \
+ sbuf_append((so), (m)); \
/* sorwakeup(so); */ \
} else { \
(flags) = tcp_reass((tp), (ti), (m)); \
@@ -117,12 +117,12 @@ int
tcp_reass(tp, ti, m)
register struct tcpcb *tp;
register struct tcpiphdr *ti;
- struct mbuf *m;
+ MBuf m;
{
register struct tcpiphdr *q;
struct socket *so = tp->t_socket;
int flags;
-
+
/*
* Call with ti==0 after become established to
* force pre-ESTABLISHED data up to user socket.
@@ -152,7 +152,7 @@ tcp_reass(tp, ti, m)
if (i >= ti->ti_len) {
tcpstat.tcps_rcvduppack++;
tcpstat.tcps_rcvdupbyte += ti->ti_len;
- m_freem(m);
+ mbuf_free(m);
/*
* Try to present any queued data
* at the left window edge to the user.
@@ -161,7 +161,7 @@ tcp_reass(tp, ti, m)
*/
goto present; /* ??? */
}
- m_adj(m, i);
+ mbuf_trim(m, i);
ti->ti_len -= i;
ti->ti_seq += i;
}
@@ -182,13 +182,13 @@ tcp_reass(tp, ti, m)
if (i < q->ti_len) {
q->ti_seq += i;
q->ti_len -= i;
- m_adj((struct mbuf *) REASS_MBUF(q), i);
+ mbuf_trim((MBuf ) REASS_MBUF(q), i);
break;
}
q = (struct tcpiphdr *)q->ti_next;
- m = (struct mbuf *) REASS_MBUF((struct tcpiphdr *)q->ti_prev);
+ m = (MBuf ) REASS_MBUF((struct tcpiphdr *)q->ti_prev);
remque_32((void *)(q->ti_prev));
- m_freem(m);
+ mbuf_free(m);
}
/*
@@ -212,16 +212,16 @@ present:
tp->rcv_nxt += ti->ti_len;
flags = ti->ti_flags & TH_FIN;
remque_32(ti);
- m = (struct mbuf *) REASS_MBUF(ti); /* XXX */
+ m = (MBuf ) REASS_MBUF(ti); /* XXX */
ti = (struct tcpiphdr *)ti->ti_next;
/* if (so->so_state & SS_FCANTRCVMORE) */
if (so->so_state & SS_FCANTSENDMORE)
- m_freem(m);
+ mbuf_free(m);
else {
if (so->so_emu) {
- if (tcp_emu(so,m)) sbappend(so, m);
+ if (tcp_emu(so,m)) sbuf_append(so, m);
} else
- sbappend(so, m);
+ sbuf_append(so, m);
}
} while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt);
/* sorwakeup(so); */
@@ -234,7 +234,7 @@ present:
*/
void
tcp_input(m, iphlen, inso)
- register struct mbuf *m;
+ register MBuf m;
int iphlen;
struct socket *inso;
{
@@ -254,15 +254,15 @@ tcp_input(m, iphlen, inso)
/* int ts_present = 0; */
DEBUG_CALL("tcp_input");
- DEBUG_ARGS((dfd," m = %8lx iphlen = %2d inso = %lx\n",
+ DEBUG_ARGS((dfd," m = %8lx iphlen = %2d inso = %lx\n",
(long )m, iphlen, (long )inso ));
-
+
/*
* If called with m == 0, then we're continuing the connect
*/
if (m == NULL) {
so = inso;
-
+
/* Re-set a few variables */
tp = sototcpcb(so);
m = so->so_m;
@@ -270,30 +270,30 @@ tcp_input(m, iphlen, inso)
ti = so->so_ti;
tiwin = ti->ti_win;
tiflags = ti->ti_flags;
-
+
goto cont_conn;
}
-
-
+
+
tcpstat.tcps_rcvtotal++;
/*
* Get IP and TCP header together in first mbuf.
* Note: IP leaves IP header in first mbuf.
*/
- ti = mtod(m, struct tcpiphdr *);
+ ti = MBUF_TO(m, struct tcpiphdr *);
if (iphlen > sizeof(struct ip )) {
- ip_stripoptions(m, (struct mbuf *)0);
+ ip_stripoptions(m, (MBuf )0);
iphlen=sizeof(struct ip );
}
/* XXX Check if too short */
-
+
/*
* Save a copy of the IP header in case we want restore it
* for sending an ICMP error message in response.
*/
- ip=mtod(m, struct ip *);
- save_ip = *ip;
+ ip=MBUF_TO(m, struct ip *);
+ save_ip = *ip;
save_ip.ip_len+= iphlen;
/*
@@ -305,7 +305,7 @@ tcp_input(m, iphlen, inso)
ti->ti_len = htons((u_int16_t)tlen);
len = sizeof(struct ip ) + tlen;
/* keep checksum for ICMP reply
- * ti->ti_sum = cksum(m, len);
+ * ti->ti_sum = cksum(m, len);
* if (ti->ti_sum) { */
if(cksum(m, len)) {
tcpstat.tcps_rcvbadsum++;
@@ -325,9 +325,9 @@ tcp_input(m, iphlen, inso)
ti->ti_len = tlen;
if (off > sizeof (struct tcphdr)) {
optlen = off - sizeof (struct tcphdr);
- optp = mtod(m, caddr_t) + sizeof (struct tcpiphdr);
+ optp = MBUF_TO(m, caddr_t) + sizeof (struct tcpiphdr);
- /*
+ /*
* Do quick retrieval of timestamp options ("options
* prediction?"). If timestamp is the only option and it's
* formatted as recommended in RFC 1323 appendix A, we
@@ -347,7 +347,7 @@ tcp_input(m, iphlen, inso)
*/
}
tiflags = ti->ti_flags;
-
+
/*
* Convert TCP protocol specific fields to host format.
*/
@@ -361,7 +361,7 @@ tcp_input(m, iphlen, inso)
*/
m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
m->m_len -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
-
+
/*
* Locate pcb for segment.
*/
@@ -385,8 +385,8 @@ findso:
* but should either do a listen or a connect soon.
*
* state == CLOSED means we've done socreate() but haven't
- * attached it to a protocol yet...
- *
+ * attached it to a protocol yet...
+ *
* XXX If a TCB does not exist, and the TH_SYN flag is
* the only flag set, then create a session, mark it
* as if it was LISTENING, and continue...
@@ -394,32 +394,32 @@ findso:
if (so == 0) {
if ((tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) != TH_SYN)
goto dropwithreset;
-
+
if ((so = socreate()) == NULL)
goto dropwithreset;
if (tcp_attach(so) < 0) {
free(so); /* Not sofree (if it failed, it's not insqued) */
goto dropwithreset;
}
-
- sbreserve(&so->so_snd, tcp_sndspace);
- sbreserve(&so->so_rcv, tcp_rcvspace);
-
+
+ sbuf_reserve(&so->so_snd, tcp_sndspace);
+ sbuf_reserve(&so->so_rcv, tcp_rcvspace);
+
/* tcp_last_so = so; */ /* XXX ? */
/* tp = sototcpcb(so); */
-
+
so->so_laddr = ti->ti_src;
so->so_lport = ti->ti_sport;
so->so_faddr = ti->ti_dst;
so->so_fport = ti->ti_dport;
-
+
if ((so->so_iptos = tcp_tos(so)) == 0)
so->so_iptos = ((struct ip *)ti)->ip_tos;
-
+
tp = sototcpcb(so);
tp->t_state = TCPS_LISTEN;
}
-
+
/*
* If this is a still-connecting socket, this probably
* a retransmit of the SYN. Whether it's a retransmit SYN
@@ -429,13 +429,13 @@ findso:
goto drop;
tp = sototcpcb(so);
-
+
/* XXX Should never fail */
if (tp == 0)
goto dropwithreset;
if (tp->t_state == TCPS_CLOSED)
goto drop;
-
+
/* Unscale the window into a 32-bit value. */
/* if ((tiflags & TH_SYN) == 0)
* tiwin = ti->ti_win << tp->snd_scale;
@@ -458,11 +458,11 @@ findso:
* else do it below (after getting remote address).
*/
if (optp && tp->t_state != TCPS_LISTEN)
- tcp_dooptions(tp, (u_char *)optp, optlen, ti);
+ tcp_dooptions(tp, (u_char *)optp, optlen, ti);
/* , */
/* &ts_present, &ts_val, &ts_ecr); */
- /*
+ /*
* Header prediction: check for the two common cases
* of a uni-directional data xfer. If the packet has
* no control flags, is in-sequence, the window didn't
@@ -486,7 +486,7 @@ findso:
ti->ti_seq == tp->rcv_nxt &&
tiwin && tiwin == tp->snd_wnd &&
tp->snd_nxt == tp->snd_max) {
- /*
+ /*
* If last ACK falls within this segment's sequence numbers,
* record the timestamp.
*/
@@ -506,16 +506,16 @@ findso:
++tcpstat.tcps_predack;
/* if (ts_present)
* tcp_xmit_timer(tp, tcp_now-ts_ecr+1);
- * else
+ * else
*/ if (tp->t_rtt &&
SEQ_GT(ti->ti_ack, tp->t_rtseq))
tcp_xmit_timer(tp, tp->t_rtt);
acked = ti->ti_ack - tp->snd_una;
tcpstat.tcps_rcvackpack++;
tcpstat.tcps_rcvackbyte += acked;
- sbdrop(&so->so_snd, acked);
+ sbuf_drop(&so->so_snd, acked);
tp->snd_una = ti->ti_ack;
- m_freem(m);
+ mbuf_free(m);
/*
* If all outstanding data are acked, stop
@@ -531,14 +531,14 @@ findso:
else if (tp->t_timer[TCPT_PERSIST] == 0)
tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
- /*
+ /*
* There's room in so_snd, sowwakup will read()
* from the socket if we can
*/
/* if (so->so_snd.sb_flags & SB_NOTIFY)
* sowwakeup(so);
*/
- /*
+ /*
* This is called because sowwakeup might have
* put data into so_snd. Since we don't so sowwakeup,
* we don't need this.. XXX???
@@ -550,7 +550,7 @@ findso:
}
} else if (ti->ti_ack == tp->snd_una &&
tp->seg_next == (tcpiphdrp_32)tp &&
- ti->ti_len <= sbspace(&so->so_rcv)) {
+ ti->ti_len <= sbuf_space(&so->so_rcv)) {
/*
* this is a pure, in-sequence data packet
* with nothing on the reassembly queue and
@@ -564,25 +564,25 @@ findso:
* Add data to socket buffer.
*/
if (so->so_emu) {
- if (tcp_emu(so,m)) sbappend(so, m);
+ if (tcp_emu(so,m)) sbuf_append(so, m);
} else
- sbappend(so, m);
-
- /*
+ sbuf_append(so, m);
+
+ /*
* XXX This is called when data arrives. Later, check
* if we can actually write() to the socket
* XXX Need to check? It's be NON_BLOCKING
*/
/* sorwakeup(so); */
-
+
/*
* If this is a short packet, then ACK now - with Nagel
* congestion avoidance sender won't send more until
* he gets an ACK.
- *
+ *
* It is better to not delay acks at all to maximize
* TCP throughput. See RFC 2581.
- */
+ */
tp->t_flags |= TF_ACKNOW;
tcp_output(tp);
return;
@@ -595,7 +595,7 @@ findso:
* but not less than advertised window.
*/
{ int win;
- win = sbspace(&so->so_rcv);
+ win = sbuf_space(&so->so_rcv);
if (win < 0)
win = 0;
tp->rcv_wnd = max(win, (int)(tp->rcv_adv - tp->rcv_nxt));
@@ -624,46 +624,26 @@ findso:
goto dropwithreset;
if ((tiflags & TH_SYN) == 0)
goto drop;
-
+
/*
* This has way too many gotos...
* But a bit of spaghetti code never hurt anybody :)
*/
-
+
/*
* If this is destined for the control address, then flag to
* tcp_ctl once connected, otherwise connect
*/
if ((so->so_faddr.s_addr&htonl(0xffffff00)) == special_addr.s_addr) {
int lastbyte=ntohl(so->so_faddr.s_addr) & 0xff;
- if (lastbyte!=CTL_ALIAS && lastbyte!=CTL_DNS) {
-#if 0
- if(lastbyte==CTL_CMD || lastbyte==CTL_EXEC) {
- /* Command or exec adress */
- so->so_state |= SS_CTL;
- } else
-#endif
- {
- /* May be an add exec */
- struct ex_list *ex_ptr;
- for(ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
- if(ex_ptr->ex_fport == so->so_fport &&
- lastbyte == ex_ptr->ex_addr) {
- so->so_state |= SS_CTL;
- break;
- }
- }
- }
- if(so->so_state & SS_CTL) goto cont_input;
- }
/* CTL_ALIAS: Do nothing, tcp_fconnect will be called on it */
}
-
+
if (so->so_emu & EMU_NOCONNECT) {
so->so_emu &= ~EMU_NOCONNECT;
goto cont_input;
}
-
+
if((tcp_fconnect(so) == -1) && (errno != EINPROGRESS) && (errno != EWOULDBLOCK)) {
u_char code=ICMP_UNREACH_NET;
DEBUG_MISC((dfd," tcp fconnect errno = %d-%s\n",
@@ -671,7 +651,7 @@ findso:
if(errno == ECONNREFUSED) {
/* ACK the SYN, send RST to refuse the connection */
tcp_respond(tp, ti, m, ti->ti_seq+1, (tcp_seq)0,
- TH_RST|TH_ACK);
+ TH_RST|TH_ACK);
} else {
if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
HTONL(ti->ti_seq); /* restore tcp header */
@@ -684,7 +664,7 @@ findso:
icmp_error(m, ICMP_UNREACH,code, 0,strerror(errno));
}
tp = tcp_close(tp);
- m_free(m);
+ mbuf_free(m);
} else {
/*
* Haven't connected yet, save the current mbuf
@@ -699,25 +679,26 @@ findso:
}
return;
- cont_conn:
- /* m==NULL
+ cont_conn:
+ /* m==NULL
* Check if the connect succeeded
*/
if (so->so_state & SS_NOFDREF) {
+ DEBUG_MISC((dfd, " tcp_input closing connecting socket %lx\n", (long)so));
tp = tcp_close(tp);
goto dropwithreset;
}
- cont_input:
+ cont_input:
tcp_template(tp);
-
+
if (optp)
tcp_dooptions(tp, (u_char *)optp, optlen, ti);
/* , */
/* &ts_present, &ts_val, &ts_ecr); */
-
+
if (iss)
tp->iss = iss;
- else
+ else
tp->iss = tcp_iss;
tcp_iss += TCP_ISSINCR/2;
tp->irs = ti->ti_seq;
@@ -727,9 +708,10 @@ findso:
tp->t_state = TCPS_SYN_RECEIVED;
tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
tcpstat.tcps_accepts++;
+ DEBUG_MISC((dfd, " tcp_input accept connected socket %lx\n", (long)so));
goto trimthenstep6;
} /* case TCPS_LISTEN */
-
+
/*
* If the state is SYN_SENT:
* if seg contains an ACK, but not for our SYN, drop the input.
@@ -770,7 +752,7 @@ findso:
tcpstat.tcps_connects++;
soisfconnected(so);
tp->t_state = TCPS_ESTABLISHED;
-
+
/* Do window scaling on this connection? */
/* if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
* (TF_RCVD_SCALE|TF_REQ_SCALE)) {
@@ -779,7 +761,7 @@ findso:
* }
*/
(void) tcp_reass(tp, (struct tcpiphdr *)0,
- (struct mbuf *)0);
+ (MBuf )0);
/*
* if we didn't have to retransmit the SYN,
* use its rtt as our initial srtt & rtt var.
@@ -798,7 +780,7 @@ trimthenstep6:
ti->ti_seq++;
if (ti->ti_len > tp->rcv_wnd) {
todrop = ti->ti_len - tp->rcv_wnd;
- m_adj(m, -todrop);
+ mbuf_trim(m, -todrop);
ti->ti_len = tp->rcv_wnd;
tiflags &= ~TH_FIN;
tcpstat.tcps_rcvpackafterwin++;
@@ -811,10 +793,10 @@ trimthenstep6:
/*
* States other than LISTEN or SYN_SENT.
* First check timestamp, if present.
- * Then check that at least some bytes of segment are within
+ * Then check that at least some bytes of segment are within
* receive window. If segment begins before rcv_nxt,
* drop leading data (and SYN); if nothing left, just ack.
- *
+ *
* RFC 1323 PAWS: If we have a timestamp reply on this segment
* and it's less than ts_recent, drop it.
*/
@@ -849,7 +831,7 @@ trimthenstep6:
if (tiflags & TH_SYN) {
tiflags &= ~TH_SYN;
ti->ti_seq++;
- if (ti->ti_urp > 1)
+ if (ti->ti_urp > 1)
ti->ti_urp--;
else
tiflags &= ~TH_URG;
@@ -866,7 +848,7 @@ trimthenstep6:
* of sequence; drop it.
*/
tiflags &= ~TH_FIN;
-
+
/*
* Send an ACK to resynchronize and drop any data.
* But keep on processing for RST or ACK.
@@ -879,7 +861,7 @@ trimthenstep6:
tcpstat.tcps_rcvpartduppack++;
tcpstat.tcps_rcvpartdupbyte += todrop;
}
- m_adj(m, todrop);
+ mbuf_trim(m, todrop);
ti->ti_seq += todrop;
ti->ti_len -= todrop;
if (ti->ti_urp > todrop)
@@ -936,7 +918,7 @@ trimthenstep6:
goto dropafterack;
} else
tcpstat.tcps_rcvbyteafterwin += todrop;
- m_adj(m, -todrop);
+ mbuf_trim(m, -todrop);
ti->ti_len -= todrop;
tiflags &= ~(TH_PUSH|TH_FIN);
}
@@ -1017,12 +999,12 @@ trimthenstep6:
goto dropwithreset;
tcpstat.tcps_connects++;
tp->t_state = TCPS_ESTABLISHED;
- /*
- * The sent SYN is ack'ed with our sequence number +1
- * The first data byte already in the buffer will get
+ /*
+ * The sent SYN is ack'ed with our sequence number +1
+ * The first data byte already in the buffer will get
* lost if no correction is made. This is only needed for
* SS_CTL since the buffer is empty otherwise.
- * tp->snd_una++; or:
+ * tp->snd_una++; or:
*/
tp->snd_una=ti->ti_ack;
if (so->so_state & SS_CTL) {
@@ -1040,7 +1022,7 @@ trimthenstep6:
} else {
soisfconnected(so);
}
-
+
/* Do window scaling? */
/* if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
* (TF_RCVD_SCALE|TF_REQ_SCALE)) {
@@ -1048,7 +1030,7 @@ trimthenstep6:
* tp->rcv_scale = tp->request_r_scale;
* }
*/
- (void) tcp_reass(tp, (struct tcpiphdr *)0, (struct mbuf *)0);
+ (void) tcp_reass(tp, (struct tcpiphdr *)0, (MBuf )0);
tp->snd_wl1 = ti->ti_seq - 1;
/* Avoid ack processing; snd_una==ti_ack => dup ack */
goto synrx_to_est;
@@ -1094,7 +1076,7 @@ trimthenstep6:
* the new ssthresh).
*
* Dup acks mean that packets have left the
- * network (they're now cached at the receiver)
+ * network (they're now cached at the receiver)
* so bump cwnd by the amount in the receiver
* to keep a constant cwnd packets in the
* network.
@@ -1159,7 +1141,7 @@ trimthenstep6:
/* if (ts_present)
* tcp_xmit_timer(tp, tcp_now-ts_ecr+1);
* else
- */
+ */
if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq))
tcp_xmit_timer(tp,tp->t_rtt);
@@ -1191,16 +1173,16 @@ trimthenstep6:
}
if (acked > so->so_snd.sb_cc) {
tp->snd_wnd -= so->so_snd.sb_cc;
- sbdrop(&so->so_snd, (int )so->so_snd.sb_cc);
+ sbuf_drop(&so->so_snd, (int )so->so_snd.sb_cc);
ourfinisacked = 1;
} else {
- sbdrop(&so->so_snd, acked);
+ sbuf_drop(&so->so_snd, acked);
tp->snd_wnd -= acked;
ourfinisacked = 0;
}
/*
* XXX sowwakup is called when data is acked and there's room for
- * for more data... it should read() the socket
+ * for more data... it should read() the socket
*/
/* if (so->so_snd.sb_flags & SB_NOTIFY)
* sowwakeup(so);
@@ -1278,7 +1260,7 @@ step6:
* Don't look at window if no ACK: TAC's send garbage on first SYN.
*/
if ((tiflags & TH_ACK) &&
- (SEQ_LT(tp->snd_wl1, ti->ti_seq) ||
+ (SEQ_LT(tp->snd_wl1, ti->ti_seq) ||
(tp->snd_wl1 == ti->ti_seq && (SEQ_LT(tp->snd_wl2, ti->ti_ack) ||
(tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd))))) {
/* keep track of pure window updates */
@@ -1313,14 +1295,14 @@ step6:
* If this segment advances the known urgent pointer,
* then mark the data stream. This should not happen
* in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since
- * a FIN has been received from the remote side.
+ * a FIN has been received from the remote side.
* In these states we ignore the URG.
*
* According to RFC961 (Assigned Protocols),
* the urgent pointer points to the last octet
* of urgent data. We continue, however,
* to consider it to indicate the first octet
- * of data past the urgent section as the original
+ * of data past the urgent section as the original
* spec states (in one of two places).
*/
if (SEQ_GT(ti->ti_seq+ti->ti_urp, tp->rcv_up)) {
@@ -1328,7 +1310,7 @@ step6:
so->so_urgc = so->so_rcv.sb_cc +
(tp->rcv_up - tp->rcv_nxt); /* -1; */
tp->rcv_up = ti->ti_seq + ti->ti_urp;
-
+
}
} else
/*
@@ -1358,7 +1340,7 @@ dodata:
*/
len = so->so_rcv.sb_datalen - (tp->rcv_adv - tp->rcv_nxt);
} else {
- m_free(m);
+ mbuf_free(m);
tiflags &= ~TH_FIN;
}
@@ -1379,7 +1361,7 @@ dodata:
*/
/* sofcantrcvmore(so); */
sofwdrain(so);
-
+
tp->t_flags |= TF_ACKNOW;
tp->rcv_nxt++;
}
@@ -1393,7 +1375,7 @@ dodata:
case TCPS_ESTABLISHED:
if(so->so_emu == EMU_CTL) /* no shutdown on socket */
tp->t_state = TCPS_LAST_ACK;
- else
+ else
tp->t_state = TCPS_CLOSE_WAIT;
break;
@@ -1407,7 +1389,7 @@ dodata:
/*
* In FIN_WAIT_2 state enter the TIME_WAIT state,
- * starting the time-wait timer, turning off the other
+ * starting the time-wait timer, turning off the other
* standard timers.
*/
case TCPS_FIN_WAIT_2:
@@ -1430,7 +1412,7 @@ dodata:
* If this is a small packet, then ACK now - with Nagel
* congestion avoidance sender won't send more until
* he gets an ACK.
- *
+ *
* See above.
*/
/* if (ti->ti_len && (unsigned)ti->ti_len < tp->t_maxseg) {
@@ -1460,13 +1442,13 @@ dropafterack:
*/
if (tiflags & TH_RST)
goto drop;
- m_freem(m);
+ mbuf_free(m);
tp->t_flags |= TF_ACKNOW;
(void) tcp_output(tp);
return;
dropwithreset:
- /* reuses m if m!=NULL, m_free() unnecessary */
+ /* reuses m if m!=NULL, mbuf_free() unnecessary */
if (tiflags & TH_ACK)
tcp_respond(tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST);
else {
@@ -1481,7 +1463,7 @@ drop:
/*
* Drop space held by incoming segment and return.
*/
- m_free(m);
+ mbuf_free(m);
return;
}
@@ -1547,7 +1529,7 @@ tcp_dooptions(tp, cp, cnt, ti)
* memcpy((char *) ts_ecr, (char *)cp + 6, sizeof(*ts_ecr));
* NTOHL(*ts_ecr);
*
- */ /*
+ */ /*
* * A timestamp received in a SYN makes
* * it ok to send timestamp requests and replies.
* */
@@ -1575,13 +1557,13 @@ void
tcp_pulloutofband(so, ti, m)
struct socket *so;
struct tcpiphdr *ti;
- register struct mbuf *m;
+ register MBuf m;
{
int cnt = ti->ti_urp - 1;
-
+
while (cnt >= 0) {
if (m->m_len > cnt) {
- char *cp = mtod(m, caddr_t) + cnt;
+ char *cp = MBUF_TO(m, caddr_t) + cnt;
struct tcpcb *tp = sototcpcb(so);
tp->t_iobc = *cp;
@@ -1615,7 +1597,7 @@ tcp_xmit_timer(tp, rtt)
DEBUG_CALL("tcp_xmit_timer");
DEBUG_ARG("tp = %lx", (long)tp);
DEBUG_ARG("rtt = %d", rtt);
-
+
tcpstat.tcps_rttupdated++;
if (tp->t_srtt != 0) {
/*
@@ -1644,7 +1626,7 @@ tcp_xmit_timer(tp, rtt)
if ((tp->t_rttvar += delta) <= 0)
tp->t_rttvar = 1;
} else {
- /*
+ /*
* No rtt measurement yet - use the unsmoothed rtt.
* Set the variance to half the rtt (so our first
* retransmit happens at 3*rtt).
@@ -1668,7 +1650,7 @@ tcp_xmit_timer(tp, rtt)
*/
TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp),
(short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */
-
+
/*
* We received an ack for a packet that wasn't retransmitted;
* it is probably safe to discard any error indications we've
@@ -1702,24 +1684,24 @@ tcp_mss(tp, offer)
{
struct socket *so = tp->t_socket;
int mss;
-
+
DEBUG_CALL("tcp_mss");
DEBUG_ARG("tp = %lx", (long)tp);
DEBUG_ARG("offer = %d", offer);
-
+
mss = min(if_mtu, if_mru) - sizeof(struct tcpiphdr);
if (offer)
mss = min(mss, offer);
mss = max(mss, 32);
if (mss < tp->t_maxseg || offer != 0)
tp->t_maxseg = mss;
-
+
tp->snd_cwnd = mss;
-
- sbreserve(&so->so_snd, tcp_sndspace+((tcp_sndspace%mss)?(mss-(tcp_sndspace%mss)):0));
- sbreserve(&so->so_rcv, tcp_rcvspace+((tcp_rcvspace%mss)?(mss-(tcp_rcvspace%mss)):0));
-
+
+ sbuf_reserve(&so->so_snd, tcp_sndspace+((tcp_sndspace%mss)?(mss-(tcp_sndspace%mss)):0));
+ sbuf_reserve(&so->so_rcv, tcp_rcvspace+((tcp_rcvspace%mss)?(mss-(tcp_rcvspace%mss)):0));
+
DEBUG_MISC((dfd, " returning mss = %d\n", mss));
-
+
return mss;
}
diff --git a/slirp/tcp_output.c b/slirp/tcp_output.c
index b79bcf1..95246aa 100644
--- a/slirp/tcp_output.c
+++ b/slirp/tcp_output.c
@@ -74,7 +74,7 @@ tcp_output(tp)
register struct socket *so = tp->t_socket;
register long len, win;
int off, flags, error;
- register struct mbuf *m;
+ register MBuf m;
register struct tcpiphdr *ti;
u_char opt[MAX_TCPOPTLEN];
unsigned optlen, hdrlen;
@@ -166,7 +166,7 @@ again:
if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc))
flags &= ~TH_FIN;
- win = sbspace(&so->so_rcv);
+ win = sbuf_space(&so->so_rcv);
/*
* Sender silly window avoidance. If connection is idle
@@ -348,7 +348,7 @@ send:
tcpstat.tcps_sndbyte += len;
}
- m = m_get();
+ m = mbuf_alloc();
if (m == NULL) {
/* error = ENOBUFS; */
error = 1;
@@ -363,11 +363,11 @@ send:
*/
/* if (len <= MHLEN - hdrlen - max_linkhdr) { */
- sbcopy(&so->so_snd, off, (int) len, mtod(m, caddr_t) + hdrlen);
+ sbuf_copy(&so->so_snd, off, (int) len, MBUF_TO(m, caddr_t) + hdrlen);
m->m_len += len;
/* } else {
- * m->m_next = m_copy(so->so_snd.sb_mb, off, (int) len);
+ * m->m_next = mbuf_copy(so->so_snd.sb_mb, off, (int) len);
* if (m->m_next == 0)
* len = 0;
* }
@@ -390,7 +390,7 @@ send:
else
tcpstat.tcps_sndwinup++;
- m = m_get();
+ m = mbuf_alloc();
if (m == NULL) {
/* error = ENOBUFS; */
error = 1;
@@ -400,7 +400,7 @@ send:
m->m_len = hdrlen;
}
- ti = mtod(m, struct tcpiphdr *);
+ ti = MBUF_TO(m, struct tcpiphdr *);
memcpy((caddr_t)ti, &tp->t_template, sizeof (struct tcpiphdr));
@@ -547,7 +547,7 @@ send:
error = ip_output(so, m);
/* #else
- * error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route,
+ * error = ip_output(m, (MBuf )0, &tp->t_inpcb->inp_route,
* so->so_options & SO_DONTROUTE);
* #endif
*/
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index e66987e..b42e6ea 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -37,13 +37,16 @@
/*
* Changes and additions relating to SLiRP
* Copyright (c) 1995 Danny Gasparovski.
- *
- * Please read the file COPYRIGHT for the
+ *
+ * Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
#define WANT_SYS_IOCTL_H
#include <slirp.h>
+#define SLIRP_COMPILATION
+#include "sockets.h"
+#include "proxy_common.h"
/* patchable/settable parameters for tcp */
int tcp_mssdflt = TCP_MSS;
@@ -60,11 +63,11 @@ tcp_init()
{
tcp_iss = 1; /* wrong */
tcb.so_next = tcb.so_prev = &tcb;
-
+
/* tcp_rcvspace = our Window we advertise to the remote */
tcp_rcvspace = TCP_RCVSPACE;
tcp_sndspace = TCP_SNDSPACE;
-
+
/* Make sure tcp_sndspace is at least 2*MSS */
if (tcp_sndspace < 2*(min(if_mtu, if_mru) - sizeof(struct tcpiphdr)))
tcp_sndspace = 2*(min(if_mtu, if_mru) - sizeof(struct tcpiphdr));
@@ -92,7 +95,7 @@ tcp_template(tp)
n->ti_dst = so->so_laddr;
n->ti_sport = so->so_fport;
n->ti_dport = so->so_lport;
-
+
n->ti_seq = 0;
n->ti_ack = 0;
n->ti_x2 = 0;
@@ -120,7 +123,7 @@ void
tcp_respond(tp, ti, m, ack, seq, flags)
struct tcpcb *tp;
register struct tcpiphdr *ti;
- register struct mbuf *m;
+ register MBuf m;
tcp_seq ack, seq;
int flags;
{
@@ -134,11 +137,11 @@ tcp_respond(tp, ti, m, ack, seq, flags)
DEBUG_ARG("ack = %u", ack);
DEBUG_ARG("seq = %u", seq);
DEBUG_ARG("flags = %x", flags);
-
+
if (tp)
- win = sbspace(&tp->t_socket->so_rcv);
+ win = sbuf_space(&tp->t_socket->so_rcv);
if (m == 0) {
- if ((m = m_get()) == NULL)
+ if ((m = mbuf_alloc()) == NULL)
return;
#ifdef TCP_COMPAT_42
tlen = 1;
@@ -146,16 +149,16 @@ tcp_respond(tp, ti, m, ack, seq, flags)
tlen = 0;
#endif
m->m_data += if_maxlinkhdr;
- *mtod(m, struct tcpiphdr *) = *ti;
- ti = mtod(m, struct tcpiphdr *);
+ *MBUF_TO(m, struct tcpiphdr *) = *ti;
+ ti = MBUF_TO(m, struct tcpiphdr *);
flags = TH_ACK;
} else {
- /*
+ /*
* ti points into m so the next line is just making
* the mbuf point to ti
*/
m->m_data = (caddr_t)ti;
-
+
m->m_len = sizeof (struct tcpiphdr);
tlen = 0;
#define xchg(a,b,type) { type t; t=a; a=b; b=t; }
@@ -183,11 +186,11 @@ tcp_respond(tp, ti, m, ack, seq, flags)
ti->ti_sum = cksum(m, tlen);
((struct ip *)ti)->ip_len = tlen;
- if(flags & TH_RST)
+ if(flags & TH_RST)
((struct ip *)ti)->ip_ttl = MAXTTL;
- else
+ else
((struct ip *)ti)->ip_ttl = ip_defttl;
-
+
(void) ip_output((struct socket *)0, m);
}
@@ -201,18 +204,18 @@ tcp_newtcpcb(so)
struct socket *so;
{
register struct tcpcb *tp;
-
+
tp = (struct tcpcb *)malloc(sizeof(*tp));
if (tp == NULL)
return ((struct tcpcb *)0);
-
+
memset((char *) tp, 0, sizeof(struct tcpcb));
tp->seg_next = tp->seg_prev = (tcpiphdrp_32)tp;
tp->t_maxseg = tcp_mssdflt;
-
+
tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
tp->t_socket = so;
-
+
/*
* Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
* rtt estimate. Set rttvar so that srtt + 2 * rttvar gives
@@ -222,14 +225,14 @@ tcp_newtcpcb(so)
tp->t_rttvar = tcp_rttdflt * PR_SLOWHZ << 2;
tp->t_rttmin = TCPTV_MIN;
- TCPT_RANGESET(tp->t_rxtcur,
+ TCPT_RANGESET(tp->t_rxtcur,
((TCPTV_SRTTBASE >> 2) + (TCPTV_SRTTDFLT << 2)) >> 1,
TCPTV_MIN, TCPTV_REXMTMAX);
tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;
tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT;
tp->t_state = TCPS_CLOSED;
-
+
so->so_tcpcb = tp;
return (tp);
@@ -240,7 +243,7 @@ tcp_newtcpcb(so)
* the specified error. If connection is synchronized,
* then send a RST to peer.
*/
-struct tcpcb *tcp_drop(struct tcpcb *tp, int err)
+struct tcpcb *tcp_drop(struct tcpcb *tp, int err)
{
/* tcp_drop(tp, errno)
register struct tcpcb *tp;
@@ -251,7 +254,7 @@ struct tcpcb *tcp_drop(struct tcpcb *tp, int err)
DEBUG_CALL("tcp_drop");
DEBUG_ARG("tp = %lx", (long)tp);
DEBUG_ARG("errno = %d", errno);
-
+
if (TCPS_HAVERCVDSYN(tp->t_state)) {
tp->t_state = TCPS_CLOSED;
(void) tcp_output(tp);
@@ -277,22 +280,22 @@ tcp_close(tp)
{
register struct tcpiphdr *t;
struct socket *so = tp->t_socket;
- register struct mbuf *m;
+ register MBuf m;
DEBUG_CALL("tcp_close");
DEBUG_ARG("tp = %lx", (long )tp);
-
+
/* free the reassembly queue, if any */
t = (struct tcpiphdr *) tp->seg_next;
while (t != (struct tcpiphdr *)tp) {
t = (struct tcpiphdr *)t->ti_next;
- m = (struct mbuf *) REASS_MBUF((struct tcpiphdr *)t->ti_prev);
+ m = (MBuf ) REASS_MBUF((struct tcpiphdr *)t->ti_prev);
remque_32((struct tcpiphdr *) t->ti_prev);
- m_freem(m);
+ mbuf_free(m);
}
/* It's static */
/* if (tp->t_template)
- * (void) m_free(dtom(tp->t_template));
+ * (void) mbuf_free(MBUF_FROM(tp->t_template));
*/
/* free(tp, M_PCB); */
free(tp);
@@ -302,8 +305,8 @@ tcp_close(tp)
if (so == tcp_last_so)
tcp_last_so = &tcb;
closesocket(so->s);
- sbfree(&so->so_rcv);
- sbfree(&so->so_snd);
+ sbuf_free(&so->so_rcv);
+ sbuf_free(&so->so_snd);
sofree(so);
tcpstat.tcps_closed++;
return ((struct tcpcb *)0);
@@ -356,7 +359,7 @@ tcp_sockclosed(tp)
DEBUG_CALL("tcp_sockclosed");
DEBUG_ARG("tp = %lx", (long)tp);
-
+
switch (tp->t_state) {
case TCPS_CLOSED:
@@ -382,56 +385,80 @@ tcp_sockclosed(tp)
tcp_output(tp);
}
-/*
+static void
+tcp_proxy_event( struct socket* so,
+ ProxyEvent event )
+{
+ so->so_state &= ~SS_PROXIFIED;
+
+ if (event == PROXY_EVENT_CONNECTED) {
+ so->so_state &= ~(SS_ISFCONNECTING);
+ }
+ else {
+ so->so_state = SS_NOFDREF;
+ }
+
+ /* continue the connect */
+ tcp_input(NULL, sizeof(struct ip), so);
+}
+
+/*
* Connect to a host on the Internet
* Called by tcp_input
* Only do a connect, the tcp fields will be set in tcp_input
* return 0 if there's a result of the connect,
* else return -1 means we're still connecting
* The return value is almost always -1 since the socket is
- * nonblocking. Connect returns after the SYN is sent, and does
+ * nonblocking. Connect returns after the SYN is sent, and does
* not wait for ACK+SYN.
*/
int tcp_fconnect(so)
struct socket *so;
{
int ret=0;
-
+ int try_proxy = 0;
+
DEBUG_CALL("tcp_fconnect");
DEBUG_ARG("so = %lx", (long )so);
if( (ret=so->s=socket(AF_INET,SOCK_STREAM,0)) >= 0) {
- int opt, s=so->s;
+ int s=so->s;
struct sockaddr_in addr;
- fd_nonblock(s);
- opt = 1;
- setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(opt ));
- opt = 1;
- setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(opt ));
-
+ socket_set_nonblock(s);
+ socket_set_xreuseaddr(s);
+ socket_set_oobinline(s);
+
addr.sin_family = AF_INET;
if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
/* It's an alias */
- switch(ntohl(so->so_faddr.s_addr) & 0xff) {
- case CTL_DNS:
- addr.sin_addr = dns_addr;
- break;
- case CTL_ALIAS:
- default:
- addr.sin_addr = loopback_addr;
- break;
- }
- } else
+ int last_byte = ntohl(so->so_faddr.s_addr) & 0xff;
+
+ if (CTL_IS_DNS(last_byte))
+ addr.sin_addr = dns_addr[last_byte - CTL_DNS];
+ else
+ addr.sin_addr = loopback_addr;
+ } else {
addr.sin_addr = so->so_faddr;
+ try_proxy = 1;
+ }
addr.sin_port = so->so_fport;
-
+
DEBUG_MISC((dfd, " connect()ing, addr.sin_port=%d, "
- "addr.sin_addr.s_addr=%.16s\n",
- ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
+ "addr.sin_addr.s_addr=%.16s\n",
+ ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
+
+ if (try_proxy) {
+ if (!proxy_manager_add(s, &addr, so, (ProxyEventFunc) tcp_proxy_event)) {
+ soisfconnecting(so);
+ so->so_state |= SS_PROXIFIED;
+ return 0;
+ }
+ }
+
/* We don't care what port we get */
ret = connect(s,(struct sockaddr *)&addr,sizeof (addr));
-
+
/*
* If it's not in progress, it failed, so we just return 0,
* without clearing SS_NOFDREF
@@ -444,16 +471,16 @@ int tcp_fconnect(so)
/*
* Accept the socket and connect to the local-host
- *
+ *
* We have a problem. The correct thing to do would be
* to first connect to the local-host, and only if the
* connection is accepted, then do an accept() here.
- * But, a) we need to know who's trying to connect
+ * But, a) we need to know who's trying to connect
* to the socket to be able to SYN the local-host, and
* b) we are already connected to the foreign host by
* the time it gets to accept(), so... We simply accept
* here and SYN the local-host.
- */
+ */
void
tcp_connect(inso)
struct socket *inso;
@@ -462,11 +489,11 @@ tcp_connect(inso)
struct sockaddr_in addr;
int addrlen = sizeof(struct sockaddr_in);
struct tcpcb *tp;
- int s, opt;
+ int s;
DEBUG_CALL("tcp_connect");
DEBUG_ARG("inso = %lx", (long)inso);
-
+
/*
* If it's an SS_ACCEPTONCE socket, no need to socreate()
* another socket, just use the accept() socket.
@@ -487,38 +514,37 @@ tcp_connect(inso)
so->so_laddr = inso->so_laddr;
so->so_lport = inso->so_lport;
}
-
+
(void) tcp_mss(sototcpcb(so), 0);
if ((s = accept(inso->s,(struct sockaddr *)&addr,&addrlen)) < 0) {
tcp_close(sototcpcb(so)); /* This will sofree() as well */
return;
}
- fd_nonblock(s);
- opt = 1;
- setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
- opt = 1;
- setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
-
+ socket_set_nonblock(s);
+ socket_set_xreuseaddr(s);
+ socket_set_oobinline(s);
+ socket_set_lowlatency(s);
+
so->so_fport = addr.sin_port;
so->so_faddr = addr.sin_addr;
/* Translate connections from localhost to the real hostname */
if (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == loopback_addr.s_addr)
so->so_faddr = alias_addr;
-
+
/* Close the accept() socket, set right state */
if (inso->so_state & SS_FACCEPTONCE) {
- closesocket(so->s); /* If we only accept once, close the accept() socket */
+ socket_close(so->s); /* If we only accept once, close the accept() socket */
so->so_state = SS_NOFDREF; /* Don't select it yet, even though we have an FD */
/* if it's not FACCEPTONCE, it's already NOFDREF */
}
so->s = s;
-
+
so->so_iptos = tcp_tos(so);
tp = sototcpcb(so);
tcp_template(tp);
-
+
/* Compute window scaling to request. */
/* while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
* (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
@@ -527,10 +553,10 @@ tcp_connect(inso)
/* soisconnecting(so); */ /* NOFDREF used instead */
tcpstat.tcps_connattempt++;
-
+
tp->t_state = TCPS_SYN_SENT;
tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
- tp->iss = tcp_iss;
+ tp->iss = tcp_iss;
tcp_iss += TCP_ISSINCR/2;
tcp_sendseqinit(tp);
tcp_output(tp);
@@ -545,7 +571,7 @@ tcp_attach(so)
{
if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL)
return -1;
-
+
insque(so, &tcb);
return 0;
@@ -570,8 +596,7 @@ struct tos_t tcptos[] = {
{0, 0, 0, 0}
};
-struct emu_t *tcpemu = 0;
-
+
/*
* Return TOS according to the above table
*/
@@ -581,7 +606,7 @@ tcp_tos(so)
{
int i = 0;
struct emu_t *emup;
-
+
while(tcptos[i].tos) {
if ((tcptos[i].fport && (ntohs(so->so_fport) == tcptos[i].fport)) ||
(tcptos[i].lport && (ntohs(so->so_lport) == tcptos[i].lport))) {
@@ -590,16 +615,7 @@ tcp_tos(so)
}
i++;
}
-
- /* Nope, lets see if there's a user-added one */
- for (emup = tcpemu; emup; emup = emup->next) {
- if ((emup->fport && (ntohs(so->so_fport) == emup->fport)) ||
- (emup->lport && (ntohs(so->so_lport) == emup->lport))) {
- so->so_emu = emup->emu;
- return emup->tos;
- }
- }
-
+
return 0;
}
@@ -610,54 +626,54 @@ int do_echo = -1;
* This includes ftp (the data connection is
* initiated by the server) and IRC (DCC CHAT and
* DCC SEND) for now
- *
+ *
* NOTE: It's possible to crash SLiRP by sending it
* unstandard strings to emulate... if this is a problem,
* more checks are needed here
*
* XXX Assumes the whole command came in one packet
- *
+ *
* XXX Some ftp clients will have their TOS set to
* LOWDELAY and so Nagel will kick in. Because of this,
* we'll get the first letter, followed by the rest, so
* we simply scan for ORT instead of PORT...
* DCC doesn't have this problem because there's other stuff
* in the packet before the DCC command.
- *
- * Return 1 if the mbuf m is still valid and should be
- * sbappend()ed
- *
- * NOTE: if you return 0 you MUST m_free() the mbuf!
+ *
+ * Return 1 if the mbuf m is still valid and should be
+ * sbuf_append()ed
+ *
+ * NOTE: if you return 0 you MUST mbuf_free() the mbuf!
*/
int
tcp_emu(so, m)
struct socket *so;
- struct mbuf *m;
+ MBuf m;
{
u_int n1, n2, n3, n4, n5, n6;
char buff[256];
u_int32_t laddr;
u_int lport;
char *bptr;
-
+
DEBUG_CALL("tcp_emu");
DEBUG_ARG("so = %lx", (long)so);
DEBUG_ARG("m = %lx", (long)m);
-
+
switch(so->so_emu) {
int x, i;
-
+
case EMU_IDENT:
/*
* Identification protocol as per rfc-1413
*/
-
+
{
struct socket *tmpso;
struct sockaddr_in addr;
int addrlen = sizeof(struct sockaddr_in);
- struct sbuf *so_rcv = &so->so_rcv;
-
+ SBuf so_rcv = &so->so_rcv;
+
memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
so_rcv->sb_wptr += m->m_len;
so_rcv->sb_rptr += m->m_len;
@@ -683,337 +699,41 @@ tcp_emu(so, m)
so_rcv->sb_rptr = so_rcv->sb_data;
so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc;
}
- m_free(m);
+ mbuf_free(m);
return 0;
}
-
-#if 0
- case EMU_RLOGIN:
- /*
- * Rlogin emulation
- * First we accumulate all the initial option negotiation,
- * then fork_exec() rlogin according to the options
- */
- {
- int i, i2, n;
- char *ptr;
- char args[100];
- char term[100];
- struct sbuf *so_snd = &so->so_snd;
- struct sbuf *so_rcv = &so->so_rcv;
-
- /* First check if they have a priveladged port, or too much data has arrived */
- if (ntohs(so->so_lport) > 1023 || ntohs(so->so_lport) < 512 ||
- (m->m_len + so_rcv->sb_wptr) > (so_rcv->sb_data + so_rcv->sb_datalen)) {
- memcpy(so_snd->sb_wptr, "Permission denied\n", 18);
- so_snd->sb_wptr += 18;
- so_snd->sb_cc += 18;
- tcp_sockclosed(sototcpcb(so));
- m_free(m);
- return 0;
- }
-
- /* Append the current data */
- memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
- so_rcv->sb_wptr += m->m_len;
- so_rcv->sb_rptr += m->m_len;
- m_free(m);
-
- /*
- * Check if we have all the initial options,
- * and build argument list to rlogin while we're here
- */
- n = 0;
- ptr = so_rcv->sb_data;
- args[0] = 0;
- term[0] = 0;
- while (ptr < so_rcv->sb_wptr) {
- if (*ptr++ == 0) {
- n++;
- if (n == 2) {
- sprintf(args, "rlogin -l %s %s",
- ptr, inet_ntoa(so->so_faddr));
- } else if (n == 3) {
- i2 = so_rcv->sb_wptr - ptr;
- for (i = 0; i < i2; i++) {
- if (ptr[i] == '/') {
- ptr[i] = 0;
-#ifdef HAVE_SETENV
- sprintf(term, "%s", ptr);
-#else
- sprintf(term, "TERM=%s", ptr);
-#endif
- ptr[i] = '/';
- break;
- }
- }
- }
- }
- }
-
- if (n != 4)
- return 0;
-
- /* We have it, set our term variable and fork_exec() */
-#ifdef HAVE_SETENV
- setenv("TERM", term, 1);
-#else
- putenv(term);
-#endif
- fork_exec(so, args, 2);
- term[0] = 0;
- so->so_emu = 0;
-
- /* And finally, send the client a 0 character */
- so_snd->sb_wptr[0] = 0;
- so_snd->sb_wptr++;
- so_snd->sb_cc++;
-
- return 0;
- }
-
- case EMU_RSH:
- /*
- * rsh emulation
- * First we accumulate all the initial option negotiation,
- * then rsh_exec() rsh according to the options
- */
- {
- int n;
- char *ptr;
- char *user;
- char *args;
- struct sbuf *so_snd = &so->so_snd;
- struct sbuf *so_rcv = &so->so_rcv;
-
- /* First check if they have a priveladged port, or too much data has arrived */
- if (ntohs(so->so_lport) > 1023 || ntohs(so->so_lport) < 512 ||
- (m->m_len + so_rcv->sb_wptr) > (so_rcv->sb_data + so_rcv->sb_datalen)) {
- memcpy(so_snd->sb_wptr, "Permission denied\n", 18);
- so_snd->sb_wptr += 18;
- so_snd->sb_cc += 18;
- tcp_sockclosed(sototcpcb(so));
- m_free(m);
- return 0;
- }
-
- /* Append the current data */
- memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
- so_rcv->sb_wptr += m->m_len;
- so_rcv->sb_rptr += m->m_len;
- m_free(m);
-
- /*
- * Check if we have all the initial options,
- * and build argument list to rlogin while we're here
- */
- n = 0;
- ptr = so_rcv->sb_data;
- user="";
- args="";
- if (so->extra==NULL) {
- struct socket *ns;
- struct tcpcb* tp;
- int port=atoi(ptr);
- if (port <= 0) return 0;
- if (port > 1023 || port < 512) {
- memcpy(so_snd->sb_wptr, "Permission denied\n", 18);
- so_snd->sb_wptr += 18;
- so_snd->sb_cc += 18;
- tcp_sockclosed(sototcpcb(so));
- return 0;
- }
- if ((ns=socreate()) == NULL)
- return 0;
- if (tcp_attach(ns)<0) {
- free(ns);
- return 0;
- }
-
- ns->so_laddr=so->so_laddr;
- ns->so_lport=htons(port);
-
- (void) tcp_mss(sototcpcb(ns), 0);
- ns->so_faddr=so->so_faddr;
- ns->so_fport=htons(IPPORT_RESERVED-1); /* Use a fake port. */
-
- if (ns->so_faddr.s_addr == 0 ||
- ns->so_faddr.s_addr == loopback_addr.s_addr)
- ns->so_faddr = alias_addr;
-
- ns->so_iptos = tcp_tos(ns);
- tp = sototcpcb(ns);
-
- tcp_template(tp);
-
- /* Compute window scaling to request. */
- /* while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
- * (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
- * tp->request_r_scale++;
- */
-
- /*soisfconnecting(ns);*/
-
- tcpstat.tcps_connattempt++;
-
- tp->t_state = TCPS_SYN_SENT;
- tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
- tp->iss = tcp_iss;
- tcp_iss += TCP_ISSINCR/2;
- tcp_sendseqinit(tp);
- tcp_output(tp);
- so->extra=ns;
- }
- while (ptr < so_rcv->sb_wptr) {
- if (*ptr++ == 0) {
- n++;
- if (n == 2) {
- user=ptr;
- } else if (n == 3) {
- args=ptr;
- }
- }
- }
-
- if (n != 4)
- return 0;
-
- rsh_exec(so,so->extra, user, inet_ntoa(so->so_faddr), args);
- so->so_emu = 0;
- so->extra=NULL;
-
- /* And finally, send the client a 0 character */
- so_snd->sb_wptr[0] = 0;
- so_snd->sb_wptr++;
- so_snd->sb_cc++;
-
- return 0;
- }
-
- case EMU_CTL:
- {
- int num;
- struct sbuf *so_snd = &so->so_snd;
- struct sbuf *so_rcv = &so->so_rcv;
-
- /*
- * If there is binary data here, we save it in so->so_m
- */
- if (!so->so_m) {
- int rxlen;
- char *rxdata;
- rxdata=mtod(m, char *);
- for (rxlen=m->m_len; rxlen; rxlen--) {
- if (*rxdata++ & 0x80) {
- so->so_m = m;
- return 0;
- }
- }
- } /* if(so->so_m==NULL) */
-
- /*
- * Append the line
- */
- sbappendsb(so_rcv, m);
-
- /* To avoid going over the edge of the buffer, we reset it */
- if (so_snd->sb_cc == 0)
- so_snd->sb_wptr = so_snd->sb_rptr = so_snd->sb_data;
-
- /*
- * A bit of a hack:
- * If the first packet we get here is 1 byte long, then it
- * was done in telnet character mode, therefore we must echo
- * the characters as they come. Otherwise, we echo nothing,
- * because in linemode, the line is already echoed
- * XXX two or more control connections won't work
- */
- if (do_echo == -1) {
- if (m->m_len == 1) do_echo = 1;
- else do_echo = 0;
- }
- if (do_echo) {
- sbappendsb(so_snd, m);
- m_free(m);
- tcp_output(sototcpcb(so)); /* XXX */
- } else
- m_free(m);
-
- num = 0;
- while (num < so->so_rcv.sb_cc) {
- if (*(so->so_rcv.sb_rptr + num) == '\n' ||
- *(so->so_rcv.sb_rptr + num) == '\r') {
- int n;
-
- *(so_rcv->sb_rptr + num) = 0;
- if (ctl_password && !ctl_password_ok) {
- /* Need a password */
- if (sscanf(so_rcv->sb_rptr, "pass %256s", buff) == 1) {
- if (strcmp(buff, ctl_password) == 0) {
- ctl_password_ok = 1;
- n = sprintf(so_snd->sb_wptr,
- "Password OK.\r\n");
- goto do_prompt;
- }
- }
- n = sprintf(so_snd->sb_wptr,
- "Error: Password required, log on with \"pass PASSWORD\"\r\n");
- goto do_prompt;
- }
- cfg_quitting = 0;
- n = do_config(so_rcv->sb_rptr, so, PRN_SPRINTF);
- if (!cfg_quitting) {
- /* Register the printed data */
-do_prompt:
- so_snd->sb_cc += n;
- so_snd->sb_wptr += n;
- /* Add prompt */
- n = sprintf(so_snd->sb_wptr, "Slirp> ");
- so_snd->sb_cc += n;
- so_snd->sb_wptr += n;
- }
- /* Drop so_rcv data */
- so_rcv->sb_cc = 0;
- so_rcv->sb_wptr = so_rcv->sb_rptr = so_rcv->sb_data;
- tcp_output(sototcpcb(so)); /* Send the reply */
- }
- num++;
- }
- return 0;
- }
-#endif
case EMU_FTP: /* ftp */
*(m->m_data+m->m_len) = 0; /* NULL terminate for strstr */
if ((bptr = (char *)strstr(m->m_data, "ORT")) != NULL) {
/*
* Need to emulate the PORT command
- */
- x = sscanf(bptr, "ORT %d,%d,%d,%d,%d,%d\r\n%256[^\177]",
+ */
+ x = sscanf(bptr, "ORT %d,%d,%d,%d,%d,%d\r\n%256[^\177]",
&n1, &n2, &n3, &n4, &n5, &n6, buff);
if (x < 6)
return 1;
-
+
laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
lport = htons((n5 << 8) | (n6));
-
+
if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL)
return 1;
-
+
n6 = ntohs(so->so_fport);
-
+
n5 = (n6 >> 8) & 0xff;
n6 &= 0xff;
-
+
laddr = ntohl(so->so_faddr.s_addr);
-
+
n1 = ((laddr >> 24) & 0xff);
n2 = ((laddr >> 16) & 0xff);
n3 = ((laddr >> 8) & 0xff);
n4 = (laddr & 0xff);
-
+
m->m_len = bptr - m->m_data; /* Adjust length */
- m->m_len += sprintf(bptr,"ORT %d,%d,%d,%d,%d,%d\r\n%s",
+ m->m_len += sprintf(bptr,"ORT %d,%d,%d,%d,%d,%d\r\n%s",
n1, n2, n3, n4, n5, n6, x==7?buff:"");
return 1;
} else if ((bptr = (char *)strstr(m->m_data, "27 Entering")) != NULL) {
@@ -1024,34 +744,34 @@ do_prompt:
&n1, &n2, &n3, &n4, &n5, &n6, buff);
if (x < 6)
return 1;
-
+
laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
lport = htons((n5 << 8) | (n6));
-
+
if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL)
return 1;
-
+
n6 = ntohs(so->so_fport);
-
+
n5 = (n6 >> 8) & 0xff;
n6 &= 0xff;
-
+
laddr = ntohl(so->so_faddr.s_addr);
-
+
n1 = ((laddr >> 24) & 0xff);
n2 = ((laddr >> 16) & 0xff);
n3 = ((laddr >> 8) & 0xff);
n4 = (laddr & 0xff);
-
+
m->m_len = bptr - m->m_data; /* Adjust length */
m->m_len += sprintf(bptr,"27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%s",
n1, n2, n3, n4, n5, n6, x==7?buff:"");
-
+
return 1;
}
-
+
return 1;
-
+
case EMU_KSH:
/*
* The kshell (Kerberos rsh) and shell services both pass
@@ -1070,7 +790,7 @@ do_prompt:
(so = solisten(0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL)
m->m_len = sprintf(m->m_data, "%d", ntohs(so->so_fport))+1;
return 1;
-
+
case EMU_IRC:
/*
* Need to emulate DCC CHAT, DCC SEND and DCC MOVE
@@ -1078,12 +798,12 @@ do_prompt:
*(m->m_data+m->m_len) = 0; /* NULL terminate the string for strstr */
if ((bptr = (char *)strstr(m->m_data, "DCC")) == NULL)
return 1;
-
+
/* The %256s is for the broken mIRC */
if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3) {
if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
return 1;
-
+
m->m_len = bptr - m->m_data; /* Adjust length */
m->m_len += sprintf(bptr, "DCC CHAT chat %lu %u%c\n",
(unsigned long)ntohl(so->so_faddr.s_addr),
@@ -1091,15 +811,15 @@ do_prompt:
} else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
return 1;
-
+
m->m_len = bptr - m->m_data; /* Adjust length */
- m->m_len += sprintf(bptr, "DCC SEND %s %lu %u %u%c\n",
+ m->m_len += sprintf(bptr, "DCC SEND %s %lu %u %u%c\n",
buff, (unsigned long)ntohl(so->so_faddr.s_addr),
ntohs(so->so_fport), n1, 1);
} else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
return 1;
-
+
m->m_len = bptr - m->m_data; /* Adjust length */
m->m_len += sprintf(bptr, "DCC MOVE %s %lu %u %u%c\n",
buff, (unsigned long)ntohl(so->so_faddr.s_addr),
@@ -1108,7 +828,7 @@ do_prompt:
return 1;
case EMU_REALAUDIO:
- /*
+ /*
* RealAudio emulation - JP. We must try to parse the incoming
* data and try to find the two characters that contain the
* port number. Then we redirect an udp port and replace the
@@ -1116,45 +836,45 @@ do_prompt:
*
* The 1.0 beta versions of the player are not supported
* any more.
- *
+ *
* A typical packet for player version 1.0 (release version):
- *
- * 0000:50 4E 41 00 05
+ *
+ * 0000:50 4E 41 00 05
* 0000:00 01 00 02 1B D7 00 00 67 E6 6C DC 63 00 12 50 .....×..gælÜc..P
* 0010:4E 43 4C 49 45 4E 54 20 31 30 31 20 41 4C 50 48 NCLIENT 101 ALPH
* 0020:41 6C 00 00 52 00 17 72 61 66 69 6C 65 73 2F 76 Al..R..rafiles/v
* 0030:6F 61 2F 65 6E 67 6C 69 73 68 5F 2E 72 61 79 42 oa/english_.rayB
- *
+ *
* Now the port number 0x1BD7 is found at offset 0x04 of the
* Now the port number 0x1BD7 is found at offset 0x04 of the
* second packet. This time we received five bytes first and
* then the rest. You never know how many bytes you get.
*
* A typical packet for player version 2.0 (beta):
- *
+ *
* 0000:50 4E 41 00 06 00 02 00 00 00 01 00 02 1B C1 00 PNA...........Á.
* 0010:00 67 75 78 F5 63 00 0A 57 69 6E 32 2E 30 2E 30 .guxõc..Win2.0.0
* 0020:2E 35 6C 00 00 52 00 1C 72 61 66 69 6C 65 73 2F .5l..R..rafiles/
* 0030:77 65 62 73 69 74 65 2F 32 30 72 65 6C 65 61 73 website/20releas
* 0040:65 2E 72 61 79 53 00 00 06 36 42 e.rayS...6B
- *
+ *
* Port number 0x1BC1 is found at offset 0x0d.
- *
+ *
* This is just a horrible switch statement. Variable ra tells
* us where we're going.
*/
-
+
bptr = m->m_data;
while (bptr < m->m_data + m->m_len) {
u_short p;
static int ra = 0;
- char ra_tbl[4];
-
+ char ra_tbl[4];
+
ra_tbl[0] = 0x50;
ra_tbl[1] = 0x4e;
ra_tbl[2] = 0x41;
ra_tbl[3] = 0;
-
+
switch (ra) {
case 0:
case 2:
@@ -1164,7 +884,7 @@ do_prompt:
continue;
}
break;
-
+
case 1:
/*
* We may get 0x50 several times, ignore them
@@ -1178,15 +898,15 @@ do_prompt:
continue;
}
break;
-
- case 4:
- /*
+
+ case 4:
+ /*
* skip version number
*/
bptr++;
break;
-
- case 5:
+
+ case 5:
/*
* The difference between versions 1.0 and
* 2.0 is here. For future versions of
@@ -1196,19 +916,19 @@ do_prompt:
bptr += 8;
else
bptr += 4;
- break;
-
+ break;
+
case 6:
/* This is the field containing the port
* number that RA-player is listening to.
*/
- lport = (((u_char*)bptr)[0] << 8)
+ lport = (((u_char*)bptr)[0] << 8)
+ ((u_char *)bptr)[1];
- if (lport < 6970)
+ if (lport < 6970)
lport += 256; /* don't know why */
if (lport < 6970 || lport > 7170)
return 1; /* failed */
-
+
/* try to get udp port between 6970 - 7170 */
for (p = 6970; p < 7071; p++) {
if (udp_listen( htons(p),
@@ -1222,17 +942,17 @@ do_prompt:
p = 0;
*(u_char *)bptr++ = (p >> 8) & 0xff;
*(u_char *)bptr++ = p & 0xff;
- ra = 0;
+ ra = 0;
return 1; /* port redirected, we're done */
- break;
-
+ break;
+
default:
- ra = 0;
+ ra = 0;
}
ra++;
}
- return 1;
-
+ return 1;
+
default:
/* Ooops, not emulated, won't call tcp_emu again */
so->so_emu = 0;
@@ -1249,15 +969,15 @@ int
tcp_ctl(so)
struct socket *so;
{
- struct sbuf *sb = &so->so_snd;
+ SBuf sb = &so->so_snd;
int command;
struct ex_list *ex_ptr;
int do_pty;
// struct socket *tmpso;
-
+
DEBUG_CALL("tcp_ctl");
DEBUG_ARG("so = %lx", (long )so);
-
+
#if 0
/*
* Check if they're authorised
@@ -1267,58 +987,20 @@ tcp_ctl(so)
sb->sb_wptr += sb->sb_cc;
return 0;
}
-#endif
+#endif
command = (ntohl(so->so_faddr.s_addr) & 0xff);
-
+
switch(command) {
- default: /* Check for exec's */
-
- /*
- * Check if it's pty_exec
- */
- for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
- if (ex_ptr->ex_fport == so->so_fport &&
- command == ex_ptr->ex_addr) {
- do_pty = ex_ptr->ex_pty;
- goto do_exec;
- }
- }
-
+ default:
/*
* Nothing bound..
*/
/* tcp_fconnect(so); */
-
- /* FALLTHROUGH */
+
case CTL_ALIAS:
sb->sb_cc = sprintf(sb->sb_wptr,
"Error: No application configured.\r\n");
sb->sb_wptr += sb->sb_cc;
return(0);
-
- do_exec:
- DEBUG_MISC((dfd, " executing %s \n",ex_ptr->ex_exec));
- return(fork_exec(so, ex_ptr->ex_exec, do_pty));
-
-#if 0
- case CTL_CMD:
- for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) {
- if (tmpso->so_emu == EMU_CTL &&
- !(tmpso->so_tcpcb?
- (tmpso->so_tcpcb->t_state & (TCPS_TIME_WAIT|TCPS_LAST_ACK))
- :0)) {
- /* Ooops, control connection already active */
- sb->sb_cc = sprintf(sb->sb_wptr,"Sorry, already connected.\r\n");
- sb->sb_wptr += sb->sb_cc;
- return 0;
- }
- }
- so->so_emu = EMU_CTL;
- ctl_password_ok = 0;
- sb->sb_cc = sprintf(sb->sb_wptr, "Slirp command-line ready (type \"help\" for help).\r\nSlirp> ");
- sb->sb_wptr += sb->sb_cc;
- do_echo=-1;
- return(2);
-#endif
}
}
diff --git a/slirp/tcp_timer.c b/slirp/tcp_timer.c
index d3146db..ad03098 100644
--- a/slirp/tcp_timer.c
+++ b/slirp/tcp_timer.c
@@ -305,10 +305,10 @@ tcp_timers(tp, timer)
* The keepalive packet must have nonzero length
* to get a 4.2 host to respond.
*/
- tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL,
+ tcp_respond(tp, &tp->t_template, (MBuf )NULL,
tp->rcv_nxt - 1, tp->snd_una - 1, 0);
#else
- tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL,
+ tcp_respond(tp, &tp->t_template, (MBuf )NULL,
tp->rcv_nxt, tp->snd_una - 1, 0);
#endif
tp->t_timer[TCPT_KEEP] = tcp_keepintvl;
diff --git a/slirp/tcp_var.h b/slirp/tcp_var.h
index 0d6cd24..b30a15d 100644
--- a/slirp/tcp_var.h
+++ b/slirp/tcp_var.h
@@ -37,6 +37,7 @@
#ifndef _TCP_VAR_H_
#define _TCP_VAR_H_
+#include "mbuf.h"
#include "tcpip.h"
#include "tcp_timer.h"
@@ -172,14 +173,14 @@ struct tcpcb {
/* XXX
* We want to avoid doing m_pullup on incoming packets but that
- * means avoiding dtom on the tcp reassembly code. That in turn means
+ * means avoiding MBUF_FROM on the tcp reassembly code. That in turn means
* keeping an mbuf pointer in the reassembly queue (since we might
* have a cluster). As a quick hack, the source & destination
* port numbers (which are no longer needed once we've located the
* tcpcb) are overlayed with an mbuf pointer.
*/
#if SIZEOF_CHAR_P == 4
-typedef struct mbuf *mbufp_32;
+typedef MBuf mbufp_32;
#else
typedef u_int32_t mbufp_32;
#endif
diff --git a/slirp/tftp.c b/slirp/tftp.c
index c9946d6..8af404a 100644
--- a/slirp/tftp.c
+++ b/slirp/tftp.c
@@ -1,8 +1,8 @@
/*
* tftp.c - a simple, read-only tftp server for qemu
- *
+ *
* Copyright (c) 2004 Magnus Damm <damm@opensource.se>
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
@@ -27,10 +27,10 @@
struct tftp_session {
int in_use;
unsigned char filename[TFTP_FILENAME_MAX];
-
+
struct in_addr client_ip;
u_int16_t client_port;
-
+
int timestamp;
};
@@ -102,8 +102,15 @@ static int tftp_read_data(struct tftp_session *spt, u_int16_t block_nr,
{
int fd;
int bytes_read = 0;
+ char buffer[1024];
+ int n;
+
+ n = snprintf(buffer, sizeof(buffer), "%s/%s",
+ tftp_prefix, spt->filename);
+ if (n >= sizeof(buffer))
+ return -1;
- fd = open(spt->filename, O_RDONLY | O_BINARY);
+ fd = open(buffer, O_RDONLY | O_BINARY);
if (fd < 0) {
return -1;
@@ -120,16 +127,55 @@ static int tftp_read_data(struct tftp_session *spt, u_int16_t block_nr,
return bytes_read;
}
-static int tftp_send_error(struct tftp_session *spt,
+static int tftp_send_oack(struct tftp_session *spt,
+ const char *key, uint32_t value,
+ struct tftp_t *recv_tp)
+{
+ struct sockaddr_in saddr, daddr;
+ MBuf m;
+ struct tftp_t *tp;
+ int n = 0;
+
+ m = mbuf_alloc();
+
+ if (!m)
+ return -1;
+
+ memset(m->m_data, 0, m->m_size);
+
+ m->m_data += if_maxlinkhdr;
+ tp = (void *)m->m_data;
+ m->m_data += sizeof(struct udpiphdr);
+
+ tp->tp_op = htons(TFTP_OACK);
+ n += sprintf((char*)tp->x.tp_buf + n, "%s", key) + 1;
+ n += sprintf((char*)tp->x.tp_buf + n, "%u", value) + 1;
+
+ saddr.sin_addr = recv_tp->ip.ip_dst;
+ saddr.sin_port = recv_tp->udp.uh_dport;
+
+ daddr.sin_addr = spt->client_ip;
+ daddr.sin_port = spt->client_port;
+
+ m->m_len = sizeof(struct tftp_t) - 514 + n -
+ sizeof(struct ip) - sizeof(struct udphdr);
+ udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
+
+ return 0;
+}
+
+
+
+static int tftp_send_error(struct tftp_session *spt,
u_int16_t errorcode, const char *msg,
struct tftp_t *recv_tp)
{
struct sockaddr_in saddr, daddr;
- struct mbuf *m;
+ MBuf m;
struct tftp_t *tp;
int nobytes;
- m = m_get();
+ m = mbuf_alloc();
if (!m) {
return -1;
@@ -140,10 +186,10 @@ static int tftp_send_error(struct tftp_session *spt,
m->m_data += if_maxlinkhdr;
tp = (void *)m->m_data;
m->m_data += sizeof(struct udpiphdr);
-
+
tp->tp_op = htons(TFTP_ERROR);
tp->x.tp_error.tp_error_code = htons(errorcode);
- strcpy(tp->x.tp_error.tp_msg, msg);
+ strcpy((char*)tp->x.tp_error.tp_msg, msg);
saddr.sin_addr = recv_tp->ip.ip_dst;
saddr.sin_port = recv_tp->udp.uh_dport;
@@ -153,7 +199,7 @@ static int tftp_send_error(struct tftp_session *spt,
nobytes = 2;
- m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg) -
+ m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg) -
sizeof(struct ip) - sizeof(struct udphdr);
udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
@@ -163,12 +209,12 @@ static int tftp_send_error(struct tftp_session *spt,
return 0;
}
-static int tftp_send_data(struct tftp_session *spt,
+static int tftp_send_data(struct tftp_session *spt,
u_int16_t block_nr,
struct tftp_t *recv_tp)
{
struct sockaddr_in saddr, daddr;
- struct mbuf *m;
+ MBuf m;
struct tftp_t *tp;
int nobytes;
@@ -176,7 +222,7 @@ static int tftp_send_data(struct tftp_session *spt,
return -1;
}
- m = m_get();
+ m = mbuf_alloc();
if (!m) {
return -1;
@@ -187,7 +233,7 @@ static int tftp_send_data(struct tftp_session *spt,
m->m_data += if_maxlinkhdr;
tp = (void *)m->m_data;
m->m_data += sizeof(struct udpiphdr);
-
+
tp->tp_op = htons(TFTP_DATA);
tp->x.tp_data.tp_block_nr = htons(block_nr);
@@ -200,7 +246,7 @@ static int tftp_send_data(struct tftp_session *spt,
nobytes = tftp_read_data(spt, block_nr - 1, tp->x.tp_data.tp_buf, 512);
if (nobytes < 0) {
- m_free(m);
+ mbuf_free(m);
/* send "file not found" error back */
@@ -209,7 +255,7 @@ static int tftp_send_data(struct tftp_session *spt,
return -1;
}
- m->m_len = sizeof(struct tftp_t) - (512 - nobytes) -
+ m->m_len = sizeof(struct tftp_t) - (512 - nobytes) -
sizeof(struct ip) - sizeof(struct udphdr);
udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
@@ -251,52 +297,95 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
else {
return;
}
-
+
if (src[k] == '\0') {
break;
}
}
-
+
if (k >= n) {
return;
}
-
+
k++;
-
+
/* check mode */
if ((n - k) < 6) {
return;
}
-
+
if (memcmp(&src[k], "octet\0", 6) != 0) {
tftp_send_error(spt, 4, "Unsupported transfer mode", tp);
return;
}
+ k += 6; /* skipping octet */
+
/* do sanity checks on the filename */
if ((spt->filename[0] != '/')
- || (spt->filename[strlen(spt->filename) - 1] == '/')
- || strstr(spt->filename, "/../")) {
+ || (spt->filename[strlen((const char*)spt->filename) - 1] == '/')
+ || strstr((const char*)spt->filename, "/../")) {
tftp_send_error(spt, 2, "Access violation", tp);
return;
}
/* only allow exported prefixes */
- if (!tftp_prefix
- || (strncmp(spt->filename, tftp_prefix, strlen(tftp_prefix)) != 0)) {
+ if (!tftp_prefix) {
tftp_send_error(spt, 2, "Access violation", tp);
return;
}
/* check if the file exists */
-
+
if (tftp_read_data(spt, 0, spt->filename, 0) < 0) {
tftp_send_error(spt, 1, "File not found", tp);
return;
}
+ if (src[n - 1] != 0) {
+ tftp_send_error(spt, 2, "Access violation", tp);
+ return;
+ }
+
+ while (k < n) {
+ const char *key, *value;
+
+ key = (const char*)src + k;
+ k += strlen(key) + 1;
+
+ if (k >= n) {
+ tftp_send_error(spt, 2, "Access violation", tp);
+ return;
+ }
+
+ value = (const char*)src + k;
+ k += strlen(value) + 1;
+
+ if (strcmp(key, "tsize") == 0) {
+ int tsize = atoi(value);
+ struct stat stat_p;
+
+ if (tsize == 0 && tftp_prefix) {
+ char buffer[1024];
+ int len;
+
+ len = snprintf(buffer, sizeof(buffer), "%s/%s",
+ tftp_prefix, spt->filename);
+
+ if (stat(buffer, &stat_p) == 0)
+ tsize = stat_p.st_size;
+ else {
+ tftp_send_error(spt, 1, "File not found", tp);
+ return;
+ }
+ }
+
+ tftp_send_oack(spt, "tsize", tsize, tp);
+ }
+ }
+
tftp_send_data(spt, 1, tp);
}
@@ -310,14 +399,14 @@ static void tftp_handle_ack(struct tftp_t *tp, int pktlen)
return;
}
- if (tftp_send_data(&tftp_sessions[s],
- ntohs(tp->x.tp_data.tp_block_nr) + 1,
+ if (tftp_send_data(&tftp_sessions[s],
+ ntohs(tp->x.tp_data.tp_block_nr) + 1,
tp) < 0) {
return;
}
}
-void tftp_input(struct mbuf *m)
+void tftp_input(MBuf m)
{
struct tftp_t *tp = (struct tftp_t *)m->m_data;
diff --git a/slirp/tftp.h b/slirp/tftp.h
index f0560b6..06018a7 100644
--- a/slirp/tftp.h
+++ b/slirp/tftp.h
@@ -9,6 +9,7 @@
#define TFTP_DATA 3
#define TFTP_ACK 4
#define TFTP_ERROR 5
+#define TFTP_OACK 6
#define TFTP_FILENAME_MAX 512
@@ -29,4 +30,4 @@ struct tftp_t {
} x;
};
-void tftp_input(struct mbuf *m);
+void tftp_input(MBuf m);
diff --git a/slirp/udp.c b/slirp/udp.c
index 0d70970..d96251d 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -37,8 +37,8 @@
/*
* Changes and additions relating to SLiRP
* Copyright (c) 1995 Danny Gasparovski.
- *
- * Please read the file COPYRIGHT for the
+ *
+ * Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
@@ -66,26 +66,26 @@ udp_init()
{
udb.so_next = udb.so_prev = &udb;
}
-/* m->m_data points at ip packet header
- * m->m_len length ip packet
+/* m->m_data points at ip packet header
+ * m->m_len length ip packet
* ip->ip_len length data (IPDU)
*/
void
udp_input(m, iphlen)
- register struct mbuf *m;
+ register MBuf m;
int iphlen;
{
register struct ip *ip;
register struct udphdr *uh;
-/* struct mbuf *opts = 0;*/
+/* MBuf opts = 0;*/
int len;
- struct ip save_ip;
+ struct ip save_ip;
struct socket *so;
-
+
DEBUG_CALL("udp_input");
DEBUG_ARG("m = %lx", (long)m);
DEBUG_ARG("iphlen = %d", iphlen);
-
+
udpstat.udps_ipackets++;
/*
@@ -95,14 +95,14 @@ udp_input(m, iphlen)
* with options still present.
*/
if(iphlen > sizeof(struct ip)) {
- ip_stripoptions(m, (struct mbuf *)0);
+ ip_stripoptions(m, (MBuf )0);
iphlen = sizeof(struct ip);
}
/*
* Get IP and UDP header together in first mbuf.
*/
- ip = mtod(m, struct ip *);
+ ip = MBUF_TO(m, struct ip *);
uh = (struct udphdr *)((caddr_t)ip + iphlen);
/*
@@ -116,15 +116,15 @@ udp_input(m, iphlen)
udpstat.udps_badlen++;
goto bad;
}
- m_adj(m, len - ip->ip_len);
+ mbuf_trim(m, len - ip->ip_len);
ip->ip_len = len;
}
-
+
/*
* Save a copy of the IP header in case we want restore it
* for sending an ICMP error message in response.
*/
- save_ip = *ip;
+ save_ip = *ip;
save_ip.ip_len+= iphlen; /* tcp_input subtracts this */
/*
@@ -136,8 +136,8 @@ udp_input(m, iphlen)
((struct ipovly *)ip)->ih_x1 = 0;
((struct ipovly *)ip)->ih_len = uh->uh_ulen;
/* keep uh_sum for ICMP reply
- * uh->uh_sum = cksum(m, len + sizeof (struct ip));
- * if (uh->uh_sum) {
+ * uh->uh_sum = cksum(m, len + sizeof (struct ip));
+ * if (uh->uh_sum) {
*/
if(cksum(m, len + sizeof(struct ip))) {
udpstat.udps_badsum++;
@@ -168,7 +168,7 @@ udp_input(m, iphlen)
if (so->so_lport != uh->uh_sport ||
so->so_laddr.s_addr != ip->ip_src.s_addr) {
struct socket *tmp;
-
+
for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) {
if (tmp->so_lport == uh->uh_sport &&
tmp->so_laddr.s_addr == ip->ip_src.s_addr) {
@@ -185,7 +185,7 @@ udp_input(m, iphlen)
udp_last_so = so;
}
}
-
+
if (so == NULL) {
/*
* If there's no socket for this packet,
@@ -193,31 +193,32 @@ udp_input(m, iphlen)
*/
if ((so = socreate()) == NULL) goto bad;
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)));
sofree(so);
goto bad;
}
-
+
/*
* Setup fields
*/
/* udp_last_so = so; */
so->so_laddr = ip->ip_src;
so->so_lport = uh->uh_sport;
- so->so_faddr = ip->ip_dst; /* XXX */
- so->so_fport = uh->uh_dport; /* XXX */
-
+
if ((so->so_iptos = udp_tos(so)) == 0)
so->so_iptos = ip->ip_tos;
-
+
/*
* XXXXX Here, check if it's in udpexec_list,
* and if it is, do the fork_exec() etc.
*/
}
- iphlen += sizeof(struct udphdr);
+ so->so_faddr = ip->ip_dst; /* XXX */
+ so->so_fport = uh->uh_dport; /* XXX */
+
+ iphlen += sizeof(struct udphdr);
m->m_len -= iphlen;
m->m_data += iphlen;
@@ -232,10 +233,10 @@ udp_input(m, iphlen)
m->m_data -= iphlen;
*ip=save_ip;
DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno)));
- icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
+ icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
}
- m_free(so->so_m); /* used for ICMP if error on sorecvfrom */
+ mbuf_free(so->so_m); /* used for ICMP if error on sorecvfrom */
/* restore the orig mbuf packet */
m->m_len += iphlen;
@@ -245,12 +246,12 @@ udp_input(m, iphlen)
return;
bad:
- m_freem(m);
- /* if (opts) m_freem(opts); */
+ mbuf_free(m);
+ /* if (opts) mbuf_free(opts); */
return;
}
-int udp_output2(struct socket *so, struct mbuf *m,
+int udp_output2(struct socket *so, MBuf m,
struct sockaddr_in *saddr, struct sockaddr_in *daddr,
int iptos)
{
@@ -268,12 +269,12 @@ int udp_output2(struct socket *so, struct mbuf *m,
*/
m->m_data -= sizeof(struct udpiphdr);
m->m_len += sizeof(struct udpiphdr);
-
+
/*
* Fill in mbuf with extended UDP header
* and addresses and length put into network format.
*/
- ui = mtod(m, struct udpiphdr *);
+ ui = MBUF_TO(m, struct udpiphdr *);
ui->ui_next = ui->ui_prev = 0;
ui->ui_x1 = 0;
ui->ui_pr = IPPROTO_UDP;
@@ -297,15 +298,15 @@ int udp_output2(struct socket *so, struct mbuf *m,
((struct ip *)ui)->ip_ttl = ip_defttl;
((struct ip *)ui)->ip_tos = iptos;
-
+
udpstat.udps_opackets++;
-
+
error = ip_output(so, m);
-
+
return (error);
}
-int udp_output(struct socket *so, struct mbuf *m,
+int udp_output(struct socket *so, MBuf m,
struct sockaddr_in *addr)
{
@@ -319,7 +320,7 @@ int udp_output(struct socket *so, struct mbuf *m,
}
daddr.sin_addr = so->so_laddr;
daddr.sin_port = so->so_lport;
-
+
return udp_output2(so, m, &saddr, &daddr, so->so_iptos);
}
@@ -328,7 +329,7 @@ udp_attach(so)
struct socket *so;
{
struct sockaddr_in addr;
-
+
if((so->s = socket(AF_INET,SOCK_DGRAM,0)) != -1) {
/*
* Here, we bind() the socket. Although not really needed
@@ -361,7 +362,7 @@ udp_detach(so)
struct socket *so;
{
closesocket(so->s);
- /* if (so->so_m) m_free(so->so_m); done by sofree */
+ /* if (so->so_m) mbuf_free(so->so_m); done by sofree */
sofree(so);
}
@@ -379,7 +380,7 @@ udp_tos(so)
struct socket *so;
{
int i = 0;
-
+
while(udptos[i].tos) {
if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) ||
(udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) {
@@ -388,7 +389,7 @@ udp_tos(so)
}
i++;
}
-
+
return 0;
}
@@ -402,7 +403,7 @@ udp_tos(so)
void
udp_emu(so, m)
struct socket *so;
- struct mbuf *m;
+ MBuf m;
{
struct sockaddr_in addr;
int addrlen = sizeof(addr);
@@ -411,17 +412,17 @@ udp_emu(so, m)
CTL_MSG *nmsg;
char buff[sizeof(CTL_MSG)];
u_char type;
-
+
struct talk_request {
struct talk_request *next;
struct socket *udp_so;
struct socket *tcp_so;
} *req;
-
- static struct talk_request *req_tbl = 0;
-
+
+ static struct talk_request *req_tbl = 0;
+
#endif
-
+
struct cu_header {
uint16_t d_family; // destination family
uint16_t d_port; // destination port
@@ -448,7 +449,7 @@ struct cu_header {
*/
if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0)
return;
-
+
#define IS_OLD (so->so_emu == EMU_TALK)
#define COPY_MSG(dest, src) { dest->type = src->type; \
@@ -465,24 +466,24 @@ struct cu_header {
if (IS_OLD) { /* old talk */
- omsg = mtod(m, CTL_MSG_OLD*);
+ omsg = MBUF_TO(m, CTL_MSG_OLD*);
nmsg = (CTL_MSG *) buff;
type = omsg->type;
OTOSIN(omsg, ctl_addr)->sin_port = addr.sin_port;
OTOSIN(omsg, ctl_addr)->sin_addr = our_addr;
strncpy(omsg->l_name, getlogin(), NAME_SIZE_OLD);
- } else { /* new talk */
+ } else { /* new talk */
omsg = (CTL_MSG_OLD *) buff;
- nmsg = mtod(m, CTL_MSG *);
+ nmsg = MBUF_TO(m, CTL_MSG *);
type = nmsg->type;
OTOSIN(nmsg, ctl_addr)->sin_port = addr.sin_port;
OTOSIN(nmsg, ctl_addr)->sin_addr = our_addr;
strncpy(nmsg->l_name, getlogin(), NAME_SIZE_OLD);
}
-
- if (type == LOOK_UP)
+
+ if (type == LOOK_UP)
return; /* for LOOK_UP this is enough */
-
+
if (IS_OLD) { /* make a copy of the message */
COPY_MSG(nmsg, omsg);
nmsg->vers = 1;
@@ -501,75 +502,75 @@ struct cu_header {
* ports, 517 and 518. This is why we have two copies
* of the message, one in old talk and one in new talk
* format.
- */
+ */
if (type == ANNOUNCE) {
int s;
u_short temp_port;
-
+
for(req = req_tbl; req; req = req->next)
if (so == req->udp_so)
break; /* found it */
-
+
if (!req) { /* no entry for so, create new */
req = (struct talk_request *)
malloc(sizeof(struct talk_request));
req->udp_so = so;
- req->tcp_so = solisten(0,
- OTOSIN(omsg, addr)->sin_addr.s_addr,
+ req->tcp_so = solisten(0,
+ OTOSIN(omsg, addr)->sin_addr.s_addr,
OTOSIN(omsg, addr)->sin_port,
SS_FACCEPTONCE);
req->next = req_tbl;
req_tbl = req;
- }
-
+ }
+
/* replace port number in addr field */
addrlen = sizeof(addr);
- getsockname(req->tcp_so->s,
+ getsockname(req->tcp_so->s,
(struct sockaddr *) &addr,
- &addrlen);
+ &addrlen);
OTOSIN(omsg, addr)->sin_port = addr.sin_port;
OTOSIN(omsg, addr)->sin_addr = our_addr;
OTOSIN(nmsg, addr)->sin_port = addr.sin_port;
- OTOSIN(nmsg, addr)->sin_addr = our_addr;
-
+ OTOSIN(nmsg, addr)->sin_addr = our_addr;
+
/* send LEAVE_INVITEs */
temp_port = OTOSIN(omsg, ctl_addr)->sin_port;
OTOSIN(omsg, ctl_addr)->sin_port = 0;
OTOSIN(nmsg, ctl_addr)->sin_port = 0;
- omsg->type = nmsg->type = LEAVE_INVITE;
-
+ omsg->type = nmsg->type = LEAVE_INVITE;
+
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
addr.sin_addr = our_addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(517);
- sendto(s, (char *)omsg, sizeof(*omsg), 0,
+ sendto(s, (char *)omsg, sizeof(*omsg), 0,
(struct sockaddr *)&addr, sizeof(addr));
addr.sin_port = htons(518);
sendto(s, (char *)nmsg, sizeof(*nmsg), 0,
(struct sockaddr *) &addr, sizeof(addr));
closesocket(s) ;
- omsg->type = nmsg->type = ANNOUNCE;
+ omsg->type = nmsg->type = ANNOUNCE;
OTOSIN(omsg, ctl_addr)->sin_port = temp_port;
OTOSIN(nmsg, ctl_addr)->sin_port = temp_port;
}
-
- /*
+
+ /*
* If it is a DELETE message, we send a copy to the
* local daemons. Then we delete the entry corresponding
* to our socket from the request table.
*/
-
+
if (type == DELETE) {
struct talk_request *temp_req, *req_next;
int s;
u_short temp_port;
-
+
temp_port = OTOSIN(omsg, ctl_addr)->sin_port;
OTOSIN(omsg, ctl_addr)->sin_port = 0;
OTOSIN(nmsg, ctl_addr)->sin_port = 0;
-
+
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
addr.sin_addr = our_addr;
addr.sin_family = AF_INET;
@@ -580,7 +581,7 @@ struct cu_header {
sendto(s, (char *)nmsg, sizeof(*nmsg), 0,
(struct sockaddr *)&addr, sizeof(addr));
closesocket(s);
-
+
OTOSIN(omsg, ctl_addr)->sin_port = temp_port;
OTOSIN(nmsg, ctl_addr)->sin_port = temp_port;
@@ -603,26 +604,26 @@ struct cu_header {
}
}
}
-
- return;
+
+ return;
#endif
-
+
case EMU_CUSEEME:
-
+
/*
* Cu-SeeMe emulation.
* Hopefully the packet is more that 16 bytes long. We don't
* do any other tests, just replace the address and port
* fields.
- */
+ */
if (m->m_len >= sizeof (*cu_head)) {
if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0)
return;
- cu_head = mtod(m, struct cu_header *);
+ cu_head = MBUF_TO(m, struct cu_header *);
cu_head->s_port = addr.sin_port;
cu_head->so_addr = our_addr.s_addr;
}
-
+
return;
}
}
@@ -636,14 +637,15 @@ udp_listen(port, laddr, lport, flags)
{
struct sockaddr_in addr;
struct socket *so;
- int addrlen = sizeof(struct sockaddr_in), opt = 1;
-
+ int addrlen = sizeof(struct sockaddr_in);
+
if ((so = socreate()) == NULL) {
free(so);
return NULL;
}
so->s = socket(AF_INET,SOCK_DGRAM,0);
so->so_expire = curtime + SO_EXPIRE;
+ so->so_hport = port;
insque(so,&udb);
addr.sin_family = AF_INET;
@@ -654,22 +656,44 @@ udp_listen(port, laddr, lport, flags)
udp_detach(so);
return NULL;
}
- setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
-/* setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); */
-
+ socket_set_xreuseaddr(so->s);
+
getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
so->so_fport = addr.sin_port;
if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
so->so_faddr = alias_addr;
else
so->so_faddr = addr.sin_addr;
-
+
so->so_lport = lport;
so->so_laddr.s_addr = laddr;
if (flags != SS_FACCEPTONCE)
so->so_expire = 0;
-
+
so->so_state = SS_ISFCONNECTED;
-
+
return so;
}
+
+int udp_unlisten (u_int port)
+{
+ struct socket *so;
+
+ for (so = udb.so_next; so != &udb; so = so->so_next) {
+ if (so->so_hport == htons(port)) {
+ break;
+ }
+ }
+
+ if (so == &udb)
+ return -1;
+
+ sofcantrcvmore( so );
+ sofcantsendmore( so );
+ close( so->s );
+ so->s = -1;
+ sofree( so );
+ return 0;
+}
+
+
diff --git a/slirp/udp.h b/slirp/udp.h
index 24c11bb..f59925d 100644
--- a/slirp/udp.h
+++ b/slirp/udp.h
@@ -97,14 +97,15 @@ extern struct socket udb;
struct mbuf;
void udp_init _P((void));
-void udp_input _P((register struct mbuf *, int));
-int udp_output _P((struct socket *, struct mbuf *, struct sockaddr_in *));
+void udp_input _P((register MBuf , int));
+int udp_output _P((struct socket *, MBuf , struct sockaddr_in *));
int udp_attach _P((struct socket *));
void udp_detach _P((struct socket *));
u_int8_t udp_tos _P((struct socket *));
-void udp_emu _P((struct socket *, struct mbuf *));
+void udp_emu _P((struct socket *, MBuf ));
struct socket * udp_listen _P((u_int, u_int32_t, u_int, int));
-int udp_output2(struct socket *so, struct mbuf *m,
+int udp_unlisten _P((u_int));
+int udp_output2(struct socket *so, MBuf m,
struct sockaddr_in *saddr, struct sockaddr_in *daddr,
int iptos);
#endif