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

1.1       misho       1: /*
1.1.1.2   misho       2:  *  $Id: libnet_build_icmp.c,v 1.17 2004/04/13 17:32:28 mike Exp $
1.1       misho       3:  *
                      4:  *  libnet
                      5:  *  libnet_build_icmp.c - ICMP packet assemblers
                      6:  *
                      7:  *  Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
                      8:  *  All rights reserved.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     29:  * SUCH DAMAGE.
                     30:  *
                     31:  */
                     32: 
1.1.1.3 ! misho      33: #include "common.h"
1.1       misho      34: 
1.1.1.2   misho      35: #include <assert.h>
                     36: 
1.1       misho      37: /* some common cruft for completing ICMP error packets */
                     38: #define LIBNET_BUILD_ICMP_ERR_FINISH(len)                                    \
                     39: do                                                                           \
                     40: {                                                                            \
1.1.1.2   misho      41:     n = libnet_pblock_append(l, p, (uint8_t *)&icmp_hdr, len);              \
1.1       misho      42:     if (n == -1)                                                             \
                     43:     {                                                                        \
                     44:         goto bad;                                                            \
                     45:     }                                                                        \
                     46:                                                                              \
1.1.1.2   misho      47:     if (payload_s && !payload)                                               \
1.1       misho      48:     {                                                                        \
                     49:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,                             \
1.1.1.3 ! misho      50:                 "%s(): payload inconsistency", __func__);                  \
1.1       misho      51:         goto bad;                                                            \
                     52:     }                                                                        \
                     53:                                                                              \
1.1.1.2   misho      54:     if (payload_s)                                                           \
1.1       misho      55:     {                                                                        \
                     56:         n = libnet_pblock_append(l, p, payload, payload_s);                  \
                     57:         if (n == -1)                                                         \
                     58:         {                                                                    \
                     59:             goto bad;                                                        \
                     60:         }                                                                    \
                     61:     }                                                                        \
                     62:                                                                              \
                     63:     if (sum == 0)                                                            \
                     64:     {                                                                        \
                     65:         libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);                \
                     66:     }                                                                        \
                     67: } while (0)
                     68: 
                     69: libnet_ptag_t
1.1.1.2   misho      70: libnet_build_icmpv4_echo(uint8_t type, uint8_t code, uint16_t sum,
                     71: uint16_t id, uint16_t seq, const uint8_t *payload, uint32_t payload_s,
1.1       misho      72: libnet_t *l, libnet_ptag_t ptag) 
                     73: {
1.1.1.2   misho      74:     uint32_t n, h;
1.1       misho      75:     libnet_pblock_t *p;
                     76:     struct libnet_icmpv4_hdr icmp_hdr;
                     77: 
                     78:     if (l == NULL)
                     79:     { 
                     80:         return (-1);
                     81:     } 
                     82: 
                     83:     n = LIBNET_ICMPV4_ECHO_H + payload_s;        /* size of memory block */
                     84:     h = LIBNET_ICMPV4_ECHO_H + payload_s;        /* hl for checksum */
                     85: 
                     86:     /*
                     87:      *  Find the existing protocol block if a ptag is specified, or create
                     88:      *  a new one.
                     89:      */
                     90:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV4_ECHO_H);
                     91:     if (p == NULL)
                     92:     {
                     93:         return (-1);
                     94:     }
                     95: 
                     96:     memset(&icmp_hdr, 0, sizeof(icmp_hdr));
                     97:     icmp_hdr.icmp_type = type;          /* packet type */
                     98:     icmp_hdr.icmp_code = code;          /* packet code */
                     99:     icmp_hdr.icmp_sum  = (sum ? htons(sum) : 0);  /* checksum */
                    100:     icmp_hdr.icmp_id   = htons(id);            /* packet id */
                    101:     icmp_hdr.icmp_seq  = htons(seq);           /* packet seq */
                    102: 
1.1.1.2   misho     103:     n = libnet_pblock_append(l, p, (uint8_t *)&icmp_hdr, LIBNET_ICMPV4_ECHO_H);
1.1       misho     104:     if (n == -1)
                    105:     {
                    106:         goto bad;
                    107:     }
                    108: 
1.1.1.2   misho     109:     /* boilerplate payload sanity check / append macro */
                    110:     LIBNET_DO_PAYLOAD(l, p);
1.1       misho     111:  
                    112:     if (sum == 0)
                    113:     {
                    114:         /*
                    115:          *  If checksum is zero, by default libnet will compute a checksum
                    116:          *  for the user.  The programmer can override this by calling
                    117:          *  libnet_toggle_checksum(l, ptag, 1);
                    118:          */
                    119:         libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
                    120:     }
                    121:     return (ptag ? ptag : libnet_pblock_update(l, p, h, 
                    122:             LIBNET_PBLOCK_ICMPV4_ECHO_H));
                    123: bad:
                    124:     libnet_pblock_delete(l, p);   
                    125:     return (-1);
                    126: }
                    127: 
                    128: libnet_ptag_t
1.1.1.2   misho     129: libnet_build_icmpv4_mask(uint8_t type, uint8_t code, uint16_t sum,
                    130: uint16_t id, uint16_t seq, uint32_t mask, const uint8_t *payload,
                    131: uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
1.1       misho     132: {
1.1.1.2   misho     133:     uint32_t n, h;
1.1       misho     134:     libnet_pblock_t *p;
                    135:     struct libnet_icmpv4_hdr icmp_hdr;
                    136: 
                    137:     if (l == NULL)
                    138:     { 
                    139:         return (-1);
                    140:     } 
                    141: 
                    142:     n = LIBNET_ICMPV4_MASK_H + payload_s;        /* size of memory block */
                    143:     h = LIBNET_ICMPV4_MASK_H + payload_s;        /* hl for checksum */
                    144: 
                    145:     /*
                    146:      *  Find the existing protocol block if a ptag is specified, or create
                    147:      *  a new one.
                    148:      */
                    149:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV4_MASK_H);
                    150:     if (p == NULL)
                    151:     {
                    152:         return (-1);
                    153:     }
                    154: 
                    155:     memset(&icmp_hdr, 0, sizeof(icmp_hdr));
                    156:     icmp_hdr.icmp_type = type;          /* packet type */
                    157:     icmp_hdr.icmp_code = code;          /* packet code */
                    158:     icmp_hdr.icmp_sum  = (sum ? htons(sum) : 0);  /* checksum */
                    159:     icmp_hdr.icmp_id   = htons(id);     /* packet id */
                    160:     icmp_hdr.icmp_seq  = htons(seq);    /* packet seq */
                    161:     icmp_hdr.icmp_mask = htonl(mask);   /* address mask */
                    162: 
1.1.1.2   misho     163:     n = libnet_pblock_append(l, p, (uint8_t *)&icmp_hdr, LIBNET_ICMPV4_MASK_H);
1.1       misho     164:     if (n == -1)
                    165:     {
                    166:         goto bad;
                    167:     }
                    168: 
1.1.1.2   misho     169:     /* boilerplate payload sanity check / append macro */
                    170:     LIBNET_DO_PAYLOAD(l, p);
1.1       misho     171:  
                    172:     if (sum == 0)
                    173:     {
                    174:         /*
                    175:          *  If checksum is zero, by default libnet will compute a checksum
                    176:          *  for the user.  The programmer can override this by calling
                    177:          *  libnet_toggle_checksum(l, ptag, 1);
                    178:          */
                    179:         libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
                    180:     }
                    181:     return (ptag ? ptag : libnet_pblock_update(l, p, h, 
                    182:             LIBNET_PBLOCK_ICMPV4_MASK_H));
                    183: bad:
                    184:     libnet_pblock_delete(l, p);
                    185:     return (-1);
                    186: }
                    187: 
                    188: libnet_ptag_t
1.1.1.2   misho     189: libnet_build_icmpv4_timestamp(uint8_t type, uint8_t code, uint16_t sum,
                    190: uint16_t id, uint16_t seq, uint32_t otime, uint32_t rtime, uint32_t ttime,
                    191: const uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
1.1       misho     192: {
1.1.1.2   misho     193:     uint32_t n, h;
1.1       misho     194:     libnet_pblock_t *p;
                    195:     struct libnet_icmpv4_hdr icmp_hdr;
                    196: 
                    197:     if (l == NULL)
                    198:     { 
                    199:         return (-1);
                    200:     } 
                    201: 
                    202:     n = LIBNET_ICMPV4_TS_H + payload_s;        /* size of memory block */
                    203:     h = LIBNET_ICMPV4_TS_H + payload_s;        /* hl for checksum */
                    204: 
                    205:     /*
                    206:      *  Find the existing protocol block if a ptag is specified, or create
                    207:      *  a new one.
                    208:      */
                    209:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV4_TS_H);
                    210:     if (p == NULL)
                    211:     {
                    212:         return (-1);
                    213:     }
                    214: 
                    215:     memset(&icmp_hdr, 0, sizeof(icmp_hdr));
                    216:     icmp_hdr.icmp_type  = type;             /* packet type */
                    217:     icmp_hdr.icmp_code  = code;             /* packet code */
                    218:     icmp_hdr.icmp_sum   = (sum ? htons(sum) : 0); /* checksum */
                    219:     icmp_hdr.icmp_id    = htons(id);        /* packet id */
                    220:     icmp_hdr.icmp_seq   = htons(seq);       /* packet seq */
                    221:     icmp_hdr.icmp_otime = htonl(otime);     /* original timestamp */
                    222:     icmp_hdr.icmp_rtime = htonl(rtime);     /* receive timestamp */
                    223:     icmp_hdr.icmp_ttime = htonl(ttime);     /* transmit timestamp */
                    224: 
1.1.1.2   misho     225:     n = libnet_pblock_append(l, p, (uint8_t *)&icmp_hdr, LIBNET_ICMPV4_TS_H);
1.1       misho     226:     if (n == -1)
                    227:     {
                    228:         goto bad;
                    229:     }
                    230: 
1.1.1.2   misho     231:     /* boilerplate payload sanity check / append macro */
                    232:     LIBNET_DO_PAYLOAD(l, p);
1.1       misho     233:  
                    234:     if (sum == 0)
                    235:     {
                    236:         /*
                    237:          *  If checksum is zero, by default libnet will compute a checksum
                    238:          *  for the user.  The programmer can override this by calling
                    239:          *  libnet_toggle_checksum(l, ptag, 1);
                    240:          */
                    241:         libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
                    242:     }
                    243:     return (ptag ? ptag : libnet_pblock_update(l, p, h, 
                    244:             LIBNET_PBLOCK_ICMPV4_TS_H));
                    245: bad:
                    246:     libnet_pblock_delete(l, p);
                    247:     return (-1);
                    248: }
                    249: 
                    250: libnet_ptag_t
1.1.1.2   misho     251: libnet_build_icmpv4_unreach(uint8_t type, uint8_t code, uint16_t sum,
                    252: const uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
1.1       misho     253: {
1.1.1.2   misho     254:     uint32_t n, h;
1.1       misho     255:     libnet_pblock_t *p;
                    256:     struct libnet_icmpv4_hdr icmp_hdr;
                    257: 
                    258:     if (l == NULL)
                    259:     { 
                    260:         return (-1);
                    261:     } 
                    262:     n = LIBNET_ICMPV4_UNREACH_H + payload_s;        /* size of memory block */
                    263: 
                    264:     /* 
                    265:      * FREDRAYNAL: as ICMP checksum includes what is embedded in 
                    266:      * the payload, and what is after the ICMP header, we need to include
                    267:      * those 2 sizes.
                    268:      */
                    269:     h = LIBNET_ICMPV4_UNREACH_H + payload_s + l->total_size; 
                    270: 
                    271:     /*
                    272:      *  Find the existing protocol block if a ptag is specified, or create
                    273:      *  a new one.
                    274:      */
                    275:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV4_UNREACH_H);
                    276:     if (p == NULL)
                    277:     {
                    278:         return (-1);
                    279:     }
                    280: 
                    281:     memset(&icmp_hdr, 0, sizeof(icmp_hdr));
                    282:     icmp_hdr.icmp_type = type;          /* packet type */
                    283:     icmp_hdr.icmp_code = code;          /* packet code */
                    284:     icmp_hdr.icmp_sum  = (sum ? htons(sum) : 0);  /* checksum */
                    285:     icmp_hdr.icmp_id   = 0;             /* must be 0 */
                    286:     icmp_hdr.icmp_seq  = 0;             /* must be 0 */
                    287: 
                    288:     LIBNET_BUILD_ICMP_ERR_FINISH(LIBNET_ICMPV4_UNREACH_H);
                    289: 
                    290:     return (ptag ? ptag : libnet_pblock_update(l, p, h,
                    291:             LIBNET_PBLOCK_ICMPV4_UNREACH_H));
                    292: bad:
                    293:     libnet_pblock_delete(l, p);
                    294:     return (-1);
                    295: }
                    296: 
                    297: libnet_ptag_t
1.1.1.2   misho     298: libnet_build_icmpv4_timeexceed(uint8_t type, uint8_t code, uint16_t sum,
                    299: const uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
1.1       misho     300: {
1.1.1.2   misho     301:     uint32_t n, h;
1.1       misho     302:     libnet_pblock_t *p;
                    303:     struct libnet_icmpv4_hdr icmp_hdr;
                    304: 
                    305:     if (l == NULL)
                    306:     { 
                    307:         return (-1);
                    308:     } 
                    309: 
                    310:     /* size of memory block */
1.1.1.2   misho     311:     n = LIBNET_ICMPV4_TIMXCEED_H + payload_s;
1.1       misho     312:     /* 
                    313:      * FREDRAYNAL: as ICMP checksum includes what is embedded in 
                    314:      * the payload, and what is after the ICMP header, we need to include
                    315:      * those 2 sizes.
                    316:      */
                    317:     h = LIBNET_ICMPV4_TIMXCEED_H + payload_s + l->total_size; 
                    318: 
                    319:     /*
                    320:      *  Find the existing protocol block if a ptag is specified, or create
                    321:      *  a new one.
                    322:      */
                    323:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV4_TIMXCEED_H);
                    324:     if (p == NULL)
                    325:     {
                    326:         return (-1);
                    327:     }
                    328: 
                    329:     memset(&icmp_hdr, 0, sizeof(icmp_hdr));
                    330:     icmp_hdr.icmp_type = type;          /* packet type */
                    331:     icmp_hdr.icmp_code = code;          /* packet code */
                    332:     icmp_hdr.icmp_sum  = (sum ? htons(sum) : 0);  /* checksum */
                    333:     icmp_hdr.icmp_id   = 0;             /* must be 0 */
                    334:     icmp_hdr.icmp_seq  = 0;             /* must be 0 */
                    335: 
                    336:     LIBNET_BUILD_ICMP_ERR_FINISH(LIBNET_ICMPV4_TIMXCEED_H);
                    337: 
                    338:     return (ptag ? ptag : libnet_pblock_update(l, p, h,
                    339:             LIBNET_PBLOCK_ICMPV4_TIMXCEED_H));
                    340: bad:
                    341:     libnet_pblock_delete(l, p);
                    342:     return (-1);
                    343: }
                    344: 
                    345: libnet_ptag_t
1.1.1.2   misho     346: libnet_build_icmpv4_redirect(uint8_t type, uint8_t code, uint16_t sum,
                    347: uint32_t gateway, const uint8_t *payload, uint32_t payload_s, libnet_t *l,
1.1       misho     348: libnet_ptag_t ptag)
                    349: 
                    350: {
1.1.1.2   misho     351:     uint32_t n, h;
1.1       misho     352:     libnet_pblock_t *p;
                    353:     struct libnet_icmpv4_hdr icmp_hdr;
                    354: 
                    355:     if (l == NULL)
                    356:     { 
                    357:         return (-1);
                    358:     } 
                    359: 
1.1.1.2   misho     360:     n = LIBNET_ICMPV4_REDIRECT_H + payload_s;               /* size of memory block */
1.1       misho     361:     /* 
                    362:      * FREDRAYNAL: as ICMP checksum includes what is embedded in 
                    363:      * the payload, and what is after the ICMP header, we need to include
                    364:      * those 2 sizes.
                    365:      */
                    366:     h = LIBNET_ICMPV4_REDIRECT_H + payload_s + l->total_size; 
                    367: 
                    368:     /*
                    369:      *  Find the existing protocol block if a ptag is specified, or create
                    370:      *  a new one.
                    371:      */
                    372:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV4_REDIRECT_H);
                    373:     if (p == NULL)
                    374:     {
                    375:         return (-1);
                    376:     }
                    377: 
                    378:     memset(&icmp_hdr, 0, sizeof(icmp_hdr));
                    379:     icmp_hdr.icmp_type      = type;             /* packet type */
                    380:     icmp_hdr.icmp_code      = code;             /* packet code */
                    381:     icmp_hdr.icmp_sum       = (sum ? htons(sum) : 0);  /* checksum */
                    382:     icmp_hdr.hun.gateway    = gateway;
                    383: 
                    384:     LIBNET_BUILD_ICMP_ERR_FINISH(LIBNET_ICMPV4_REDIRECT_H);
                    385: 
                    386:     return (ptag ? ptag : libnet_pblock_update(l, p, h,
                    387:             LIBNET_PBLOCK_ICMPV4_REDIRECT_H));
                    388: bad:
                    389:     libnet_pblock_delete(l, p);
                    390:     return (-1);
                    391: }
                    392: 
1.1.1.2   misho     393: 
                    394: libnet_ptag_t
                    395: libnet_build_icmpv6_common(
                    396:         uint8_t type, uint8_t code, uint16_t sum,
                    397:         const void* specific, uint32_t specific_s, uint8_t pblock_type,
                    398:         uint8_t *payload, uint32_t payload_s,
                    399:         libnet_t *l, libnet_ptag_t ptag
                    400:         )
                    401: {
                    402:     uint32_t n;
                    403:     libnet_pblock_t *p;
                    404:     struct libnet_icmpv6_hdr icmp_hdr;
                    405: 
                    406:     if (l == NULL)
                    407:     { 
                    408:         return (-1);
                    409:     } 
                    410: 
                    411:     n = LIBNET_ICMPV6_COMMON_H + specific_s + payload_s;
                    412: 
                    413:     p = libnet_pblock_probe(l, ptag, n, pblock_type);
                    414: 
                    415:     if (p == NULL)
                    416:     {
                    417:         return (-1);
                    418:     }
                    419: 
                    420:     memset(&icmp_hdr, 0, sizeof(icmp_hdr));
                    421:     icmp_hdr.icmp_type = type;
                    422:     icmp_hdr.icmp_code = code;
                    423:     icmp_hdr.icmp_sum  = htons(sum);
                    424: 
                    425:     if (libnet_pblock_append(l, p, (uint8_t *)&icmp_hdr, LIBNET_ICMPV6_COMMON_H) < 0)
                    426:     {
                    427:         goto bad;
                    428:     }
                    429: 
                    430:     if (libnet_pblock_append(l, p, specific, specific_s) < 0)
                    431:     {
                    432:         goto bad;
                    433:     }
                    434: 
                    435:     if (libnet_pblock_append(l, p, payload, payload_s) < 0)
                    436:     {
                    437:         goto bad;
                    438:     }
                    439: 
                    440:     if (sum == 0)
                    441:     {
                    442:         libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
                    443:     }
                    444: 
                    445:     return ptag ? ptag : libnet_pblock_update(l, p, 0, pblock_type);
                    446: 
                    447: bad:
                    448:     libnet_pblock_delete(l, p);
                    449: 
                    450:     return -1;
                    451: }
                    452: 
                    453: libnet_ptag_t libnet_build_icmpv6(uint8_t type, uint8_t code, uint16_t sum,
                    454:                                   uint8_t* payload, uint32_t payload_s,
                    455:                                   libnet_t* l, libnet_ptag_t ptag)
                    456: {
                    457:     return libnet_build_icmpv6_common(
                    458:             type, code, sum,
                    459:             NULL, 0, LIBNET_PBLOCK_ICMPV6_UNREACH_H,
                    460:             payload, payload_s,
                    461:             l, ptag);
                    462: }
                    463: 
                    464: libnet_ptag_t
                    465: libnet_build_icmpv6_unreach(
                    466:         uint8_t type, uint8_t code, uint16_t sum,
                    467:         uint8_t *payload, uint32_t payload_s,
                    468:         libnet_t *l, libnet_ptag_t ptag
                    469:         )
                    470: {
                    471:     struct libnet_icmpv6_unreach specific;
                    472: 
                    473:     memset(&specific, 0, sizeof(specific));
                    474: 
                    475:     return libnet_build_icmpv6_common(
                    476:             type, code, sum,
                    477:             &specific, sizeof(specific), LIBNET_PBLOCK_ICMPV6_UNREACH_H,
                    478:             payload, payload_s,
                    479:             l, ptag);
                    480: }
                    481: 
                    482: libnet_ptag_t
                    483: libnet_build_icmpv6_echo(
                    484:         uint8_t type, uint8_t code, uint16_t sum,
                    485:         uint16_t id, uint16_t seq,
                    486:         uint8_t *payload, uint32_t payload_s,
                    487:         libnet_t *l, libnet_ptag_t ptag
                    488:         )
                    489: {
                    490:     struct libnet_icmpv6_echo specific;
                    491: 
                    492:     memset(&specific, 0, sizeof(specific));
                    493:     specific.id = htons(id);
                    494:     specific.seq = htons(seq);
                    495: 
                    496:     return libnet_build_icmpv6_common(
                    497:             type, code, sum,
                    498:             &specific, sizeof(specific), LIBNET_PBLOCK_ICMPV6_ECHO_H,
                    499:             payload, payload_s,
                    500:             l, ptag);
                    501: }
                    502: 
                    503: 
                    504: libnet_ptag_t libnet_build_icmpv6_ndp_nsol(
                    505:         uint8_t type, uint8_t code, uint16_t sum,
                    506:         struct libnet_in6_addr target,
                    507:         uint8_t *payload, uint32_t payload_s,
                    508:         libnet_t* l, libnet_ptag_t ptag)
                    509: {
                    510:     struct libnet_icmpv6_ndp_nsol specific;
                    511: 
                    512:     memset(&specific, 0, sizeof(specific));
                    513:     specific.reserved = 0;
                    514:     specific.target_addr = target;
                    515: 
                    516:     return libnet_build_icmpv6_common(
                    517:             type, code, sum,
                    518:             &specific, sizeof(specific), LIBNET_PBLOCK_ICMPV6_NDP_NSOL_H,
                    519:             payload, payload_s,
                    520:             l, ptag);
                    521: }
                    522: 
                    523: 
                    524: libnet_ptag_t libnet_build_icmpv6_ndp_nadv(
                    525:         uint8_t type, uint8_t code, uint16_t sum,
                    526:         uint32_t flags, struct libnet_in6_addr target,
                    527:         uint8_t *payload, uint32_t payload_s,
                    528:         libnet_t* l, libnet_ptag_t ptag)
                    529: {
                    530: 
                    531:     struct libnet_icmpv6_ndp_nadv specific;
                    532: 
                    533:     memset(&specific, 0, sizeof(specific));
                    534:     specific.flags = htonl(flags);
                    535:     specific.target_addr = target;
                    536: 
                    537:     return libnet_build_icmpv6_common(
                    538:             type, code, sum,
                    539:             &specific, sizeof(specific), LIBNET_PBLOCK_ICMPV6_NDP_NADV_H,
                    540:             payload, payload_s,
                    541:             l, ptag);
                    542: }
                    543: 
                    544: libnet_ptag_t libnet_build_icmpv6_ndp_opt(
                    545:         uint8_t type, uint8_t* option, uint32_t option_s,
                    546:         libnet_t* l, libnet_ptag_t ptag)
                    547: {
                    548:     struct libnet_icmpv6_ndp_opt opt;
                    549:     uint32_t n;
                    550:     static uint8_t pad[8] = { 0 };
                    551:     uint32_t pad_s = 0;
                    552:     libnet_pblock_t* p;
                    553: 
                    554:     if(l == NULL)
                    555:         return -1;
                    556: 
                    557:     if(!option)
                    558:         option_s = 0;
                    559: 
                    560:     /* options need to be padded to a multiple of 8-bytes, and opts.len is in units of 8-bytes */
                    561:     n = sizeof(opt) + option_s;
                    562: 
                    563:     if(n % 8)
                    564:     {
                    565:         n += 8 - (n % 8);
                    566:     }
                    567: 
                    568:     if(n > (0xff * 8))
                    569:     {
                    570:         return -1;
                    571:     }
                    572: 
                    573:     pad_s = n - option_s - sizeof(opt);
                    574: 
                    575:     assert((n % 8) == 0);
                    576:     assert(pad_s < sizeof(pad));
                    577: 
                    578:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV6_NDP_OPT_H);
                    579:     if(p == NULL)
                    580:         return -1;
                    581: 
                    582:     memset(&opt, 0, sizeof(opt));
                    583:     opt.type = type;
                    584:     opt.len  = n / 8;
                    585: 
                    586:     if(libnet_pblock_append(l, p, &opt, sizeof(opt)) == -1)
                    587:         goto bad;
                    588: 
                    589:     if(libnet_pblock_append(l, p, option, option_s) == -1)
                    590:         goto bad;
                    591: 
                    592:     if(libnet_pblock_append(l, p, pad, pad_s) == -1)
                    593:         goto bad;
                    594: 
                    595:     return ptag ? ptag : libnet_pblock_update(l, p, n, LIBNET_PBLOCK_ICMPV6_NDP_OPT_H);
                    596: 
                    597: bad:
                    598:     libnet_pblock_delete(l, p);
                    599:     return -1;
                    600: }
                    601: 
1.1.1.3 ! misho     602: /**
        !           603:  * Local Variables:
        !           604:  *  indent-tabs-mode: nil
        !           605:  *  c-file-style: "stroustrup"
        !           606:  * End:
        !           607:  */

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