[PATCH] checksum + icmp error

Frédéric Raynal <[email protected]>
Newsgroups gmane.comp.security.libnet
Message-ID <20040314202630.A29644@batman>
Hello,

Here is a patch that fix 2 bugs and perform some small optimizations:

- ICMP error messages: as Aaron illustrated in a previous mail, there
  was a problem when several ICMP error messages where built (Aaron
  used icmp_unreach, but it was probably the same with icmp_timeexceed
  and icmp_redirect).
  Problem: this patch breaks the current API
  To solve the bug, I had to remove IP stuff from the ICMP message. Now,
  you need to perform:
    libnet_build_anything_you_want()
    libnet_build_ipv4()
    libnet_icmp_unreach()
    libnet_build_ipv4()

  However, I find it is much more convenient as you can put anything
  you want in the ICMP message (no sanity check is performed to
  control the presence of a IP header)

- Checksum problem: 
  As illustrated in my sample/gre.c, the checksum could not be
  correctly computed when an IP header was embedded in another one. 
  I fix that by adding a new field in the pblock structure (called
  ip_offset). The bug was caused because libnet_do_checksum() assumes
  the buffer passed in argument start at the proper IP header ... which
  may be false when several IP headers are present.

  Now, each time a new IPv4 header is built, all headers placed above record
  the offset of this header in the packet (it is given by the current
  l->total_size when the IP header is built).
  So, when a pblock needs to compute a checksum, we provide the proper
  IP header to libnet_do_checksum()

- Lastly, some small optimizations:
  - libnet_init(): remove some useless affectations 
  - libnet_pblock_new(): mostly  rewritten


I did not have time to perform enough tests, especially for the
checksum trick. I dont think it breaks something else ... but if
someone could test all the program in sample to check, that would be
very helpful.


If some of you want to send me a gift either because of this patch of
because it is my birthday on Wednesday, let me know so that I update
my wishlist ;-)))

	Fred Raynal
crc_icmp.patch (text/plain, 32.7 KB)
--- /home/raynal/LIBNET/libnet/src/libnet_build_icmp.c	Tue Mar  2 02:42:59 2004
+++ /home/raynal/LIBNET/libnet-fr/src/libnet_build_icmp.c	Sun Mar 14 19:52:03 2004
@@ -194,7 +194,7 @@
     struct libnet_icmpv4_hdr icmp_hdr;
 
     if (l == NULL)
-    { 
+    {  
         return (-1);
     } 
 
@@ -259,16 +259,51 @@
     return (-1);
 }
 
+
+#define libnet_complete_icmp_error(type)                                     \
+  do {                                                                       \
+    n = libnet_pblock_append(l, p, (u_int8_t *)&icmp_hdr, type);             \
+    if (n == -1)                                                             \
+    {                                                                        \
+        /* error set elsewhere */                                            \
+        goto bad;                                                            \
+    }                                                                        \
+                                                                             \
+    if ((payload && !payload_s) || (!payload && payload_s))                  \
+    {                                                                        \
+         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,                            \
+			     "%s(): payload inconsistency\n", __func__);     \
+        goto bad;                                                            \
+    }                                                                        \
+                                                                             \
+    if (payload && payload_s)                                                \
+    {                                                                        \
+        n = libnet_pblock_append(l, p, payload, payload_s);                  \
+        if (n == -1)                                                         \
+        {                                                                    \
+            goto bad;                                                        \
+        }                                                                    \
+    }                                                                        \
+                                                                             \
+    if (sum == 0)                                                            \
+    {                                                                        \
+        /*                                                                   \
+         *  If checksum is zero, by default libnet will compute a checksum   \
+         *  for the user.  The programmer can override this by calling       \
+         *  libnet_toggle_checksum(l, ptag, 1);                              \
+         */                                                                  \
+        libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);                \
+    }                                                                        \
+  } while(0)
+
+
+
 libnet_ptag_t
 libnet_build_icmpv4_unreach(u_int8_t type, u_int8_t code, u_int16_t sum,
-u_int16_t orig_len, u_int8_t orig_tos, u_int16_t orig_id, u_int16_t orig_frag,
-u_int8_t orig_ttl, u_int8_t orig_prot, u_int16_t orig_check,
-u_int32_t orig_src, u_int32_t orig_dst, u_int8_t *payload, u_int32_t payload_s,
-libnet_t *l, libnet_ptag_t ptag)
+u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
 {
     u_int32_t n, h;
-    libnet_ptag_t ipv4;
-    libnet_pblock_t *p, *q;
+    libnet_pblock_t *p;
     struct libnet_icmpv4_hdr icmp_hdr;
 
     if (l == NULL)
@@ -276,48 +311,15 @@
         return (-1);
     } 
 
-    p = NULL;
-    /* payload refers to the payload in the original IP header */
-    if ((payload && !payload_s) || (!payload && payload_s))
-    {
-        snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
-                "%s(): payload inconsistency\n", __func__);
-        goto bad;
-    }
-
-    /*
-     *  Build the original IPv4 header in its own pblock.  We stick the
-     *  payload here.
-     */
-    ipv4 = libnet_build_ipv4(orig_len, orig_tos, orig_id, orig_frag, orig_ttl,
-        orig_prot, orig_check, orig_src, orig_dst, payload, payload_s, l, 0);
+    n = LIBNET_ICMPV4_UNREACH_H + payload_s;        /* size of memory block */
 
-    if (ipv4 == -1)
-    {
-        /* error set elsewhere */
-        return (-1);
-    }
-
-    if (orig_check == 0)
-    {
-       int c = 0;
-       l->aligner = 8 - (l->link_offset % 8);
-       q = libnet_pblock_find(l, ipv4);
-       c = libnet_do_checksum(l, q->buf, libnet_pblock_p2p(q->type),
-                              q->h_len);
-       if (c == -1)
-       {
-           /* err msg set in libnet_do_checksum() */
-           return (-1);
-       }
-    }
-
-    /*
-     * Now we can build the ICMP part of the packet
-     */
-    n = LIBNET_ICMPV4_UNREACH_H;        /* size of memory block */
     /* hl for checksum */
-    h = LIBNET_ICMPV4_UNREACH_H + LIBNET_IPV4_H + payload_s;
+    /* 
+     * FREDRAYNAL: as ICMP checksum includes what is embedded in 
+     * the payload, and what is after the ICMP header, we need to include
+     * those 2 sizes.
+     */
+    h = LIBNET_ICMPV4_UNREACH_H + payload_s + l->total_size; 
 
     /*
      *  Find the existing protocol block if a ptag is specified, or create
@@ -328,7 +330,7 @@
     {
         return (-1);
     }
-
+    
     memset(&icmp_hdr, 0, sizeof(icmp_hdr));
     icmp_hdr.icmp_type = type;          /* packet type */
     icmp_hdr.icmp_code = code;          /* packet code */
@@ -336,23 +338,8 @@
     icmp_hdr.icmp_id   = 0;             /* must be 0 */
     icmp_hdr.icmp_seq  = 0;             /* must be 0 */
 
-    n = libnet_pblock_append(l, p, (u_int8_t *)&icmp_hdr,
-            LIBNET_ICMPV4_UNREACH_H);
-    if (n == -1)
-    {
-        /* error set elsewhere */
-        goto bad;
-    }
+    libnet_complete_icmp_error(LIBNET_ICMPV4_UNREACH_H);
 
-    if (sum == 0)
-    {
-        /*
-         *  If checksum is zero, by default libnet will compute a checksum
-         *  for the user.  The programmer can override this by calling
-         *  libnet_toggle_checksum(l, ptag, 1);
-         */
-        libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
-    }
     return (ptag ? ptag : libnet_pblock_update(l, p, h,
             LIBNET_PBLOCK_ICMPV4_UNREACH_H));
 bad:
@@ -362,14 +349,10 @@
 
 libnet_ptag_t
 libnet_build_icmpv4_timeexceed(u_int8_t type, u_int8_t code, u_int16_t sum,
-u_int16_t orig_len, u_int8_t orig_tos, u_int16_t orig_id, u_int16_t orig_frag,
-u_int8_t orig_ttl, u_int8_t orig_prot, u_int16_t orig_check,
-u_int32_t orig_src, u_int32_t orig_dst, u_int8_t *payload, u_int32_t payload_s,
-libnet_t *l, libnet_ptag_t ptag)
+u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
 {
     u_int32_t n, h;
-    libnet_ptag_t ipv4;
-    libnet_pblock_t *p, *q;
+    libnet_pblock_t *p;
     struct libnet_icmpv4_hdr icmp_hdr;
 
     if (l == NULL)
@@ -377,46 +360,16 @@
         return (-1);
     } 
 
-    p = NULL;
-    /* payload refers to the payload in the original IP header */
-    if ((payload && !payload_s) || (!payload && payload_s))
-    {
-         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
-			     "%s(): payload inconsistency\n", __func__);
-        goto bad;
-    }
-
-    /*
-     *  Build the original IPv4 header in its own pblock.  We stick the
-     *  payload here.
-     */
-    ipv4 = libnet_build_ipv4(orig_len, orig_tos, orig_id, orig_frag, orig_ttl,
-        orig_prot, orig_check, orig_src, orig_dst, payload, payload_s, l, 0);
-
-    if (ipv4 == -1)
-    {
-        /* error set elsewhere */
-	return (-1);
-    }
-
-    if (orig_check == 0)
-    {
-       int c = 0;
-       l->aligner = 8 - (l->link_offset % 8);
-       q = libnet_pblock_find(l, ipv4);
-       c = libnet_do_checksum(l, q->buf, libnet_pblock_p2p(q->type),
-                              q->h_len);
-       if (c == -1)
-       {
-           /* err msg set in libnet_do_checksum() */
-           return (-1);
-       }
-    }
-
     /* size of memory block */
     n = LIBNET_ICMPV4_TIMXCEED_H;
+
     /* hl for checksum */
-    h = LIBNET_ICMPV4_TIMXCEED_H + LIBNET_IPV4_H + payload_s;
+    /* 
+     * FREDRAYNAL: as ICMP checksum includes what is embedded in 
+     * the payload, and what is after the ICMP header, we need to include
+     * those 2 sizes.
+     */
+    h = LIBNET_ICMPV4_TIMXCEED_H + payload_s + l->total_size; 
 
     /*
      *  Find the existing protocol block if a ptag is specified, or create
@@ -435,22 +388,8 @@
     icmp_hdr.icmp_id   = 0;             /* must be 0 */
     icmp_hdr.icmp_seq  = 0;             /* must be 0 */
 
-    n = libnet_pblock_append(l, p, (u_int8_t *)&icmp_hdr,
-            LIBNET_ICMPV4_TIMXCEED_H);
-    if (n == -1)
-    {
-        goto bad;
-    }
- 
-    if (sum == 0)
-    {
-        /*
-         *  If checksum is zero, by default libnet will compute a checksum
-         *  for the user.  The programmer can override this by calling
-         *  libnet_toggle_checksum(l, ptag, 1);
-         */
-        libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
-    }
+    libnet_complete_icmp_error(LIBNET_ICMPV4_TIMXCEED_H);
+
     return (ptag ? ptag : libnet_pblock_update(l, p, h,
             LIBNET_PBLOCK_ICMPV4_TIMXCEED_H));
 bad:
@@ -460,15 +399,10 @@
 
 libnet_ptag_t
 libnet_build_icmpv4_redirect(u_int8_t type, u_int8_t code, u_int16_t sum,
-u_int32_t gateway, u_int16_t orig_len, u_int8_t orig_tos, u_int16_t orig_id,
-u_int16_t orig_frag, u_int8_t orig_ttl, u_int8_t orig_prot,
-u_int16_t orig_check, u_int32_t orig_src, u_int32_t orig_dst,
-u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
-
+u_int32_t gateway, u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
 {
     u_int32_t n, h;
-    libnet_ptag_t ipv4;
-    libnet_pblock_t *p, *q;
+    libnet_pblock_t *p;
     struct libnet_icmpv4_hdr icmp_hdr;
 
     if (l == NULL)
@@ -476,45 +410,15 @@
         return (-1);
     } 
 
-    p = NULL;
-    /* payload refers to the payload in the original IP header */
-    if ((payload && !payload_s) || (!payload && payload_s))
-    {
-         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
-                 "%s(): payload inconsistency\n", __func__);
-        goto bad;
-    }
-
-    /*
-     *  Build the original IPv4 header in its own pblock.  We stick the
-     *  payload here.
-     */
-    ipv4 = libnet_build_ipv4(orig_len, orig_tos, orig_id, orig_frag, orig_ttl,
-        orig_prot, orig_check, orig_src, orig_dst, payload, payload_s, l, 0);
-
-    if (ipv4 == -1)
-    {
-       /* error set elsewhere */
-       return (-1);
-    }
-
-    if (orig_check == 0)
-    {
-       int c = 0;
-       l->aligner = 8 - (l->link_offset % 8);
-       q = libnet_pblock_find(l, ipv4);
-       c = libnet_do_checksum(l, q->buf, libnet_pblock_p2p(q->type),
-                              q->h_len);
-       if (c == -1)
-       {
-           /* err msg set in libnet_do_checksum() */
-           return (-1);
-       }
-    }
-
     n = LIBNET_ICMPV4_REDIRECT_H;               /* size of memory block */
+
     /* hl for checksum */
-    h = LIBNET_ICMPV4_REDIRECT_H + LIBNET_IPV4_H + payload_s;
+    /* 
+     * FREDRAYNAL: as ICMP checksum includes what is embedded in 
+     * the payload, and what is after the ICMP header, we need to include
+     * those 2 sizes.
+     */
+    h = LIBNET_ICMPV4_REDIRECT_H + payload_s + l->total_size; 
 
     /*
      *  Find the existing protocol block if a ptag is specified, or create
@@ -532,22 +436,8 @@
     icmp_hdr.icmp_sum       = (sum ? htons(sum) : 0);  /* checksum */
     icmp_hdr.hun.gateway    = gateway;
 
-    n = libnet_pblock_append(l, p, (u_int8_t *)&icmp_hdr, 
-        LIBNET_ICMPV4_REDIRECT_H);
-    if (n == -1)
-    {
-        goto bad;
-    }
- 
-    if (sum == 0)
-    {
-        /*
-         *  If checksum is zero, by default libnet will compute a checksum
-         *  for the user.  The programmer can override this by calling
-         *  libnet_toggle_checksum(l, ptag, 1);
-         */
-        libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
-    }
+    libnet_complete_icmp_error(LIBNET_ICMPV4_REDIRECT_H);
+
     return (ptag ? ptag : libnet_pblock_update(l, p, h,
             LIBNET_PBLOCK_ICMPV4_REDIRECT_H));
 bad:
--- /home/raynal/LIBNET/libnet/src/libnet_build_ip.c	Fri Feb 20 19:53:49 2004
+++ /home/raynal/LIBNET/libnet-fr/src/libnet_build_ip.c	Sun Mar 14 19:35:28 2004
@@ -233,6 +233,13 @@
          */
         libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
     }
+
+    /*
+     * FREDRAYNAL: as we insert a new IP header, all checksums for headers
+     * placed after this one will refer to here.
+     */
+    libnet_pblock_record_ip_offset(l, l->total_size);
+
     return (ptag);
 bad:
     libnet_pblock_delete(l, p);
@@ -310,7 +317,16 @@
     }
 
     libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
-    return (libnet_pblock_update(l, p, LIBNET_IPV4_H, LIBNET_PBLOCK_IPV4_H));
+    ptag = libnet_pblock_update(l, p, LIBNET_IPV4_H, LIBNET_PBLOCK_IPV4_H);
+
+    /*
+     * FREDRAYNAL: as we insert a new IP header, all checksums for headers
+     * placed after this one will refer to here.
+     */
+    libnet_pblock_record_ip_offset(l, l->total_size);
+
+    return (ptag);
+
 bad:
     libnet_pblock_delete(l, p);
     return (-1);
--- /home/raynal/LIBNET/libnet/src/libnet_init.c	Mon Mar  1 21:26:12 2004
+++ /home/raynal/LIBNET/libnet-fr/src/libnet_init.c	Sun Mar 14 16:59:25 2004
@@ -75,9 +75,12 @@
     l->injection_type   = injection_type;
     l->ptag_state       = LIBNET_PTAG_INITIALIZER;
     l->device           = (device ? strdup(device) : NULL);
+    /* FREDRAYNAL: useless because of the previous memset(l, 0, sizeof (*l));
     l->protocol_blocks  = NULL;
     l->pblock_end       = NULL;
+    l->n_pblocks        = 0;
     l->total_size       = 0;
+    */
 
     strncpy(l->label, LIBNET_LABEL_DEFAULT, LIBNET_LABEL_SIZE);
     l->label[sizeof(l->label)] = '\0';
--- /home/raynal/LIBNET/libnet/src/libnet_internal.c	Mon Mar  1 21:26:12 2004
+++ /home/raynal/LIBNET/libnet-fr/src/libnet_internal.c	Sun Mar 14 18:54:31 2004
@@ -136,6 +136,7 @@
         fprintf(stderr, "pblock type:\t%s\n", 
                 libnet_diag_dump_pblock_type(p->type));
         fprintf(stderr, "ptag number:\t%d\n", p->ptag);
+        fprintf(stderr, "IP offset:  \t%d\n", p->ip_offset);
         fprintf(stderr, "pblock address:\t%p\n", p);
         fprintf(stderr, "next pblock\t%p ", p->next);
         if (p->next)
--- /home/raynal/LIBNET/libnet/src/libnet_pblock.c	Sat Feb 28 07:47:48 2004
+++ /home/raynal/LIBNET/libnet-fr/src/libnet_pblock.c	Sun Mar 14 19:57:56 2004
@@ -123,34 +123,17 @@
     /* make the head node if it doesn't exist */
     if (l->protocol_blocks == NULL)
     {
-        l->protocol_blocks = malloc(sizeof (libnet_pblock_t));
-        if (l->protocol_blocks == NULL)
+        p = l->protocol_blocks = malloc(sizeof (libnet_pblock_t));
+        if (p == NULL)
         {
             goto bad;
         }
-        memset(l->protocol_blocks, 0, sizeof (libnet_pblock_t));
-        l->protocol_blocks->buf = malloc(size);
-        if (l->protocol_blocks->buf == NULL)
-        {
-            free(l->protocol_blocks);
-            l->protocol_blocks = NULL;
-            goto bad;
-        }
-        memset(l->protocol_blocks->buf, 0, size);
-        l->protocol_blocks->b_len   = size;
-        l->protocol_blocks->copied  = 0;
-        l->protocol_blocks->next    = NULL;
-        l->protocol_blocks->prev    = NULL;
-        l->total_size               = size;
-        l->protocol_blocks->flags   = 0;
-        return (l->protocol_blocks);
+        memset(p, 0, sizeof (libnet_pblock_t));
     }
     else
     {
-        /* walk to the end of the list */
-        for (p = l->protocol_blocks; p->next; p = p->next) ;
-
-        p->next = malloc(sizeof (libnet_pblock_t));
+	p = l->pblock_end;
+	p->next = malloc(sizeof (libnet_pblock_t));
         if (p->next == NULL)
         {
             goto bad;
@@ -158,21 +141,19 @@
         memset(p->next, 0, sizeof (libnet_pblock_t));
         p->next->prev = p;
         p = p->next;
-        p->buf = malloc(size);
-        if (p->buf == NULL)
-        {
-            free(p);
-            p = NULL;
-            goto bad;
-        }
-        memset(p->buf, 0, size);
-        p->b_len    = size;
-        p->copied   = 0;
-        p->next     = NULL;
-        l->total_size += size;
-        p->flags    = 0;
-        return (p);
     }
+    p->buf = malloc(size);
+    if (p->buf == NULL)
+    {
+	free(p);
+	p = NULL;
+	goto bad;
+    }
+    memset(p->buf, 0, size);
+    p->b_len   = size;
+    l->total_size += size;
+    l->n_pblocks++;
+    return (p);
 
     bad:
     snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): malloc(): %s\n", __func__, 
@@ -301,6 +282,18 @@
     return (p->ptag);
 }
 
+void
+libnet_pblock_record_ip_offset(libnet_t *l, u_int32_t offset)
+{
+    libnet_pblock_t *p = l->pblock_end;
+
+    do
+    {
+	p->ip_offset = offset;
+	p = p->prev;
+    } while (p && p->type != LIBNET_PBLOCK_IPV4_H);
+}
+
 int
 libnet_pblock_coalesce(libnet_t *l, u_int8_t **packet, u_int32_t *size)
 {
@@ -331,6 +324,7 @@
                 __func__, strerror(errno));
         return (-1);
     }
+    memset(*packet, 0, l->aligner + l->total_size);
 
     if (l->injection_type == LIBNET_RAW4 && 
         l->pblock_end->type == LIBNET_PBLOCK_IPV4_H)
@@ -404,9 +398,8 @@
             {
                 if ((q->flags) & LIBNET_PBLOCK_DO_CHECKSUM)
                 {
-                    c = libnet_do_checksum(l, (l->injection_type == LIBNET_LINK
-                            || l->injection_type == LIBNET_LINK_ADV) ?
-                            *packet + l->link_offset + l->aligner : *packet,
+		    int offset = (l->total_size + l->aligner) - q->ip_offset;
+                    c = libnet_do_checksum(l, *packet + offset,
                             libnet_pblock_p2p(q->type), q->h_len);
                     if (c == -1)
                     {
@@ -443,6 +436,7 @@
     if (p)
     {
         l->total_size -= p->b_len;
+	l->n_pblocks--;
         if (p->prev) 
         {
             p->prev->next = p->next;
--- /home/raynal/LIBNET/libnet/sample/gre.c	Sun Feb 22 20:44:24 2004
+++ /home/raynal/LIBNET/libnet-fr/sample/gre.c	Sun Mar 14 19:30:54 2004
@@ -239,7 +239,7 @@
 	    0x02020202,                                 /* acknowledgement num */
 	    TH_SYN,                                     /* control flags */
 	    32767,                                      /* window size */
-	    0x6666,                                     /* checksum */
+	    0,                                          /* checksum */
 	    0,                                          /* urgent pointer */
 	    size,                                       /* TCP packet size */
 	    NULL,                                       /* payload */
--- /home/raynal/LIBNET/libnet/sample/icmp_redirect.c	Sat Jan  3 21:31:01 2004
+++ /home/raynal/LIBNET/libnet-fr/sample/icmp_redirect.c	Sun Mar 14 20:02:06 2004
@@ -99,23 +99,34 @@
         exit(EXIT_FAILURE);
     }
     
+    t = libnet_build_ipv4(
+        LIBNET_IPV4_H + payload_s,                  /* length */
+        IPTOS_LOWDELAY | IPTOS_THROUGHPUT,          /* TOS */
+        0x42,                                       /* IP ID */
+        0,                                          /* IP Frag */
+        64,                                         /* TTL */
+        IPPROTO_ICMP,                               /* protocol */
+        0,                                          /* checksum */
+        dst_ip,                                     /* source IP */
+        src_ip,                                     /* destination IP */
+        payload,                                    /* payload */
+        payload_s,                                  /* payload size */
+        l,                                          /* libnet handle */
+        0);
+    if (t == -1)
+    {
+        fprintf(stderr, "Can't build error IP header: %s\n", libnet_geterror(l));
+        goto bad;
+    }
+
    t = libnet_build_icmpv4_redirect(
            ICMP_REDIRECT,                 /* type */
            ICMP_REDIRECT_HOST,            /* code */
            0,                             /* checksum */
            gw_ip,
-               LIBNET_IPV4_H + payload_s,              /* o length */
-               IPTOS_LOWDELAY | IPTOS_THROUGHPUT,      /* o IP tos */
-               0xff,                                   /* o IP ID */
-               0,                                      /* o frag */
-               64,                                     /* o TTL */
-               IPPROTO_UDP,                            /* o protocol */
-               0,                                      /* o checksum */
-               dst_ip,                                 /* o source IP */
-               src_ip,                                 /* o destination IP */
-               payload,                                /* payload */
-               payload_s,                              /* payload size */
-           l,             /* libnet handle */
+	   NULL,                          /* payload */
+	   0,                             /* payload size */
+           l,                             /* libnet handle */
            0);                            /* libnet id */
     if (t == -1)
     {
--- /home/raynal/LIBNET/libnet/sample/icmp_timeexceed.c	Sat Jan  3 21:31:01 2004
+++ /home/raynal/LIBNET/libnet-fr/sample/icmp_timeexceed.c	Sun Mar 14 20:00:40 2004
@@ -91,21 +91,32 @@
         exit(EXIT_FAILURE);
     }
 
+    t = libnet_build_ipv4(
+        LIBNET_IPV4_H + payload_s,                  /* length */
+        IPTOS_LOWDELAY | IPTOS_THROUGHPUT,          /* TOS */
+        0xee,                                       /* IP ID */
+        0,                                          /* IP Frag */
+        64,                                         /* TTL */
+        IPPROTO_UDP,                                /* protocol */
+        0,                                          /* checksum */
+        dst_ip,                                     /* source IP */
+        src_ip,                                     /* destination IP */
+        payload,                                    /* payload */
+        payload_s,                                  /* payload size */
+        l,                                          /* libnet handle */
+        0);
+    if (t == -1)
+    {
+        fprintf(stderr, "Can't build error IP header: %s\n", libnet_geterror(l));
+        goto bad;
+    }
+
     t = libnet_build_icmpv4_timeexceed(
         ICMP_TIMXCEED,                              /* type */
         ICMP_TIMXCEED_INTRANS,                      /* code */
         0,                                          /* checksum */
-            LIBNET_IPV4_H + payload_s,              /* o length */
-            IPTOS_LOWDELAY | IPTOS_THROUGHPUT,      /* o IP tos */
-            0xff,                                   /* o IP ID */
-            0,                                      /* o frag */
-            64,                                     /* o TTL */
-            IPPROTO_UDP,                            /* o protocol */
-            0,                                      /* o checksum */
-            dst_ip,                                 /* o source IP */
-            src_ip,                                 /* o destination IP */
-            payload,                                /* payload */
-            payload_s,                              /* payload size */
+        NULL,                                       /* payload */
+        0,                                          /* payload size */
         l,                                          /* libnet handle */
         0);
     if (t == -1)
--- /home/raynal/LIBNET/libnet/sample/icmp_unreach.c	Tue Mar  2 02:49:42 2004
+++ /home/raynal/LIBNET/libnet-fr/sample/icmp_unreach.c	Sun Mar 14 20:05:57 2004
@@ -4,6 +4,9 @@
  *  libnet 1.1
  *  Build an ICMP unreachable packet
  *
+ *  Hacked by Frederic Raynal <[email protected]> to illustrate
+ *  the new API of ICMP error messages fixing Aaron's bugs.
+ * 
  *  Hacked by Aaron Turner <[email protected]> to illustrate two bugs
  *
  *  Copyright (c) 1998 - 2004 Mike D. Schiffman <[email protected]>
@@ -40,13 +43,13 @@
 int
 main(int argc, char **argv)
 {
-    int c, i;
+    int c;
     libnet_t *l = NULL;
-    libnet_ptag_t icmp = 0, ip = 0, eth = 0;
+    libnet_ptag_t ip_err = 0, icmp = 0, ip = 0, eth = 0;
     u_long src_ip, dst_ip; 
     u_char payload[8] = {0x11, 0x11, 0x22, 0x22, 0x00, 0x08, 0xc6, 0xa5};
     u_long payload_s = 8;
-    int mode = LIBNET_LINK;
+    int mode = LIBNET_LINK, i;
     char errbuf[LIBNET_ERRBUF_SIZE];
 
     printf("libnet 1.1 packet shaping: ICMP unreachable[link]\n"); 
@@ -96,23 +99,35 @@
         fprintf(stderr, "libnet_init() failed: %s", errbuf);
         exit(EXIT_FAILURE);
     }
+    
+  for (i=0; i<255; i++)
+  {
+    ip_err = libnet_build_ipv4(
+	LIBNET_IPV4_H + payload_s,              /* o length */
+	IPTOS_LOWDELAY | IPTOS_THROUGHPUT,      /* o IP tos */
+	(u_int16_t)i,                           /* o IP ID */
+	0,                                      /* o frag */
+	64,                                     /* o TTL */
+	IPPROTO_UDP,                            /* o protocol */
+	0,                                      /* o checksum */
+	dst_ip,                                 /* o source IP */
+	src_ip,                                 /* o destination IP */
+	payload,                                /* payload */
+	payload_s,                              /* payload size */
+	l,
+	ip_err);
+    if (ip_err == -1)
+    {
+        fprintf(stderr, "Can't build error IPv4 header: %s\n", libnet_geterror(l));
+        goto bad;
+    }
 
-for (i = 1; i <= 255; i ++) {
     icmp = libnet_build_icmpv4_unreach(
         ICMP_UNREACH,                               /* type */
         ICMP_UNREACH_PORT,                          /* code */
         0,                                          /* checksum */
-            LIBNET_IPV4_H + payload_s,              /* o length */
-            IPTOS_LOWDELAY | IPTOS_THROUGHPUT,      /* o IP tos */
-            (u_int16_t)i,                           /* o IP ID */
-            0,                                      /* o frag */
-            64,                                     /* o TTL */
-            IPPROTO_UDP,                            /* o protocol */
-            0,                                      /* o checksum */
-            dst_ip,                                 /* o source IP */
-            src_ip,                                 /* o destination IP */
-            payload,                                /* payload */
-            payload_s,                              /* payload size */
+        NULL,                                       /* payload */
+        0,                                          /* payload size */
         l,                                          /* libnet handle */
         icmp);
     if (icmp == -1)
@@ -125,7 +140,7 @@
         LIBNET_IPV4_H + LIBNET_ICMPV4_UNREACH_H +
         LIBNET_IPV4_H + payload_s,                  /* length */
         IPTOS_LOWDELAY | IPTOS_THROUGHPUT,          /* TOS */
-        (u_int16_t)i,                               /* IP ID */
+        (u_int16_t)i+1,                             /* IP ID */
         0,                                          /* IP Frag */
         64,                                         /* TTL */
         IPPROTO_ICMP,                               /* protocol */
@@ -172,7 +187,7 @@
     {
         fprintf(stderr, "Wrote %d byte ICMP packet; check the wire.\n", c);
     }
-}
+  }
     libnet_destroy(l);
     return (EXIT_SUCCESS);
 bad:
--- /home/raynal/LIBNET/libnet/include/libnet/libnet-functions.h	Mon Mar  1 21:26:11 2004
+++ /home/raynal/LIBNET/libnet-fr/include/libnet/libnet-functions.h	Sun Mar 14 19:53:10 2004
@@ -709,13 +709,6 @@
  * @param type type of ICMP packet (should be ICMP_UNREACH)
  * @param code code of ICMP packet (should be one of the 16 unreachable codes)
  * @param sum checksum (0 for libnet to autofill)
- * @param orig_id original IP header identification
- * @param orig_frag original IP header fragmentation information
- * @param orig_ttl orginal IP header time to live
- * @param orig_prot original IP header protocol
- * @param orig_check original IP header checksum
- * @param orig_src original IP header source address
- * @param orig_dst original IP header destination address
  * @param payload optional payload or NULL
  * @param payload_s payload length or 0
  * @param l pointer to a libnet context
@@ -724,10 +717,7 @@
  */
 libnet_ptag_t
 libnet_build_icmpv4_unreach(u_int8_t type, u_int8_t code, u_int16_t sum,
-u_int16_t orig_len, u_int8_t orig_tos, u_int16_t orig_id, u_int16_t orig_frag,
-u_int8_t orig_ttl, u_int8_t orig_prot,  u_int16_t orig_check, 
-u_int32_t orig_src, u_int32_t orig_dst, u_int8_t *payload, u_int32_t payload_s,
-libnet_t *l, libnet_ptag_t ptag);
+u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag);
 
 /**
  * Builds an IP version 4 RFC 792 Internet Message Control Protocol (ICMP) 
@@ -737,13 +727,7 @@
  * @param type type of ICMP packet (should be ICMP_REDIRECT)
  * @param code code of ICMP packet (should be one of the four redirect codes)
  * @param sum checksum (0 for libnet to autofill)
- * @param orig_id original IP header identification
- * @param orig_frag original IP header fragmentation information
- * @param orig_ttl orginal IP header time to live
- * @param orig_prot original IP header protocol
- * @param orig_check original IP header checksum
- * @param orig_src original IP header source address
- * @param orig_dst original IP header destination address
+ * @param gateway gateway for redirection
  * @param payload optional payload or NULL
  * @param payload_s payload length or 0
  * @param l pointer to a libnet context
@@ -752,9 +736,7 @@
  */
 libnet_ptag_t
 libnet_build_icmpv4_redirect(u_int8_t type, u_int8_t code, u_int16_t sum,
-u_int32_t gateway, u_int16_t orig_len, u_int8_t orig_tos, u_int16_t orig_id,
-u_int16_t orig_frag, u_int8_t orig_ttl, u_int8_t orig_prot,
-u_int16_t orig_check, u_int32_t orig_src, u_int32_t orig_dst,
+u_int32_t gateway, 
 u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag);
 
 /**
@@ -766,13 +748,6 @@
  * @param type type of ICMP packet (should be ICMP_TIMXCEED)
  * @param code code of ICMP packet (ICMP_TIMXCEED_INTRANS / ICMP_TIMXCEED_REASS)
  * @param sum checksum (0 for libnet to autofill)
- * @param orig_id original IP header identification
- * @param orig_frag original IP header fragmentation information
- * @param orig_ttl orginal IP header time to live
- * @param orig_prot original IP header protocol
- * @param orig_check original IP header checksum
- * @param orig_src original IP header source address
- * @param orig_dst original IP header destination address
  * @param payload optional payload or NULL
  * @param payload optional payload or NULL
  * @param payload_s payload length or 0
@@ -782,10 +757,7 @@
  */
 libnet_ptag_t
 libnet_build_icmpv4_timeexceed(u_int8_t type, u_int8_t code, u_int16_t sum,
-u_int16_t orig_len, u_int8_t orig_tos, u_int16_t orig_id, u_int16_t orig_frag,
-u_int8_t orig_ttl, u_int8_t orig_prot, u_int16_t orig_check,
-u_int32_t orig_src, u_int32_t orig_dst, u_int8_t *payload, u_int32_t payload_s,
-libnet_t *l, libnet_ptag_t ptag);
+u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag);
 
 /**
  * Builds an IP version 4 RFC 792 Internet Control Message Protocol (ICMP)
@@ -2076,6 +2048,18 @@
 
 /*
  * [Internal] 
+ * Checksums are a real pain in the <beep>!!!
+ * Function updates referer used to compute the checksum. All
+ * pblock need to know where is their referer (ie IP header).
+ * So, this function is called each time a new IP header is inserted.
+ * It updates the ip_pos field (referer) of each subsequent pblock.
+ */
+void
+libnet_pblock_record_ip_offset(libnet_t *l, u_int32_t offset);
+
+
+/*
+ * [Internal] 
  * Function locates a given block by it's ptag. 
  */
 libnet_pblock_t *
--- /home/raynal/LIBNET/libnet/include/libnet/libnet-structures.h	Tue Feb 17 00:13:38 2004
+++ /home/raynal/LIBNET/libnet-fr/include/libnet/libnet-structures.h	Sun Mar 14 18:54:04 2004
@@ -79,6 +79,7 @@
     u_int8_t *buf;                      /* protocol buffer */
     u_int32_t b_len;                    /* length of buf */
     u_int16_t h_len;                    /* header length (for checksumming) */
+    u_int32_t ip_offset;                /* offset from the end of the packet of the previous IP header (for checksumming) */
     u_int32_t copied;                   /* bytes copied */
     u_int8_t type;                      /* type of pblock */
 /* this needs to be updated every time a new packet builder is added */
@@ -178,6 +179,7 @@
 
     libnet_pblock_t *protocol_blocks;   /* protocol headers / data */
     libnet_pblock_t *pblock_end;        /* last node in list */
+    u_int32_t       n_pblocks;          /* # of pblocks */
 
     int link_type;                      /* link-layer type */
     int link_offset;                    /* link-layer header size */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.