File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libnet / src / libnet_build_icmp.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:14:23 2012 UTC (12 years, 4 months ago) by misho
Branches: libnet, MAIN
CVS tags: v1_1_2_1, HEAD
libnet

    1: /*
    2:  *  $Id: libnet_build_icmp.c,v 1.1.1.1 2012/02/21 22:14:23 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: /* some common cruft for completing ICMP error packets */
   43: #define LIBNET_BUILD_ICMP_ERR_FINISH(len)                                    \
   44: do                                                                           \
   45: {                                                                            \
   46:     n = libnet_pblock_append(l, p, (u_int8_t *)&icmp_hdr, len);              \
   47:     if (n == -1)                                                             \
   48:     {                                                                        \
   49:         goto bad;                                                            \
   50:     }                                                                        \
   51:                                                                              \
   52:     if ((payload && !payload_s) || (!payload && payload_s))                  \
   53:     {                                                                        \
   54:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,                             \
   55:                 "%s(): payload inconsistency\n", __func__);                  \
   56:         goto bad;                                                            \
   57:     }                                                                        \
   58:                                                                              \
   59:     if (payload && payload_s)                                                \
   60:     {                                                                        \
   61:         n = libnet_pblock_append(l, p, payload, payload_s);                  \
   62:         if (n == -1)                                                         \
   63:         {                                                                    \
   64:             goto bad;                                                        \
   65:         }                                                                    \
   66:     }                                                                        \
   67:                                                                              \
   68:     if (sum == 0)                                                            \
   69:     {                                                                        \
   70:         libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);                \
   71:     }                                                                        \
   72: } while (0)
   73: 
   74: libnet_ptag_t
   75: libnet_build_icmpv4_echo(u_int8_t type, u_int8_t code, u_int16_t sum,
   76: u_int16_t id, u_int16_t seq, u_int8_t *payload, u_int32_t payload_s,
   77: libnet_t *l, libnet_ptag_t ptag) 
   78: {
   79:     u_int32_t n, h;
   80:     libnet_pblock_t *p;
   81:     struct libnet_icmpv4_hdr icmp_hdr;
   82: 
   83:     if (l == NULL)
   84:     { 
   85:         return (-1);
   86:     } 
   87: 
   88:     n = LIBNET_ICMPV4_ECHO_H + payload_s;        /* size of memory block */
   89:     h = LIBNET_ICMPV4_ECHO_H + payload_s;        /* hl for checksum */
   90: 
   91:     /*
   92:      *  Find the existing protocol block if a ptag is specified, or create
   93:      *  a new one.
   94:      */
   95:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV4_ECHO_H);
   96:     if (p == NULL)
   97:     {
   98:         return (-1);
   99:     }
  100: 
  101:     memset(&icmp_hdr, 0, sizeof(icmp_hdr));
  102:     icmp_hdr.icmp_type = type;          /* packet type */
  103:     icmp_hdr.icmp_code = code;          /* packet code */
  104:     icmp_hdr.icmp_sum  = (sum ? htons(sum) : 0);  /* checksum */
  105:     icmp_hdr.icmp_id   = htons(id);            /* packet id */
  106:     icmp_hdr.icmp_seq  = htons(seq);           /* packet seq */
  107: 
  108:     n = libnet_pblock_append(l, p, (u_int8_t *)&icmp_hdr, LIBNET_ICMPV4_ECHO_H);
  109:     if (n == -1)
  110:     {
  111:         goto bad;
  112:     }
  113: 
  114:     if ((payload && !payload_s) || (!payload && payload_s))
  115:     {
  116:          snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  117:                  "%s(): payload inconsistency\n", __func__);
  118:         goto bad;
  119:     }
  120:  
  121:     if (payload && payload_s)
  122:     {
  123:         n = libnet_pblock_append(l, p, payload, payload_s);
  124:         if (n == -1)
  125:         {
  126:             goto bad;
  127:         }
  128:     }
  129:  
  130:     if (sum == 0)
  131:     {
  132:         /*
  133:          *  If checksum is zero, by default libnet will compute a checksum
  134:          *  for the user.  The programmer can override this by calling
  135:          *  libnet_toggle_checksum(l, ptag, 1);
  136:          */
  137:         libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
  138:     }
  139:     return (ptag ? ptag : libnet_pblock_update(l, p, h, 
  140:             LIBNET_PBLOCK_ICMPV4_ECHO_H));
  141: bad:
  142:     libnet_pblock_delete(l, p);   
  143:     return (-1);
  144: }
  145: 
  146: libnet_ptag_t
  147: libnet_build_icmpv4_mask(u_int8_t type, u_int8_t code, u_int16_t sum,
  148: u_int16_t id, u_int16_t seq, u_int32_t mask, u_int8_t *payload,
  149: u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
  150: {
  151:     u_int32_t n, h;
  152:     libnet_pblock_t *p;
  153:     struct libnet_icmpv4_hdr icmp_hdr;
  154: 
  155:     if (l == NULL)
  156:     { 
  157:         return (-1);
  158:     } 
  159: 
  160:     n = LIBNET_ICMPV4_MASK_H + payload_s;        /* size of memory block */
  161:     h = LIBNET_ICMPV4_MASK_H + payload_s;        /* hl for checksum */
  162: 
  163:     /*
  164:      *  Find the existing protocol block if a ptag is specified, or create
  165:      *  a new one.
  166:      */
  167:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV4_MASK_H);
  168:     if (p == NULL)
  169:     {
  170:         return (-1);
  171:     }
  172: 
  173:     memset(&icmp_hdr, 0, sizeof(icmp_hdr));
  174:     icmp_hdr.icmp_type = type;          /* packet type */
  175:     icmp_hdr.icmp_code = code;          /* packet code */
  176:     icmp_hdr.icmp_sum  = (sum ? htons(sum) : 0);  /* checksum */
  177:     icmp_hdr.icmp_id   = htons(id);     /* packet id */
  178:     icmp_hdr.icmp_seq  = htons(seq);    /* packet seq */
  179:     icmp_hdr.icmp_mask = htonl(mask);   /* address mask */
  180: 
  181:     n = libnet_pblock_append(l, p, (u_int8_t *)&icmp_hdr, LIBNET_ICMPV4_MASK_H);
  182:     if (n == -1)
  183:     {
  184:         goto bad;
  185:     }
  186: 
  187:     if ((payload && !payload_s) || (!payload && payload_s))
  188:     {
  189:          snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  190: 			     "%s(): payload inconsistency\n", __func__);
  191:         goto bad;
  192:     }
  193:  
  194:     if (payload && payload_s)
  195:     {
  196:         n = libnet_pblock_append(l, p, payload, payload_s);
  197:         if (n == -1)
  198:         {
  199:             goto bad;
  200:         }
  201:     }
  202:  
  203:     if (sum == 0)
  204:     {
  205:         /*
  206:          *  If checksum is zero, by default libnet will compute a checksum
  207:          *  for the user.  The programmer can override this by calling
  208:          *  libnet_toggle_checksum(l, ptag, 1);
  209:          */
  210:         libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
  211:     }
  212:     return (ptag ? ptag : libnet_pblock_update(l, p, h, 
  213:             LIBNET_PBLOCK_ICMPV4_MASK_H));
  214: bad:
  215:     libnet_pblock_delete(l, p);
  216:     return (-1);
  217: }
  218: 
  219: libnet_ptag_t
  220: libnet_build_icmpv4_timestamp(u_int8_t type, u_int8_t code, u_int16_t sum,
  221: u_int16_t id, u_int16_t seq, n_time otime, n_time rtime, n_time ttime,
  222: u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
  223: {
  224:     u_int32_t n, h;
  225:     libnet_pblock_t *p;
  226:     struct libnet_icmpv4_hdr icmp_hdr;
  227: 
  228:     if (l == NULL)
  229:     { 
  230:         return (-1);
  231:     } 
  232: 
  233:     n = LIBNET_ICMPV4_TS_H + payload_s;        /* size of memory block */
  234:     h = LIBNET_ICMPV4_TS_H + payload_s;        /* hl for checksum */
  235: 
  236:     /*
  237:      *  Find the existing protocol block if a ptag is specified, or create
  238:      *  a new one.
  239:      */
  240:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV4_TS_H);
  241:     if (p == NULL)
  242:     {
  243:         return (-1);
  244:     }
  245: 
  246:     memset(&icmp_hdr, 0, sizeof(icmp_hdr));
  247:     icmp_hdr.icmp_type  = type;             /* packet type */
  248:     icmp_hdr.icmp_code  = code;             /* packet code */
  249:     icmp_hdr.icmp_sum   = (sum ? htons(sum) : 0); /* checksum */
  250:     icmp_hdr.icmp_id    = htons(id);        /* packet id */
  251:     icmp_hdr.icmp_seq   = htons(seq);       /* packet seq */
  252:     icmp_hdr.icmp_otime = htonl(otime);     /* original timestamp */
  253:     icmp_hdr.icmp_rtime = htonl(rtime);     /* receive timestamp */
  254:     icmp_hdr.icmp_ttime = htonl(ttime);     /* transmit timestamp */
  255: 
  256:     n = libnet_pblock_append(l, p, (u_int8_t *)&icmp_hdr, LIBNET_ICMPV4_TS_H);
  257:     if (n == -1)
  258:     {
  259:         goto bad;
  260:     }
  261: 
  262:     if ((payload && !payload_s) || (!payload && payload_s))
  263:     {
  264:          snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  265: 			     "%s(): payload inconsistency\n", __func__);
  266:         goto bad;
  267:     }
  268:  
  269:     if (payload && payload_s)
  270:     {
  271:         n = libnet_pblock_append(l, p, payload, payload_s);
  272:         if (n == -1)
  273:         {
  274:             goto bad;
  275:         }
  276:     }
  277:  
  278:     if (sum == 0)
  279:     {
  280:         /*
  281:          *  If checksum is zero, by default libnet will compute a checksum
  282:          *  for the user.  The programmer can override this by calling
  283:          *  libnet_toggle_checksum(l, ptag, 1);
  284:          */
  285:         libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
  286:     }
  287:     return (ptag ? ptag : libnet_pblock_update(l, p, h, 
  288:             LIBNET_PBLOCK_ICMPV4_TS_H));
  289: bad:
  290:     libnet_pblock_delete(l, p);
  291:     return (-1);
  292: }
  293: 
  294: libnet_ptag_t
  295: libnet_build_icmpv4_unreach(u_int8_t type, u_int8_t code, u_int16_t sum,
  296: u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
  297: {
  298:     u_int32_t n, h;
  299:     libnet_pblock_t *p;
  300:     struct libnet_icmpv4_hdr icmp_hdr;
  301: 
  302:     if (l == NULL)
  303:     { 
  304:         return (-1);
  305:     } 
  306:     n = LIBNET_ICMPV4_UNREACH_H + payload_s;        /* size of memory block */
  307: 
  308:     /* 
  309:      * FREDRAYNAL: as ICMP checksum includes what is embedded in 
  310:      * the payload, and what is after the ICMP header, we need to include
  311:      * those 2 sizes.
  312:      */
  313:     h = LIBNET_ICMPV4_UNREACH_H + payload_s + l->total_size; 
  314: 
  315:     /*
  316:      *  Find the existing protocol block if a ptag is specified, or create
  317:      *  a new one.
  318:      */
  319:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV4_UNREACH_H);
  320:     if (p == NULL)
  321:     {
  322:         return (-1);
  323:     }
  324: 
  325:     memset(&icmp_hdr, 0, sizeof(icmp_hdr));
  326:     icmp_hdr.icmp_type = type;          /* packet type */
  327:     icmp_hdr.icmp_code = code;          /* packet code */
  328:     icmp_hdr.icmp_sum  = (sum ? htons(sum) : 0);  /* checksum */
  329:     icmp_hdr.icmp_id   = 0;             /* must be 0 */
  330:     icmp_hdr.icmp_seq  = 0;             /* must be 0 */
  331: 
  332:     LIBNET_BUILD_ICMP_ERR_FINISH(LIBNET_ICMPV4_UNREACH_H);
  333: 
  334:     return (ptag ? ptag : libnet_pblock_update(l, p, h,
  335:             LIBNET_PBLOCK_ICMPV4_UNREACH_H));
  336: bad:
  337:     libnet_pblock_delete(l, p);
  338:     return (-1);
  339: }
  340: 
  341: libnet_ptag_t
  342: libnet_build_icmpv4_timeexceed(u_int8_t type, u_int8_t code, u_int16_t sum,
  343: u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
  344: {
  345:     u_int32_t n, h;
  346:     libnet_pblock_t *p;
  347:     struct libnet_icmpv4_hdr icmp_hdr;
  348: 
  349:     if (l == NULL)
  350:     { 
  351:         return (-1);
  352:     } 
  353: 
  354:     /* size of memory block */
  355:     n = LIBNET_ICMPV4_TIMXCEED_H;
  356:     /* 
  357:      * FREDRAYNAL: as ICMP checksum includes what is embedded in 
  358:      * the payload, and what is after the ICMP header, we need to include
  359:      * those 2 sizes.
  360:      */
  361:     h = LIBNET_ICMPV4_TIMXCEED_H + payload_s + l->total_size; 
  362: 
  363:     /*
  364:      *  Find the existing protocol block if a ptag is specified, or create
  365:      *  a new one.
  366:      */
  367:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV4_TIMXCEED_H);
  368:     if (p == NULL)
  369:     {
  370:         return (-1);
  371:     }
  372: 
  373:     memset(&icmp_hdr, 0, sizeof(icmp_hdr));
  374:     icmp_hdr.icmp_type = type;          /* packet type */
  375:     icmp_hdr.icmp_code = code;          /* packet code */
  376:     icmp_hdr.icmp_sum  = (sum ? htons(sum) : 0);  /* checksum */
  377:     icmp_hdr.icmp_id   = 0;             /* must be 0 */
  378:     icmp_hdr.icmp_seq  = 0;             /* must be 0 */
  379: 
  380:     LIBNET_BUILD_ICMP_ERR_FINISH(LIBNET_ICMPV4_TIMXCEED_H);
  381: 
  382:     return (ptag ? ptag : libnet_pblock_update(l, p, h,
  383:             LIBNET_PBLOCK_ICMPV4_TIMXCEED_H));
  384: bad:
  385:     libnet_pblock_delete(l, p);
  386:     return (-1);
  387: }
  388: 
  389: libnet_ptag_t
  390: libnet_build_icmpv4_redirect(u_int8_t type, u_int8_t code, u_int16_t sum,
  391: u_int32_t gateway, u_int8_t *payload, u_int32_t payload_s, libnet_t *l,
  392: libnet_ptag_t ptag)
  393: 
  394: {
  395:     u_int32_t n, h;
  396:     libnet_pblock_t *p;
  397:     struct libnet_icmpv4_hdr icmp_hdr;
  398: 
  399:     if (l == NULL)
  400:     { 
  401:         return (-1);
  402:     } 
  403: 
  404:     n = LIBNET_ICMPV4_REDIRECT_H;               /* size of memory block */
  405:     /* 
  406:      * FREDRAYNAL: as ICMP checksum includes what is embedded in 
  407:      * the payload, and what is after the ICMP header, we need to include
  408:      * those 2 sizes.
  409:      */
  410:     h = LIBNET_ICMPV4_REDIRECT_H + payload_s + l->total_size; 
  411: 
  412:     /*
  413:      *  Find the existing protocol block if a ptag is specified, or create
  414:      *  a new one.
  415:      */
  416:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV4_REDIRECT_H);
  417:     if (p == NULL)
  418:     {
  419:         return (-1);
  420:     }
  421: 
  422:     memset(&icmp_hdr, 0, sizeof(icmp_hdr));
  423:     icmp_hdr.icmp_type      = type;             /* packet type */
  424:     icmp_hdr.icmp_code      = code;             /* packet code */
  425:     icmp_hdr.icmp_sum       = (sum ? htons(sum) : 0);  /* checksum */
  426:     icmp_hdr.hun.gateway    = gateway;
  427: 
  428:     LIBNET_BUILD_ICMP_ERR_FINISH(LIBNET_ICMPV4_REDIRECT_H);
  429: 
  430:     return (ptag ? ptag : libnet_pblock_update(l, p, h,
  431:             LIBNET_PBLOCK_ICMPV4_REDIRECT_H));
  432: bad:
  433:     libnet_pblock_delete(l, p);
  434:     return (-1);
  435: }
  436: 
  437: /* EOF */

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