Dear Maintainer,
I tried to find some more information about this issue.
Attached is a file containing some hints how I did run
the UML process and some debugging output.

As far as I see it is yet another issue with some "caddr32_t"
sizes, this time they are used to map the input data.
Therefore 8 Bytes get written instead of 4, when assigning
the next and prev pointer inside function tcp_input, line 306. [2]

Therefore the checksum for each IP packet does not
match anymore and gets dropped. ("11 discarded for bad checksums")

As it seems this type is sometimes mapped to input data and
then used for holding real pointers, it looks their size
cannot be just increased as done in patch 012_ipq64.patch.

Related bugs seem to be: #948268 or #922323.


When realising this type being the issue I found this patch [1],
which might have been created in the Qemu area.

Unfortunately this patch did not apply cleanly, but attached
patch c11b4078042_fix_64_bit_issue_in_slirp.patch is created from
the package with all patches applied and additionally
949003_explicit_extern_declaration.patch to fix a build failure.


One thing to note is building the package with -DDEBUG allows to
use the '-d 7' switch to get some verbose output in file 'slirp_debug'.


A package built with both patches and "-DDEBUG" was able to
do some http downloads.

Kind regards,
Bernhard


[1] 
https://gitlab.freedesktop.org/slirp/libslirp/-/commit/c11b407804272b71e5bdd7a2a9181c64c7a594ed


[2]
    (gdb) bt
    #0  tcp_input (m=0x558551242be0, iphlen=<optimized out>, 
inso=inso@entry=0x0) at ./tcp_input.c:313
    #1  0x000055854f58399c in ip_input (m=<optimized out>) at ip_input.c:214
    #2  0x000055854f58c01f in sl_dispatch (ttyp=ttyp@entry=0x55855123e2c0) at 
./sl.c:127
    #3  0x000055854f58c1ee in sl_input (ttyp=0x55855123e2c0, 
if_bptr=0x7ffddbe4f67e "\300\264\004\002\b\n`\354\303a", if_n=63) at ./sl.c:35
    #4  0x000055854f581ed2 in if_input (ttyp=0x55855123e2c0) at ./if.c:191
    #5  0x000055854f58567f in main_loop () at ./main.c:1158
    #6  0x000055854f5757d7 in main (argc=3, argv=0x7ffddbe504f8) at ./main.c:95
Description: 949003

Author: Bernhard Übelacker <bernha...@mailbox.org>
Bug-Debian: https://bugs.debian.org/949003
Forwarded: no
Last-Update: 2020-09-02

Index: slirp-1.0.17/src/options.c
===================================================================
--- slirp-1.0.17.orig/src/options.c
+++ slirp-1.0.17/src/options.c
@@ -74,8 +74,8 @@ int     nozeros;                /* If se
  * Read the config file
  */
 
-int (*lprint_print) _P((void *, const char *format, va_list));
-char *lprint_ptr, *lprint_ptr2, **lprint_arg;
+extern int (*lprint_print) _P((void *, const char *format, va_list));
+extern char *lprint_ptr, *lprint_ptr2, **lprint_arg;
 struct sbuf *lprint_sb;
 
 int cfg_unit;
Description: Fix 64 bit issue in slirp

Origin: https://gitlab.freedesktop.org/slirp/libslirp/-/commit/c11b407804272b71e5bdd7a2a9181c64c7a594ed
Bug-Debian: https://bugs.debian.org/949003
Last-Update: 2020-09-02

Index: slirp-1.0.17/src/ip.h
===================================================================
--- slirp-1.0.17.orig/src/ip.h
+++ slirp-1.0.17/src/ip.h
@@ -187,35 +187,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 void* 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 void* ipqp_32;
-typedef void* 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 */
 	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
@@ -225,44 +221,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) */
-	int16_t	ip_len;
-	u_int16_t	ip_id;
-	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.
Index: slirp-1.0.17/src/ip_input.c
===================================================================
--- slirp-1.0.17.orig/src/ip_input.c
+++ slirp-1.0.17/src/ip_input.c
@@ -43,12 +43,23 @@
  */
 
 #include <slirp.h>
+#include <stddef.h>
 #include "ip_icmp.h"
 
+#ifndef container_of
+#define container_of(ptr, type, member)              \
+    __extension__({                                  \
+        void *__mptr = (void *)(ptr);                \
+        ((type *)(__mptr - offsetof(type, member))); \
+    })
+#endif
+
 int ip_defttl;
 struct ipstat ipstat;
 struct ipq ipq;
 
+static struct ip *ip_reass(register struct ip *ip, register struct ipq *fp);
+
 /*
  * IP initialization: fill in IP protocol switch table.
  * All protocols not implemented in kernel go to raw IP protocol handler.
@@ -56,7 +67,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();
@@ -159,18 +170,20 @@ ip_input(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:
 
 		/*
@@ -180,9 +193,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;
 
@@ -191,9 +204,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++;
@@ -229,16 +242,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.
  */
-struct ip *
-ip_reass(ip, fp)
-	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;
@@ -265,13 +277,13 @@ ip_reass(ip, fp)
 	  struct mbuf *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;
 	}
@@ -279,9 +291,9 @@ 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 = fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link;
+			q = q->ipf_next)
+		if (q->ipf_off > ip->ip_off)
 			break;
 
 	/*
@@ -289,9 +301,9 @@ ip_reass(ip, fp)
 	 * 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;
@@ -305,17 +317,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 = q->ipf_next;
+		m_freem(dtom(q->ipf_prev));
+		ip_deq(q->ipf_prev);
 	}
 
 insert:
@@ -323,27 +336,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);
 	  m_cat(m, t);
 	  q = (struct ipasfrag *) q->ipf_next;
 	}
@@ -354,7 +366,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
@@ -366,23 +378,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++;
@@ -400,13 +412,13 @@ ip_freef(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));
 }
 
@@ -420,10 +432,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;
 }
 
 /*
@@ -445,20 +457,21 @@ ip_deq(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) {
 			ipstat.ips_fragtimeout++;
-			ip_freef((struct ipq *) fp->prev);
+			ip_freef(fp);
 		}
 	}
 }
Index: slirp-1.0.17/src/main.c
===================================================================
--- slirp-1.0.17.orig/src/main.c
+++ slirp-1.0.17/src/main.c
@@ -760,8 +760,8 @@ while(1) {
 		 * *_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;
Index: slirp-1.0.17/src/misc.c
===================================================================
--- slirp-1.0.17.orig/src/misc.c
+++ slirp-1.0.17/src/misc.c
@@ -98,39 +98,6 @@ getouraddr()
 	our_addr = *(struct in_addr *)he->h_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;
Index: slirp-1.0.17/src/slirp.h
===================================================================
--- slirp-1.0.17.orig/src/slirp.h
+++ slirp-1.0.17/src/slirp.h
@@ -244,14 +244,6 @@ void lprint _P((const char *, ...));
 
 extern int do_echo;
 
-#if SIZEOF_CHAR_P == 4
-# define insque_32 insque
-# define remque_32 remque
-#else
- inline void insque_32 _P((void *, void *));
- inline void remque_32 _P((void *));
-#endif
-
 #include <pwd.h>
 #include <netdb.h>
 
Index: slirp-1.0.17/src/tcp_input.c
===================================================================
--- slirp-1.0.17.orig/src/tcp_input.c
+++ slirp-1.0.17/src/tcp_input.c
@@ -72,47 +72,49 @@ tcp_seq tcp_iss;                /* tcp i
  * 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; \
-               tcpstat.tcps_rcvpack++;\
-               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;                           \
+            tcpstat.tcps_rcvpack++;                                    \
+            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; \
-		tcpstat.tcps_rcvpack++;\
-		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;                           \
+            tcpstat.tcps_rcvpack++;                                    \
+            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
 
@@ -136,8 +138,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;
 
@@ -146,9 +148,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)) {
 		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) {
@@ -168,36 +170,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)) {
 		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:
 	/*
@@ -206,17 +208,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);
@@ -303,7 +305,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;
@@ -551,8 +554,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
Index: slirp-1.0.17/src/tcp_subr.c
===================================================================
--- slirp-1.0.17.orig/src/tcp_subr.c
+++ slirp-1.0.17/src/tcp_subr.c
@@ -84,7 +84,7 @@ tcp_template(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));
@@ -167,7 +167,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);
@@ -207,7 +207,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;
@@ -284,11 +284,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 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 */
Index: slirp-1.0.17/src/tcp_var.h
===================================================================
--- slirp-1.0.17.orig/src/tcp_var.h
+++ slirp-1.0.17/src/tcp_var.h
@@ -40,18 +40,12 @@
 #include "tcpip.h"
 #include "tcp_timer.h"
 
-#if SIZEOF_CHAR_P == 4
- typedef struct tcpiphdr *tcpiphdrp_32;
-#else
- typedef void* 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 */
@@ -170,21 +164,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 void* mbufp_32;
-#endif
-#define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t))
-
 /*
  * TCP statistics.
  * Many of these should be kept per connection,
Index: slirp-1.0.17/src/tcpip.h
===================================================================
--- slirp-1.0.17.orig/src/tcpip.h
+++ slirp-1.0.17/src/tcpip.h
@@ -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
Index: slirp-1.0.17/src/udp.c
===================================================================
--- slirp-1.0.17.orig/src/udp.c
+++ slirp-1.0.17/src/udp.c
@@ -131,8 +131,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
@@ -259,7 +258,7 @@ udp_output(so, m, addr)
 	 * 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)); */
Index: slirp-1.0.17/src/udp.h
===================================================================
--- slirp-1.0.17.orig/src/udp.h
+++ slirp-1.0.17/src/udp.h
@@ -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

# Bullseye/testing amd64 qemu VM 2020-09-01





https://wiki.debian.org/UserModeLinux
https://web.archive.org/web/20100212221731/http://www.wlug.org.nz/UserModeLinux
https://christine.website/blog/howto-usermode-linux-2019-07-07







dpkg --add-architecture i386
apt update
apt dist-upgrade


apt install systemd-coredump dpkg-dev devscripts quilt colordiff cdbs fakeroot 
meson cmake pkg-config libglib2.0-dev socat mc lightdm xserver-xorg openbox 
xterm htop gdb debootstrap user-mode-linux
wget http://ftp.de.debian.org/debian/pool/main/s/slirp/slirp_1.0.17-10_amd64.deb
wget http://ftp.de.debian.org/debian/pool/main/s/slirp/slirp_1.0.17-10_i386.deb
dpkg -i slirp_1.0.17-10_amd64.deb
apt install -f


reboot




mkdir /home/benutzer/source/slirp/orig -p
cd    /home/benutzer/source/slirp/orig
dget http://deb.debian.org/debian/pool/main/s/slirp/slirp_1.0.17-10.dsc
cd

cd /home/benutzer/source/slirp
cp orig try1 -a
cd try1/slirp-1.0.17/

        slirp-1.0.17/debian/rules
        -CFLAGS   += $(CPPFLAGS) -I. -DUSE_PPP -DUSE_MS_DNS 
-fno-strict-aliasing -Wno-unused -std=gnu89
        +CFLAGS   += $(CPPFLAGS) -I. -DUSE_PPP -DUSE_MS_DNS 
-fno-strict-aliasing -Wno-unused -std=gnu89 -DDEBUG

dpkg-buildpackage








debootstrap --arch=amd64 --include=net-tools,bind9-dnsutils,mc,socat,wget 
bullseye /root/chroot 
http://192.168.178.25:9999/debian-11-bullseye-deb.debian.org
env -i TERM=xterm LANG=de_DE.UTF-8 /usr/sbin/chroot chroot /bin/su -
    passwd

    cat <<EOF > /etc/network/interfaces.d/eth0
auto eth0
#iface eth0 inet dhcp
iface eth0 inet static
  address 10.0.2.14
  netmask 255.255.255.240
  gateway 10.0.2.2
#   #resolv.conf:
#       #nameserver 192.168.178.2
EOF

    exit
.




cat <<EOF > /root/slirp
#!/bin/bash
exec /usr/bin/slirp -d 7
EOF
chmod +x /root/slirp



export DISPLAY=:0
export XAUTHORITY=/home/benutzer/.Xauthority

/usr/bin/linux.uml \
    root=/dev/root \
    rootfstype=hostfs \
    rootflags=/root/chroot \
    rw \
    mem=128M \
    eth0=slirp,,/root/slirp






# Inside user mode linux

systemctl stop systemd-timesyncd.service
    # to stop udp

wget http://192.168.178.1 -O /tmp/x









tail -f /root/slirp_debug
        ...
        TCP stats:
        ...
            11 packets received
                    0 acks (for 0 bytes)
                    0 duplicate acks
                    0 acks for unsent data
                    0 packets received in sequence (0 bytes)
                    0 completely duplicate packets (0 bytes)
                    0 packets with some duplicate data (0 bytes duped)
                    0 out-of-order packets (0 bytes)
                    0 packets of data after window (0 bytes)
                    0 window probes
                    0 window update packets
                    0 packets received after close
                    11 discarded for bad checksums
                    0 discarded for bad header offset fields
        ...

        UDP stats:
            136 datagrams received
            0 with packets shorter than header
            136 with bad checksums
        ...
.





root@debian:/home/benutzer/source/slirp/try1/slirp-1.0.17/src# gdb -q --pid 
$(pidof slirp)

b tcp_input
cont
















i386 example debugging:

(gdb) x/60xb w 
0x57f708a4:     0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x57f708ac:     0x00    0x06    0x00    0x28    0x0a    0x00    0x02    0x0e
0x57f708b4:     0xc0    0xa8    0xb2    0x01    0xaf    0xc6    0x00    0x50
0x57f708bc:     0x41    0xd3    0xf5    0x58    0x00    0x00    0x00    0x00
0x57f708c4:     0xa0    0x02    0xfa    0xf0    0x44    0x2a    0x00    0x00
0x57f708cc:     0x02    0x04    0x05    0xb4    0x04    0x02    0x08    0x0a
0x57f708d4:     0x1e    0x7f    0x84    0x6e    0x00    0x00    0x00    0x00
0x57f708dc:     0x01    0x03    0x03    0x04
(gdb) display/x sum
1: /x sum = 0x0
(gdb) display/x len 
2: /x len = 0x3c
(gdb) display len   
3: len = 60
(gdb) undisp 2
(gdb) next
82              if ((1 & (long) w) && (mlen > 0)) {
1: /x sum = 0x0
3: len = <optimized out>
(gdb) display mlen
4: mlen = <optimized out>
(gdb) next
94              while ((mlen -= 32) >= 0) {
1: /x sum = 0x0
3: len = <optimized out>
4: mlen = 28
(gdb) 
95                      sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
1: /x sum = <optimized out>
3: len = <optimized out>
4: mlen = <optimized out>
(gdb) 
96                      sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
1: /x sum = 0x0
3: len = <optimized out>
4: mlen = <optimized out>
(gdb) 
97                      sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
1: /x sum = 0x3c0c
3: len = <optimized out>
4: mlen = <optimized out>
(gdb) 
98                      sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
1: /x sum = 0x1fd2d
3: len = <optimized out>
4: mlen = <optimized out>
(gdb) 
99                      w += 16;
1: /x sum = 0x32963
3: len = <optimized out>
4: mlen = <optimized out>
(gdb) 
102             while ((mlen -= 8) >= 0) {
1: /x sum = <optimized out>
3: len = <optimized out>
4: mlen = 20
(gdb) 
103                     sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
1: /x sum = <optimized out>
3: len = <optimized out>
4: mlen = <optimized out>
(gdb) 
104                     w += 4;
1: /x sum = 0x44741
3: len = <optimized out>
4: mlen = <optimized out>
(gdb) 
103                     sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
1: /x sum = <optimized out>
3: len = <optimized out>
4: mlen = <optimized out>
(gdb) 
104                     w += 4;
1: /x sum = 0x50b54
3: len = <optimized out>
4: mlen = <optimized out>
(gdb) 
103                     sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
1: /x sum = <optimized out>
3: len = <optimized out>
4: mlen = <optimized out>
(gdb) 
104                     w += 4;
1: /x sum = 0x5f8f6
3: len = <optimized out>
4: mlen = <optimized out>
(gdb) 
107             if (mlen == 0 && byte_swapped == 0)
1: /x sum = <optimized out>
3: len = <optimized out>
4: mlen = <optimized out>
(gdb) 
109             REDUCE;
1: /x sum = <optimized out>
3: len = <optimized out>
4: mlen = <optimized out>
(gdb) 
110             while ((mlen -= 2) >= 0) {
1: /x sum = 0xf8fb
3: len = <optimized out>
4: mlen = 2
(gdb) 
111                     sum += *w++;
1: /x sum = 0xf8fb
3: len = <optimized out>
4: mlen = <optimized out>
(gdb) 
110             while ((mlen -= 2) >= 0) {
1: /x sum = 0xfbfc
3: len = <optimized out>
4: mlen = <optimized out>
(gdb) 
111                     sum += *w++;
1: /x sum = 0xfbfc
3: len = <optimized out>
4: mlen = <optimized out>
(gdb) 
110             while ((mlen -= 2) >= 0) {
1: /x sum = 0xffff
3: len = <optimized out>
4: mlen = <optimized out>
(gdb) 
114             if (byte_swapped) {
1: /x sum = 0xffff
3: len = <optimized out>
4: mlen = <optimized out>
(gdb) 
125             } else if (mlen == -1)
1: /x sum = 0xffff
3: len = <optimized out>
4: mlen = <optimized out>
(gdb) 
142             REDUCE;
1: /x sum = <optimized out>
3: len = <optimized out>
4: mlen = <optimized out>
(gdb) 
tcp_input (m=0x57f70850, iphlen=<optimized out>, inso=0x0) at ./tcp_input.c:322
322             off = ti->ti_off << 2;











# Filling in a amd64 debug session the buffer with the values found valid at 
i386:


(gdb) x/60xb w
0x558551242c50: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x558551242c58: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x558551242c60: 0x00    0xa8    0x00    0x28    0xb6    0xaa    0x00    0x50
0x558551242c68: 0x0d    0x71    0x80    0xd2    0x00    0x00    0x00    0x00
0x558551242c70: 0xa0    0x02    0xfa    0xf0    0x42    0xd8    0x00    0x00
0x558551242c78: 0x02    0x04    0x05    0xb4    0x04    0x02    0x08    0x0a
0x558551242c80: 0x60    0xc5    0xe5    0x7e    0x00    0x00    0x00    0x00
0x558551242c88: 0x01    0x03    0x03    0x04
(gdb) set *(((char*)0x558551242c50)+ 0) = 0x00
(gdb) set *(((char*)0x558551242c50)+ 1) = 0x00
(gdb) set *(((char*)0x558551242c50)+ 2) = 0x00
(gdb) set *(((char*)0x558551242c50)+ 3) = 0x00
(gdb) set *(((char*)0x558551242c50)+ 4) = 0x00
(gdb) set *(((char*)0x558551242c50)+ 5) = 0x00
(gdb) set *(((char*)0x558551242c50)+ 6) = 0x00
(gdb) set *(((char*)0x558551242c50)+ 7) = 0x00
(gdb) set *(((char*)0x558551242c50)+ 8) = 0x00
(gdb) set *(((char*)0x558551242c50)+ 9) = 0x06
(gdb) set *(((char*)0x558551242c50)+10) = 0x00
(gdb) set *(((char*)0x558551242c50)+11) = 0x28
(gdb) set *(((char*)0x558551242c50)+12) = 0x0a
(gdb) set *(((char*)0x558551242c50)+13) = 0x00
(gdb) set *(((char*)0x558551242c50)+14) = 0x02
(gdb) set *(((char*)0x558551242c50)+15) = 0x0e
(gdb) set *(((char*)0x558551242c50)+16) = 0xc0
(gdb) set *(((char*)0x558551242c50)+17) = 0xa8
(gdb) set *(((char*)0x558551242c50)+18) = 0xb2
(gdb) set *(((char*)0x558551242c50)+19) = 0x01
(gdb) set *(((char*)0x558551242c50)+20) = 0xaf
(gdb) set *(((char*)0x558551242c50)+21) = 0xc6
(gdb) set *(((char*)0x558551242c50)+22) = 0x00
(gdb) set *(((char*)0x558551242c50)+23) = 0x50
(gdb) set *(((char*)0x558551242c50)+24) = 0x41
(gdb) set *(((char*)0x558551242c50)+25) = 0xd3
(gdb) set *(((char*)0x558551242c50)+26) = 0xf5
(gdb) set *(((char*)0x558551242c50)+27) = 0x58
(gdb) set *(((char*)0x558551242c50)+28) = 0x00
(gdb) set *(((char*)0x558551242c50)+29) = 0x00
(gdb) set *(((char*)0x558551242c50)+30) = 0x00
(gdb) set *(((char*)0x558551242c50)+31) = 0x00
(gdb) set *(((char*)0x558551242c50)+32) = 0xa0
(gdb) set *(((char*)0x558551242c50)+33) = 0x02
(gdb) set *(((char*)0x558551242c50)+34) = 0xfa
(gdb) set *(((char*)0x558551242c50)+35) = 0xf0
(gdb) set *(((char*)0x558551242c50)+36) = 0x44
(gdb) set *(((char*)0x558551242c50)+37) = 0x2a
(gdb) set *(((char*)0x558551242c50)+38) = 0x00
(gdb) set *(((char*)0x558551242c50)+39) = 0x00
(gdb) set *(((char*)0x558551242c50)+40) = 0x02
(gdb) set *(((char*)0x558551242c50)+41) = 0x04
(gdb) set *(((char*)0x558551242c50)+42) = 0x05
(gdb) set *(((char*)0x558551242c50)+43) = 0xb4
(gdb) set *(((char*)0x558551242c50)+44) = 0x04
(gdb) set *(((char*)0x558551242c50)+45) = 0x02
(gdb) set *(((char*)0x558551242c50)+46) = 0x08
(gdb) set *(((char*)0x558551242c50)+47) = 0x0a
(gdb) set *(((char*)0x558551242c50)+48) = 0x1e
(gdb) set *(((char*)0x558551242c50)+49) = 0x7f
(gdb) set *(((char*)0x558551242c50)+50) = 0x84
(gdb) set *(((char*)0x558551242c50)+51) = 0x6e
(gdb) set *(((char*)0x558551242c50)+52) = 0x00
(gdb) set *(((char*)0x558551242c50)+53) = 0x00
(gdb) set *(((char*)0x558551242c50)+54) = 0x00
(gdb) set *(((char*)0x558551242c50)+55) = 0x00
(gdb) set *(((char*)0x558551242c50)+56) = 0x01
(gdb) set *(((char*)0x558551242c50)+57) = 0x03
(gdb) set *(((char*)0x558551242c50)+58) = 0x03
(gdb) set *(((char*)0x558551242c50)+59) = 0x04
(gdb) x/60xb w
0x558551242c50: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x558551242c58: 0x00    0x06    0x00    0x28    0x0a    0x00    0x02    0x0e
0x558551242c60: 0xc0    0xa8    0xb2    0x01    0xaf    0xc6    0x00    0x50
0x558551242c68: 0x41    0xd3    0xf5    0x58    0x00    0x00    0x00    0x00
0x558551242c70: 0xa0    0x02    0xfa    0xf0    0x44    0x2a    0x00    0x00
0x558551242c78: 0x02    0x04    0x05    0xb4    0x04    0x02    0x08    0x0a
0x558551242c80: 0x1e    0x7f    0x84    0x6e    0x00    0x00    0x00    0x00
0x558551242c88: 0x01    0x03    0x03    0x04
(gdb) display/x sum
1: /x sum = 0x0
(gdb) display/x len
2: /x len = 0x3c
(gdb) display len
3: len = 60
(gdb) undisp 2
(gdb) next
78              len -= mlen;
1: /x sum = 0x0
3: len = 60
(gdb) display mlen
4: mlen = 60
(gdb) next
82              if ((1 & (long) w) && (mlen > 0)) {
1: /x sum = 0x0
3: len = 0
4: mlen = 60
(gdb) 
94              while ((mlen -= 32) >= 0) {
1: /x sum = 0x0
3: len = 0
4: mlen = 28
(gdb) 
95                      sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
1: /x sum = 0x0
3: len = 0
4: mlen = 28
(gdb) 
96                      sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
1: /x sum = 0x0
3: len = 0
4: mlen = 28
(gdb) 
97                      sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
1: /x sum = 0x3c0c
3: len = 0
4: mlen = 28
(gdb) 
98                      sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
1: /x sum = 0x1fd2d
3: len = 0
4: mlen = 28
(gdb) 
99                      w += 16;
1: /x sum = 0x32963
3: len = 0
4: mlen = 28
(gdb) 
102             while ((mlen -= 8) >= 0) {
1: /x sum = 0x32963
3: len = 0
4: mlen = 20
(gdb) 
103                     sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
1: /x sum = 0x32963
3: len = 0
4: mlen = <optimized out>
(gdb) 
104                     w += 4;
1: /x sum = 0x44741
3: len = 0
4: mlen = <optimized out>
(gdb) 
103                     sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
1: /x sum = 0x44741
3: len = 0
4: mlen = <optimized out>
(gdb) 
104                     w += 4;
1: /x sum = 0x50b54
3: len = 0
4: mlen = <optimized out>
(gdb) 
103                     sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
1: /x sum = 0x50b54
3: len = 0
4: mlen = <optimized out>
(gdb) 
104                     w += 4;
1: /x sum = 0x5f8f6
3: len = 0
4: mlen = <optimized out>
(gdb) 
107             if (mlen == 0 && byte_swapped == 0)
1: /x sum = 0x5f8f6
3: len = 0
4: mlen = <optimized out>
(gdb) 
109             REDUCE;
1: /x sum = 0x5f8f6
3: len = 0
4: mlen = <optimized out>
(gdb) 
110             while ((mlen -= 2) >= 0) {
1: /x sum = 0xf8fb
3: len = 0
4: mlen = 2
(gdb) 
111                     sum += *w++;
1: /x sum = 0xf8fb
3: len = 0
4: mlen = <optimized out>
(gdb) 
110             while ((mlen -= 2) >= 0) {
1: /x sum = 0xfbfc
3: len = 0
4: mlen = <optimized out>
(gdb) 
111                     sum += *w++;
1: /x sum = 0xfbfc
3: len = 0
4: mlen = <optimized out>
(gdb) 
110             while ((mlen -= 2) >= 0) {
1: /x sum = 0xffff
3: len = 0
4: mlen = <optimized out>
(gdb) next
114             if (byte_swapped) {
1: /x sum = 0xffff
3: len = 0
4: mlen = <optimized out>
(gdb) 
125             } else if (mlen == -1)
1: /x sum = 0xffff
3: len = 0
4: mlen = <optimized out>
(gdb) 
130             if (len) {
1: /x sum = 0xffff
3: len = 0
4: mlen = -2
(gdb) 
142             REDUCE;
1: /x sum = 0xffff
3: len = 0
4: mlen = <optimized out>
(gdb) 
143             return (~sum & 0xffff);
1: /x sum = 0xffff
3: len = <optimized out>
4: mlen = <optimized out>
(gdb) 
tcp_input (m=0x558551242be0, iphlen=<optimized out>, inso=inso@entry=0x0) at 
./tcp_input.c:322
322             off = ti->ti_off << 2;


--> cksum works right at amd64 too !












############

git clone https://gitlab.freedesktop.org/slirp/libslirp.git
cd libslirp/
meson build
ninja -C build

-> does not build a executable ?









############



(gdb) step
tcp_input (m=0x558551242be0, iphlen=20, inso=inso@entry=0x0) at 
./tcp_input.c:259
259             DEBUG_CALL("tcp_input");
(gdb) next
260             DEBUG_ARGS((dfd," m = %8lx  iphlen = %2d  inso = %lx\n", 
(gdb) 
266             if (m == NULL) {
(gdb) 
281             tcpstat.tcps_rcvtotal++;
(gdb) 
286             ti = mtod(m, struct tcpiphdr *);
(gdb) x/60xb m->m_hdr.mh_data
0x558551242c50: 0x45    0x00    0x28    0x00    0xfe    0x75    0x00    0x40
0x558551242c58: 0x40    0x06    0x46    0x06    0x0a    0x00    0x02    0x0e
0x558551242c60: 0xc0    0xa8    0xb2    0x01    0xb6    0xd2    0x00    0x50
0x558551242c68: 0xfb    0x4b    0xa6    0x32    0x00    0x00    0x00    0x00
0x558551242c70: 0xa0    0x02    0xfa    0xf0    0x13    0x4d    0x00    0x00
0x558551242c78: 0x02    0x04    0x05    0xb4    0x04    0x02    0x08    0x0a
0x558551242c80: 0x61    0x01    0x01    0x6b    0x00    0x00    0x00    0x00
0x558551242c88: 0x01    0x03    0x03    0x04
(gdb) next
287             if (iphlen > sizeof(struct ip )) {
(gdb) 
299             save_ip = *ip; 
(gdb) 
313             if(cksum(m, len)) {
(gdb) x/60xb m->m_hdr.mh_data
0x558551242c50: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x558551242c58: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x558551242c60: 0x00    0xa8    0x00    0x28    0xb6    0xd2    0x00    0x50
0x558551242c68: 0xfb    0x4b    0xa6    0x32    0x00    0x00    0x00    0x00
0x558551242c70: 0xa0    0x02    0xfa    0xf0    0x13    0x4d    0x00    0x00
0x558551242c78: 0x02    0x04    0x05    0xb4    0x04    0x02    0x08    0x0a
0x558551242c80: 0x61    0x01    0x01    0x6b    0x00    0x00    0x00    0x00
0x558551242c88: 0x01    0x03    0x03    0x04
(gdb) bt
#0  tcp_input (m=0x558551242be0, iphlen=<optimized out>, inso=inso@entry=0x0) 
at ./tcp_input.c:313
#1  0x000055854f58399c in ip_input (m=<optimized out>) at ip_input.c:214
#2  0x000055854f58c01f in sl_dispatch (ttyp=ttyp@entry=0x55855123e2c0) at 
./sl.c:127
#3  0x000055854f58c1ee in sl_input (ttyp=0x55855123e2c0, if_bptr=0x7ffddbe4f67e 
"\300\264\004\002\b\n`\354\303a", if_n=63) at ./sl.c:35
#4  0x000055854f581ed2 in if_input (ttyp=0x55855123e2c0) at ./if.c:191
#5  0x000055854f58567f in main_loop () at ./main.c:1158
#6  0x000055854f5757d7 in main (argc=3, argv=0x7ffddbe504f8) at ./main.c:95

(gdb) print sizeof(*ti)
$12 = 56                                                                        
  <<<<<<<<<<<  this is just 40 bytes on 32 bit

(gdb) ptype /o struct tcpiphdr
/* offset    |  size */  type = struct tcpiphdr {
/*    0      |    32 */    struct ipovly {                                      
  <<<<<<<<<<<  this is just 20 bytes on 32 bit
/*    0      |     8 */        caddr32_t ih_next;
/*    8      |     8 */        caddr32_t ih_prev;
/*   16      |     1 */        u_int8_t ih_x1;
/*   17      |     1 */        u_int8_t ih_pr;
/*   18      |     2 */        int16_t ih_len;
/*   20      |     4 */        struct in_addr {
/*   20      |     4 */            in_addr_t s_addr;

                                   /* total size (bytes):    4 */
                               } ih_src;
/*   24      |     4 */        struct in_addr {
/*   24      |     4 */            in_addr_t s_addr;

                                   /* total size (bytes):    4 */
                               } ih_dst;
/* XXX  4-byte padding  */

                               /* total size (bytes):   32 */
                           } ti_i;
/*   32      |    20 */    struct tcphdr {
/*   32      |     2 */        u_int16_t th_sport;
/*   34      |     2 */        u_int16_t th_dport;
/*   36      |     4 */        tcp_seq th_seq;
/*   40      |     4 */        tcp_seq th_ack;
/*   44: 0   |     4 */        u_int th_x2 : 4;
/*   44: 4   |     4 */        u_int th_off : 4;
/*   45      |     1 */        u_int8_t th_flags;
/*   46      |     2 */        u_int16_t th_win;
/*   48      |     2 */        u_int16_t th_sum;
/*   50      |     2 */        u_int16_t th_urp;

                               /* total size (bytes):   20 */
                           } ti_t;
/* XXX  4-byte padding  */

                           /* total size (bytes):   56 */
                         }
(gdb) print sizeof(void*)
$14 = 8

(gdb) print sizeof(struct ipovly)
$15 = 32
(gdb) ptype /o struct ipovly
/* offset    |  size */  type = struct ipovly {
/*    0      |     8 */    caddr32_t ih_next;                                   
   <<<<<<<<<<< this is just 4 bytes on 32 bit
/*    8      |     8 */    caddr32_t ih_prev;                                   
   <<<<<<<<<<< this is just 4 bytes on 32 bit
/*   16      |     1 */    u_int8_t ih_x1;
/*   17      |     1 */    u_int8_t ih_pr;
/*   18      |     2 */    int16_t ih_len;
/*   20      |     4 */    struct in_addr {
/*   20      |     4 */        in_addr_t s_addr;

                               /* total size (bytes):    4 */
                           } ih_src;
/*   24      |     4 */    struct in_addr {
/*   24      |     4 */        in_addr_t s_addr;

                               /* total size (bytes):    4 */
                           } ih_dst;
/* XXX  4-byte padding  */

                           /* total size (bytes):   32 */
                         }
(gdb) detach











############

https://gitlab.freedesktop.org/slirp/libslirp/-/commit/c11b407804272b71e5bdd7a2a9181c64c7a594ed
https://gitlab.freedesktop.org/slirp/libslirp/-/commit/c11b407804272b71e5bdd7a2a9181c64c7a594ed.patch

Reply via email to