Annotation of embedaddon/libnet/src/libnet_build_icmp.c, revision 1.1
1.1 ! misho 1: /*
! 2: * $Id: libnet_build_icmp.c,v 1.16 2004/03/29 17:24:34 mike 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>