diff options
author | blueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162> | 2009-01-13 19:48:42 +0000 |
---|---|---|
committer | blueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162> | 2009-01-13 19:48:42 +0000 |
commit | c11b407804272b71e5bdd7a2a9181c64c7a594ed (patch) | |
tree | 9e9e7762cebbdce72bfe557dfc36c39a7f6a0447 | |
parent | 5c9505f9dd23cc70dce30d575056d8277bcfdfd3 (diff) | |
download | slirp-c11b407804272b71e5bdd7a2a9181c64c7a594ed.zip slirp-c11b407804272b71e5bdd7a2a9181c64c7a594ed.tar.gz slirp-c11b407804272b71e5bdd7a2a9181c64c7a594ed.tar.bz2 |
Fix 64 bit issue in slirp
Signed-off-by: Gleb Natapov <gleb@redhat.com>
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6288 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r-- | ip.h | 62 | ||||
-rw-r--r-- | ip_input.c | 128 | ||||
-rw-r--r-- | misc.c | 28 | ||||
-rw-r--r-- | slirp.c | 4 | ||||
-rw-r--r-- | slirp.h | 8 | ||||
-rw-r--r-- | tcp_input.c | 124 | ||||
-rw-r--r-- | tcp_subr.c | 16 | ||||
-rw-r--r-- | tcp_var.h | 25 | ||||
-rw-r--r-- | tcpip.h | 13 | ||||
-rw-r--r-- | udp.c | 5 | ||||
-rw-r--r-- | udp.h | 3 |
11 files changed, 176 insertions, 240 deletions
@@ -183,35 +183,31 @@ struct ip_timestamp { #define IP_MSS 576 /* default maximum segment size */ -#ifdef HAVE_SYS_TYPES32_H /* Overcome some Solaris 2.x junk */ -#include <sys/types32.h> -#else #if SIZEOF_CHAR_P == 4 -typedef caddr_t caddr32_t; -#else -typedef u_int32_t caddr32_t; -#endif -#endif - -#if SIZEOF_CHAR_P == 4 -typedef struct ipq *ipqp_32; -typedef struct ipasfrag *ipasfragp_32; +struct mbuf_ptr { + struct mbuf *mptr; + uint32_t dummy; +}; #else -typedef caddr32_t ipqp_32; -typedef caddr32_t ipasfragp_32; +struct mbuf_ptr { + struct mbuf *mptr; +}; #endif +struct qlink { + void *next, *prev; +}; /* * Overlay for ip header used by other protocols (tcp, udp). */ 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 */ struct in_addr ih_src; /* source internet address */ struct in_addr ih_dst; /* destination internet address */ -}; +} __attribute__((packed)); /* * Ip reassembly queue structure. Each fragment @@ -221,42 +217,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_int ip_v : 4, ip_hl : 4; -#else - u_int 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. @@ -43,6 +43,7 @@ */ #include <slirp.h> +#include <osdep.h> #include "ip_icmp.h" #ifdef LOG_ENABLED @@ -51,8 +52,7 @@ struct ipstat ipstat; struct ipq ipq; -static struct ip *ip_reass(register struct ipasfrag *ip, - register struct ipq *fp); +static struct ip *ip_reass(register struct ip *ip, register struct ipq *fp); static void ip_freef(struct ipq *fp); static void ip_enq(register struct ipasfrag *p, register struct ipasfrag *prev); static void ip_deq(register struct ipasfrag *p); @@ -63,7 +63,7 @@ static void ip_deq(register struct ipasfrag *p); */ 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(); @@ -184,18 +184,20 @@ void ip_input(m) struct mbuf *m; */ if (ip->ip_off & ~IP_DF) { register 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) + for (l = ipq.ip_link.next; l != &ipq.ip_link; l = l->next) { + fp = container_of(l, struct ipq, ip_link); if (ip->ip_id == fp->ipq_id && ip->ip_src.s_addr == fp->ipq_src.s_addr && ip->ip_dst.s_addr == fp->ipq_dst.s_addr && ip->ip_p == fp->ipq_p) goto found; - fp = 0; + } + fp = NULL; found: /* @@ -205,9 +207,9 @@ void ip_input(m) struct mbuf *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; @@ -216,9 +218,9 @@ void ip_input(m) struct mbuf *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) { STAT(ipstat.ips_fragments++); - ip = ip_reass((struct ipasfrag *)ip, fp); + ip = ip_reass(ip, fp); if (ip == 0) return; STAT(ipstat.ips_reassembled++); @@ -253,14 +255,15 @@ 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. */ -static struct ip *ip_reass(register struct ipasfrag *ip, - register struct ipq *fp) +static struct ip *ip_reass(register struct ip *ip, register struct ipq *fp) { register struct mbuf *m = dtom(ip); register struct ipasfrag *q; @@ -288,13 +291,13 @@ static struct ip *ip_reass(register struct ipasfrag *ip, 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; } @@ -302,9 +305,9 @@ static struct ip *ip_reass(register struct ipasfrag *ip, /* * 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 = fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link; + q = q->ipf_next) + if (q->ipf_off > ip->ip_off) break; /* @@ -312,9 +315,9 @@ static struct ip *ip_reass(register struct ipasfrag *ip, * 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 = q->ipf_prev; + i = pq->ipf_off + pq->ipf_len - ip->ip_off; if (i > 0) { if (i >= ip->ip_len) goto dropfrag; @@ -328,17 +331,18 @@ static struct ip *ip_reass(register struct ipasfrag *ip, * 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 = q->ipf_next; + m_freem(dtom(q->ipf_prev)); + ip_deq(q->ipf_prev); } insert: @@ -346,27 +350,26 @@ insert: * Stick new segment in its place; * check for complete reassembly. */ - ip_enq(ip, (struct ipasfrag *)q->ipf_prev); + ip_enq(iptofrag(ip), 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) + for (q = fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link; + q = q->ipf_next) { + if (q->ipf_off != next) return (0); - next += q->ip_len; + 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 = fp->frag_link.next; m = dtom(q); q = (struct ipasfrag *)q->ipf_next; - while (q != (struct ipasfrag *)fp) { - struct mbuf *t; - t = dtom(q); + while (q != (struct ipasfrag *)&fp->frag_link) { + struct mbuf *t = dtom(q); q = (struct ipasfrag *)q->ipf_next; m_cat(m, t); } @@ -377,7 +380,7 @@ insert: * dequeue and discard fragment reassembly header. * Make header visible. */ - ip = (struct ipasfrag *)fp->ipq_next; + q = fp->frag_link.next; /* * If the fragments concatenated to an mbuf that's @@ -389,23 +392,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: STAT(ipstat.ips_fragdropped++); @@ -421,13 +424,13 @@ static void ip_freef(struct ipq *fp) { register struct ipasfrag *q, *p; - for (q = (struct ipasfrag *)fp->ipq_next; q != (struct ipasfrag *)fp; + for (q = fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link; q = p) { - p = (struct ipasfrag *)q->ipf_next; + p = q->ipf_next; ip_deq(q); m_freem(dtom(q)); } - remque_32(fp); + remque(&fp->ip_link); (void)m_free(dtom(fp)); } @@ -439,10 +442,10 @@ static void ip_enq(register struct ipasfrag *p, register struct ipasfrag *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; } /* @@ -461,20 +464,21 @@ static void ip_deq(register struct ipasfrag *p) */ void ip_slowtimo() { - register struct ipq *fp; + struct qlink *l; DEBUG_CALL("ip_slowtimo"); - fp = (struct ipq *)ipq.next; - if (fp == 0) + l = ipq.ip_link.next; + + if (l == 0) return; - while (fp != &ipq) { - --fp->ipq_ttl; - fp = (struct ipq *)fp->next; - if (((struct ipq *)(fp->prev))->ipq_ttl == 0) { + while (l != &ipq.ip_link) { + struct ipq *fp = container_of(l, struct ipq, ip_link); + l = l->next; + if (--fp->ipq_ttl == 0) { STAT(ipstat.ips_fragtimeout++); - ip_freef((struct ipq *)fp->prev); + ip_freef(fp); } } } @@ -82,34 +82,6 @@ void getouraddr() our_addr.s_addr = loopback_addr.s_addr; } -#if SIZEOF_CHAR_P == 8 - -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 */ - struct quehead { struct quehead *qh_link; struct quehead *qh_rlink; @@ -265,8 +265,8 @@ void slirp_select_fill(int *pnfds, fd_set *readfds, fd_set *writefds, * *_slowtimo needs calling if there are IP fragments * in the fragment queue, or there are TCP connections active */ - do_slowtimo = ((tcb.so_next != &tcb) || ((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; @@ -268,14 +268,6 @@ long gethostid _P((void)); void lprint _P((const char *, ...)); -#if SIZEOF_CHAR_P == 4 -#define insque_32 insque -#define remque_32 remque -#else -void insque_32 _P((void *, void *)); -void remque_32 _P((void *)); -#endif - #ifndef _WIN32 #include <netdb.h> #endif diff --git a/tcp_input.c b/tcp_input.c index e22b460..c82cc9c 100644 --- a/tcp_input.c +++ b/tcp_input.c @@ -69,51 +69,49 @@ tcp_seq tcp_iss; /* tcp initial send seq # */ * when segments are out of order (so fast retransmit can work). */ #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) && \ - (tp)->t_state == TCPS_ESTABLISHED) { \ - if (ti->ti_flags & TH_PUSH) \ - tp->t_flags |= TF_ACKNOW; \ - else \ - tp->t_flags |= TF_DELACK; \ - (tp)->rcv_nxt += (ti)->ti_len; \ - flags = (ti)->ti_flags & TH_FIN; \ - STAT(tcpstat.tcps_rcvpack++); \ - STAT(tcpstat.tcps_rcvbyte += (ti)->ti_len); \ - if (so->so_emu) { \ - if (tcp_emu((so), (m))) \ - sbappend((so), (m)); \ - } else \ - sbappend((so), (m)); \ - /* sorwakeup(so); */ \ - } else { \ - (flags) = tcp_reass((tp), (ti), (m)); \ - tp->t_flags |= TF_ACKNOW; \ - } \ +#define TCP_REASS(tp, ti, m, so, flags) \ + { \ + if ((ti)->ti_seq == (tp)->rcv_nxt && tcpfrag_list_empty(tp) && \ + (tp)->t_state == TCPS_ESTABLISHED) { \ + if (ti->ti_flags & TH_PUSH) \ + tp->t_flags |= TF_ACKNOW; \ + else \ + tp->t_flags |= TF_DELACK; \ + (tp)->rcv_nxt += (ti)->ti_len; \ + flags = (ti)->ti_flags & TH_FIN; \ + STAT(tcpstat.tcps_rcvpack++); \ + STAT(tcpstat.tcps_rcvbyte += (ti)->ti_len); \ + if (so->so_emu) { \ + if (tcp_emu((so), (m))) \ + sbappend((so), (m)); \ + } else \ + sbappend((so), (m)); \ + /* sorwakeup(so); */ \ + } else { \ + (flags) = tcp_reass((tp), (ti), (m)); \ + tp->t_flags |= TF_ACKNOW; \ + } \ } #else -#define TCP_REASS(tp, ti, m, so, flags) \ - { \ - if ((ti)->ti_seq == (tp)->rcv_nxt && \ - (tp)->seg_next == (tcpiphdrp_32)(tp) && \ - (tp)->t_state == TCPS_ESTABLISHED) { \ - tp->t_flags |= TF_DELACK; \ - (tp)->rcv_nxt += (ti)->ti_len; \ - flags = (ti)->ti_flags & TH_FIN; \ - STAT(tcpstat.tcps_rcvpack++); \ - STAT(tcpstat.tcps_rcvbyte += (ti)->ti_len); \ - if (so->so_emu) { \ - if (tcp_emu((so), (m))) \ - sbappend(so, (m)); \ - } else \ - sbappend((so), (m)); \ - /* sorwakeup(so); */ \ - } else { \ - (flags) = tcp_reass((tp), (ti), (m)); \ - tp->t_flags |= TF_ACKNOW; \ - } \ +#define TCP_REASS(tp, ti, m, so, flags) \ + { \ + if ((ti)->ti_seq == (tp)->rcv_nxt && tcpfrag_list_empty(tp) && \ + (tp)->t_state == TCPS_ESTABLISHED) { \ + tp->t_flags |= TF_DELACK; \ + (tp)->rcv_nxt += (ti)->ti_len; \ + flags = (ti)->ti_flags & TH_FIN; \ + STAT(tcpstat.tcps_rcvpack++); \ + STAT(tcpstat.tcps_rcvbyte += (ti)->ti_len); \ + if (so->so_emu) { \ + if (tcp_emu((so), (m))) \ + sbappend(so, (m)); \ + } else \ + sbappend((so), (m)); \ + /* sorwakeup(so); */ \ + } else { \ + (flags) = tcp_reass((tp), (ti), (m)); \ + tp->t_flags |= TF_ACKNOW; \ + } \ } #endif static void tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, @@ -137,8 +135,8 @@ static int tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti, /* * 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; @@ -147,9 +145,9 @@ static int tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti, * 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)) { register 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) { @@ -169,36 +167,36 @@ static int tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti, ti->ti_len -= i; ti->ti_seq += i; } - q = (struct tcpiphdr *)(q->ti_next); + q = tcpiphdr_next(q); } STAT(tcpstat.tcps_rcvoopack++); STAT(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)) { register 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 mbuf *)REASS_MBUF(q), i); + m_adj(q->ti_mbuf, i); break; } - q = (struct tcpiphdr *)q->ti_next; - m = (struct mbuf *)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: /* @@ -207,17 +205,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 mbuf *)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); @@ -304,7 +302,8 @@ struct socket *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; @@ -558,8 +557,7 @@ findso: return; } - } else if (ti->ti_ack == tp->snd_una && - tp->seg_next == (tcpiphdrp_32)tp && + } else if (ti->ti_ack == tp->snd_una && tcpfrag_list_empty(tp) && ti->ti_len <= sbspace(&so->so_rcv)) { /* * this is a pure, in-sequence data packet @@ -70,7 +70,7 @@ void tcp_template(tp) struct tcpcb *tp; struct socket *so = tp->t_socket; register 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)); @@ -157,7 +157,7 @@ int 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); @@ -195,7 +195,7 @@ struct tcpcb *tcp_newtcpcb(so) struct socket *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_MSS; tp->t_flags = TCP_DO_RFC1323 ? (TF_REQ_SCALE | TF_REQ_TSTMP) : 0; @@ -269,11 +269,11 @@ struct tcpcb *tcp_close(tp) register struct tcpcb *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 mbuf *)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 */ @@ -40,18 +40,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 */ @@ -169,21 +163,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 mbuf *mbufp_32; -#else -typedef u_int32_t mbufp_32; -#endif -#define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t)) - #ifdef LOG_ENABLED /* * TCP statistics. @@ -44,8 +44,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.mptr #define ti_x1 ti_i.ih_x1 #define ti_pr ti_i.ih_pr #define ti_len ti_i.ih_len @@ -62,6 +61,16 @@ 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 @@ -133,8 +133,7 @@ int 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 @@ -280,7 +279,7 @@ int udp_output2(struct socket *so, struct mbuf *m, struct sockaddr_in *saddr, * 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 = @@ -60,8 +60,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.mptr #define ui_x1 ui_i.ih_x1 #define ui_pr ui_i.ih_pr #define ui_len ui_i.ih_len |