File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libnet / src / libnet_build_icmp.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Sep 27 11:11:38 2023 UTC (8 months, 4 weeks ago) by misho
Branches: libnet, MAIN
CVS tags: v1_2p1, HEAD
Version 1.2p1

    1: /*
    2:  *  $Id: libnet_build_icmp.c,v 1.1.1.3 2023/09/27 11:11:38 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: #include "common.h"
   34: 
   35: #include <assert.h>
   36: 
   37: /* some common cruft for completing ICMP error packets */
   38: #define LIBNET_BUILD_ICMP_ERR_FINISH(len)                                    \
   39: do                                                                           \
   40: {                                                                            \
   41:     n = libnet_pblock_append(l, p, (uint8_t *)&icmp_hdr, len);              \
   42:     if (n == -1)                                                             \
   43:     {                                                                        \
   44:         goto bad;                                                            \
   45:     }                                                                        \
   46:                                                                              \
   47:     if (payload_s && !payload)                                               \
   48:     {                                                                        \
   49:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,                             \
   50:                 "%s(): payload inconsistency", __func__);                  \
   51:         goto bad;                                                            \
   52:     }                                                                        \
   53:                                                                              \
   54:     if (payload_s)                                                           \
   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
   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,
   72: libnet_t *l, libnet_ptag_t ptag) 
   73: {
   74:     uint32_t n, h;
   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: 
  103:     n = libnet_pblock_append(l, p, (uint8_t *)&icmp_hdr, LIBNET_ICMPV4_ECHO_H);
  104:     if (n == -1)
  105:     {
  106:         goto bad;
  107:     }
  108: 
  109:     /* boilerplate payload sanity check / append macro */
  110:     LIBNET_DO_PAYLOAD(l, p);
  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
  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)
  132: {
  133:     uint32_t n, h;
  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: 
  163:     n = libnet_pblock_append(l, p, (uint8_t *)&icmp_hdr, LIBNET_ICMPV4_MASK_H);
  164:     if (n == -1)
  165:     {
  166:         goto bad;
  167:     }
  168: 
  169:     /* boilerplate payload sanity check / append macro */
  170:     LIBNET_DO_PAYLOAD(l, p);
  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
  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)
  192: {
  193:     uint32_t n, h;
  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: 
  225:     n = libnet_pblock_append(l, p, (uint8_t *)&icmp_hdr, LIBNET_ICMPV4_TS_H);
  226:     if (n == -1)
  227:     {
  228:         goto bad;
  229:     }
  230: 
  231:     /* boilerplate payload sanity check / append macro */
  232:     LIBNET_DO_PAYLOAD(l, p);
  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
  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)
  253: {
  254:     uint32_t n, h;
  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
  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)
  300: {
  301:     uint32_t n, h;
  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 */
  311:     n = LIBNET_ICMPV4_TIMXCEED_H + payload_s;
  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
  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,
  348: libnet_ptag_t ptag)
  349: 
  350: {
  351:     uint32_t n, h;
  352:     libnet_pblock_t *p;
  353:     struct libnet_icmpv4_hdr icmp_hdr;
  354: 
  355:     if (l == NULL)
  356:     { 
  357:         return (-1);
  358:     } 
  359: 
  360:     n = LIBNET_ICMPV4_REDIRECT_H + payload_s;               /* size of memory block */
  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: 
  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: 
  602: /**
  603:  * Local Variables:
  604:  *  indent-tabs-mode: nil
  605:  *  c-file-style: "stroustrup"
  606:  * End:
  607:  */

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