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

1.1       misho       1: /*
                      2:  *  $Id: libnet_build_ip.c,v 1.18 2004/03/16 18:40:59 mike 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>