Fix slirp crash on 64bit

This commit is contained in:
Seg 2020-12-11 17:15:53 -08:00
parent 226a3845e0
commit 54ea2c9354
11 changed files with 158 additions and 214 deletions

View File

@ -195,23 +195,19 @@ struct ip_timestamp {
#define IP_MSS 576 /* default maximum segment size */ #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 #if SIZEOF_CHAR_P == 4
typedef caddr_t caddr32_t; struct mbuf_ptr {
struct mbuf *mptr;
uint32_t dummy;
};
#else #else
typedef u_int32_t caddr32_t; struct mbuf_ptr {
#endif struct mbuf *mptr;
#endif };
#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 #endif
struct qlink {
void *next, *prev;
};
/* /*
* Overlay for ip header used by other protocols (tcp, udp). * Overlay for ip header used by other protocols (tcp, udp).
@ -221,13 +217,13 @@ typedef caddr32_t ipasfragp_32;
#endif #endif
struct ipovly { 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_x1; /* (unused) */
u_int8_t ih_pr; /* protocol */ u_int8_t ih_pr; /* protocol */
u_int16_t ih_len; /* protocol length */ u_int16_t ih_len; /* protocol length */
struct in_addr ih_src; /* source internet address */ struct in_addr ih_src; /* source internet address */
struct in_addr ih_dst; /* destination internet address */ struct in_addr ih_dst; /* destination internet address */
} PACKED__; } __attribute__((packed));
#ifdef PRAGMA_PACK_SUPPORTED #ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(PACK_RESET) #pragma pack(PACK_RESET)
@ -241,12 +237,13 @@ struct ipovly {
* size 28 bytes * size 28 bytes
*/ */
struct ipq { 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_ttl; /* time for reass q to live */
u_int8_t ipq_p; /* protocol of this fragment */ u_int8_t ipq_p; /* protocol of this fragment */
u_int16_t ipq_id; /* sequence id for reassembly */ 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; struct in_addr ipq_src,ipq_dst;
}; };
@ -256,29 +253,16 @@ struct ipq {
* Note: ipf_next must be at same offset as ipq_next above * Note: ipf_next must be at same offset as ipq_next above
*/ */
struct ipasfrag { struct ipasfrag {
#ifdef WORDS_BIGENDIAN struct qlink ipf_link;
u_char ip_v:4, struct ip ipf_ip;
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 */
}; };
#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 * Structure stored in mbuf in inpcb.ip_options
* and passed to ip_output when ip options are in use. * and passed to ip_output when ip options are in use.

View File

@ -38,6 +38,16 @@
* terms and conditions of the copyright. * terms and conditions of the copyright.
*/ */
#include <stdarg.h>
#include <stddef.h>
#include <stdbool.h>
#include <sys/types.h>
#define container_of(ptr, type, member) ({ \
const typeof(((type *) 0)->member) *__mptr = (ptr); \
(type *) ((char *) __mptr - offsetof(type, member));})
#include <slirp.h> #include <slirp.h>
#include "ip_icmp.h" #include "ip_icmp.h"
@ -52,7 +62,7 @@ struct ipq ipq;
void void
ip_init() 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; ip_id = tt.tv_sec & 0xffff;
udp_init(); udp_init();
tcp_init(); tcp_init();
@ -155,18 +165,20 @@ ip_input(m)
*/ */
if (ip->ip_off &~ IP_DF) { if (ip->ip_off &~ IP_DF) {
register struct ipq *fp; register struct ipq *fp;
struct qlink *l;
/* /*
* Look for queue of fragments * Look for queue of fragments
* of this datagram. * of this datagram.
*/ */
for (fp = (struct ipq *) ipq.next; fp != &ipq; for (l = ipq.ip_link.next; l != &ipq.ip_link; l = l->next) {
fp = (struct ipq *) fp->next) fp = container_of(l, struct ipq, ip_link);
if (ip->ip_id == fp->ipq_id && if (ip->ip_id == fp->ipq_id &&
ip->ip_src.s_addr == fp->ipq_src.s_addr && ip->ip_src.s_addr == fp->ipq_src.s_addr &&
ip->ip_dst.s_addr == fp->ipq_dst.s_addr && ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
ip->ip_p == fp->ipq_p) ip->ip_p == fp->ipq_p)
goto found; goto found;
fp = 0; }
fp = NULL;
found: found:
/* /*
@ -176,9 +188,9 @@ ip_input(m)
*/ */
ip->ip_len -= hlen; ip->ip_len -= hlen;
if (ip->ip_off & IP_MF) if (ip->ip_off & IP_MF)
((struct ipasfrag *)ip)->ipf_mff |= 1; ip->ip_tos |= 1;
else else
((struct ipasfrag *)ip)->ipf_mff &= ~1; ip->ip_tos &= ~1;
ip->ip_off <<= 3; ip->ip_off <<= 3;
@ -187,9 +199,9 @@ ip_input(m)
* or if this is not the first fragment, * or if this is not the first fragment,
* attempt reassembly; if it succeeds, proceed. * 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++; ipstat.ips_fragments++;
ip = ip_reass((struct ipasfrag *)ip, fp); ip = ip_reass(ip, fp);
if (ip == 0) if (ip == 0)
return; return;
ipstat.ips_reassembled++; ipstat.ips_reassembled++;
@ -225,16 +237,16 @@ bad:
return; 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 * Take incoming datagram fragment and try to
* reassemble it into whole datagram. If a chain for * reassemble it into whole datagram. If a chain for
* reassembly of this datagram already exists, then it * reassembly of this datagram already exists, then it
* is given as fp; otherwise have to make a chain. * is given as fp; otherwise have to make a chain.
*/ */
struct ip * static struct ip *
ip_reass(ip, fp) ip_reass(register struct ip *ip, register struct ipq *fp)
register struct ipasfrag *ip;
register struct ipq *fp;
{ {
register struct mbuf *m = dtom(ip); register struct mbuf *m = dtom(ip);
register struct ipasfrag *q; register struct ipasfrag *q;
@ -261,13 +273,13 @@ ip_reass(ip, fp)
struct mbuf *t; struct mbuf *t;
if ((t = m_get()) == NULL) goto dropfrag; if ((t = m_get()) == NULL) goto dropfrag;
fp = mtod(t, struct ipq *); fp = mtod(t, struct ipq *);
insque_32(fp, &ipq); insque(&fp->ip_link, &ipq.ip_link);
fp->ipq_ttl = IPFRAGTTL; fp->ipq_ttl = IPFRAGTTL;
fp->ipq_p = ip->ip_p; fp->ipq_p = ip->ip_p;
fp->ipq_id = ip->ip_id; fp->ipq_id = ip->ip_id;
fp->ipq_next = fp->ipq_prev = (ipasfragp_32)fp; fp->frag_link.next = fp->frag_link.prev = &fp->frag_link;
fp->ipq_src = ((struct ip *)ip)->ip_src; fp->ipq_src = ip->ip_src;
fp->ipq_dst = ((struct ip *)ip)->ip_dst; fp->ipq_dst = ip->ip_dst;
q = (struct ipasfrag *)fp; q = (struct ipasfrag *)fp;
goto insert; goto insert;
} }
@ -275,9 +287,9 @@ ip_reass(ip, fp)
/* /*
* Find a segment which begins after this one does. * Find a segment which begins after this one does.
*/ */
for (q = (struct ipasfrag *)fp->ipq_next; q != (struct ipasfrag *)fp; for (q = fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link;
q = (struct ipasfrag *)q->ipf_next) q = q->ipf_next)
if (q->ip_off > ip->ip_off) if (q->ipf_off > ip->ip_off)
break; break;
/* /*
@ -285,9 +297,9 @@ ip_reass(ip, fp)
* our data already. If so, drop the data from the incoming * our data already. If so, drop the data from the incoming
* segment. If it provides all of our data, drop us. * segment. If it provides all of our data, drop us.
*/ */
if (q->ipf_prev != (ipasfragp_32)fp) { if (q->ipf_prev != &fp->frag_link) {
i = ((struct ipasfrag *)(q->ipf_prev))->ip_off + struct ipasfrag *pq = q->ipf_prev;
((struct ipasfrag *)(q->ipf_prev))->ip_len - ip->ip_off; i = pq->ipf_off + pq->ipf_len - ip->ip_off;
if (i > 0) { if (i > 0) {
if (i >= ip->ip_len) if (i >= ip->ip_len)
goto dropfrag; goto dropfrag;
@ -301,17 +313,18 @@ ip_reass(ip, fp)
* While we overlap succeeding segments trim them or, * While we overlap succeeding segments trim them or,
* if they are completely covered, dequeue them. * if they are completely covered, dequeue them.
*/ */
while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) { while (q != (struct ipasfrag*)&fp->frag_link &&
i = (ip->ip_off + ip->ip_len) - q->ip_off; ip->ip_off + ip->ip_len > q->ipf_off) {
if (i < q->ip_len) { i = (ip->ip_off + ip->ip_len) - q->ipf_off;
q->ip_len -= i; if (i < q->ipf_len) {
q->ip_off += i; q->ipf_len -= i;
q->ipf_off += i;
m_adj(dtom(q), i); m_adj(dtom(q), i);
break; break;
} }
q = (struct ipasfrag *) q->ipf_next; q = q->ipf_next;
m_freem(dtom((struct ipasfrag *) q->ipf_prev)); m_freem(dtom(q->ipf_prev));
ip_deq((struct ipasfrag *) q->ipf_prev); ip_deq(q->ipf_prev);
} }
insert: insert:
@ -319,27 +332,26 @@ insert:
* Stick new segment in its place; * Stick new segment in its place;
* check for complete reassembly. * check for complete reassembly.
*/ */
ip_enq(ip, (struct ipasfrag *) q->ipf_prev); ip_enq(iptofrag(ip), q->ipf_prev);
next = 0; next = 0;
for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp; for (q = fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link;
q = (struct ipasfrag *) q->ipf_next) { q = q->ipf_next) {
if (q->ip_off != next) if (q->ipf_off != next)
return (0); 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); return (0);
/* /*
* Reassembly is complete; concatenate fragments. * Reassembly is complete; concatenate fragments.
*/ */
q = (struct ipasfrag *) fp->ipq_next; q = fp->frag_link.next;
m = dtom(q); m = dtom(q);
q = (struct ipasfrag *) q->ipf_next; q = (struct ipasfrag *) q->ipf_next;
while (q != (struct ipasfrag *)fp) { while (q != (struct ipasfrag*)&fp->frag_link) {
struct mbuf *t; struct mbuf *t = dtom(q);
t = dtom(q);
q = (struct ipasfrag *) q->ipf_next; q = (struct ipasfrag *) q->ipf_next;
m_cat(m, t); m_cat(m, t);
} }
@ -350,7 +362,7 @@ insert:
* dequeue and discard fragment reassembly header. * dequeue and discard fragment reassembly header.
* Make header visible. * Make header visible.
*/ */
ip = (struct ipasfrag *) fp->ipq_next; q = fp->frag_link.next;
/* /*
* If the fragments concatenated to an mbuf that's * If the fragments concatenated to an mbuf that's
@ -362,23 +374,23 @@ insert:
if (m->m_flags & M_EXT) { if (m->m_flags & M_EXT) {
int delta; int delta;
delta = (char *)ip - m->m_dat; 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); /* DEBUG_ARG("ip = %lx", (long)ip);
* ip=(struct ipasfrag *)m->m_data; */ * ip=(struct ipasfrag *)m->m_data; */
ip = fragtoip(q);
ip->ip_len = next; ip->ip_len = next;
ip->ipf_mff &= ~1; ip->ip_tos &= ~1;
((struct ip *)ip)->ip_src = fp->ipq_src; ip->ip_src = fp->ipq_src;
((struct ip *)ip)->ip_dst = fp->ipq_dst; ip->ip_dst = fp->ipq_dst;
remque_32(fp); remque(&fp->ip_link);
(void) m_free(dtom(fp)); (void) m_free(dtom(fp));
m = dtom(ip);
m->m_len += (ip->ip_hl << 2); m->m_len += (ip->ip_hl << 2);
m->m_data -= (ip->ip_hl << 2); m->m_data -= (ip->ip_hl << 2);
return ((struct ip *)ip); return ip;
dropfrag: dropfrag:
ipstat.ips_fragdropped++; ipstat.ips_fragdropped++;
@ -396,13 +408,12 @@ ip_freef(fp)
{ {
register struct ipasfrag *q, *p; 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) {
q = p) { p = q->ipf_next;
p = (struct ipasfrag *) q->ipf_next;
ip_deq(q); ip_deq(q);
m_freem(dtom(q)); m_freem(dtom(q));
} }
remque_32(fp); remque(&fp->ip_link);
(void) m_free(dtom(fp)); (void) m_free(dtom(fp));
} }
@ -416,10 +427,10 @@ ip_enq(p, prev)
{ {
DEBUG_CALL("ip_enq"); DEBUG_CALL("ip_enq");
DEBUG_ARG("prev = %lx", (long)prev); DEBUG_ARG("prev = %lx", (long)prev);
p->ipf_prev = (ipasfragp_32) prev; p->ipf_prev = prev;
p->ipf_next = prev->ipf_next; p->ipf_next = prev->ipf_next;
((struct ipasfrag *)(prev->ipf_next))->ipf_prev = (ipasfragp_32) p; ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = p;
prev->ipf_next = (ipasfragp_32) p; prev->ipf_next = p;
} }
/* /*
@ -441,20 +452,21 @@ ip_deq(p)
void void
ip_slowtimo() ip_slowtimo()
{ {
register struct ipq *fp; struct qlink *l;
DEBUG_CALL("ip_slowtimo"); DEBUG_CALL("ip_slowtimo");
fp = (struct ipq *) ipq.next; l = ipq.ip_link.next;
if (fp == 0)
if (l == 0)
return; return;
while (fp != &ipq) { while (l != &ipq.ip_link) {
--fp->ipq_ttl; struct ipq *fp = container_of(l, struct ipq, ip_link);
fp = (struct ipq *) fp->next; l = l->next;
if (((struct ipq *)(fp->prev))->ipq_ttl == 0) { if (--fp->ipq_ttl == 0) {
ipstat.ips_fragtimeout++; ipstat.ips_fragtimeout++;
ip_freef((struct ipq *) fp->prev); ip_freef(fp);
} }
} }
} }

View File

@ -90,34 +90,6 @@ void getouraddr()
our_addr.s_addr = loopback_addr.s_addr; 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(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(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 {
struct quehead *qh_link; struct quehead *qh_link;
struct quehead *qh_rlink; struct quehead *qh_rlink;

View File

@ -211,7 +211,7 @@ int slirp_select_fill(int *pnfds,
* in the fragment queue, or there are TCP connections active * in the fragment queue, or there are TCP connections active
*/ */
do_slowtimo = ((tcb.so_next != &tcb) || do_slowtimo = ((tcb.so_next != &tcb) ||
((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next)); (&ipq.ip_link != ipq.ip_link.next));
for (so = tcb.so_next; so != &tcb; so = so_next) { for (so = tcb.so_next; so != &tcb; so = so_next) {
so_next = so->so_next; so_next = so->so_next;

View File

@ -281,14 +281,6 @@ void lprint(const char *, ...);
extern int do_echo; extern int do_echo;
#if SIZEOF_CHAR_P == 4
# define insque_32 insque
# define remque_32 remque
#else
extern inline void insque_32(void *, void *);
extern inline void remque_32(void *);
#endif
#ifndef _WIN32 #ifndef _WIN32
#include <netdb.h> #include <netdb.h>
#endif #endif
@ -305,7 +297,8 @@ void if_output(struct socket *, struct mbuf *);
/* ip_input.c */ /* ip_input.c */
void ip_init(void); void ip_init(void);
void ip_input (struct mbuf *); void ip_input (struct mbuf *);
struct ip * ip_reass(register struct ipasfrag *, register struct ipq *); static struct ip *
ip_reass(register struct ip *ip, register struct ipq *);
void ip_freef (struct ipq *); void ip_freef (struct ipq *);
void ip_enq (register struct ipasfrag *, register struct ipasfrag *); void ip_enq (register struct ipasfrag *, register struct ipasfrag *);
void ip_deq (register struct ipasfrag *); void ip_deq (register struct ipasfrag *);

View File

@ -68,7 +68,7 @@ tcp_seq tcp_iss; /* tcp initial send seq # */
#ifdef TCP_ACK_HACK #ifdef TCP_ACK_HACK
#define TCP_REASS(tp, ti, m, so, flags) {\ #define TCP_REASS(tp, ti, m, so, flags) {\
if ((ti)->ti_seq == (tp)->rcv_nxt && \ if ((ti)->ti_seq == (tp)->rcv_nxt && \
(tp)->seg_next == (tcpiphdrp_32)(tp) && \ tcpfrag_list_empty(tp) && \
(tp)->t_state == TCPS_ESTABLISHED) {\ (tp)->t_state == TCPS_ESTABLISHED) {\
if (ti->ti_flags & TH_PUSH) \ if (ti->ti_flags & TH_PUSH) \
tp->t_flags |= TF_ACKNOW; \ tp->t_flags |= TF_ACKNOW; \
@ -91,7 +91,7 @@ tcp_seq tcp_iss; /* tcp initial send seq # */
#else #else
#define TCP_REASS(tp, ti, m, so, flags) { \ #define TCP_REASS(tp, ti, m, so, flags) { \
if ((ti)->ti_seq == (tp)->rcv_nxt && \ if ((ti)->ti_seq == (tp)->rcv_nxt && \
(tp)->seg_next == (tcpiphdrp_32)(tp) && \ tcpfrag_list_empty(tp) && \
(tp)->t_state == TCPS_ESTABLISHED) { \ (tp)->t_state == TCPS_ESTABLISHED) { \
tp->t_flags |= TF_DELACK; \ tp->t_flags |= TF_DELACK; \
(tp)->rcv_nxt += (ti)->ti_len; \ (tp)->rcv_nxt += (ti)->ti_len; \
@ -127,8 +127,8 @@ tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti, struct mbuf *
/* /*
* Find a segment which begins after this one does. * Find a segment which begins after this one does.
*/ */
for (q = (struct tcpiphdr *)tp->seg_next; q != (struct tcpiphdr *)tp; for (q = tcpfrag_list_first(tp); !tcpfrag_list_end(q, tp);
q = (struct tcpiphdr *)q->ti_next) q = tcpiphdr_next(q))
if (SEQ_GT(q->ti_seq, ti->ti_seq)) if (SEQ_GT(q->ti_seq, ti->ti_seq))
break; break;
@ -137,9 +137,9 @@ tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti, struct mbuf *
* our data already. If so, drop the data from the incoming * our data already. If so, drop the data from the incoming
* segment. If it provides all of our data, drop us. * 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; register int i;
q = (struct tcpiphdr *)q->ti_prev; q = tcpiphdr_prev(q);
/* conversion to int (in i) handles seq wraparound */ /* conversion to int (in i) handles seq wraparound */
i = q->ti_seq + q->ti_len - ti->ti_seq; i = q->ti_seq + q->ti_len - ti->ti_seq;
if (i > 0) { if (i > 0) {
@ -159,37 +159,36 @@ tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti, struct mbuf *
ti->ti_len -= i; ti->ti_len -= i;
ti->ti_seq += i; ti->ti_seq += i;
} }
q = (struct tcpiphdr *)(q->ti_next); q = tcpiphdr_next(q);
} }
tcpstat.tcps_rcvoopack++; tcpstat.tcps_rcvoopack++;
tcpstat.tcps_rcvoobyte += ti->ti_len; 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, * While we overlap succeeding segments trim them or,
* if they are completely covered, dequeue them. * 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; register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq;
if (i <= 0) if (i <= 0)
break; break;
if (i < q->ti_len) { if (i < q->ti_len) {
q->ti_seq += i; q->ti_seq += i;
q->ti_len -= i; q->ti_len -= i;
m_adj((struct mbuf *) REASS_MBUF(q), i); m_adj(q->ti_mbuf, i);
break; break;
} }
q = (struct tcpiphdr *)q->ti_next; q = tcpiphdr_next(q);
m = (struct mbuf *) REASS_MBUF((struct tcpiphdr *)q->ti_prev); m = tcpiphdr_prev(q)->ti_mbuf;
remque_32((void *)(q->ti_prev)); remque(tcpiphdr2qlink(tcpiphdr_prev(q)));
m_freem(m); m_freem(m);
} }
/* /*
* Stick new segment in its place. * Stick new segment in its place.
*/ */
insque_32(ti, (void *)(q->ti_prev)); insque(tcpiphdr2qlink(ti), tcpiphdr2qlink(tcpiphdr_prev(q)));
present: present:
/* /*
* Present data to user, advancing rcv_nxt through * Present data to user, advancing rcv_nxt through
@ -197,17 +196,17 @@ present:
*/ */
if (!TCPS_HAVEESTABLISHED(tp->t_state)) if (!TCPS_HAVEESTABLISHED(tp->t_state))
return (0); return (0);
ti = (struct tcpiphdr *) tp->seg_next; ti = tcpfrag_list_first(tp);
if (ti == (struct tcpiphdr *)tp || ti->ti_seq != tp->rcv_nxt) if (tcpfrag_list_end(ti, tp) || ti->ti_seq != tp->rcv_nxt)
return (0); return (0);
if (tp->t_state == TCPS_SYN_RECEIVED && ti->ti_len) if (tp->t_state == TCPS_SYN_RECEIVED && ti->ti_len)
return (0); return (0);
do { do {
tp->rcv_nxt += ti->ti_len; tp->rcv_nxt += ti->ti_len;
flags = ti->ti_flags & TH_FIN; flags = ti->ti_flags & TH_FIN;
remque_32(ti); remque(tcpiphdr2qlink(ti));
m = (struct mbuf *) REASS_MBUF(ti); /* XXX */ m = ti->ti_mbuf;
ti = (struct tcpiphdr *)ti->ti_next; ti = tcpiphdr_next(ti);
/* if (so->so_state & SS_FCANTRCVMORE) */ /* if (so->so_state & SS_FCANTRCVMORE) */
if (so->so_state & SS_FCANTSENDMORE) if (so->so_state & SS_FCANTSENDMORE)
m_freem(m); m_freem(m);
@ -292,7 +291,8 @@ void tcp_input(register struct mbuf *m, int iphlen, struct socket *inso)
* Checksum extended TCP header and data. * Checksum extended TCP header and data.
*/ */
tlen = ((struct ip *)ti)->ip_len; 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_x1 = 0;
ti->ti_len = htons((u_int16_t)tlen); ti->ti_len = htons((u_int16_t)tlen);
len = sizeof(struct ip) + tlen; len = sizeof(struct ip) + tlen;
@ -540,9 +540,8 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq))
return; return;
} }
} } else if (ti->ti_ack == tp->snd_una &&
else if (ti->ti_ack == tp->snd_una && tcpfrag_list_empty(tp) &&
tp->seg_next == (tcpiphdrp_32)tp &&
ti->ti_len <= sbspace(&so->so_rcv)) { ti->ti_len <= sbspace(&so->so_rcv)) {
/* /*
* this is a pure, in-sequence data packet * this is a pure, in-sequence data packet

View File

@ -78,7 +78,7 @@ void tcp_template(struct tcpcb *tp)
struct socket *so = tp->t_socket; struct socket *so = tp->t_socket;
register struct tcpiphdr *n = &tp->t_template; register struct tcpiphdr *n = &tp->t_template;
n->ti_next = n->ti_prev = 0; n->ti_mbuf = NULL;
n->ti_x1 = 0; n->ti_x1 = 0;
n->ti_pr = IPPROTO_TCP; n->ti_pr = IPPROTO_TCP;
n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip)); n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
@ -156,7 +156,7 @@ void tcp_respond(struct tcpcb *tp, register struct tcpiphdr *ti,
tlen += sizeof (struct tcpiphdr); tlen += sizeof (struct tcpiphdr);
m->m_len = tlen; m->m_len = tlen;
ti->ti_next = ti->ti_prev = 0; ti->ti_mbuf = 0;
ti->ti_x1 = 0; ti->ti_x1 = 0;
ti->ti_seq = htonl(seq); ti->ti_seq = htonl(seq);
ti->ti_ack = htonl(ack); ti->ti_ack = htonl(ack);
@ -194,7 +194,7 @@ struct tcpcb *tcp_newtcpcb(struct socket *so)
return ((struct tcpcb *)0); return ((struct tcpcb *)0);
memset((char *) tp, 0, sizeof(struct tcpcb)); 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_maxseg = tcp_mssdflt;
tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0; tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
@ -268,11 +268,11 @@ struct tcpcb *tcp_close(register struct tcpcb *tp)
DEBUG_ARG("tp = %lx", (long )tp); DEBUG_ARG("tp = %lx", (long )tp);
/* free the reassembly queue, if any */ /* free the reassembly queue, if any */
t = (struct tcpiphdr *) tp->seg_next; t = tcpfrag_list_first(tp);
while (t != (struct tcpiphdr *)tp) { while (!tcpfrag_list_end(t, tp)) {
t = (struct tcpiphdr *)t->ti_next; t = tcpiphdr_next(t);
m = (struct mbuf *) REASS_MBUF((struct tcpiphdr *)t->ti_prev); m = tcpiphdr_prev(t)->ti_mbuf;
remque_32((struct tcpiphdr *) t->ti_prev); remque(tcpiphdr2qlink(tcpiphdr_prev(t)));
m_freem(m); m_freem(m);
} }
/* It's static */ /* It's static */

View File

@ -36,18 +36,12 @@
#include "tcpip.h" #include "tcpip.h"
#include "tcp_timer.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: * Tcp control block, one per tcp; fields:
*/ */
struct tcpcb { struct tcpcb {
tcpiphdrp_32 seg_next; /* sequencing queue */ struct tcpiphdr *seg_next; /* sequencing queue */
tcpiphdrp_32 seg_prev; struct tcpiphdr *seg_prev;
short t_state; /* state of this connection */ short t_state; /* state of this connection */
short t_timer[TCPT_NTIMERS]; /* tcp timers */ short t_timer[TCPT_NTIMERS]; /* tcp timers */
short t_rxtshift; /* log(2) of rexmt exp. backoff */ short t_rxtshift; /* log(2) of rexmt exp. backoff */
@ -166,21 +160,6 @@ struct tcpcb {
#define TCP_REXMTVAL(tp) \ #define TCP_REXMTVAL(tp) \
(((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar) (((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar)
/* 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))
/* /*
* TCP statistics. * TCP statistics.
* Many of these should be kept per connection, * Many of these should be kept per connection,

View File

@ -40,8 +40,7 @@ struct tcpiphdr {
struct ipovly ti_i; /* overlaid ip structure */ struct ipovly ti_i; /* overlaid ip structure */
struct tcphdr ti_t; /* tcp header */ struct tcphdr ti_t; /* tcp header */
}; };
#define ti_next ti_i.ih_next #define ti_mbuf ti_i.ih_mbuf.mptr
#define ti_prev ti_i.ih_prev
#define ti_x1 ti_i.ih_x1 #define ti_x1 ti_i.ih_x1
#define ti_pr ti_i.ih_pr #define ti_pr ti_i.ih_pr
#define ti_len ti_i.ih_len #define ti_len ti_i.ih_len
@ -58,6 +57,14 @@ struct tcpiphdr {
#define ti_sum ti_t.th_sum #define ti_sum ti_t.th_sum
#define ti_urp ti_t.th_urp #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 * Just a clean way to get to the first byte
* of the packet * of the packet

View File

@ -128,8 +128,7 @@ udp_input(m, iphlen)
* Checksum extended UDP header and data. * Checksum extended UDP header and data.
*/ */
if (udpcksum && uh->uh_sum) { if (udpcksum && uh->uh_sum) {
((struct ipovly *)ip)->ih_next = 0; memset(&((struct ipovly *)ip)->ih_mbuf, 0, sizeof(struct mbuf_ptr));
((struct ipovly *)ip)->ih_prev = 0;
((struct ipovly *)ip)->ih_x1 = 0; ((struct ipovly *)ip)->ih_x1 = 0;
((struct ipovly *)ip)->ih_len = uh->uh_ulen; ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
/* keep uh_sum for ICMP reply /* keep uh_sum for ICMP reply
@ -272,7 +271,7 @@ int udp_output2(struct socket *so, struct mbuf *m,
* and addresses and length put into network format. * and addresses and length put into network format.
*/ */
ui = mtod(m, struct udpiphdr *); 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_x1 = 0;
ui->ui_pr = IPPROTO_UDP; ui->ui_pr = IPPROTO_UDP;
ui->ui_len = htons((u_short) (m->m_len - sizeof(struct ip))); /* + sizeof (struct udphdr)); */ ui->ui_len = htons((u_short) (m->m_len - sizeof(struct ip))); /* + sizeof (struct udphdr)); */

View File

@ -64,8 +64,7 @@ struct udpiphdr {
struct ipovly ui_i; /* overlaid ip structure */ struct ipovly ui_i; /* overlaid ip structure */
struct udphdr ui_u; /* udp header */ struct udphdr ui_u; /* udp header */
}; };
#define ui_next ui_i.ih_next #define ui_mbuf ui_i.ih_mbuf.mptr
#define ui_prev ui_i.ih_prev
#define ui_x1 ui_i.ih_x1 #define ui_x1 ui_i.ih_x1
#define ui_pr ui_i.ih_pr #define ui_pr ui_i.ih_pr
#define ui_len ui_i.ih_len #define ui_len ui_i.ih_len