Annotation of embedaddon/libnet/src/libnet_build_ip.c, revision 1.1.1.3

1.1       misho       1: /*
1.1.1.2   misho       2:  *  $Id: libnet_build_ip.c,v 1.19 2004/04/13 17:32:28 mike Exp $
1.1       misho       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: 
1.1.1.3 ! misho      33: #include "common.h"
1.1       misho      34: 
1.1.1.2   misho      35: /* TODO len - should be calculated if -1 */
1.1       misho      36: libnet_ptag_t
1.1.1.2   misho      37: libnet_build_ipv4(uint16_t ip_len, uint8_t tos, uint16_t id, uint16_t frag,
                     38: uint8_t ttl, uint8_t prot, uint16_t sum, uint32_t src, uint32_t dst,
                     39: const uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
1.1       misho      40: {
1.1.1.2   misho      41:     uint32_t n = LIBNET_IPV4_H; /* size of memory block */
1.1       misho      42:     libnet_pblock_t *p, *p_data, *p_temp;
                     43:     struct libnet_ipv4_hdr ip_hdr;
1.1.1.2   misho      44:     libnet_ptag_t ptag_data = 0; /* used if there is ipv4 payload */
                     45:     libnet_ptag_t ptag_hold;
1.1       misho      46: 
                     47:     if (l == NULL)
                     48:     { 
                     49:         return (-1);
                     50:     } 
                     51: 
                     52:     /*
                     53:      *  Find the existing protocol block if a ptag is specified, or create
                     54:      *  a new one.
                     55:      */
                     56:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV4_H);
                     57:     if (p == NULL)
                     58:     {
                     59:         return (-1);
                     60:     }
                     61: 
1.1.1.2   misho      62:     memset(&ip_hdr, 0, sizeof(ip_hdr));
                     63:     ip_hdr.ip_v          = 4;      /* version 4 */
                     64:     ip_hdr.ip_hl         = 5;      /* 20 byte header,  measured in 32-bit words */
1.1       misho      65: 
                     66:     /* check to see if there are IP options to include */
                     67:     if (p->prev)
                     68:     {
                     69:         if (p->prev->type == LIBNET_PBLOCK_IPO_H)
                     70:         {
1.1.1.2   misho      71:             /* IPO block's length must be multiple of 4, or it's incorrectly
                     72:              * padded, in which case there is no "correct" IP header length,
                     73:              * it will too short or too long, we choose too short.
1.1       misho      74:              */
1.1.1.2   misho      75:             ip_hdr.ip_hl += p->prev->b_len / 4;
1.1       misho      76:         }
                     77:     }
1.1.1.2   misho      78:     /* Note that p->h_len is not adjusted. This seems a bug, but it is because
                     79:      * it is not used!  libnet_do_checksum() is passed the h_len (as `len'),
                     80:      * but for IPPROTO_IP it is ignored in favor of the ip_hl.
                     81:      */
1.1       misho      82: 
                     83:     ip_hdr.ip_tos        = tos;                       /* IP tos */
1.1.1.2   misho      84:     ip_hdr.ip_len        = htons(ip_len);             /* total length */
1.1       misho      85:     ip_hdr.ip_id         = htons(id);                 /* IP ID */
                     86:     ip_hdr.ip_off        = htons(frag);               /* fragmentation flags */
                     87:     ip_hdr.ip_ttl        = ttl;                       /* time to live */
                     88:     ip_hdr.ip_p          = prot;                      /* transport protocol */
                     89:     ip_hdr.ip_sum        = (sum ? htons(sum) : 0);    /* checksum */
                     90:     ip_hdr.ip_src.s_addr = src;                       /* source ip */
                     91:     ip_hdr.ip_dst.s_addr = dst;                       /* destination ip */
                     92:     
1.1.1.2   misho      93:     n = libnet_pblock_append(l, p, (uint8_t *)&ip_hdr, LIBNET_IPV4_H);
1.1       misho      94:     if (n == -1)
                     95:     {
                     96:         goto bad;
                     97:     }
                     98: 
                     99:     /* save the original ptag value */
                    100:     ptag_hold = ptag;
                    101: 
                    102:     if (ptag == LIBNET_PTAG_INITIALIZER)
                    103:     {
                    104:         ptag = libnet_pblock_update(l, p, LIBNET_IPV4_H, LIBNET_PBLOCK_IPV4_H);
                    105:     }
                    106: 
                    107:     /* find and set the appropriate ptag, or else use the default of 0 */
1.1.1.2   misho     108:     /* When updating the ipv4 block, we need to find the data block, and
                    109:      * adjust our ip_offset if the new payload size is different from what
                    110:      * it used to be.
                    111:      */
1.1       misho     112:     if (ptag_hold && p->prev)
                    113:     {
                    114:         p_temp = p->prev;
                    115:         while (p_temp->prev &&
                    116:               (p_temp->type != LIBNET_PBLOCK_IPDATA) &&
                    117:               (p_temp->type != LIBNET_PBLOCK_IPV4_H))
                    118:         {
                    119:             p_temp = p_temp->prev;
                    120:         }
                    121: 
                    122:         if (p_temp->type == LIBNET_PBLOCK_IPDATA)
                    123:         {
                    124:             ptag_data = p_temp->ptag;
                    125:         }
                    126:         else
                    127:         {
                    128:              snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho     129:                      "%s(): IPv4 data pblock not found", __func__);
1.1       misho     130:         }
                    131:     }
                    132: 
1.1.1.2   misho     133:     if (payload_s && !payload)
1.1       misho     134:     {
                    135:          snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho     136:                  "%s(): payload inconsistency", __func__);
1.1       misho     137:         goto bad;
                    138:     }
                    139: 
1.1.1.2   misho     140:     if (payload_s)
1.1       misho     141:     {
                    142:         /* update ptag_data with the new payload */
1.1.1.2   misho     143:         /* on create:
                    144:          *    b_len = payload_s
                    145:          *    l->total_size += b_len
                    146:          *    h_len = 0
                    147:          * on update:
                    148:          *    b_len = payload_s
                    149:          *    h_len += <diff in size between new b_len and old b_len>
                    150:          *      increments if if b_len goes up, down if it goes down
                    151:          * in either case:
                    152:          *    copied = 0
                    153:         */
1.1       misho     154:         p_data = libnet_pblock_probe(l, ptag_data, payload_s,
                    155:                 LIBNET_PBLOCK_IPDATA);
                    156:         if (p_data == NULL)
                    157:         {
                    158:             return (-1);
                    159:         }
                    160: 
                    161:         if (libnet_pblock_append(l, p_data, payload, payload_s) == -1)
                    162:         {
                    163:             goto bad;
                    164:         }
                    165: 
                    166:         if (ptag_data == LIBNET_PTAG_INITIALIZER)
                    167:         {
1.1.1.2   misho     168:             /* IPDATA's h_len gets set to payload_s in both branches */
1.1       misho     169:             if (p_data->prev->type == LIBNET_PBLOCK_IPV4_H)
                    170:             {
                    171:                 libnet_pblock_update(l, p_data, payload_s,
                    172:                         LIBNET_PBLOCK_IPDATA);
                    173:                 /* swap pblocks to correct the protocol order */
                    174:                 libnet_pblock_swap(l, p->ptag, p_data->ptag); 
                    175:             }
                    176:             else
                    177:             {
1.1.1.2   misho     178:                 /* SR - I'm not sure how to reach this code. Maybe if the first
                    179:                  * time we added an ipv4 block, there was no payload, but when
                    180:                  * we modify the block the next time, we have payload?
                    181:                 */
                    182: 
1.1       misho     183:                 /* update without setting this as the final pblock */
                    184:                 p_data->type  =  LIBNET_PBLOCK_IPDATA;
                    185:                 p_data->ptag  =  ++(l->ptag_state);
1.1.1.2   misho     186:                 p_data->h_len =  payload_s; /* TODO dead code, data blocks don't have headers */
1.1       misho     187: 
                    188:                 /* data was added after the initial construction */
                    189:                 for (p_temp = l->protocol_blocks;
                    190:                         p_temp->type == LIBNET_PBLOCK_IPV4_H ||
                    191:                         p_temp->type == LIBNET_PBLOCK_IPO_H;
                    192:                         p_temp = p_temp->next)
                    193:                 {
                    194:                     libnet_pblock_insert_before(l, p_temp->ptag, p_data->ptag);
                    195:                     break;
                    196:                 }
                    197: 
                    198:                 /* the end block needs to have its next pointer cleared */
                    199:                 l->pblock_end->next = NULL;
                    200:             }
                    201: 
                    202:             if (p_data->prev && p_data->prev->type == LIBNET_PBLOCK_IPO_H)
                    203:             {
                    204:                 libnet_pblock_swap(l, p_data->prev->ptag, p_data->ptag); 
                    205:             }
                    206:         }
                    207:     }
                    208:     else
                    209:     {
                    210:         p_data = libnet_pblock_find(l, ptag_data);
                    211:         if (p_data) 
                    212:         {
                    213:             libnet_pblock_delete(l, p_data);
                    214:         }
                    215:         else
                    216:         {
                    217:             /* 
                    218:              * XXX - When this completes successfully, libnet errbuf contains 
                    219:              * an error message so to come correct, we'll clear it.
                    220:              */ 
                    221:             memset(l->err_buf, 0, sizeof (l->err_buf));
                    222:         }
                    223:     }
                    224:     if (sum == 0)
                    225:     {
                    226:         /*
                    227:          *  If checksum is zero, by default libnet will compute a checksum
                    228:          *  for the user.  The programmer can override this by calling
                    229:          *  libnet_toggle_checksum(l, ptag, 1);
                    230:          */
                    231:         libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
                    232:     }
                    233: 
                    234:     return (ptag);
                    235: bad:
                    236:     libnet_pblock_delete(l, p);
                    237:     return (-1);
                    238: }
                    239: 
                    240: libnet_ptag_t
1.1.1.2   misho     241: libnet_autobuild_ipv4(uint16_t len, uint8_t prot, uint32_t dst, libnet_t *l)
1.1       misho     242: {
1.1.1.2   misho     243:     uint32_t n, i, j, src;
                    244:     uint16_t h;
1.1       misho     245:     libnet_pblock_t *p;
                    246:     libnet_ptag_t ptag;
                    247:     struct libnet_ipv4_hdr ip_hdr;
                    248: 
                    249:     if (l == NULL)
                    250:     { 
                    251:         return (-1);
                    252:     } 
                    253: 
                    254:     n = LIBNET_IPV4_H;                                /* size of memory block */
                    255:     h = len;                                          /* header length */
                    256:     ptag = LIBNET_PTAG_INITIALIZER;
                    257:     src = libnet_get_ipaddr4(l);
                    258:     if (src == -1)
                    259:     {
                    260:         /* err msg set in libnet_get_ipaddr() */ 
                    261:         return (-1);
                    262:     }
                    263: 
                    264:     /*
                    265:      *  Create a new pblock.
                    266:      */
                    267:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV4_H);
                    268:     if (p == NULL)
                    269:     {
                    270:         return (-1);
                    271:     }
                    272:        
                    273:     memset(&ip_hdr, 0, sizeof(ip_hdr));
                    274:     ip_hdr.ip_v          = 4;                         /* version 4 */
                    275:     ip_hdr.ip_hl         = 5;                         /* 20 byte header */
                    276: 
                    277:     /* check to see if there are IP options to include */
                    278:     if (p->prev)
                    279:     {
                    280:         if (p->prev->type == LIBNET_PBLOCK_IPO_H)
                    281:         {
                    282:             /*
                    283:              *  Count up number of 32-bit words in options list, padding if
                    284:              *  neccessary.
                    285:              */
                    286:             for (i = 0, j = 0; i < p->prev->b_len; i++)
                    287:             {
                    288:                 (i % 4) ? j : j++;
                    289:             }
                    290:             ip_hdr.ip_hl += j;
                    291:         }
                    292:     }
                    293: 
                    294:     ip_hdr.ip_tos        = 0;                         /* IP tos */
                    295:     ip_hdr.ip_len        = htons(h);                  /* total length */
                    296:     ip_hdr.ip_id         = htons((l->ptag_state) & 0x0000ffff); /* IP ID */
                    297:     ip_hdr.ip_off        = 0;                         /* fragmentation flags */
                    298:     ip_hdr.ip_ttl        = 64;                        /* time to live */
                    299:     ip_hdr.ip_p          = prot;                      /* transport protocol */
                    300:     ip_hdr.ip_sum        = 0;                         /* checksum */
                    301:     ip_hdr.ip_src.s_addr = src;                       /* source ip */
                    302:     ip_hdr.ip_dst.s_addr = dst;                       /* destination ip */
                    303: 
1.1.1.2   misho     304:     n = libnet_pblock_append(l, p, (uint8_t *)&ip_hdr, LIBNET_IPV4_H);
1.1       misho     305:     if (n == -1)
                    306:     {
                    307:         goto bad;
                    308:     }
                    309: 
                    310:     libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
                    311:     ptag = libnet_pblock_update(l, p, LIBNET_IPV4_H, LIBNET_PBLOCK_IPV4_H);
                    312: 
                    313:     return (ptag);
                    314: 
                    315: bad:
                    316:     libnet_pblock_delete(l, p);
                    317:     return (-1);
                    318: }
                    319: 
                    320: libnet_ptag_t
1.1.1.2   misho     321: libnet_build_ipv4_options(const uint8_t *options, uint32_t options_s, libnet_t *l, 
1.1       misho     322: libnet_ptag_t ptag)
                    323: {
1.1.1.2   misho     324:     int options_size_increase = 0; /* increase will be negative if it's a decrease */
                    325:     uint32_t n, adj_size;
1.1       misho     326:     libnet_pblock_t *p, *p_temp;
                    327:     struct libnet_ipv4_hdr *ip_hdr;
                    328: 
                    329:     if (l == NULL)
                    330:     { 
                    331:         return (-1);
                    332:     }
                    333: 
                    334:     /* check options list size */
                    335:     if (options_s > LIBNET_MAXOPTION_SIZE)
                    336:     {
                    337:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho     338:             "%s(): options list is too large %d", __func__, options_s);
1.1       misho     339:         return (-1);
                    340:     }
                    341: 
                    342:     adj_size = options_s;
                    343:     if (adj_size % 4)
                    344:     {
                    345:         /* size of memory block with padding */
                    346:         adj_size += 4 - (options_s % 4);
                    347:     }
                    348: 
                    349:     /* if this pblock already exists, determine if there is a size diff */
                    350:     if (ptag)
                    351:     {
                    352:         p_temp = libnet_pblock_find(l, ptag);
                    353:         if (p_temp)
                    354:         {
1.1.1.2   misho     355:             options_size_increase = adj_size - p_temp->b_len;
1.1       misho     356:         }
                    357:     }
1.1.1.2   misho     358:     /* If we aren't modifying an options block, we are pushing a new one, and
                    359:      * since it must be pushed before the IPv4 block is pushed, there is no
                    360:      * need to remember that options size has "increased".
                    361:      */
                    362:     
1.1       misho     363:     /*
                    364:      *  Find the existing protocol block if a ptag is specified, or create
                    365:      *  a new one.
                    366:      */
                    367:     p = libnet_pblock_probe(l, ptag, adj_size, LIBNET_PBLOCK_IPO_H);
                    368:     if (p == NULL)
                    369:     {
                    370:         return (-1);
                    371:     }
                    372: 
                    373:     /* append options */
                    374:     n = libnet_pblock_append(l, p, options, options_s);
                    375:     if (n == -1)
                    376:     {
                    377:         goto bad;
                    378:     }
                    379: 
                    380:     /* append padding */
1.1.1.2   misho     381:     n = libnet_pblock_append(l, p, (uint8_t*)"\0\0\0", adj_size - options_s);
1.1       misho     382:     if (n == -1)
                    383:     {
                    384:         goto bad;
                    385:     }
                    386: 
                    387:     if (ptag && p->next)
                    388:     {
                    389:         p_temp = p->next;
                    390: 
1.1.1.2   misho     391:         /* fix the IP header sizes */
1.1       misho     392:         if (p_temp->type == LIBNET_PBLOCK_IPV4_H)
                    393:         {
                    394:             ip_hdr = (struct libnet_ipv4_hdr *) p_temp->buf;
1.1.1.2   misho     395:             ip_hdr->ip_hl = 5 + adj_size / 4; /* 4 bits wide, so no byte order concerns */
                    396:             ip_hdr->ip_len = htons(ntohs(ip_hdr->ip_len) + options_size_increase);
1.1       misho     397: 
1.1.1.2   misho     398:             p_temp->h_len = ip_hdr->ip_hl * 4; /* Dead code, h_len isn't used for IPv4 block */
1.1       misho     399:         }
                    400:     }
                    401: 
                    402:     return (ptag ? ptag : libnet_pblock_update(l, p, adj_size,
                    403:             LIBNET_PBLOCK_IPO_H));
                    404: bad:
                    405:     libnet_pblock_delete(l, p);
                    406:     return (-1);
                    407: }
                    408: 
                    409: libnet_ptag_t
1.1.1.2   misho     410: libnet_build_ipv6(uint8_t tc, uint32_t fl, uint16_t len, uint8_t nh,
                    411: uint8_t hl, struct libnet_in6_addr src, struct libnet_in6_addr dst, 
                    412: const uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
1.1       misho     413: {   
1.1.1.2   misho     414:     uint32_t n;
1.1       misho     415:     libnet_pblock_t *p;
                    416:     struct libnet_ipv6_hdr ip_hdr;
                    417: 
                    418:     if (l == NULL)
                    419:     {
                    420:         return (-1);
                    421:     }
                    422: 
                    423:     n = LIBNET_IPV6_H + payload_s;          /* size of memory block */
                    424:        
                    425:     if (LIBNET_IPV6_H + payload_s > IP_MAXPACKET)
                    426:     {  
                    427:          snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho     428:                  "%s(): IP packet too large", __func__);
1.1       misho     429:         return (-1);
                    430:     }  
                    431:        
                    432:     /*
                    433:      *  Find the existing protocol block if a ptag is specified, or create
                    434:      *  a new one.
                    435:      */
                    436:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV6_H);
                    437:     if (p == NULL)
                    438:     {   
                    439:         return (-1);
                    440:     }  
                    441:     
                    442:     memset(&ip_hdr, 0, sizeof(ip_hdr));
1.1.1.2   misho     443:     ip_hdr.ip_flags[0] = (0x06 << 4) | ((tc & 0xF0) >> 4);
1.1       misho     444:     ip_hdr.ip_flags[1] = ((tc & 0x0F) << 4) | ((fl & 0xF0000) >> 16);
1.1.1.3 ! misho     445:     ip_hdr.ip_flags[2] = (fl & 0x0FF00) >> 8;
1.1       misho     446:     ip_hdr.ip_flags[3] = fl & 0x000FF;
                    447:     ip_hdr.ip_len      = htons(len);
                    448:     ip_hdr.ip_nh       = nh;
                    449:     ip_hdr.ip_hl       = hl;
                    450:     ip_hdr.ip_src      = src;
                    451:     ip_hdr.ip_dst      = dst;
                    452:      
1.1.1.2   misho     453:     n = libnet_pblock_append(l, p, (uint8_t *)&ip_hdr, LIBNET_IPV6_H);
1.1       misho     454:     if (n == -1)
                    455:     {
                    456:         goto bad;
                    457:     }
                    458: 
1.1.1.2   misho     459:     /* boilerplate payload sanity check / append macro */
                    460:     LIBNET_DO_PAYLOAD(l, p);
1.1       misho     461: 
                    462:     /* no checksum for IPv6 */
1.1.1.2   misho     463:     ptag = ptag ? ptag : libnet_pblock_update(l, p, LIBNET_IPV6_H,
                    464:             LIBNET_PBLOCK_IPV6_H);
                    465: 
                    466:     return ptag;
                    467: 
1.1       misho     468: bad:
                    469:     libnet_pblock_delete(l, p);
                    470:     return (-1);
                    471: }
                    472: 
                    473: libnet_ptag_t
1.1.1.2   misho     474: libnet_build_ipv6_frag(uint8_t nh, uint8_t reserved, uint16_t frag,
                    475: uint32_t id, const uint8_t *payload, uint32_t payload_s, libnet_t *l,
1.1       misho     476: libnet_ptag_t ptag)
                    477: {
1.1.1.2   misho     478:     uint32_t n;
                    479:     uint16_t h;
1.1       misho     480:     libnet_pblock_t *p;
                    481:     struct libnet_ipv6_frag_hdr ipv6_frag_hdr;
                    482: 
                    483:     if (l == NULL)
                    484:     { 
                    485:         return (-1);
                    486:     }
                    487: 
                    488:     n = LIBNET_IPV6_FRAG_H + payload_s;
                    489:     h = 0; 
                    490: 
                    491:     if (LIBNET_IPV6_FRAG_H + payload_s > IP_MAXPACKET)
                    492:     {
                    493:          snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho     494:                  "%s(): IP packet too large", __func__);
1.1       misho     495:         return (-1);
                    496:     }
                    497: 
                    498:     /*
                    499:      *  Find the existing protocol block if a ptag is specified, or create
                    500:      *  a new one.
                    501:      */
                    502:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV6_FRAG_H);
                    503:     if (p == NULL)
                    504:     {
                    505:         return (-1);
                    506:     }
                    507: 
                    508:     memset(&ipv6_frag_hdr, 0 , sizeof(ipv6_frag_hdr));
                    509:     ipv6_frag_hdr.ip_nh       = nh;
                    510:     ipv6_frag_hdr.ip_reserved = reserved;
                    511:     ipv6_frag_hdr.ip_frag     = frag;
                    512:     ipv6_frag_hdr.ip_id       = id;
                    513: 
                    514:     /*
                    515:      *  Appened the protocol unit to the list.
                    516:      */
1.1.1.2   misho     517:     n = libnet_pblock_append(l, p, (uint8_t *)&ipv6_frag_hdr,
1.1       misho     518:         LIBNET_IPV6_FRAG_H);
                    519:     if (n == -1)
                    520:     {
                    521:         goto bad;
                    522:     }
                    523: 
1.1.1.2   misho     524:     /* boilerplate payload sanity check / append macro */
                    525:     LIBNET_DO_PAYLOAD(l, p);
1.1       misho     526: 
                    527:     /*
                    528:      *  Update the protocol block's meta information and return the protocol
                    529:      *  tag id of this pblock.  This tag will be used to locate the pblock
                    530:      *  in order to modify the protocol header in subsequent calls.
                    531:      */
                    532:     return (ptag ? ptag : libnet_pblock_update(l, p, h, 
                    533:             LIBNET_PBLOCK_IPV6_FRAG_H));
                    534: bad:
                    535:     libnet_pblock_delete(l, p);
                    536:     return (-1);
                    537: }
                    538: 
                    539: libnet_ptag_t
1.1.1.2   misho     540: libnet_build_ipv6_routing(uint8_t nh, uint8_t len, uint8_t rtype, 
                    541: uint8_t segments, const uint8_t *payload, uint32_t payload_s, libnet_t *l,
1.1       misho     542: libnet_ptag_t ptag)
                    543: {
1.1.1.2   misho     544:     uint32_t n;
                    545:     uint16_t h;
1.1       misho     546:     libnet_pblock_t *p;
                    547:     struct libnet_ipv6_routing_hdr ipv6_routing_hdr;
                    548: 
                    549:     if (l == NULL)
                    550:     { 
                    551:         return (-1);
                    552:     }
                    553: 
                    554:     /* Important: IPv6 routing header routes are specified using the payload
                    555:      * interface!
                    556:      */
                    557:     n = LIBNET_IPV6_ROUTING_H + payload_s;
                    558:     h = 0;
                    559: 
                    560:     if (LIBNET_IPV6_ROUTING_H + payload_s > IP_MAXPACKET)
                    561:     {
                    562:          snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho     563:                  "%s(): IP packet too large", __func__);
1.1       misho     564:         return (-1);
                    565:     }
                    566: 
                    567:     /*
                    568:      *  Find the existing protocol block if a ptag is specified, or create
                    569:      *  a new one.
                    570:      */
                    571:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV6_ROUTING_H);
                    572:     if (p == NULL)
                    573:     {
                    574:         return (-1);
                    575:     }
                    576: 
                    577:     memset(&ipv6_routing_hdr, 0 , sizeof(ipv6_routing_hdr));
                    578:     ipv6_routing_hdr.ip_nh       = nh;
                    579:     ipv6_routing_hdr.ip_len      = len;
                    580:     ipv6_routing_hdr.ip_rtype    = rtype;
                    581:     ipv6_routing_hdr.ip_segments = segments;
                    582: 
                    583:     /*
                    584:      *  Appened the protocol unit to the list.
                    585:      */
1.1.1.2   misho     586:     n = libnet_pblock_append(l, p, (uint8_t *)&ipv6_routing_hdr,
1.1       misho     587:         LIBNET_IPV6_ROUTING_H);
                    588:     if (n == -1)
                    589:     {
                    590:         goto bad;
                    591:     }
                    592: 
1.1.1.2   misho     593:     /* boilerplate payload sanity check / append macro */
                    594:     LIBNET_DO_PAYLOAD(l, p);
1.1       misho     595: 
                    596:     /*
                    597:      *  Update the protocol block's meta information and return the protocol
                    598:      *  tag id of this pblock.  This tag will be used to locate the pblock
                    599:      *  in order to modify the protocol header in subsequent calls.
                    600:      */
                    601:     return (ptag ? ptag : libnet_pblock_update(l, p, h, 
                    602:             LIBNET_PBLOCK_IPV6_ROUTING_H));
                    603: bad:
                    604:     libnet_pblock_delete(l, p);
                    605:     return (-1);
                    606: }
                    607: 
                    608: libnet_ptag_t
1.1.1.2   misho     609: libnet_build_ipv6_destopts(uint8_t nh, uint8_t len, const uint8_t *payload,
                    610: uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
1.1       misho     611: {
1.1.1.2   misho     612:     uint32_t n;
                    613:     uint16_t h;
1.1       misho     614:     libnet_pblock_t *p;
                    615:     struct libnet_ipv6_destopts_hdr ipv6_destopts_hdr;
                    616: 
                    617:     if (l == NULL)
                    618:     { 
                    619:         return (-1);
                    620:     }
                    621: 
                    622:     /* Important: IPv6 dest opts information is specified using the payload
                    623:      * interface!
                    624:      */
                    625:     n = LIBNET_IPV6_DESTOPTS_H + payload_s;
                    626:     h = 0;
                    627: 
                    628:     if (LIBNET_IPV6_DESTOPTS_H + payload_s > IP_MAXPACKET)
                    629:     {
                    630:          snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho     631:                  "%s(): IP packet too large", __func__);
1.1       misho     632:         return (-1);
                    633:     }
                    634: 
                    635:     /*
                    636:      *  Find the existing protocol block if a ptag is specified, or create
                    637:      *  a new one.
                    638:      */
                    639:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV6_DESTOPTS_H);
                    640:     if (p == NULL)
                    641:     {
                    642:         return (-1);
                    643:     }
                    644: 
                    645:     memset(&ipv6_destopts_hdr, 0 , sizeof(ipv6_destopts_hdr));
                    646:     ipv6_destopts_hdr.ip_nh  = nh;
                    647:     ipv6_destopts_hdr.ip_len = len;
                    648: 
                    649:     /*
                    650:      *  Appened the protocol unit to the list.
                    651:      */
1.1.1.2   misho     652:     n = libnet_pblock_append(l, p, (uint8_t *)&ipv6_destopts_hdr,
1.1       misho     653:         LIBNET_IPV6_DESTOPTS_H);
                    654:     if (n == -1)
                    655:     {
                    656:         goto bad;
                    657:     }
                    658: 
1.1.1.2   misho     659:     /* boilerplate payload sanity check / append macro */
                    660:     LIBNET_DO_PAYLOAD(l, p);
1.1       misho     661: 
                    662:     /*
                    663:      *  Update the protocol block's meta information and return the protocol
                    664:      *  tag id of this pblock.  This tag will be used to locate the pblock
                    665:      *  in order to modify the protocol header in subsequent calls.
                    666:      */
                    667:     return (ptag ? ptag : libnet_pblock_update(l, p, h, 
                    668:             LIBNET_PBLOCK_IPV6_DESTOPTS_H));
                    669: bad:
                    670:     libnet_pblock_delete(l, p);
                    671:     return (-1);
                    672: }
                    673: 
                    674: libnet_ptag_t
1.1.1.2   misho     675: libnet_build_ipv6_hbhopts(uint8_t nh, uint8_t len, const uint8_t *payload,
                    676: uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
1.1       misho     677: {
1.1.1.2   misho     678:     uint32_t n;
                    679:     uint16_t h;
1.1       misho     680:     libnet_pblock_t *p;
                    681:     struct libnet_ipv6_hbhopts_hdr ipv6_hbhopts_hdr;
                    682: 
                    683:     if (l == NULL)
                    684:     { 
                    685:         return (-1);
                    686:     }
                    687: 
                    688:     /* Important: IPv6 hop by hop opts information is specified using the
                    689:      * payload interface!
                    690:      */
                    691:     n = LIBNET_IPV6_HBHOPTS_H + payload_s;
                    692:     h = 0;
                    693: 
                    694:     if (LIBNET_IPV6_HBHOPTS_H + payload_s > IP_MAXPACKET)
                    695:     {
                    696:          snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho     697:                  "%s(): IP packet too large", __func__);
1.1       misho     698:         return (-1);
                    699:     }
                    700: 
                    701:     /*
                    702:      *  Find the existing protocol block if a ptag is specified, or create
                    703:      *  a new one.
                    704:      */
                    705:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV6_HBHOPTS_H);
                    706:     if (p == NULL)
                    707:     {
                    708:         return (-1);
                    709:     }
                    710: 
                    711:     memset(&ipv6_hbhopts_hdr, 0 , sizeof(ipv6_hbhopts_hdr));
                    712:     ipv6_hbhopts_hdr.ip_nh  = nh;
                    713:     ipv6_hbhopts_hdr.ip_len = len;
                    714: 
                    715:     /*
                    716:      *  Appened the protocol unit to the list.
                    717:      */
1.1.1.2   misho     718:     n = libnet_pblock_append(l, p, (uint8_t *)&ipv6_hbhopts_hdr,
1.1       misho     719:         LIBNET_IPV6_HBHOPTS_H);
                    720:     if (n == -1)
                    721:     {
                    722:         goto bad;
                    723:     }
                    724: 
1.1.1.2   misho     725:     /* boilerplate payload sanity check / append macro */
                    726:     LIBNET_DO_PAYLOAD(l, p);
1.1       misho     727: 
                    728:     /*
                    729:      *  Update the protocol block's meta information and return the protocol
                    730:      *  tag id of this pblock.  This tag will be used to locate the pblock
                    731:      *  in order to modify the protocol header in subsequent calls.
                    732:      */
                    733:     return (ptag ? ptag : libnet_pblock_update(l, p, h, 
                    734:             LIBNET_PBLOCK_IPV6_HBHOPTS_H));
                    735: bad:
                    736:     libnet_pblock_delete(l, p);
                    737:     return (-1);
                    738: }
                    739: 
                    740: libnet_ptag_t
1.1.1.2   misho     741: libnet_autobuild_ipv6(uint16_t len, uint8_t nh, struct libnet_in6_addr dst,
                    742:             libnet_t *l, libnet_ptag_t ptag)
1.1       misho     743: {
1.1.1.2   misho     744:     struct libnet_in6_addr src;
1.1       misho     745: 
1.1.1.2   misho     746:     src = libnet_get_ipaddr6(l);
                    747: 
                    748:     if (libnet_in6_is_error(src))
                    749:     {
                    750:         return (-1);
                    751:     }
                    752: 
                    753:     return libnet_build_ipv6(0, 0, len, nh, 64, src, dst, NULL, 0, l, ptag);
1.1       misho     754: }
                    755: 
1.1.1.3 ! misho     756: /**
        !           757:  * Local Variables:
        !           758:  *  indent-tabs-mode: nil
        !           759:  *  c-file-style: "stroustrup"
        !           760:  * End:
        !           761:  */

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