diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
commit | 55f4e4a5ec657a017e3bf75299ad71fd1c968dd3 (patch) | |
tree | 550ce922ea0e125ac6a9738210ce2939bf2fe901 /slirp | |
parent | 413f05aaf54fa08c0ae7e997327a4f4a473c0a8d (diff) | |
download | external_qemu-55f4e4a5ec657a017e3bf75299ad71fd1c968dd3.zip external_qemu-55f4e4a5ec657a017e3bf75299ad71fd1c968dd3.tar.gz external_qemu-55f4e4a5ec657a017e3bf75299ad71fd1c968dd3.tar.bz2 |
Initial Contribution
Diffstat (limited to 'slirp')
-rw-r--r-- | slirp/bootp.c | 13 | ||||
-rw-r--r-- | slirp/bootp.h | 2 | ||||
-rw-r--r-- | slirp/cksum.c | 4 | ||||
-rw-r--r-- | slirp/ctl.h | 3 | ||||
-rw-r--r-- | slirp/debug.c | 26 | ||||
-rw-r--r-- | slirp/if.c | 12 | ||||
-rw-r--r-- | slirp/if.h | 2 | ||||
-rw-r--r-- | slirp/ip_icmp.c | 83 | ||||
-rw-r--r-- | slirp/ip_icmp.h | 6 | ||||
-rw-r--r-- | slirp/ip_input.c | 54 | ||||
-rw-r--r-- | slirp/ip_output.c | 20 | ||||
-rw-r--r-- | slirp/libslirp.h | 12 | ||||
-rw-r--r-- | slirp/main.h | 9 | ||||
-rw-r--r-- | slirp/mbuf.c | 195 | ||||
-rw-r--r-- | slirp/mbuf.h | 130 | ||||
-rw-r--r-- | slirp/misc.c | 724 | ||||
-rw-r--r-- | slirp/misc.h | 25 | ||||
-rw-r--r-- | slirp/sbuf.c | 91 | ||||
-rw-r--r-- | slirp/sbuf.h | 40 | ||||
-rw-r--r-- | slirp/slirp.c | 540 | ||||
-rw-r--r-- | slirp/slirp.h | 18 | ||||
-rw-r--r-- | slirp/socket.c | 245 | ||||
-rw-r--r-- | slirp/socket.h | 27 | ||||
-rw-r--r-- | slirp/tcp.h | 4 | ||||
-rw-r--r-- | slirp/tcp_input.c | 270 | ||||
-rw-r--r-- | slirp/tcp_output.c | 16 | ||||
-rw-r--r-- | slirp/tcp_subr.c | 680 | ||||
-rw-r--r-- | slirp/tcp_timer.c | 4 | ||||
-rw-r--r-- | slirp/tcp_var.h | 5 | ||||
-rw-r--r-- | slirp/tftp.c | 149 | ||||
-rw-r--r-- | slirp/tftp.h | 3 | ||||
-rw-r--r-- | slirp/udp.c | 204 | ||||
-rw-r--r-- | slirp/udp.h | 9 |
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]; @@ -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; @@ -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 |