From 5a957e5d00b7db0299b9ada0567cbf04f93f62af Mon Sep 17 00:00:00 2001 From: SarahW Date: Tue, 8 Aug 2017 21:19:36 +0100 Subject: [PATCH] SLiRP 64-bit fixes. Originally written by Gleb Natapov for QEMU. --- src/slirp/ip.h | 65 +++++++------------ src/slirp/ip_input.c | 148 +++++++++++++++++++++--------------------- src/slirp/misc.c | 35 ---------- src/slirp/slirp.c | 5 +- src/slirp/slirp.h | 23 +++---- src/slirp/tcp_input.c | 45 ++++++------- src/slirp/tcp_subr.c | 22 +++---- src/slirp/tcp_var.h | 25 +------ src/slirp/tcpip.h | 11 +++- src/slirp/udp.c | 5 +- src/slirp/udp.h | 3 +- 11 files changed, 155 insertions(+), 232 deletions(-) diff --git a/src/slirp/ip.h b/src/slirp/ip.h index f7fc59f..f11a847 100644 --- a/src/slirp/ip.h +++ b/src/slirp/ip.h @@ -199,23 +199,18 @@ struct ip_timestamp { #define IP_MSS 576 /* default maximum segment size */ -#ifdef HAVE_SYS_TYPES32_H /* Overcome some Solaris 2.x junk */ -#include -#else -#if SIZEOF_CHAR_P == 4 -typedef SLIRPcaddr_t caddr32_t; -#else -typedef u_int32_t caddr32_t; -#endif -#endif +struct mbuf_ptr { + union + { + struct mbuf *mptr; + uint64_t dummy; + } m; +}; -#if SIZEOF_CHAR_P == 4 -typedef struct ipq *ipqp_32; -typedef struct ipasfrag *ipasfragp_32; -#else -typedef caddr32_t ipqp_32; -typedef caddr32_t ipasfragp_32; -#endif + +struct qlink { + void *next, *prev; +}; /* * Overlay for ip header used by other protocols (tcp, udp). @@ -225,7 +220,7 @@ typedef caddr32_t ipasfragp_32; #endif struct ipovly { - caddr32_t ih_next, ih_prev; /* for protocol sequence q's */ + struct mbuf_ptr ih_mbuf; /* backpointer to mbuf */ u_int8_t ih_x1; /* (unused) */ u_int8_t ih_pr; /* protocol */ u_int16_t ih_len; /* protocol length */ @@ -249,44 +244,30 @@ struct ipovly { * size 28 bytes */ struct ipq { - ipqp_32 next,prev; /* to other reass headers */ + struct qlink frag_link; /* to ip headers of fragments */ + struct qlink ip_link; /* to other reass headers */ u_int8_t ipq_ttl; /* time for reass q to live */ u_int8_t ipq_p; /* protocol of this fragment */ u_int16_t ipq_id; /* sequence id for reassembly */ - ipasfragp_32 ipq_next,ipq_prev; - /* to ip headers of fragments */ struct in_addr ipq_src,ipq_dst; }; /* * Ip header, when holding a fragment. * - * Note: ipf_next must be at same offset as ipq_next above + * Note: ipf_link must be at same offset as frag_link above */ struct ipasfrag { -#ifdef WORDS_BIGENDIAN - u_char ip_v:4, - ip_hl:4; -#else - u_char ip_hl:4, - ip_v:4; -#endif - /* BUG : u_int changed to u_int8_t. - * sizeof(u_int)==4 on linux 2.0 - */ - u_int8_t ipf_mff; /* XXX overlays ip_tos: use low bit - * to avoid destroying tos (PPPDTRuu); - * copied from (ip_off&IP_MF) */ - u_int16_t ip_len; - u_int16_t ip_id; - u_int16_t ip_off; - u_int8_t ip_ttl; - u_int8_t ip_p; - u_int16_t ip_sum; - ipasfragp_32 ipf_next; /* next fragment */ - ipasfragp_32 ipf_prev; /* previous fragment */ + struct qlink ipf_link; + struct ip ipf_ip; }; +#define ipf_off ipf_ip.ip_off +#define ipf_tos ipf_ip.ip_tos +#define ipf_len ipf_ip.ip_len +#define ipf_next ipf_link.next +#define ipf_prev ipf_link.prev + /* * Structure stored in mbuf in inpcb.ip_options * and passed to ip_output when ip options are in use. diff --git a/src/slirp/ip_input.c b/src/slirp/ip_input.c index 70d3fc8..7600f24 100644 --- a/src/slirp/ip_input.c +++ b/src/slirp/ip_input.c @@ -52,7 +52,7 @@ struct ipq ipq; void ip_init() { - ipq.next = ipq.prev = (ipqp_32)&ipq; + ipq.ip_link.next = ipq.ip_link.prev = &ipq.ip_link; ip_id = tt.tv_sec & 0xffff; udp_init(); tcp_init(); @@ -154,19 +154,21 @@ ip_input(m) * XXX This should fail, don't fragment yet */ if (ip->ip_off &~ IP_DF) { - register struct ipq *fp; + struct ipq *fp; + struct qlink *l; /* * Look for queue of fragments * of this datagram. */ - for (fp = (struct ipq *) ipq.next; fp != &ipq; - fp = (struct ipq *) fp->next) - if (ip->ip_id == fp->ipq_id && - ip->ip_src.s_addr == fp->ipq_src.s_addr && - ip->ip_dst.s_addr == fp->ipq_dst.s_addr && - ip->ip_p == fp->ipq_p) + for (l = (struct qlink*)(ipq.ip_link.next); l != &ipq.ip_link; l = (struct qlink*)(l->next)) { + fp = container_of(l, struct ipq, ip_link); + if (ip->ip_id == fp->ipq_id && + ip->ip_src.s_addr == fp->ipq_src.s_addr && + ip->ip_dst.s_addr == fp->ipq_dst.s_addr && + ip->ip_p == fp->ipq_p) goto found; - fp = 0; + } + fp = NULL; found: /* @@ -176,9 +178,9 @@ ip_input(m) */ ip->ip_len -= hlen; if (ip->ip_off & IP_MF) - ((struct ipasfrag *)ip)->ipf_mff |= 1; + ip->ip_tos |= 1; else - ((struct ipasfrag *)ip)->ipf_mff &= ~1; + ip->ip_tos &= ~1; ip->ip_off <<= 3; @@ -187,9 +189,9 @@ ip_input(m) * or if this is not the first fragment, * attempt reassembly; if it succeeds, proceed. */ - if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) { + if ((ip->ip_tos & 1) || ip->ip_off) { ipstat.ips_fragments++; - ip = ip_reass((struct ipasfrag *)ip, fp); + ip = ip_reass(ip, fp); if (ip == 0) return; ipstat.ips_reassembled++; @@ -225,16 +227,16 @@ bad: return; } +#define iptofrag(P) ((struct ipasfrag *)(((char*)(P)) - sizeof(struct qlink))) +#define fragtoip(P) ((struct ip*)(((char*)(P)) + sizeof(struct qlink))) + /* * Take incoming datagram fragment and try to * reassemble it into whole datagram. If a chain for * reassembly of this datagram already exists, then it * is given as fp; otherwise have to make a chain. */ -struct ip * -ip_reass(ip, fp) - register struct ipasfrag *ip; - register struct ipq *fp; +struct ip *ip_reass(struct ip *ip, struct ipq *fp) { register struct SLIRPmbuf *m = dtom(ip); register struct ipasfrag *q; @@ -261,13 +263,13 @@ ip_reass(ip, fp) struct SLIRPmbuf *t; if ((t = m_get()) == NULL) goto dropfrag; fp = mtod(t, struct ipq *); - insque_32(fp, &ipq); + insque(&fp->ip_link, &ipq.ip_link); fp->ipq_ttl = IPFRAGTTL; fp->ipq_p = ip->ip_p; fp->ipq_id = ip->ip_id; - fp->ipq_next = fp->ipq_prev = (ipasfragp_32)fp; - fp->ipq_src = ((struct ip *)ip)->ip_src; - fp->ipq_dst = ((struct ip *)ip)->ip_dst; + fp->frag_link.next = fp->frag_link.prev = &fp->frag_link; + fp->ipq_src = ip->ip_src; + fp->ipq_dst = ip->ip_dst; q = (struct ipasfrag *)fp; goto insert; } @@ -275,19 +277,19 @@ ip_reass(ip, fp) /* * Find a segment which begins after this one does. */ - for (q = (struct ipasfrag *)fp->ipq_next; q != (struct ipasfrag *)fp; - q = (struct ipasfrag *)q->ipf_next) - if (q->ip_off > ip->ip_off) + for (q = (struct ipasfrag*)fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link; q = (struct ipasfrag*)(q->ipf_next)) { + if (q->ipf_off > ip->ip_off) break; + } /* * If there is a preceding segment, it may provide some of * our data already. If so, drop the data from the incoming * segment. If it provides all of our data, drop us. */ - if (q->ipf_prev != (ipasfragp_32)fp) { - i = ((struct ipasfrag *)(q->ipf_prev))->ip_off + - ((struct ipasfrag *)(q->ipf_prev))->ip_len - ip->ip_off; + if (q->ipf_prev != &fp->frag_link) { + struct ipasfrag *pq = (struct ipasfrag*)(q->ipf_prev); + i = pq->ipf_off + pq->ipf_len - ip->ip_off; if (i > 0) { if (i >= ip->ip_len) goto dropfrag; @@ -301,17 +303,18 @@ ip_reass(ip, fp) * While we overlap succeeding segments trim them or, * if they are completely covered, dequeue them. */ - while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) { - i = (ip->ip_off + ip->ip_len) - q->ip_off; - if (i < q->ip_len) { - q->ip_len -= i; - q->ip_off += i; + while (q != (struct ipasfrag*)&fp->frag_link && + ip->ip_off + ip->ip_len > q->ipf_off) { + i = (ip->ip_off + ip->ip_len) - q->ipf_off; + if (i < q->ipf_len) { + q->ipf_len -= i; + q->ipf_off += i; m_adj(dtom(q), i); break; } - q = (struct ipasfrag *) q->ipf_next; - m_freem(dtom((struct ipasfrag *) q->ipf_prev)); - ip_deq((struct ipasfrag *) q->ipf_prev); + q = (struct ipasfrag*)(q->ipf_next); + m_freem(dtom(q->ipf_prev)); + ip_deq((struct ipasfrag*)(q->ipf_prev)); } insert: @@ -319,29 +322,27 @@ insert: * Stick new segment in its place; * check for complete reassembly. */ - ip_enq(ip, (struct ipasfrag *) q->ipf_prev); + ip_enq(iptofrag(ip), (struct ipasfrag*)(q->ipf_prev)); next = 0; - for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp; - q = (struct ipasfrag *) q->ipf_next) { - if (q->ip_off != next) - return (0); - next += q->ip_len; + for (q = (struct ipasfrag*)(fp->frag_link.next); q != (struct ipasfrag*)&fp->frag_link; q = (struct ipasfrag*)(q->ipf_next)) { + if (q->ipf_off != next) + return 0; + next += q->ipf_len; } - if (((struct ipasfrag *)(q->ipf_prev))->ipf_mff & 1) + if (((struct ipasfrag *)(q->ipf_prev))->ipf_tos & 1) return (0); /* * Reassembly is complete; concatenate fragments. */ - q = (struct ipasfrag *) fp->ipq_next; + q = (struct ipasfrag*)(fp->frag_link.next); m = dtom(q); q = (struct ipasfrag *) q->ipf_next; - while (q != (struct ipasfrag *)fp) { - struct SLIRPmbuf *t; - t = dtom(q); - q = (struct ipasfrag *) q->ipf_next; - m_cat(m, t); + while (q != (struct ipasfrag*)&fp->frag_link) { + struct mbuf *t = dtom(q); + q = (struct ipasfrag *) q->ipf_next; + m_cat(m, t); } /* @@ -350,7 +351,7 @@ insert: * dequeue and discard fragment reassembly header. * Make header visible. */ - ip = (struct ipasfrag *) fp->ipq_next; + q = (struct ipasfrag*)(fp->frag_link.next); /* * If the fragments concatenated to an SLIRPmbuf that's @@ -362,23 +363,23 @@ insert: if (m->m_flags & M_EXT) { int delta; delta = (char *)ip - m->m_dat; - ip = (struct ipasfrag *)(m->m_ext + delta); + q = (struct ipasfrag *)(m->m_ext + delta); } /* DEBUG_ARG("ip = %lx", (long)ip); * ip=(struct ipasfrag *)m->m_data; */ + ip = fragtoip(q); ip->ip_len = next; - ip->ipf_mff &= ~1; - ((struct ip *)ip)->ip_src = fp->ipq_src; - ((struct ip *)ip)->ip_dst = fp->ipq_dst; - remque_32(fp); + ip->ip_tos &= ~1; + ip->ip_src = fp->ipq_src; + ip->ip_dst = fp->ipq_dst; + remque(&fp->ip_link); (void) m_free(dtom(fp)); - m = dtom(ip); m->m_len += (ip->ip_hl << 2); m->m_data -= (ip->ip_hl << 2); - return ((struct ip *)ip); + return ip; dropfrag: ipstat.ips_fragdropped++; @@ -396,13 +397,12 @@ ip_freef(fp) { register struct ipasfrag *q, *p; - for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp; - q = p) { - p = (struct ipasfrag *) q->ipf_next; + for (q = (struct ipasfrag*)(fp->frag_link.next); q != (struct ipasfrag*)&fp->frag_link; q = p) { + p = (struct ipasfrag*)(q->ipf_next); ip_deq(q); m_freem(dtom(q)); } - remque_32(fp); + remque(&fp->ip_link); (void) m_free(dtom(fp)); } @@ -416,10 +416,10 @@ ip_enq(p, prev) { DEBUG_CALL("ip_enq"); DEBUG_ARG("prev = %lx", (long)prev); - p->ipf_prev = (ipasfragp_32) prev; + p->ipf_prev = prev; p->ipf_next = prev->ipf_next; - ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = (ipasfragp_32) p; - prev->ipf_next = (ipasfragp_32) p; + ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = p; + prev->ipf_next = p; } /* @@ -438,23 +438,23 @@ ip_deq(p) * if a timer expires on a reassembly * queue, discard it. */ -void -ip_slowtimo() +void ip_slowtimo() { - register struct ipq *fp; + struct qlink *l; DEBUG_CALL("ip_slowtimo"); - fp = (struct ipq *) ipq.next; - if (fp == 0) - return; + l = (struct qlink*)(ipq.ip_link.next); - while (fp != &ipq) { - --fp->ipq_ttl; - fp = (struct ipq *) fp->next; - if (((struct ipq *)(fp->prev))->ipq_ttl == 0) { + if (l == 0) + return; + + while (l != &ipq.ip_link) { + struct ipq *fp = container_of(l, struct ipq, ip_link); + l = (struct qlink*)(l->next); + if (--fp->ipq_ttl == 0) { ipstat.ips_fragtimeout++; - ip_freef((struct ipq *) fp->prev); + ip_freef(fp); } } } diff --git a/src/slirp/misc.c b/src/slirp/misc.c index b1e2df2..e88567e 100644 --- a/src/slirp/misc.c +++ b/src/slirp/misc.c @@ -117,41 +117,6 @@ getouraddr() #undef ANCIENT } -//#if SIZEOF_CHAR_P == 8 -//what?! - -struct quehead_32 { - u_int32_t qh_link; - u_int32_t qh_rlink; -}; - -inline void -insque_32(a, b) - void *a; - void *b; -{ - register struct quehead_32 *element = (struct quehead_32 *) a; - register struct quehead_32 *head = (struct quehead_32 *) b; - element->qh_link = head->qh_link; - head->qh_link = (u_int32_t)element; - element->qh_rlink = (u_int32_t)head; - ((struct quehead_32 *)(element->qh_link))->qh_rlink - = (u_int32_t)element; -} - -inline void -remque_32(a) - void *a; -{ - register struct quehead_32 *element = (struct quehead_32 *) a; - ((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink; - ((struct quehead_32 *)(element->qh_rlink))->qh_link = element->qh_link; - element->qh_rlink = 0; -} - -//#endif /* SIZEOF_CHAR_P == 8 */ -//Should be for 64bit - struct quehead { struct quehead *qh_link; struct quehead *qh_rlink; diff --git a/src/slirp/slirp.c b/src/slirp/slirp.c index 1ac66ae..a53ceb8 100644 --- a/src/slirp/slirp.c +++ b/src/slirp/slirp.c @@ -215,9 +215,8 @@ int slirp_select_fill(int *pnfds, * *_slowtimo needs calling if there are IP fragments * in the fragment queue, or there are TCP connections active */ - do_slowtimo = ((tcb.so_next != &tcb) || - ((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next)); - + do_slowtimo = ((tcb.so_next != &tcb) || (&ipq.ip_link != ipq.ip_link.next)); + for (so = tcb.so_next; (so != &tcb); so = so_next) { so_next = so->so_next; diff --git a/src/slirp/slirp.h b/src/slirp/slirp.h index 83a1b6d..416b402 100644 --- a/src/slirp/slirp.h +++ b/src/slirp/slirp.h @@ -11,6 +11,12 @@ #include "config.h" #include "slirp_config.h" +#ifndef container_of +#define container_of(address, type, field) ((type *)( \ + (uintptr_t)(address) - \ + (uintptr_t)(&((type *)0)->field))) +#endif + #ifdef _WIN32 #ifdef __GNUC__ //MINGW? # include @@ -63,6 +69,7 @@ typedef int ioctlsockopt_t; # define ioctlsocket ioctl # define closesocket(s) close(s) # define O_BINARY 0 +typedef char *SLIRPcaddr_t; #endif #include @@ -320,20 +327,6 @@ void if_start _P((struct ttys *)); void lprint _P((const char *, ...)); -extern int do_echo; - -#ifdef _MSC_VER -#define inline -#endif - -#if SIZEOF_CHAR_P == 4 -# define insque_32 insque -# define remque_32 remque -#else - extern inline void insque_32 _P((void *, void *)); - extern inline void remque_32 _P((void *)); -#endif - #ifndef _WIN32 #include #endif @@ -350,7 +343,7 @@ void if_output _P((struct SLIRPsocket *, struct SLIRPmbuf *)); /* ip_input.c */ void ip_init _P((void)); void ip_input _P((struct SLIRPmbuf *)); -struct ip * ip_reass _P((register struct ipasfrag *, register struct ipq *)); +struct ip * ip_reass _P((struct ip *, 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 *)); diff --git a/src/slirp/tcp_input.c b/src/slirp/tcp_input.c index 369ec00..f4c90bf 100644 --- a/src/slirp/tcp_input.c +++ b/src/slirp/tcp_input.c @@ -68,7 +68,7 @@ tcp_seq tcp_iss; /* tcp initial send seq # */ #ifdef TCP_ACK_HACK #define TCP_REASS(tp, ti, m, so, flags) {\ if ((ti)->ti_seq == (tp)->rcv_nxt && \ - (tp)->seg_next == (tcpiphdrp_32)(tp) && \ + tcpfrag_list_empty(tp) && \ (tp)->t_state == TCPS_ESTABLISHED) {\ if (ti->ti_flags & TH_PUSH) \ tp->t_flags |= TF_ACKNOW; \ @@ -91,7 +91,7 @@ tcp_seq tcp_iss; /* tcp initial send seq # */ #else #define TCP_REASS(tp, ti, m, so, flags) { \ if ((ti)->ti_seq == (tp)->rcv_nxt && \ - (tp)->seg_next == (tcpiphdrp_32)(tp) && \ + tcpfrag_list_empty(tp) && \ (tp)->t_state == TCPS_ESTABLISHED) { \ tp->t_flags |= TF_DELACK; \ (tp)->rcv_nxt += (ti)->ti_len; \ @@ -130,8 +130,8 @@ tcp_reass(tp, ti, m) /* * Find a segment which begins after this one does. */ - for (q = (struct tcpiphdr *)tp->seg_next; q != (struct tcpiphdr *)tp; - q = (struct tcpiphdr *)q->ti_next) + for (q = tcpfrag_list_first(tp); !tcpfrag_list_end(q, tp); + q = tcpiphdr_next(q)) if (SEQ_GT(q->ti_seq, ti->ti_seq)) break; @@ -140,9 +140,9 @@ tcp_reass(tp, ti, m) * our data already. If so, drop the data from the incoming * segment. If it provides all of our data, drop us. */ - if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) { + if (!tcpfrag_list_end(tcpiphdr_prev(q), tp)) { int i; - q = (struct tcpiphdr *)q->ti_prev; + q = tcpiphdr_prev(q); /* conversion to int (in i) handles seq wraparound */ i = q->ti_seq + q->ti_len - ti->ti_seq; if (i > 0) { @@ -162,36 +162,36 @@ tcp_reass(tp, ti, m) ti->ti_len -= i; ti->ti_seq += i; } - q = (struct tcpiphdr *)(q->ti_next); + q = tcpiphdr_next(q); } tcpstat.tcps_rcvoopack++; tcpstat.tcps_rcvoobyte += ti->ti_len; - REASS_MBUF(ti) = (mbufp_32) m; /* XXX */ + ti->ti_mbuf = m; /* * While we overlap succeeding segments trim them or, * if they are completely covered, dequeue them. */ - while (q != (struct tcpiphdr *)tp) { + while (!tcpfrag_list_end(q, tp)) { int i = (ti->ti_seq + ti->ti_len) - q->ti_seq; if (i <= 0) break; if (i < q->ti_len) { q->ti_seq += i; q->ti_len -= i; - m_adj((struct SLIRPmbuf *) REASS_MBUF(q), i); + m_adj(q->ti_mbuf, i); break; } - q = (struct tcpiphdr *)q->ti_next; - m = (struct SLIRPmbuf *) REASS_MBUF((struct tcpiphdr *)q->ti_prev); - remque_32((void *)(q->ti_prev)); + q = tcpiphdr_next(q); + m = tcpiphdr_prev(q)->ti_mbuf; + remque(tcpiphdr2qlink(tcpiphdr_prev(q))); m_freem(m); } /* * Stick new segment in its place. */ - insque_32(ti, (void *)(q->ti_prev)); + insque(tcpiphdr2qlink(ti), tcpiphdr2qlink(tcpiphdr_prev(q))); present: /* @@ -200,17 +200,17 @@ present: */ if (!TCPS_HAVEESTABLISHED(tp->t_state)) return (0); - ti = (struct tcpiphdr *) tp->seg_next; - if (ti == (struct tcpiphdr *)tp || ti->ti_seq != tp->rcv_nxt) + ti = tcpfrag_list_first(tp); + if (tcpfrag_list_end(ti, tp) || ti->ti_seq != tp->rcv_nxt) return (0); if (tp->t_state == TCPS_SYN_RECEIVED && ti->ti_len) return (0); do { tp->rcv_nxt += ti->ti_len; flags = ti->ti_flags & TH_FIN; - remque_32(ti); - m = (struct SLIRPmbuf *) REASS_MBUF(ti); /* XXX */ - ti = (struct tcpiphdr *)ti->ti_next; + remque(tcpiphdr2qlink(ti)); + m = ti->ti_mbuf; + ti = tcpiphdr_next(ti); /* if (so->so_state & SS_FCANTRCVMORE) */ if (so->so_state & SS_FCANTSENDMORE) m_freem(m); @@ -297,7 +297,8 @@ tcp_input(m, iphlen, inso) * Checksum extended TCP header and data. */ tlen = ((struct ip *)ti)->ip_len; - ti->ti_next = ti->ti_prev = 0; + tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = 0; + memset(&ti->ti_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr)); ti->ti_x1 = 0; ti->ti_len = htons((u_int16_t)tlen); len = sizeof(struct ip ) + tlen; @@ -546,8 +547,8 @@ findso: return; } } else if (ti->ti_ack == tp->snd_una && - tp->seg_next == (tcpiphdrp_32)tp && - ti->ti_len <= sbspace(&so->so_rcv)) { + tcpfrag_list_empty(tp) && + ti->ti_len <= sbspace(&so->so_rcv)) { /* * this is a pure, in-sequence data packet * with nothing on the reassembly queue and diff --git a/src/slirp/tcp_subr.c b/src/slirp/tcp_subr.c index f275244..70661c2 100644 --- a/src/slirp/tcp_subr.c +++ b/src/slirp/tcp_subr.c @@ -81,7 +81,7 @@ tcp_template(tp) struct SLIRPsocket *so = tp->t_socket; struct tcpiphdr *n = &tp->t_template; - n->ti_next = n->ti_prev = 0; + n->ti_mbuf = NULL; n->ti_x1 = 0; n->ti_pr = IPPROTO_TCP; n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip)); @@ -164,7 +164,7 @@ tcp_respond(tp, ti, m, ack, seq, flags) tlen += sizeof (struct tcpiphdr); m->m_len = tlen; - ti->ti_next = ti->ti_prev = 0; + ti->ti_mbuf = 0; ti->ti_x1 = 0; ti->ti_seq = htonl(seq); ti->ti_ack = htonl(ack); @@ -204,7 +204,7 @@ tcp_newtcpcb(so) return ((struct tcpcb *)0); memset((char *) tp, 0, sizeof(struct tcpcb)); - tp->seg_next = tp->seg_prev = (tcpiphdrp_32)tp; + tp->seg_next = tp->seg_prev = (struct tcpiphdr*)tp; tp->t_maxseg = tcp_mssdflt; tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0; @@ -280,11 +280,11 @@ tcp_close(tp) 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 SLIRPmbuf *) REASS_MBUF((struct tcpiphdr *)t->ti_prev); - remque_32((struct tcpiphdr *) t->ti_prev); + t = tcpfrag_list_first(tp); + while (!tcpfrag_list_end(t, tp)) { + t = tcpiphdr_next(t); + m = tcpiphdr_prev(t)->ti_mbuf; + remque(tcpiphdr2qlink(tcpiphdr_prev(t))); m_freem(m); } /* It's static */ @@ -1120,7 +1120,7 @@ do_prompt: * A typical packet for player version 1.0 (release version): * * 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 + * 0000:00 01 00 02 1B D7 00 00 67 E6 6C DC 63 00 12 50 .......glc..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 @@ -1132,8 +1132,8 @@ do_prompt: * * 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 + * 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 .guxc..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 diff --git a/src/slirp/tcp_var.h b/src/slirp/tcp_var.h index 422a57b..a0281cb 100644 --- a/src/slirp/tcp_var.h +++ b/src/slirp/tcp_var.h @@ -36,18 +36,12 @@ #include "tcpip.h" #include "tcp_timer.h" -#if SIZEOF_CHAR_P == 4 - typedef struct tcpiphdr *tcpiphdrp_32; -#else - typedef u_int32_t tcpiphdrp_32; -#endif - /* * Tcp control block, one per tcp; fields: */ struct tcpcb { - tcpiphdrp_32 seg_next; /* sequencing queue */ - tcpiphdrp_32 seg_prev; + struct tcpiphdr *seg_next; /* sequencing queue */ + struct tcpiphdr *seg_prev; short t_state; /* state of this connection */ short t_timer[TCPT_NTIMERS]; /* tcp timers */ short t_rxtshift; /* log(2) of rexmt exp. backoff */ @@ -166,21 +160,6 @@ struct tcpcb { #define TCP_REXMTVAL(tp) \ (((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar) -/* 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 - * 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 SLIRPmbuf *mbufp_32; -#else -typedef u_int32_t mbufp_32; -#endif -#define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t)) - /* * TCP statistics. * Many of these should be kept per connection, diff --git a/src/slirp/tcpip.h b/src/slirp/tcpip.h index 2edccb2..5dbe0ff 100644 --- a/src/slirp/tcpip.h +++ b/src/slirp/tcpip.h @@ -40,8 +40,7 @@ struct tcpiphdr { struct ipovly ti_i; /* overlaid ip structure */ struct tcphdr ti_t; /* tcp header */ }; -#define ti_next ti_i.ih_next -#define ti_prev ti_i.ih_prev +#define ti_mbuf ti_i.ih_mbuf.m.mptr #define ti_x1 ti_i.ih_x1 #define ti_pr ti_i.ih_pr #define ti_len ti_i.ih_len @@ -58,6 +57,14 @@ struct tcpiphdr { #define ti_sum ti_t.th_sum #define ti_urp ti_t.th_urp +#define tcpiphdr2qlink(T) ((struct qlink*)(((char*)(T)) - sizeof(struct qlink))) +#define qlink2tcpiphdr(Q) ((struct tcpiphdr*)(((char*)(Q)) + sizeof(struct qlink))) +#define tcpiphdr_next(T) qlink2tcpiphdr(tcpiphdr2qlink(T)->next) +#define tcpiphdr_prev(T) qlink2tcpiphdr(tcpiphdr2qlink(T)->prev) +#define tcpfrag_list_first(T) qlink2tcpiphdr((T)->seg_next) +#define tcpfrag_list_end(F, T) (tcpiphdr2qlink(F) == (struct qlink*)(T)) +#define tcpfrag_list_empty(T) ((T)->seg_next == (struct tcpiphdr*)(T)) + /* * Just a clean way to get to the first byte * of the packet diff --git a/src/slirp/udp.c b/src/slirp/udp.c index 928a64f..0efd8e5 100644 --- a/src/slirp/udp.c +++ b/src/slirp/udp.c @@ -128,8 +128,7 @@ udp_input(m, iphlen) * Checksum extended UDP header and data. */ if (udpcksum && uh->uh_sum) { - ((struct ipovly *)ip)->ih_next = 0; - ((struct ipovly *)ip)->ih_prev = 0; + memset(&((struct ipovly *)ip)->ih_mbuf, 0, sizeof(struct mbuf_ptr)); ((struct ipovly *)ip)->ih_x1 = 0; ((struct ipovly *)ip)->ih_len = uh->uh_ulen; /* keep uh_sum for ICMP reply @@ -272,7 +271,7 @@ int udp_output2(struct SLIRPsocket *so, struct SLIRPmbuf *m, * and addresses and length put into network format. */ ui = mtod(m, struct udpiphdr *); - ui->ui_next = ui->ui_prev = 0; + memset(&ui->ui_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr)); ui->ui_x1 = 0; ui->ui_pr = IPPROTO_UDP; ui->ui_len = htons(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */ diff --git a/src/slirp/udp.h b/src/slirp/udp.h index 807e55b..58ca011 100644 --- a/src/slirp/udp.h +++ b/src/slirp/udp.h @@ -64,8 +64,7 @@ struct udpiphdr { struct ipovly ui_i; /* overlaid ip structure */ struct udphdr ui_u; /* udp header */ }; -#define ui_next ui_i.ih_next -#define ui_prev ui_i.ih_prev +#define ui_mbuf ui_i.ih_mbuf.m.mptr #define ui_x1 ui_i.ih_x1 #define ui_pr ui_i.ih_pr #define ui_len ui_i.ih_len