File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libnet / src / libnet_build_ip.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:14:23 2012 UTC (12 years, 5 months ago) by misho
Branches: libnet, MAIN
CVS tags: v1_1_2_1, HEAD
libnet

    1: /*
    2:  *  $Id: libnet_build_ip.c,v 1.1.1.1 2012/02/21 22:14:23 misho Exp $
    3:  *
    4:  *  libnet
    5:  *  libnet_build_ip.c - IP packet assembler
    6:  *
    7:  *  Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
    8:  *  All rights reserved.
    9:  *
   10:  * Redistribution and use in source and binary forms, with or without
   11:  * modification, are permitted provided that the following conditions
   12:  * are met:
   13:  * 1. Redistributions of source code must retain the above copyright
   14:  *    notice, this list of conditions and the following disclaimer.
   15:  * 2. Redistributions in binary form must reproduce the above copyright
   16:  *    notice, this list of conditions and the following disclaimer in the
   17:  *    documentation and/or other materials provided with the distribution.
   18:  *
   19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29:  * SUCH DAMAGE.
   30:  *
   31:  */
   32: 
   33: #if (HAVE_CONFIG_H)
   34: #include "../include/config.h"
   35: #endif
   36: #if (!(_WIN32) || (__CYGWIN__)) 
   37: #include "../include/libnet.h"
   38: #else
   39: #include "../include/win32/libnet.h"
   40: #endif
   41: 
   42: 
   43: libnet_ptag_t
   44: libnet_build_ipv4(u_int16_t len, u_int8_t tos, u_int16_t id, u_int16_t frag,
   45: u_int8_t ttl, u_int8_t prot, u_int16_t sum, u_int32_t src, u_int32_t dst,
   46: u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
   47: {
   48:     int offset;
   49:     u_int32_t h, n, i, j;
   50:     libnet_pblock_t *p, *p_data, *p_temp;
   51:     struct libnet_ipv4_hdr ip_hdr;
   52:     libnet_ptag_t ptag_data, ptag_hold;
   53: 
   54:     if (l == NULL)
   55:     { 
   56:         return (-1);
   57:     } 
   58: 
   59:     n = LIBNET_IPV4_H;                      /* size of memory block */
   60:     h = len;                                /* header length */
   61:     ptag_data = 0;                          /* used if options are present */
   62: 
   63:     if (h + payload_s > IP_MAXPACKET)
   64:     {
   65:          snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
   66:                 "%s(): IP packet too large\n", __func__);
   67:         return (-1);
   68:     }
   69: 
   70:     /*
   71:      *  Find the existing protocol block if a ptag is specified, or create
   72:      *  a new one.
   73:      */
   74:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV4_H);
   75:     if (p == NULL)
   76:     {
   77:         return (-1);
   78:     }
   79: 
   80: 	memset(&ip_hdr, 0, sizeof(ip_hdr));
   81:     ip_hdr.ip_v          = 4;                         /* version 4 */
   82:     ip_hdr.ip_hl         = 5;                         /* 20 byte header */
   83: 
   84:     /* check to see if there are IP options to include */
   85:     if (p->prev)
   86:     {
   87:         if (p->prev->type == LIBNET_PBLOCK_IPO_H)
   88:         {
   89:             /*
   90:              *  Count up number of 32-bit words in options list, padding if
   91:              *  neccessary.
   92:              */
   93:             for (i = 0, j = 0; i < p->prev->b_len; i++)
   94:             {
   95:                 (i % 4) ? j : j++;
   96:             }
   97:             ip_hdr.ip_hl += j;
   98:         }
   99:     }
  100: 
  101:     ip_hdr.ip_tos        = tos;                       /* IP tos */
  102:     ip_hdr.ip_len        = htons(h);                  /* total length */
  103:     ip_hdr.ip_id         = htons(id);                 /* IP ID */
  104:     ip_hdr.ip_off        = htons(frag);               /* fragmentation flags */
  105:     ip_hdr.ip_ttl        = ttl;                       /* time to live */
  106:     ip_hdr.ip_p          = prot;                      /* transport protocol */
  107:     ip_hdr.ip_sum        = (sum ? htons(sum) : 0);    /* checksum */
  108:     ip_hdr.ip_src.s_addr = src;                       /* source ip */
  109:     ip_hdr.ip_dst.s_addr = dst;                       /* destination ip */
  110:     
  111:     n = libnet_pblock_append(l, p, (u_int8_t *)&ip_hdr, LIBNET_IPV4_H);
  112:     if (n == -1)
  113:     {
  114:         goto bad;
  115:     }
  116: 
  117:     /* save the original ptag value */
  118:     ptag_hold = ptag;
  119: 
  120:     if (ptag == LIBNET_PTAG_INITIALIZER)
  121:     {
  122:         ptag = libnet_pblock_update(l, p, LIBNET_IPV4_H, LIBNET_PBLOCK_IPV4_H);
  123:     }
  124: 
  125:     /* find and set the appropriate ptag, or else use the default of 0 */
  126:     offset = payload_s;
  127:     if (ptag_hold && p->prev)
  128:     {
  129:         p_temp = p->prev;
  130:         while (p_temp->prev &&
  131:               (p_temp->type != LIBNET_PBLOCK_IPDATA) &&
  132:               (p_temp->type != LIBNET_PBLOCK_IPV4_H))
  133:         {
  134:             p_temp = p_temp->prev;
  135:         }
  136: 
  137:         if (p_temp->type == LIBNET_PBLOCK_IPDATA)
  138:         {
  139:             ptag_data = p_temp->ptag;
  140:             offset -=  p_temp->b_len;
  141:             p->h_len += offset;
  142:         }
  143:         else
  144:         {
  145:              snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  146:                      "%s(): IPv4 data pblock not found\n", __func__);
  147:         }
  148:     }
  149: 
  150:     if ((payload && !payload_s) || (!payload && payload_s))
  151:     {
  152:          snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  153:                  "%s(): payload inconsistency\n", __func__);
  154:         goto bad;
  155:     }
  156: 
  157:     if (payload && payload_s)
  158:     {
  159:         /* update ptag_data with the new payload */
  160:         p_data = libnet_pblock_probe(l, ptag_data, payload_s,
  161:                 LIBNET_PBLOCK_IPDATA);
  162:         if (p_data == NULL)
  163:         {
  164:             return (-1);
  165:         }
  166: 
  167:         if (libnet_pblock_append(l, p_data, payload, payload_s) == -1)
  168:         {
  169:             goto bad;
  170:         }
  171: 
  172:         if (ptag_data == LIBNET_PTAG_INITIALIZER)
  173:         {
  174:             if (p_data->prev->type == LIBNET_PBLOCK_IPV4_H)
  175:             {
  176:                 libnet_pblock_update(l, p_data, payload_s,
  177:                         LIBNET_PBLOCK_IPDATA);
  178:                 /* swap pblocks to correct the protocol order */
  179:                 libnet_pblock_swap(l, p->ptag, p_data->ptag); 
  180:             }
  181:             else
  182:             {
  183:                 /* update without setting this as the final pblock */
  184:                 p_data->type  =  LIBNET_PBLOCK_IPDATA;
  185:                 p_data->ptag  =  ++(l->ptag_state);
  186:                 p_data->h_len =  payload_s;
  187: 
  188:                 /* Adjust h_len for checksum. */
  189:                 p->h_len += payload_s;
  190: 
  191:                 /* data was added after the initial construction */
  192:                 for (p_temp = l->protocol_blocks;
  193:                         p_temp->type == LIBNET_PBLOCK_IPV4_H ||
  194:                         p_temp->type == LIBNET_PBLOCK_IPO_H;
  195:                         p_temp = p_temp->next)
  196:                 {
  197:                     libnet_pblock_insert_before(l, p_temp->ptag, p_data->ptag);
  198:                     break;
  199:                 }
  200: 
  201:                 /* the end block needs to have its next pointer cleared */
  202:                 l->pblock_end->next = NULL;
  203:             }
  204: 
  205:             if (p_data->prev && p_data->prev->type == LIBNET_PBLOCK_IPO_H)
  206:             {
  207:                 libnet_pblock_swap(l, p_data->prev->ptag, p_data->ptag); 
  208:             }
  209:         }
  210:     }
  211:     else
  212:     {
  213:         p_data = libnet_pblock_find(l, ptag_data);
  214:         if (p_data) 
  215:         {
  216:             libnet_pblock_delete(l, p_data);
  217:         }
  218:         else
  219:         {
  220:             /* 
  221:              * XXX - When this completes successfully, libnet errbuf contains 
  222:              * an error message so to come correct, we'll clear it.
  223:              */ 
  224:             memset(l->err_buf, 0, sizeof (l->err_buf));
  225:         }
  226:     }
  227:     if (sum == 0)
  228:     {
  229:         /*
  230:          *  If checksum is zero, by default libnet will compute a checksum
  231:          *  for the user.  The programmer can override this by calling
  232:          *  libnet_toggle_checksum(l, ptag, 1);
  233:          */
  234:         libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
  235:     }
  236: 
  237:     /*
  238:      * FREDRAYNAL: as we insert a new IP header, all checksums for headers
  239:      * placed after this one will refer to here.
  240:      */
  241:     libnet_pblock_record_ip_offset(l, l->total_size);
  242: 
  243:     return (ptag);
  244: bad:
  245:     libnet_pblock_delete(l, p);
  246:     return (-1);
  247: }
  248: 
  249: libnet_ptag_t
  250: libnet_autobuild_ipv4(u_int16_t len, u_int8_t prot, u_int32_t dst, libnet_t *l)
  251: {
  252:     u_int32_t n, i, j, src;
  253:     u_int16_t h;
  254:     libnet_pblock_t *p;
  255:     libnet_ptag_t ptag;
  256:     struct libnet_ipv4_hdr ip_hdr;
  257: 
  258:     if (l == NULL)
  259:     { 
  260:         return (-1);
  261:     } 
  262: 
  263:     n = LIBNET_IPV4_H;                                /* size of memory block */
  264:     h = len;                                          /* header length */
  265:     ptag = LIBNET_PTAG_INITIALIZER;
  266:     src = libnet_get_ipaddr4(l);
  267:     if (src == -1)
  268:     {
  269:         /* err msg set in libnet_get_ipaddr() */ 
  270:         return (-1);
  271:     }
  272: 
  273:     /*
  274:      *  Create a new pblock.
  275:      */
  276:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV4_H);
  277:     if (p == NULL)
  278:     {
  279:         return (-1);
  280:     }
  281: 	
  282:     memset(&ip_hdr, 0, sizeof(ip_hdr));
  283:     ip_hdr.ip_v          = 4;                         /* version 4 */
  284:     ip_hdr.ip_hl         = 5;                         /* 20 byte header */
  285: 
  286:     /* check to see if there are IP options to include */
  287:     if (p->prev)
  288:     {
  289:         if (p->prev->type == LIBNET_PBLOCK_IPO_H)
  290:         {
  291:             /*
  292:              *  Count up number of 32-bit words in options list, padding if
  293:              *  neccessary.
  294:              */
  295:             for (i = 0, j = 0; i < p->prev->b_len; i++)
  296:             {
  297:                 (i % 4) ? j : j++;
  298:             }
  299:             ip_hdr.ip_hl += j;
  300:         }
  301:     }
  302: 
  303:     ip_hdr.ip_tos        = 0;                         /* IP tos */
  304:     ip_hdr.ip_len        = htons(h);                  /* total length */
  305:     ip_hdr.ip_id         = htons((l->ptag_state) & 0x0000ffff); /* IP ID */
  306:     ip_hdr.ip_off        = 0;                         /* fragmentation flags */
  307:     ip_hdr.ip_ttl        = 64;                        /* time to live */
  308:     ip_hdr.ip_p          = prot;                      /* transport protocol */
  309:     ip_hdr.ip_sum        = 0;                         /* checksum */
  310:     ip_hdr.ip_src.s_addr = src;                       /* source ip */
  311:     ip_hdr.ip_dst.s_addr = dst;                       /* destination ip */
  312: 
  313:     n = libnet_pblock_append(l, p, (u_int8_t *)&ip_hdr, LIBNET_IPV4_H);
  314:     if (n == -1)
  315:     {
  316:         goto bad;
  317:     }
  318: 
  319:     libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
  320:     ptag = libnet_pblock_update(l, p, LIBNET_IPV4_H, LIBNET_PBLOCK_IPV4_H);
  321: 
  322:     /*
  323:      * FREDRAYNAL: as we insert a new IP header, all checksums for headers
  324:      * placed after this one will refer to here.
  325:      */
  326:     libnet_pblock_record_ip_offset(l, l->total_size);
  327:     return (ptag);
  328: 
  329: bad:
  330:     libnet_pblock_delete(l, p);
  331:     return (-1);
  332: }
  333: 
  334: libnet_ptag_t
  335: libnet_build_ipv4_options(u_int8_t *options, u_int32_t options_s, libnet_t *l, 
  336: libnet_ptag_t ptag)
  337: {
  338:     int offset, underflow;
  339:     u_int32_t i, j, n, adj_size;
  340:     libnet_pblock_t *p, *p_temp;
  341:     struct libnet_ipv4_hdr *ip_hdr;
  342: 
  343:     if (l == NULL)
  344:     { 
  345:         return (-1);
  346:     }
  347: 
  348:     underflow = 0;
  349:     offset = 0;
  350: 
  351:     /* check options list size */
  352:     if (options_s > LIBNET_MAXOPTION_SIZE)
  353:     {
  354:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  355:             "%s(): options list is too large %d\n", __func__, options_s);
  356:         return (-1);
  357:     }
  358: 
  359:     adj_size = options_s;
  360:     if (adj_size % 4)
  361:     {
  362:         /* size of memory block with padding */
  363:         adj_size += 4 - (options_s % 4);
  364:     }
  365: 
  366:     /* if this pblock already exists, determine if there is a size diff */
  367:     if (ptag)
  368:     {
  369:         p_temp = libnet_pblock_find(l, ptag);
  370:         if (p_temp)
  371:         {
  372:             if (adj_size >= p_temp->b_len)
  373:             {                                   
  374:                 offset = adj_size - p_temp->b_len;                             
  375:             }
  376:             else
  377:             {                                                           
  378:                 offset = p_temp->b_len - adj_size;                             
  379:                 underflow = 1;
  380:             }
  381:         }
  382:         else
  383:         {
  384:             /* 
  385:              * XXX - When this completes successfully, libnet errbuf contains 
  386:              * an error message so to come correct, we'll clear it.
  387:              */ 
  388:             memset(l->err_buf, 0, sizeof (l->err_buf));
  389:         }
  390:     }
  391: 
  392:     /*
  393:      *  Find the existing protocol block if a ptag is specified, or create
  394:      *  a new one.
  395:      */
  396:     p = libnet_pblock_probe(l, ptag, adj_size, LIBNET_PBLOCK_IPO_H);
  397:     if (p == NULL)
  398:     {
  399:         return (-1);
  400:     }
  401: 
  402:     /* append options */
  403:     n = libnet_pblock_append(l, p, options, options_s);
  404:     if (n == -1)
  405:     {
  406:         goto bad;
  407:     }
  408: 
  409:     /* append padding */
  410:     n = libnet_pblock_append(l, p, "\0\0\0", adj_size - options_s);
  411:     if (n == -1)
  412:     {
  413:         goto bad;
  414:     }
  415: 
  416:     if (ptag && p->next)
  417:     {
  418:         p_temp = p->next;
  419:         while ((p_temp->next) && (p_temp->type != LIBNET_PBLOCK_IPV4_H))
  420:         {
  421:             p_temp = p_temp->next;
  422:         }
  423: 
  424:         /* fix the IP header size */
  425:         if (p_temp->type == LIBNET_PBLOCK_IPV4_H)
  426:         {
  427:             /*
  428:              *  Count up number of 32-bit words in options list, padding if
  429:              *  neccessary.
  430:              */
  431:             for (i = 0, j = 0; i < p->b_len; i++)
  432:             {
  433:                 (i % 4) ? j : j++;
  434:             }
  435:             ip_hdr = (struct libnet_ipv4_hdr *) p_temp->buf;
  436:             ip_hdr->ip_hl = j + 5;
  437: 
  438:             if (!underflow)
  439:             {
  440:                 p_temp->h_len += offset;
  441:             }
  442:             else
  443:             {
  444:                 p_temp->h_len -= offset;
  445:             }
  446:         }
  447:     }
  448: 
  449:     return (ptag ? ptag : libnet_pblock_update(l, p, adj_size,
  450:             LIBNET_PBLOCK_IPO_H));
  451: bad:
  452:     libnet_pblock_delete(l, p);
  453:     return (-1);
  454: }
  455: 
  456: libnet_ptag_t
  457: libnet_build_ipv6(u_int8_t tc, u_int32_t fl, u_int16_t len, u_int8_t nh,
  458: u_int8_t hl, struct libnet_in6_addr src, struct libnet_in6_addr dst, 
  459: u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
  460: {   
  461:     u_int32_t n;
  462:     libnet_pblock_t *p;
  463:     struct libnet_ipv6_hdr ip_hdr;
  464: 
  465:     if (l == NULL)
  466:     {
  467:         return (-1);
  468:     }
  469: 
  470:     n = LIBNET_IPV6_H + payload_s;          /* size of memory block */
  471:        
  472:     if (LIBNET_IPV6_H + payload_s > IP_MAXPACKET)
  473:     {  
  474:          snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  475:                  "%s(): IP packet too large\n", __func__);
  476:         return (-1);
  477:     }  
  478:        
  479:     /*
  480:      *  Find the existing protocol block if a ptag is specified, or create
  481:      *  a new one.
  482:      */
  483:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV6_H);
  484:     if (p == NULL)
  485:     {   
  486:         return (-1);
  487:     }  
  488:     
  489:     memset(&ip_hdr, 0, sizeof(ip_hdr));
  490:     ip_hdr.ip_flags[0] = 0x06 << 4;
  491:     ip_hdr.ip_flags[1] = ((tc & 0x0F) << 4) | ((fl & 0xF0000) >> 16);
  492:     ip_hdr.ip_flags[2] = fl & 0x0FF00 >> 8;
  493:     ip_hdr.ip_flags[3] = fl & 0x000FF;
  494:     ip_hdr.ip_len      = htons(len);
  495:     ip_hdr.ip_nh       = nh;
  496:     ip_hdr.ip_hl       = hl;
  497:     ip_hdr.ip_src      = src;
  498:     ip_hdr.ip_dst      = dst;
  499:      
  500:     n = libnet_pblock_append(l, p, (u_int8_t *)&ip_hdr, LIBNET_IPV6_H);
  501:     if (n == -1)
  502:     {
  503:         goto bad;
  504:     }
  505: 
  506:     if ((payload && !payload_s) || (!payload && payload_s))
  507:     {
  508:          snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  509:                  "%s(): payload inconsistency\n", __func__);
  510:         goto bad;
  511:     }
  512:  
  513:     if (payload && payload_s)
  514:     {  
  515:         n = libnet_pblock_append(l, p, payload, payload_s);
  516:         if (n == -1)
  517:         {
  518:             goto bad;
  519:         }
  520:     }
  521: 
  522:     /* no checksum for IPv6 */
  523:     return (ptag ? ptag : libnet_pblock_update(l, p, LIBNET_IPV6_H,
  524:             LIBNET_PBLOCK_IPV6_H));
  525: bad:
  526:     libnet_pblock_delete(l, p);
  527:     return (-1);
  528: }
  529: 
  530: libnet_ptag_t
  531: libnet_build_ipv6_frag(u_int8_t nh, u_int8_t reserved, u_int16_t frag,
  532: u_int32_t id, u_int8_t *payload, u_int32_t payload_s, libnet_t *l,
  533: libnet_ptag_t ptag)
  534: {
  535:     u_int32_t n;
  536:     u_int16_t h;
  537:     libnet_pblock_t *p;
  538:     struct libnet_ipv6_frag_hdr ipv6_frag_hdr;
  539: 
  540:     if (l == NULL)
  541:     { 
  542:         return (-1);
  543:     }
  544: 
  545:     n = LIBNET_IPV6_FRAG_H + payload_s;
  546:     h = 0; 
  547: 
  548:     if (LIBNET_IPV6_FRAG_H + payload_s > IP_MAXPACKET)
  549:     {
  550:          snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  551:                  "%s(): IP packet too large\n", __func__);
  552:         return (-1);
  553:     }
  554: 
  555:     /*
  556:      *  Find the existing protocol block if a ptag is specified, or create
  557:      *  a new one.
  558:      */
  559:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV6_FRAG_H);
  560:     if (p == NULL)
  561:     {
  562:         return (-1);
  563:     }
  564: 
  565:     memset(&ipv6_frag_hdr, 0 , sizeof(ipv6_frag_hdr));
  566:     ipv6_frag_hdr.ip_nh       = nh;
  567:     ipv6_frag_hdr.ip_reserved = reserved;
  568:     ipv6_frag_hdr.ip_frag     = frag;
  569:     ipv6_frag_hdr.ip_id       = id;
  570: 
  571:     /*
  572:      *  Appened the protocol unit to the list.
  573:      */
  574:     n = libnet_pblock_append(l, p, (u_int8_t *)&ipv6_frag_hdr,
  575:         LIBNET_IPV6_FRAG_H);
  576:     if (n == -1)
  577:     {
  578:         goto bad;
  579:     }
  580: 
  581:     /*
  582:      *  Sanity check the payload arguments.
  583:      */
  584:     if ((payload && !payload_s) || (!payload && payload_s))
  585:     {
  586:         sprintf(l->err_buf, "%s(): payload inconsistency\n", __func__);
  587:         goto bad;
  588:     }
  589: 
  590:     /*
  591:      *  Append the payload to the list if it exists.
  592:      */
  593:     if (payload && payload_s)
  594:     {
  595:         n = libnet_pblock_append(l, p, payload, payload_s);
  596:         if (n == -1)
  597:         {
  598:             goto bad;
  599:         }
  600:     }
  601: 
  602:     /*
  603:      *  Update the protocol block's meta information and return the protocol
  604:      *  tag id of this pblock.  This tag will be used to locate the pblock
  605:      *  in order to modify the protocol header in subsequent calls.
  606:      */
  607:     return (ptag ? ptag : libnet_pblock_update(l, p, h, 
  608:             LIBNET_PBLOCK_IPV6_FRAG_H));
  609: bad:
  610:     libnet_pblock_delete(l, p);
  611:     return (-1);
  612: }
  613: 
  614: libnet_ptag_t
  615: libnet_build_ipv6_routing(u_int8_t nh, u_int8_t len, u_int8_t rtype, 
  616: u_int8_t segments, u_int8_t *payload, u_int32_t payload_s, libnet_t *l,
  617: libnet_ptag_t ptag)
  618: {
  619:     u_int32_t n;
  620:     u_int16_t h;
  621:     libnet_pblock_t *p;
  622:     struct libnet_ipv6_routing_hdr ipv6_routing_hdr;
  623: 
  624:     if (l == NULL)
  625:     { 
  626:         return (-1);
  627:     }
  628: 
  629:     /* Important: IPv6 routing header routes are specified using the payload
  630:      * interface!
  631:      */
  632:     n = LIBNET_IPV6_ROUTING_H + payload_s;
  633:     h = 0;
  634: 
  635:     if (LIBNET_IPV6_ROUTING_H + payload_s > IP_MAXPACKET)
  636:     {
  637:          snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  638:                  "%s(): IP packet too large\n", __func__);
  639:         return (-1);
  640:     }
  641: 
  642:     /*
  643:      *  Find the existing protocol block if a ptag is specified, or create
  644:      *  a new one.
  645:      */
  646:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV6_ROUTING_H);
  647:     if (p == NULL)
  648:     {
  649:         return (-1);
  650:     }
  651: 
  652:     memset(&ipv6_routing_hdr, 0 , sizeof(ipv6_routing_hdr));
  653:     ipv6_routing_hdr.ip_nh       = nh;
  654:     ipv6_routing_hdr.ip_len      = len;
  655:     ipv6_routing_hdr.ip_rtype    = rtype;
  656:     ipv6_routing_hdr.ip_segments = segments;
  657: 
  658:     /*
  659:      *  Appened the protocol unit to the list.
  660:      */
  661:     n = libnet_pblock_append(l, p, (u_int8_t *)&ipv6_routing_hdr,
  662:         LIBNET_IPV6_ROUTING_H);
  663:     if (n == -1)
  664:     {
  665:         goto bad;
  666:     }
  667: 
  668:     /*
  669:      *  Sanity check the payload arguments.
  670:      */
  671:     if ((payload && !payload_s) || (!payload && payload_s))
  672:     {
  673:         sprintf(l->err_buf, "%s(): payload inconsistency\n", __func__);
  674:         goto bad;
  675:     }
  676: 
  677:     /*
  678:      *  Append the payload to the list if it exists.
  679:      */
  680:     if (payload && payload_s)
  681:     {
  682:         n = libnet_pblock_append(l, p, payload, payload_s);
  683:         if (n == -1)
  684:         {
  685:             goto bad;
  686:         }
  687:     }
  688: 
  689:     /*
  690:      *  Update the protocol block's meta information and return the protocol
  691:      *  tag id of this pblock.  This tag will be used to locate the pblock
  692:      *  in order to modify the protocol header in subsequent calls.
  693:      */
  694:     return (ptag ? ptag : libnet_pblock_update(l, p, h, 
  695:             LIBNET_PBLOCK_IPV6_ROUTING_H));
  696: bad:
  697:     libnet_pblock_delete(l, p);
  698:     return (-1);
  699: }
  700: 
  701: libnet_ptag_t
  702: libnet_build_ipv6_destopts(u_int8_t nh, u_int8_t len, u_int8_t *payload,
  703: u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
  704: {
  705:     u_int32_t n;
  706:     u_int16_t h;
  707:     libnet_pblock_t *p;
  708:     struct libnet_ipv6_destopts_hdr ipv6_destopts_hdr;
  709: 
  710:     if (l == NULL)
  711:     { 
  712:         return (-1);
  713:     }
  714: 
  715:     /* Important: IPv6 dest opts information is specified using the payload
  716:      * interface!
  717:      */
  718:     n = LIBNET_IPV6_DESTOPTS_H + payload_s;
  719:     h = 0;
  720: 
  721:     if (LIBNET_IPV6_DESTOPTS_H + payload_s > IP_MAXPACKET)
  722:     {
  723:          snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  724:                  "%s(): IP packet too large\n", __func__);
  725:         return (-1);
  726:     }
  727: 
  728:     /*
  729:      *  Find the existing protocol block if a ptag is specified, or create
  730:      *  a new one.
  731:      */
  732:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV6_DESTOPTS_H);
  733:     if (p == NULL)
  734:     {
  735:         return (-1);
  736:     }
  737: 
  738:     memset(&ipv6_destopts_hdr, 0 , sizeof(ipv6_destopts_hdr));
  739:     ipv6_destopts_hdr.ip_nh  = nh;
  740:     ipv6_destopts_hdr.ip_len = len;
  741: 
  742:     /*
  743:      *  Appened the protocol unit to the list.
  744:      */
  745:     n = libnet_pblock_append(l, p, (u_int8_t *)&ipv6_destopts_hdr,
  746:         LIBNET_IPV6_DESTOPTS_H);
  747:     if (n == -1)
  748:     {
  749:         goto bad;
  750:     }
  751: 
  752:     /*
  753:      *  Sanity check the payload arguments.
  754:      */
  755:     if ((payload && !payload_s) || (!payload && payload_s))
  756:     {
  757:         sprintf(l->err_buf, "%s(): payload inconsistency\n", __func__);
  758:         goto bad;
  759:     }
  760: 
  761:     /*
  762:      *  Append the payload to the list if it exists.
  763:      */
  764:     if (payload && payload_s)
  765:     {
  766:         n = libnet_pblock_append(l, p, payload, payload_s);
  767:         if (n == -1)
  768:         {
  769:             goto bad;
  770:         }
  771:     }
  772: 
  773:     /*
  774:      *  Update the protocol block's meta information and return the protocol
  775:      *  tag id of this pblock.  This tag will be used to locate the pblock
  776:      *  in order to modify the protocol header in subsequent calls.
  777:      */
  778:     return (ptag ? ptag : libnet_pblock_update(l, p, h, 
  779:             LIBNET_PBLOCK_IPV6_DESTOPTS_H));
  780: bad:
  781:     libnet_pblock_delete(l, p);
  782:     return (-1);
  783: }
  784: 
  785: libnet_ptag_t
  786: libnet_build_ipv6_hbhopts(u_int8_t nh, u_int8_t len, u_int8_t *payload,
  787: u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
  788: {
  789:     u_int32_t n;
  790:     u_int16_t h;
  791:     libnet_pblock_t *p;
  792:     struct libnet_ipv6_hbhopts_hdr ipv6_hbhopts_hdr;
  793: 
  794:     if (l == NULL)
  795:     { 
  796:         return (-1);
  797:     }
  798: 
  799:     /* Important: IPv6 hop by hop opts information is specified using the
  800:      * payload interface!
  801:      */
  802:     n = LIBNET_IPV6_HBHOPTS_H + payload_s;
  803:     h = 0;
  804: 
  805:     if (LIBNET_IPV6_HBHOPTS_H + payload_s > IP_MAXPACKET)
  806:     {
  807:          snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  808:                  "%s(): IP packet too large\n", __func__);
  809:         return (-1);
  810:     }
  811: 
  812:     /*
  813:      *  Find the existing protocol block if a ptag is specified, or create
  814:      *  a new one.
  815:      */
  816:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV6_HBHOPTS_H);
  817:     if (p == NULL)
  818:     {
  819:         return (-1);
  820:     }
  821: 
  822:     memset(&ipv6_hbhopts_hdr, 0 , sizeof(ipv6_hbhopts_hdr));
  823:     ipv6_hbhopts_hdr.ip_nh  = nh;
  824:     ipv6_hbhopts_hdr.ip_len = len;
  825: 
  826:     /*
  827:      *  Appened the protocol unit to the list.
  828:      */
  829:     n = libnet_pblock_append(l, p, (u_int8_t *)&ipv6_hbhopts_hdr,
  830:         LIBNET_IPV6_HBHOPTS_H);
  831:     if (n == -1)
  832:     {
  833:         goto bad;
  834:     }
  835: 
  836:     /*
  837:      *  Sanity check the payload arguments.
  838:      */
  839:     if ((payload && !payload_s) || (!payload && payload_s))
  840:     {
  841:         sprintf(l->err_buf, "%s(): payload inconsistency\n", __func__);
  842:         goto bad;
  843:     }
  844: 
  845:     /*
  846:      *  Append the payload to the list if it exists.
  847:      */
  848:     if (payload && payload_s)
  849:     {
  850:         n = libnet_pblock_append(l, p, payload, payload_s);
  851:         if (n == -1)
  852:         {
  853:             goto bad;
  854:         }
  855:     }
  856: 
  857:     /*
  858:      *  Update the protocol block's meta information and return the protocol
  859:      *  tag id of this pblock.  This tag will be used to locate the pblock
  860:      *  in order to modify the protocol header in subsequent calls.
  861:      */
  862:     return (ptag ? ptag : libnet_pblock_update(l, p, h, 
  863:             LIBNET_PBLOCK_IPV6_HBHOPTS_H));
  864: bad:
  865:     libnet_pblock_delete(l, p);
  866:     return (-1);
  867: }
  868: 
  869: libnet_ptag_t
  870: libnet_autobuild_ipv6(u_int16_t len, u_int8_t nh, struct libnet_in6_addr dst,
  871:             libnet_t *l)
  872: {
  873: 
  874:     /* NYI */
  875:      snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  876:              "%s(): not yet implemented\n", __func__);
  877:     return (-1);
  878: }
  879: 
  880: /* EOF */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>