File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libnet / src / libnet_build_icmp.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 11:54:42 2013 UTC (11 years ago) by misho
Branches: libnet, MAIN
CVS tags: v1_1_6p5, v1_1_6p4, v1_1_6p0, v1_1_6, HEAD
1.1.6

    1: /*
    2:  *  $Id: libnet_build_icmp.c,v 1.1.1.2 2013/07/22 11:54:42 misho Exp $
    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: 
   42: #include <assert.h>
   43: 
   44: /* some common cruft for completing ICMP error packets */
   45: #define LIBNET_BUILD_ICMP_ERR_FINISH(len)                                    \
   46: do                                                                           \
   47: {                                                                            \
   48:     n = libnet_pblock_append(l, p, (uint8_t *)&icmp_hdr, len);              \
   49:     if (n == -1)                                                             \
   50:     {                                                                        \
   51:         goto bad;                                                            \
   52:     }                                                                        \
   53:                                                                              \
   54:     if (payload_s && !payload)                                               \
   55:     {                                                                        \
   56:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,                             \
   57:                 "%s(): payload inconsistency\n", __func__);                  \
   58:         goto bad;                                                            \
   59:     }                                                                        \
   60:                                                                              \
   61:     if (payload_s)                                                           \
   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
   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,
   79: libnet_t *l, libnet_ptag_t ptag) 
   80: {
   81:     uint32_t n, h;
   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: 
  110:     n = libnet_pblock_append(l, p, (uint8_t *)&icmp_hdr, LIBNET_ICMPV4_ECHO_H);
  111:     if (n == -1)
  112:     {
  113:         goto bad;
  114:     }
  115: 
  116:     /* boilerplate payload sanity check / append macro */
  117:     LIBNET_DO_PAYLOAD(l, p);
  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
  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)
  139: {
  140:     uint32_t n, h;
  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: 
  170:     n = libnet_pblock_append(l, p, (uint8_t *)&icmp_hdr, LIBNET_ICMPV4_MASK_H);
  171:     if (n == -1)
  172:     {
  173:         goto bad;
  174:     }
  175: 
  176:     /* boilerplate payload sanity check / append macro */
  177:     LIBNET_DO_PAYLOAD(l, p);
  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
  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)
  199: {
  200:     uint32_t n, h;
  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: 
  232:     n = libnet_pblock_append(l, p, (uint8_t *)&icmp_hdr, LIBNET_ICMPV4_TS_H);
  233:     if (n == -1)
  234:     {
  235:         goto bad;
  236:     }
  237: 
  238:     /* boilerplate payload sanity check / append macro */
  239:     LIBNET_DO_PAYLOAD(l, p);
  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
  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)
  260: {
  261:     uint32_t n, h;
  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
  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)
  307: {
  308:     uint32_t n, h;
  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 */
  318:     n = LIBNET_ICMPV4_TIMXCEED_H + payload_s;
  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
  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,
  355: libnet_ptag_t ptag)
  356: 
  357: {
  358:     uint32_t n, h;
  359:     libnet_pblock_t *p;
  360:     struct libnet_icmpv4_hdr icmp_hdr;
  361: 
  362:     if (l == NULL)
  363:     { 
  364:         return (-1);
  365:     } 
  366: 
  367:     n = LIBNET_ICMPV4_REDIRECT_H + payload_s;               /* size of memory block */
  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: 
  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>