Annotation of embedaddon/libnet/src/libnet_build_ip.c, revision 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>