Compare commits

...

4 Commits

Author SHA1 Message Date
Seg
7d87addf22 Don't use linker script on x86_64, there is no need for it and it
breaks flatpak builds
2020-12-11 18:02:12 -08:00
Seg
afe93778ca Update config.guess and config.sub 2020-12-11 17:26:27 -08:00
Seg
54ea2c9354 Fix slirp crash on 64bit 2020-12-11 17:15:53 -08:00
Seg
226a3845e0 Fix crash on linux aarch64 2020-12-11 16:54:16 -08:00
18 changed files with 2807 additions and 2343 deletions

View File

@ -83,6 +83,10 @@ typedef unsigned long vm_uintptr_t;
#define MAP_ANONYMOUS 0
#endif
/* NOTE: on linux MAP_32BIT is only implemented on AMD64
it is a null op on all other architectures
thus the MAP_BASE setting below is the only thing
ensuring low addresses on aarch64 for example */
#define MAP_EXTRA_FLAGS (MAP_32BIT)
#ifdef HAVE_MMAP_VM
@ -91,6 +95,16 @@ typedef unsigned long vm_uintptr_t;
don't get addresses above when the program is run on AMD64.
NOTE: this is empirically determined on Linux/x86. */
#define MAP_BASE 0x10000000
#elif DIRECT_ADDRESSING
/* linux does not implement any useful fallback behavior
such as allocating the next available address
and the first 4k-64k of address space is marked unavailable
for security reasons (see https://wiki.debian.org/mmap_min_addr)
so we must start requesting after the first page
or we get a high 64bit address that will crash direct addressing
leaving NULL unmapped is a good idea anyway for debugging reasons */
#define MAP_BASE 0x00010000
#else
#define MAP_BASE 0x00000000
#endif
@ -255,9 +269,13 @@ void * vm_acquire(size_t size, int options)
if ((addr = mmap((caddr_t)next_address, size, VM_PAGE_DEFAULT, the_map_flags, fd, 0)) == (void *)MAP_FAILED)
return VM_MAP_FAILED;
// Sanity checks for 64-bit platforms
if (sizeof(void *) == 8 && (options & VM_MAP_32BIT) && !((char *)addr <= (char *)0xffffffff))
return VM_MAP_FAILED;
#if DIRECT_ADDRESSING
// If MAP_32BIT and MAP_BASE fail to ensure
// a 32-bit address crash now instead of later.
// FIXME: make everything 64-bit clean and tear this all out.
if(sizeof(void *) > 4 && (options & VM_MAP_32BIT))
assert((size_t)addr<0xffffffffL);
#endif
next_address = (char *)addr + size;
#elif defined(HAVE_WIN32_VM)

View File

@ -36,6 +36,8 @@ extern "C" {
}
#endif
#include <cassert>
/* Return value of `vm_acquire' in case of an error. */
#ifdef HAVE_MACH_VM
#define VM_MAP_FAILED ((void *)-1)

View File

@ -239,7 +239,6 @@
7539E20C1F23B32A006B2DF2 /* freebsd-i386.ld */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "freebsd-i386.ld"; sourceTree = "<group>"; };
7539E20D1F23B32A006B2DF2 /* linux-i386.ld */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "linux-i386.ld"; sourceTree = "<group>"; };
7539E20E1F23B32A006B2DF2 /* linux-ppc.ld */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "linux-ppc.ld"; sourceTree = "<group>"; };
7539E20F1F23B32A006B2DF2 /* linux-x86_64.ld */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "linux-x86_64.ld"; sourceTree = "<group>"; };
7539E2181F23B32A006B2DF2 /* egrep.m4 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = egrep.m4; sourceTree = "<group>"; };
7539E2191F23B32A006B2DF2 /* esd.m4 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = esd.m4; sourceTree = "<group>"; };
7539E21A1F23B32A006B2DF2 /* gettext.m4 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = gettext.m4; sourceTree = "<group>"; };
@ -692,7 +691,6 @@
7539E20C1F23B32A006B2DF2 /* freebsd-i386.ld */,
7539E20D1F23B32A006B2DF2 /* linux-i386.ld */,
7539E20E1F23B32A006B2DF2 /* linux-ppc.ld */,
7539E20F1F23B32A006B2DF2 /* linux-x86_64.ld */,
);
path = ldscripts;
sourceTree = "<group>";

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1399,7 +1399,6 @@ AC_PATH_PROG([BLESS], "true")
dnl Check for linker script support
case $target_os:$target_cpu in
linux*:i?86) LINKER_SCRIPT_FLAGS="-Wl,-T,ldscripts/linux-i386.ld";;
linux*:x86_64) LINKER_SCRIPT_FLAGS="-Wl,-T,ldscripts/linux-x86_64.ld";;
linux*:powerpc) LINKER_SCRIPT_FLAGS="-Wl,-T,ldscripts/linux-ppc.ld";;
netbsd*:i?86) LINKER_SCRIPT_FLAGS="-Wl,-T,ldscripts/linux-i386.ld";;
freebsd*:i?86) LINKER_SCRIPT_FLAGS="-Wl,-T,ldscripts/freebsd-i386.ld";;

View File

@ -1,171 +0,0 @@
/* Default linker script, for normal executables */
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(_start)
SEARCH_DIR("/lib64"); SEARCH_DIR("/usr/lib64"); SEARCH_DIR("/usr/local/lib64");
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = 0x78048000 + SIZEOF_HEADERS;
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
.rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
.rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
.rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
.rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
.rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
.rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
.rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
.rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
.rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
.init :
{
KEEP (*(.init))
} =0x90909090
.plt : { *(.plt) }
.text :
{
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
} =0x90909090
.fini :
{
KEEP (*(.fini))
} =0x90909090
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.eh_frame_hdr : { *(.eh_frame_hdr) }
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = ALIGN (0x100000) - ((0x100000 - .) & (0x100000 - 1)); . = DATA_SEGMENT_ALIGN (0x100000, 0x1000);
/* Ensure the __preinit_array_start label is properly aligned. We
could instead move the label definition inside the section, but
the linker would then create the section even if it turns out to
be empty, which isn't pretty. */
. = ALIGN(64 / 8);
PROVIDE (__preinit_array_start = .);
.preinit_array : { *(.preinit_array) }
PROVIDE (__preinit_array_end = .);
PROVIDE (__init_array_start = .);
.init_array : { *(.init_array) }
PROVIDE (__init_array_end = .);
PROVIDE (__fini_array_start = .);
.fini_array : { *(.fini_array) }
PROVIDE (__fini_array_end = .);
.data :
{
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
.data1 : { *(.data1) }
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table) }
.dynamic : { *(.dynamic) }
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
/* We don't want to include the .ctor section from
from the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
.jcr : { KEEP (*(.jcr)) }
.got : { *(.got.plt) *(.got) }
_edata = .;
PROVIDE (edata = .);
__bss_start = .;
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections. */
. = ALIGN(64 / 8);
}
. = ALIGN(64 / 8);
_end = .;
PROVIDE (end = .);
. = DATA_SEGMENT_END (.);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
}

View File

@ -195,23 +195,19 @@ 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;
struct mbuf_ptr {
struct mbuf *mptr;
uint32_t dummy;
};
#else
typedef u_int32_t caddr32_t;
#endif
#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;
struct mbuf_ptr {
struct mbuf *mptr;
};
#endif
struct qlink {
void *next, *prev;
};
/*
* Overlay for ip header used by other protocols (tcp, udp).
@ -221,13 +217,13 @@ typedef caddr32_t ipasfragp_32;
#endif
struct ipovly {
caddr32_t ih_next, ih_prev; /* for protocol sequence q's */
struct mbuf_ptr ih_mbuf; /* backpointer to mbuf */
u_int8_t ih_x1; /* (unused) */
u_int8_t ih_pr; /* protocol */
u_int16_t ih_len; /* protocol length */
struct in_addr ih_src; /* source internet address */
struct in_addr ih_dst; /* destination internet address */
} PACKED__;
} __attribute__((packed));
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(PACK_RESET)
@ -241,12 +237,13 @@ 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;
};
@ -256,29 +253,16 @@ struct ipq {
* Note: ipf_next must be at same offset as ipq_next above
*/
struct ipasfrag {
#ifdef WORDS_BIGENDIAN
u_char ip_v:4,
ip_hl:4;
#else
u_char ip_hl:4,
ip_v:4;
#endif
/* BUG : u_int changed to u_int8_t.
* sizeof(u_int)==4 on linux 2.0
*/
u_int8_t ipf_mff; /* XXX overlays ip_tos: use low bit
* to avoid destroying tos (PPPDTRuu);
* copied from (ip_off&IP_MF) */
u_int16_t ip_len;
u_int16_t ip_id;
u_int16_t ip_off;
u_int8_t ip_ttl;
u_int8_t ip_p;
u_int16_t ip_sum;
ipasfragp_32 ipf_next; /* next fragment */
ipasfragp_32 ipf_prev; /* previous fragment */
struct qlink ipf_link;
struct ip ipf_ip;
};
#define ipf_off ipf_ip.ip_off
#define ipf_tos ipf_ip.ip_tos
#define ipf_len ipf_ip.ip_len
#define ipf_next ipf_link.next
#define ipf_prev ipf_link.prev
/*
* Structure stored in mbuf in inpcb.ip_options
* and passed to ip_output when ip options are in use.

View File

@ -38,6 +38,16 @@
* 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 "ip_icmp.h"
@ -52,7 +62,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();
@ -155,18 +165,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)
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;
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 = NULL;
found:
/*
@ -176,9 +188,9 @@ ip_input(m)
*/
ip->ip_len -= hlen;
if (ip->ip_off & IP_MF)
((struct ipasfrag *)ip)->ipf_mff |= 1;
ip->ip_tos |= 1;
else
((struct ipasfrag *)ip)->ipf_mff &= ~1;
ip->ip_tos &= ~1;
ip->ip_off <<= 3;
@ -187,9 +199,9 @@ ip_input(m)
* or if this is not the first fragment,
* attempt reassembly; if it succeeds, proceed.
*/
if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {
if (ip->ip_tos & 1 || ip->ip_off) {
ipstat.ips_fragments++;
ip = ip_reass((struct ipasfrag *)ip, fp);
ip = ip_reass(ip, fp);
if (ip == 0)
return;
ipstat.ips_reassembled++;
@ -225,16 +237,16 @@ bad:
return;
}
#define iptofrag(P) ((struct ipasfrag *)(((char*)(P)) - sizeof(struct qlink)))
#define fragtoip(P) ((struct ip*)(((char*)(P)) + sizeof(struct qlink)))
/*
* Take incoming datagram fragment and try to
* reassemble it into whole datagram. If a chain for
* reassembly of this datagram already exists, then it
* is given as fp; otherwise have to make a chain.
*/
struct ip *
ip_reass(ip, fp)
register struct ipasfrag *ip;
register struct ipq *fp;
static struct ip *
ip_reass(register struct ip *ip, register struct ipq *fp)
{
register struct mbuf *m = dtom(ip);
register struct ipasfrag *q;
@ -261,13 +273,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;
}
@ -275,9 +287,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;
/*
@ -285,9 +297,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;
@ -301,17 +313,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:
@ -319,27 +332,26 @@ insert:
* Stick new segment in its place;
* check for complete reassembly.
*/
ip_enq(ip, (struct ipasfrag *) q->ipf_prev);
ip_enq(iptofrag(ip), q->ipf_prev);
next = 0;
for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;
q = (struct ipasfrag *) q->ipf_next) {
if (q->ip_off != next)
for (q = fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link;
q = q->ipf_next) {
if (q->ipf_off != next)
return (0);
next += q->ip_len;
next += q->ipf_len;
}
if (((struct ipasfrag *)(q->ipf_prev))->ipf_mff & 1)
if (((struct ipasfrag *)(q->ipf_prev))->ipf_tos & 1)
return (0);
/*
* Reassembly is complete; concatenate fragments.
*/
q = (struct ipasfrag *) fp->ipq_next;
q = fp->frag_link.next;
m = dtom(q);
q = (struct ipasfrag *) q->ipf_next;
while (q != (struct ipasfrag *)fp) {
struct mbuf *t;
t = dtom(q);
while (q != (struct ipasfrag*)&fp->frag_link) {
struct mbuf *t = dtom(q);
q = (struct ipasfrag *) q->ipf_next;
m_cat(m, t);
}
@ -350,7 +362,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
@ -362,23 +374,23 @@ insert:
if (m->m_flags & M_EXT) {
int delta;
delta = (char *)ip - m->m_dat;
ip = (struct ipasfrag *)(m->m_ext + delta);
q = (struct ipasfrag *)(m->m_ext + delta);
}
/* DEBUG_ARG("ip = %lx", (long)ip);
* ip=(struct ipasfrag *)m->m_data; */
ip = fragtoip(q);
ip->ip_len = next;
ip->ipf_mff &= ~1;
((struct ip *)ip)->ip_src = fp->ipq_src;
((struct ip *)ip)->ip_dst = fp->ipq_dst;
remque_32(fp);
ip->ip_tos &= ~1;
ip->ip_src = fp->ipq_src;
ip->ip_dst = fp->ipq_dst;
remque(&fp->ip_link);
(void) m_free(dtom(fp));
m = dtom(ip);
m->m_len += (ip->ip_hl << 2);
m->m_data -= (ip->ip_hl << 2);
return ((struct ip *)ip);
return ip;
dropfrag:
ipstat.ips_fragdropped++;
@ -396,13 +408,12 @@ ip_freef(fp)
{
register struct ipasfrag *q, *p;
for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;
q = p) {
p = (struct ipasfrag *) q->ipf_next;
for (q = fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link; q = p) {
p = q->ipf_next;
ip_deq(q);
m_freem(dtom(q));
}
remque_32(fp);
remque(&fp->ip_link);
(void) m_free(dtom(fp));
}
@ -416,10 +427,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;
}
/*
@ -441,20 +452,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);
}
}
}

View File

@ -90,34 +90,6 @@ void getouraddr()
our_addr.s_addr = loopback_addr.s_addr;
}
#if SIZEOF_CHAR_P == 8
struct quehead_32 {
u_int32_t qh_link;
u_int32_t qh_rlink;
};
inline void insque_32(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 *qh_link;
struct quehead *qh_rlink;

View File

@ -211,8 +211,8 @@ int slirp_select_fill(int *pnfds,
* in the fragment queue, or there are TCP connections active
*/
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) {
so_next = so->so_next;

View File

@ -281,14 +281,6 @@ void lprint(const char *, ...);
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
#include <netdb.h>
#endif
@ -304,11 +296,12 @@ void if_output(struct socket *, struct mbuf *);
/* ip_input.c */
void ip_init(void);
void ip_input(struct mbuf *);
struct ip * ip_reass(register struct ipasfrag *, register struct ipq *);
void ip_freef(struct ipq *);
void ip_enq(register struct ipasfrag *, register struct ipasfrag *);
void ip_deq(register struct ipasfrag *);
void ip_input (struct mbuf *);
static struct ip *
ip_reass(register struct ip *ip, register struct ipq *);
void ip_freef (struct ipq *);
void ip_enq (register struct ipasfrag *, register struct ipasfrag *);
void ip_deq (register struct ipasfrag *);
void ip_slowtimo(void);
void ip_stripoptions(register struct mbuf *, struct mbuf *);

View File

@ -68,7 +68,7 @@ tcp_seq tcp_iss; /* tcp initial send seq # */
#ifdef TCP_ACK_HACK
#define TCP_REASS(tp, ti, m, so, flags) {\
if ((ti)->ti_seq == (tp)->rcv_nxt && \
(tp)->seg_next == (tcpiphdrp_32)(tp) && \
tcpfrag_list_empty(tp) && \
(tp)->t_state == TCPS_ESTABLISHED) {\
if (ti->ti_flags & TH_PUSH) \
tp->t_flags |= TF_ACKNOW; \
@ -91,7 +91,7 @@ tcp_seq tcp_iss; /* tcp initial send seq # */
#else
#define TCP_REASS(tp, ti, m, so, flags) { \
if ((ti)->ti_seq == (tp)->rcv_nxt && \
(tp)->seg_next == (tcpiphdrp_32)(tp) && \
tcpfrag_list_empty(tp) && \
(tp)->t_state == TCPS_ESTABLISHED) { \
tp->t_flags |= TF_DELACK; \
(tp)->rcv_nxt += (ti)->ti_len; \
@ -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.
*/
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;
@ -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
* 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) {
@ -159,37 +159,36 @@ tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti, struct mbuf *
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:
/*
* Present data to user, advancing rcv_nxt through
@ -197,17 +196,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);
@ -292,7 +291,8 @@ void tcp_input(register struct mbuf *m, int iphlen, struct socket *inso)
* Checksum extended TCP header and data.
*/
tlen = ((struct ip *)ti)->ip_len;
ti->ti_next = ti->ti_prev = 0;
tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = 0;
memset(&ti->ti_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));
ti->ti_x1 = 0;
ti->ti_len = htons((u_int16_t)tlen);
len = sizeof(struct ip) + tlen;
@ -540,10 +540,9 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq))
return;
}
}
else if (ti->ti_ack == tp->snd_una &&
tp->seg_next == (tcpiphdrp_32)tp &&
ti->ti_len <= sbspace(&so->so_rcv)) {
} 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
* with nothing on the reassembly queue and

View File

@ -78,7 +78,7 @@ void tcp_template(struct tcpcb *tp)
struct socket *so = tp->t_socket;
register struct tcpiphdr *n = &tp->t_template;
n->ti_next = n->ti_prev = 0;
n->ti_mbuf = NULL;
n->ti_x1 = 0;
n->ti_pr = IPPROTO_TCP;
n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
@ -156,7 +156,7 @@ void tcp_respond(struct tcpcb *tp, register struct tcpiphdr *ti,
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);
@ -194,7 +194,7 @@ struct tcpcb *tcp_newtcpcb(struct socket *so)
return ((struct tcpcb *)0);
memset((char *) tp, 0, sizeof(struct tcpcb));
tp->seg_next = tp->seg_prev = (tcpiphdrp_32)tp;
tp->seg_next = tp->seg_prev = (struct tcpiphdr*)tp;
tp->t_maxseg = tcp_mssdflt;
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);
/* 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 */

View File

@ -36,18 +36,12 @@
#include "tcpip.h"
#include "tcp_timer.h"
#if SIZEOF_CHAR_P == 4
typedef struct tcpiphdr *tcpiphdrp_32;
#else
typedef u_int32_t tcpiphdrp_32;
#endif
/*
* Tcp control block, one per tcp; fields:
*/
struct tcpcb {
tcpiphdrp_32 seg_next; /* sequencing queue */
tcpiphdrp_32 seg_prev;
struct tcpiphdr *seg_next; /* sequencing queue */
struct tcpiphdr *seg_prev;
short t_state; /* state of this connection */
short t_timer[TCPT_NTIMERS]; /* tcp timers */
short t_rxtshift; /* log(2) of rexmt exp. backoff */
@ -166,21 +160,6 @@ struct tcpcb {
#define TCP_REXMTVAL(tp) \
(((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar)
/* XXX
* We want to avoid doing m_pullup on incoming packets but that
* means avoiding dtom on the tcp reassembly code. That in turn means
* keeping an mbuf pointer in the reassembly queue (since we might
* have a cluster). As a quick hack, the source & destination
* port numbers (which are no longer needed once we've located the
* tcpcb) are overlayed with an mbuf pointer.
*/
#if SIZEOF_CHAR_P == 4
typedef struct mbuf *mbufp_32;
#else
typedef u_int32_t mbufp_32;
#endif
#define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t))
/*
* TCP statistics.
* Many of these should be kept per connection,

View File

@ -40,8 +40,7 @@ struct tcpiphdr {
struct ipovly ti_i; /* overlaid ip structure */
struct tcphdr ti_t; /* tcp header */
};
#define ti_next ti_i.ih_next
#define ti_prev ti_i.ih_prev
#define ti_mbuf ti_i.ih_mbuf.mptr
#define ti_x1 ti_i.ih_x1
#define ti_pr ti_i.ih_pr
#define ti_len ti_i.ih_len
@ -58,6 +57,14 @@ struct tcpiphdr {
#define ti_sum ti_t.th_sum
#define ti_urp ti_t.th_urp
#define tcpiphdr2qlink(T) ((struct qlink*)(((char*)(T)) - sizeof(struct qlink)))
#define qlink2tcpiphdr(Q) ((struct tcpiphdr*)(((char*)(Q)) + sizeof(struct qlink)))
#define tcpiphdr_next(T) qlink2tcpiphdr(tcpiphdr2qlink(T)->next)
#define tcpiphdr_prev(T) qlink2tcpiphdr(tcpiphdr2qlink(T)->prev)
#define tcpfrag_list_first(T) qlink2tcpiphdr((T)->seg_next)
#define tcpfrag_list_end(F, T) (tcpiphdr2qlink(F) == (struct qlink*)(T))
#define tcpfrag_list_empty(T) ((T)->seg_next == (struct tcpiphdr*)(T))
/*
* Just a clean way to get to the first byte
* of the packet

View File

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