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

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

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