SLiRP 64-bit fixes. Originally written by Gleb Natapov for QEMU.
This commit is contained in:
parent
03749ab0fb
commit
5a957e5d00
11 changed files with 156 additions and 233 deletions
|
|
@ -199,23 +199,18 @@ 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 */
|
struct mbuf_ptr {
|
||||||
#include <sys/types32.h>
|
union
|
||||||
#else
|
{
|
||||||
#if SIZEOF_CHAR_P == 4
|
struct mbuf *mptr;
|
||||||
typedef SLIRPcaddr_t caddr32_t;
|
uint64_t dummy;
|
||||||
#else
|
} m;
|
||||||
typedef u_int32_t caddr32_t;
|
};
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if SIZEOF_CHAR_P == 4
|
|
||||||
typedef struct ipq *ipqp_32;
|
struct qlink {
|
||||||
typedef struct ipasfrag *ipasfragp_32;
|
void *next, *prev;
|
||||||
#else
|
};
|
||||||
typedef caddr32_t ipqp_32;
|
|
||||||
typedef caddr32_t ipasfragp_32;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Overlay for ip header used by other protocols (tcp, udp).
|
* Overlay for ip header used by other protocols (tcp, udp).
|
||||||
|
|
@ -225,7 +220,7 @@ 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 */
|
||||||
|
|
@ -249,44 +244,30 @@ 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;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ip header, when holding a fragment.
|
* 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 {
|
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.
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,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();
|
||||||
|
|
@ -154,19 +154,21 @@ ip_input(m)
|
||||||
* XXX This should fail, don't fragment yet
|
* XXX This should fail, don't fragment yet
|
||||||
*/
|
*/
|
||||||
if (ip->ip_off &~ IP_DF) {
|
if (ip->ip_off &~ IP_DF) {
|
||||||
register struct ipq *fp;
|
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 = (struct qlink*)(ipq.ip_link.next); l != &ipq.ip_link; l = (struct qlink*)(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 +178,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 +189,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 +227,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 *
|
struct ip *ip_reass(struct ip *ip, struct ipq *fp)
|
||||||
ip_reass(ip, fp)
|
|
||||||
register struct ipasfrag *ip;
|
|
||||||
register struct ipq *fp;
|
|
||||||
{
|
{
|
||||||
register struct SLIRPmbuf *m = dtom(ip);
|
register struct SLIRPmbuf *m = dtom(ip);
|
||||||
register struct ipasfrag *q;
|
register struct ipasfrag *q;
|
||||||
|
|
@ -261,13 +263,13 @@ ip_reass(ip, fp)
|
||||||
struct SLIRPmbuf *t;
|
struct SLIRPmbuf *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,19 +277,19 @@ 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 = (struct ipasfrag*)fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link; q = (struct ipasfrag*)(q->ipf_next)) {
|
||||||
q = (struct ipasfrag *)q->ipf_next)
|
if (q->ipf_off > ip->ip_off)
|
||||||
if (q->ip_off > ip->ip_off)
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If there is a preceding segment, it may provide some of
|
* If there is a preceding segment, it may provide some of
|
||||||
* 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 = (struct ipasfrag*)(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 +303,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 = (struct ipasfrag*)(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((struct ipasfrag*)(q->ipf_prev));
|
||||||
}
|
}
|
||||||
|
|
||||||
insert:
|
insert:
|
||||||
|
|
@ -319,29 +322,27 @@ 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), (struct ipasfrag*)(q->ipf_prev));
|
||||||
next = 0;
|
next = 0;
|
||||||
for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;
|
for (q = (struct ipasfrag*)(fp->frag_link.next); q != (struct ipasfrag*)&fp->frag_link; q = (struct ipasfrag*)(q->ipf_next)) {
|
||||||
q = (struct ipasfrag *) q->ipf_next) {
|
if (q->ipf_off != next)
|
||||||
if (q->ip_off != next)
|
return 0;
|
||||||
return (0);
|
next += q->ipf_len;
|
||||||
next += q->ip_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 = (struct ipasfrag*)(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 SLIRPmbuf *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 +351,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 = (struct ipasfrag*)(fp->frag_link.next);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the fragments concatenated to an SLIRPmbuf that's
|
* If the fragments concatenated to an SLIRPmbuf that's
|
||||||
|
|
@ -362,23 +363,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 +397,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 = (struct ipasfrag*)(fp->frag_link.next); q != (struct ipasfrag*)&fp->frag_link; q = p) {
|
||||||
q = p) {
|
p = (struct ipasfrag*)(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 +416,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -438,23 +438,23 @@ ip_deq(p)
|
||||||
* if a timer expires on a reassembly
|
* if a timer expires on a reassembly
|
||||||
* queue, discard it.
|
* queue, discard it.
|
||||||
*/
|
*/
|
||||||
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 = (struct qlink*)(ipq.ip_link.next);
|
||||||
if (fp == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
while (fp != &ipq) {
|
if (l == 0)
|
||||||
--fp->ipq_ttl;
|
return;
|
||||||
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 = (struct qlink*)(l->next);
|
||||||
|
if (--fp->ipq_ttl == 0) {
|
||||||
ipstat.ips_fragtimeout++;
|
ipstat.ips_fragtimeout++;
|
||||||
ip_freef((struct ipq *) fp->prev);
|
ip_freef(fp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -117,41 +117,6 @@ getouraddr()
|
||||||
#undef ANCIENT
|
#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 {
|
||||||
struct quehead *qh_link;
|
struct quehead *qh_link;
|
||||||
struct quehead *qh_rlink;
|
struct quehead *qh_rlink;
|
||||||
|
|
|
||||||
|
|
@ -215,8 +215,7 @@ int slirp_select_fill(int *pnfds,
|
||||||
* *_slowtimo needs calling if there are IP fragments
|
* *_slowtimo needs calling if there are IP fragments
|
||||||
* 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) || (&ipq.ip_link != ipq.ip_link.next));
|
||||||
((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.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;
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,12 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "slirp_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 _WIN32
|
||||||
#ifdef __GNUC__ //MINGW?
|
#ifdef __GNUC__ //MINGW?
|
||||||
# include <inttypes.h>
|
# include <inttypes.h>
|
||||||
|
|
@ -63,6 +69,7 @@ typedef int ioctlsockopt_t;
|
||||||
# define ioctlsocket ioctl
|
# define ioctlsocket ioctl
|
||||||
# define closesocket(s) close(s)
|
# define closesocket(s) close(s)
|
||||||
# define O_BINARY 0
|
# define O_BINARY 0
|
||||||
|
typedef char *SLIRPcaddr_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
@ -320,20 +327,6 @@ void if_start _P((struct ttys *));
|
||||||
|
|
||||||
void lprint _P((const char *, ...));
|
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
|
#ifndef _WIN32
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -350,7 +343,7 @@ void if_output _P((struct SLIRPsocket *, struct SLIRPmbuf *));
|
||||||
/* ip_input.c */
|
/* ip_input.c */
|
||||||
void ip_init _P((void));
|
void ip_init _P((void));
|
||||||
void ip_input _P((struct SLIRPmbuf *));
|
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_freef _P((struct ipq *));
|
||||||
void ip_enq _P((register struct ipasfrag *, register struct ipasfrag *));
|
void ip_enq _P((register struct ipasfrag *, register struct ipasfrag *));
|
||||||
void ip_deq _P((register struct ipasfrag *));
|
void ip_deq _P((register struct ipasfrag *));
|
||||||
|
|
|
||||||
|
|
@ -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; \
|
||||||
|
|
@ -130,8 +130,8 @@ tcp_reass(tp, ti, m)
|
||||||
/*
|
/*
|
||||||
* 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;
|
||||||
|
|
||||||
|
|
@ -140,9 +140,9 @@ tcp_reass(tp, ti, m)
|
||||||
* 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)) {
|
||||||
int i;
|
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) {
|
||||||
|
|
@ -162,36 +162,36 @@ tcp_reass(tp, ti, m)
|
||||||
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)) {
|
||||||
int i = (ti->ti_seq + ti->ti_len) - q->ti_seq;
|
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 SLIRPmbuf *) REASS_MBUF(q), i);
|
m_adj(q->ti_mbuf, i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
q = (struct tcpiphdr *)q->ti_next;
|
q = tcpiphdr_next(q);
|
||||||
m = (struct SLIRPmbuf *) 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:
|
||||||
/*
|
/*
|
||||||
|
|
@ -200,17 +200,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 SLIRPmbuf *) 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);
|
||||||
|
|
@ -297,7 +297,8 @@ tcp_input(m, iphlen, 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;
|
||||||
|
|
@ -546,8 +547,8 @@ findso:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (ti->ti_ack == tp->snd_una &&
|
} else if (ti->ti_ack == tp->snd_una &&
|
||||||
tp->seg_next == (tcpiphdrp_32)tp &&
|
tcpfrag_list_empty(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
|
||||||
* with nothing on the reassembly queue and
|
* with nothing on the reassembly queue and
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ tcp_template(tp)
|
||||||
struct SLIRPsocket *so = tp->t_socket;
|
struct SLIRPsocket *so = tp->t_socket;
|
||||||
struct tcpiphdr *n = &tp->t_template;
|
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));
|
||||||
|
|
@ -164,7 +164,7 @@ tcp_respond(tp, ti, m, ack, seq, flags)
|
||||||
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);
|
||||||
|
|
@ -204,7 +204,7 @@ tcp_newtcpcb(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;
|
||||||
|
|
@ -280,11 +280,11 @@ tcp_close(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 SLIRPmbuf *) 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 */
|
||||||
|
|
@ -1120,7 +1120,7 @@ do_prompt:
|
||||||
* A typical packet for player version 1.0 (release version):
|
* 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
|
* 0000:00 01 00 02 1B D7 00 00 67 E6 6C DC 63 00 12 50 ..... | ||||||