Annotation of embedaddon/libnet/src/libnet_build_ip.c, revision 1.1
1.1 ! misho 1: /*
! 2: * $Id: libnet_build_ip.c,v 1.18 2004/03/16 18:40:59 mike Exp $
! 3: *
! 4: * libnet
! 5: * libnet_build_ip.c - IP packet assembler
! 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:
! 43: libnet_ptag_t
! 44: libnet_build_ipv4(u_int16_t len, u_int8_t tos, u_int16_t id, u_int16_t frag,
! 45: u_int8_t ttl, u_int8_t prot, u_int16_t sum, u_int32_t src, u_int32_t dst,
! 46: u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
! 47: {
! 48: int offset;
! 49: u_int32_t h, n, i, j;
! 50: libnet_pblock_t *p, *p_data, *p_temp;
! 51: struct libnet_ipv4_hdr ip_hdr;
! 52: libnet_ptag_t ptag_data, ptag_hold;
! 53:
! 54: if (l == NULL)
! 55: {
! 56: return (-1);
! 57: }
! 58:
! 59: n = LIBNET_IPV4_H; /* size of memory block */
! 60: h = len; /* header length */
! 61: ptag_data = 0; /* used if options are present */
! 62:
! 63: if (h + payload_s > IP_MAXPACKET)
! 64: {
! 65: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
! 66: "%s(): IP packet too large\n", __func__);
! 67: return (-1);
! 68: }
! 69:
! 70: /*
! 71: * Find the existing protocol block if a ptag is specified, or create
! 72: * a new one.
! 73: */
! 74: p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV4_H);
! 75: if (p == NULL)
! 76: {
! 77: return (-1);
! 78: }
! 79:
! 80: memset(&ip_hdr, 0, sizeof(ip_hdr));
! 81: ip_hdr.ip_v = 4; /* version 4 */
! 82: ip_hdr.ip_hl = 5; /* 20 byte header */
! 83:
! 84: /* check to see if there are IP options to include */
! 85: if (p->prev)
! 86: {
! 87: if (p->prev->type == LIBNET_PBLOCK_IPO_H)
! 88: {
! 89: /*
! 90: * Count up number of 32-bit words in options list, padding if
! 91: * neccessary.
! 92: */
! 93: for (i = 0, j = 0; i < p->prev->b_len; i++)
! 94: {
! 95: (i % 4) ? j : j++;
! 96: }
! 97: ip_hdr.ip_hl += j;
! 98: }
! 99: }
! 100:
! 101: ip_hdr.ip_tos = tos; /* IP tos */
! 102: ip_hdr.ip_len = htons(h); /* total length */
! 103: ip_hdr.ip_id = htons(id); /* IP ID */
! 104: ip_hdr.ip_off = htons(frag); /* fragmentation flags */
! 105: ip_hdr.ip_ttl = ttl; /* time to live */
! 106: ip_hdr.ip_p = prot; /* transport protocol */
! 107: ip_hdr.ip_sum = (sum ? htons(sum) : 0); /* checksum */
! 108: ip_hdr.ip_src.s_addr = src; /* source ip */
! 109: ip_hdr.ip_dst.s_addr = dst; /* destination ip */
! 110:
! 111: n = libnet_pblock_append(l, p, (u_int8_t *)&ip_hdr, LIBNET_IPV4_H);
! 112: if (n == -1)
! 113: {
! 114: goto bad;
! 115: }
! 116:
! 117: /* save the original ptag value */
! 118: ptag_hold = ptag;
! 119:
! 120: if (ptag == LIBNET_PTAG_INITIALIZER)
! 121: {
! 122: ptag = libnet_pblock_update(l, p, LIBNET_IPV4_H, LIBNET_PBLOCK_IPV4_H);
! 123: }
! 124:
! 125: /* find and set the appropriate ptag, or else use the default of 0 */
! 126: offset = payload_s;
! 127: if (ptag_hold && p->prev)
! 128: {
! 129: p_temp = p->prev;
! 130: while (p_temp->prev &&
! 131: (p_temp->type != LIBNET_PBLOCK_IPDATA) &&
! 132: (p_temp->type != LIBNET_PBLOCK_IPV4_H))
! 133: {
! 134: p_temp = p_temp->prev;
! 135: }
! 136:
! 137: if (p_temp->type == LIBNET_PBLOCK_IPDATA)
! 138: {
! 139: ptag_data = p_temp->ptag;
! 140: offset -= p_temp->b_len;
! 141: p->h_len += offset;
! 142: }
! 143: else
! 144: {
! 145: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
! 146: "%s(): IPv4 data pblock not found\n", __func__);
! 147: }
! 148: }
! 149:
! 150: if ((payload && !payload_s) || (!payload && payload_s))
! 151: {
! 152: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
! 153: "%s(): payload inconsistency\n", __func__);
! 154: goto bad;
! 155: }
! 156:
! 157: if (payload && payload_s)
! 158: {
! 159: /* update ptag_data with the new payload */
! 160: p_data = libnet_pblock_probe(l, ptag_data, payload_s,
! 161: LIBNET_PBLOCK_IPDATA);
! 162: if (p_data == NULL)
! 163: {
! 164: return (-1);
! 165: }
! 166:
! 167: if (libnet_pblock_append(l, p_data, payload, payload_s) == -1)
! 168: {
! 169: goto bad;
! 170: }
! 171:
! 172: if (ptag_data == LIBNET_PTAG_INITIALIZER)
! 173: {
! 174: if (p_data->prev->type == LIBNET_PBLOCK_IPV4_H)
! 175: {
! 176: libnet_pblock_update(l, p_data, payload_s,
! 177: LIBNET_PBLOCK_IPDATA);
! 178: /* swap pblocks to correct the protocol order */
! 179: libnet_pblock_swap(l, p->ptag, p_data->ptag);
! 180: }
! 181: else
! 182: {
! 183: /* update without setting this as the final pblock */
! 184: p_data->type = LIBNET_PBLOCK_IPDATA;
! 185: p_data->ptag = ++(l->ptag_state);
! 186: p_data->h_len = payload_s;
! 187:
! 188: /* Adjust h_len for checksum. */
! 189: p->h_len += payload_s;
! 190:
! 191: /* data was added after the initial construction */
! 192: for (p_temp = l->protocol_blocks;
! 193: p_temp->type == LIBNET_PBLOCK_IPV4_H ||
! 194: p_temp->type == LIBNET_PBLOCK_IPO_H;
! 195: p_temp = p_temp->next)
! 196: {
! 197: libnet_pblock_insert_before(l, p_temp->ptag, p_data->ptag);
! 198: break;
! 199: }
! 200:
! 201: /* the end block needs to have its next pointer cleared */
! 202: l->pblock_end->next = NULL;
! 203: }
! 204:
! 205: if (p_data->prev && p_data->prev->type == LIBNET_PBLOCK_IPO_H)
! 206: {
! 207: libnet_pblock_swap(l, p_data->prev->ptag, p_data->ptag);
! 208: }
! 209: }
! 210: }
! 211: else
! 212: {
! 213: p_data = libnet_pblock_find(l, ptag_data);
! 214: if (p_data)
! 215: {
! 216: libnet_pblock_delete(l, p_data);
! 217: }
! 218: else
! 219: {
! 220: /*
! 221: * XXX - When this completes successfully, libnet errbuf contains
! 222: * an error message so to come correct, we'll clear it.
! 223: */
! 224: memset(l->err_buf, 0, sizeof (l->err_buf));
! 225: }
! 226: }
! 227: if (sum == 0)
! 228: {
! 229: /*
! 230: * If checksum is zero, by default libnet will compute a checksum
! 231: * for the user. The programmer can override this by calling
! 232: * libnet_toggle_checksum(l, ptag, 1);
! 233: */
! 234: libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
! 235: }
! 236:
! 237: /*
! 238: * FREDRAYNAL: as we insert a new IP header, all checksums for headers
! 239: * placed after this one will refer to here.
! 240: */
! 241: libnet_pblock_record_ip_offset(l, l->total_size);
! 242:
! 243: return (ptag);
! 244: bad:
! 245: libnet_pblock_delete(l, p);
! 246: return (-1);
! 247: }
! 248:
! 249: libnet_ptag_t
! 250: libnet_autobuild_ipv4(u_int16_t len, u_int8_t prot, u_int32_t dst, libnet_t *l)
! 251: {
! 252: u_int32_t n, i, j, src;
! 253: u_int16_t h;
! 254: libnet_pblock_t *p;
! 255: libnet_ptag_t ptag;
! 256: struct libnet_ipv4_hdr ip_hdr;
! 257:
! 258: if (l == NULL)
! 259: {
! 260: return (-1);
! 261: }
! 262:
! 263: n = LIBNET_IPV4_H; /* size of memory block */
! 264: h = len; /* header length */
! 265: ptag = LIBNET_PTAG_INITIALIZER;
! 266: src = libnet_get_ipaddr4(l);
! 267: if (src == -1)
! 268: {
! 269: /* err msg set in libnet_get_ipaddr() */
! 270: return (-1);
! 271: }
! 272:
! 273: /*
! 274: * Create a new pblock.
! 275: */
! 276: p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV4_H);
! 277: if (p == NULL)
! 278: {
! 279: return (-1);
! 280: }
! 281:
! 282: memset(&ip_hdr, 0, sizeof(ip_hdr));
! 283: ip_hdr.ip_v = 4; /* version 4 */
! 284: ip_hdr.ip_hl = 5; /* 20 byte header */
! 285:
! 286: /* check to see if there are IP options to include */
! 287: if (p->prev)
! 288: {
! 289: if (p->prev->type == LIBNET_PBLOCK_IPO_H)
! 290: {
! 291: /*
! 292: * Count up number of 32-bit words in options list, padding if
! 293: * neccessary.
! 294: */
! 295: for (i = 0, j = 0; i < p->prev->b_len; i++)
! 296: {
! 297: (i % 4) ? j : j++;
! 298: }
! 299: ip_hdr.ip_hl += j;
! 300: }
! 301: }
! 302:
! 303: ip_hdr.ip_tos = 0; /* IP tos */
! 304: ip_hdr.ip_len = htons(h); /* total length */
! 305: ip_hdr.ip_id = htons((l->ptag_state) & 0x0000ffff); /* IP ID */
! 306: ip_hdr.ip_off = 0; /* fragmentation flags */
! 307: ip_hdr.ip_ttl = 64; /* time to live */
! 308: ip_hdr.ip_p = prot; /* transport protocol */
! 309: ip_hdr.ip_sum = 0; /* checksum */
! 310: ip_hdr.ip_src.s_addr = src; /* source ip */
! 311: ip_hdr.ip_dst.s_addr = dst; /* destination ip */
! 312:
! 313: n = libnet_pblock_append(l, p, (u_int8_t *)&ip_hdr, LIBNET_IPV4_H);
! 314: if (n == -1)
! 315: {
! 316: goto bad;
! 317: }
! 318:
! 319: libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
! 320: ptag = libnet_pblock_update(l, p, LIBNET_IPV4_H, LIBNET_PBLOCK_IPV4_H);
! 321:
! 322: /*
! 323: * FREDRAYNAL: as we insert a new IP header, all checksums for headers
! 324: * placed after this one will refer to here.
! 325: */
! 326: libnet_pblock_record_ip_offset(l, l->total_size);
! 327: return (ptag);
! 328:
! 329: bad:
! 330: libnet_pblock_delete(l, p);
! 331: return (-1);
! 332: }
! 333:
! 334: libnet_ptag_t
! 335: libnet_build_ipv4_options(u_int8_t *options, u_int32_t options_s, libnet_t *l,
! 336: libnet_ptag_t ptag)
! 337: {
! 338: int offset, underflow;
! 339: u_int32_t i, j, n, adj_size;
! 340: libnet_pblock_t *p, *p_temp;
! 341: struct libnet_ipv4_hdr *ip_hdr;
! 342:
! 343: if (l == NULL)
! 344: {
! 345: return (-1);
! 346: }
! 347:
! 348: underflow = 0;
! 349: offset = 0;
! 350:
! 351: /* check options list size */
! 352: if (options_s > LIBNET_MAXOPTION_SIZE)
! 353: {
! 354: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
! 355: "%s(): options list is too large %d\n", __func__, options_s);
! 356: return (-1);
! 357: }
! 358:
! 359: adj_size = options_s;
! 360: if (adj_size % 4)
! 361: {
! 362: /* size of memory block with padding */
! 363: adj_size += 4 - (options_s % 4);
! 364: }
! 365:
! 366: /* if this pblock already exists, determine if there is a size diff */
! 367: if (ptag)
! 368: {
! 369: p_temp = libnet_pblock_find(l, ptag);
! 370: if (p_temp)
! 371: {
! 372: if (adj_size >= p_temp->b_len)
! 373: {
! 374: offset = adj_size - p_temp->b_len;
! 375: }
! 376: else
! 377: {
! 378: offset = p_temp->b_len - adj_size;
! 379: underflow = 1;
! 380: }
! 381: }
! 382: else
! 383: {
! 384: /*
! 385: * XXX - When this completes successfully, libnet errbuf contains
! 386: * an error message so to come correct, we'll clear it.
! 387: */
! 388: memset(l->err_buf, 0, sizeof (l->err_buf));
! 389: }
! 390: }
! 391:
! 392: /*
! 393: * Find the existing protocol block if a ptag is specified, or create
! 394: * a new one.
! 395: */
! 396: p = libnet_pblock_probe(l, ptag, adj_size, LIBNET_PBLOCK_IPO_H);
! 397: if (p == NULL)
! 398: {
! 399: return (-1);
! 400: }
! 401:
! 402: /* append options */
! 403: n = libnet_pblock_append(l, p, options, options_s);
! 404: if (n == -1)
! 405: {
! 406: goto bad;
! 407: }
! 408:
! 409: /* append padding */
! 410: n = libnet_pblock_append(l, p, "\0\0\0", adj_size - options_s);
! 411: if (n == -1)
! 412: {
! 413: goto bad;
! 414: }
! 415:
! 416: if (ptag && p->next)
! 417: {
! 418: p_temp = p->next;
! 419: while ((p_temp->next) && (p_temp->type != LIBNET_PBLOCK_IPV4_H))
! 420: {
! 421: p_temp = p_temp->next;
! 422: }
! 423:
! 424: /* fix the IP header size */
! 425: if (p_temp->type == LIBNET_PBLOCK_IPV4_H)
! 426: {
! 427: /*
! 428: * Count up number of 32-bit words in options list, padding if
! 429: * neccessary.
! 430: */
! 431: for (i = 0, j = 0; i < p->b_len; i++)
! 432: {
! 433: (i % 4) ? j : j++;
! 434: }
! 435: ip_hdr = (struct libnet_ipv4_hdr *) p_temp->buf;
! 436: ip_hdr->ip_hl = j + 5;
! 437:
! 438: if (!underflow)
! 439: {
! 440: p_temp->h_len += offset;
! 441: }
! 442: else
! 443: {
! 444: p_temp->h_len -= offset;
! 445: }
! 446: }
! 447: }
! 448:
! 449: return (ptag ? ptag : libnet_pblock_update(l, p, adj_size,
! 450: LIBNET_PBLOCK_IPO_H));
! 451: bad:
! 452: libnet_pblock_delete(l, p);
! 453: return (-1);
! 454: }
! 455:
! 456: libnet_ptag_t
! 457: libnet_build_ipv6(u_int8_t tc, u_int32_t fl, u_int16_t len, u_int8_t nh,
! 458: u_int8_t hl, struct libnet_in6_addr src, struct libnet_in6_addr dst,
! 459: u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
! 460: {
! 461: u_int32_t n;
! 462: libnet_pblock_t *p;
! 463: struct libnet_ipv6_hdr ip_hdr;
! 464:
! 465: if (l == NULL)
! 466: {
! 467: return (-1);
! 468: }
! 469:
! 470: n = LIBNET_IPV6_H + payload_s; /* size of memory block */
! 471:
! 472: if (LIBNET_IPV6_H + payload_s > IP_MAXPACKET)
! 473: {
! 474: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
! 475: "%s(): IP packet too large\n", __func__);
! 476: return (-1);
! 477: }
! 478:
! 479: /*
! 480: * Find the existing protocol block if a ptag is specified, or create
! 481: * a new one.
! 482: */
! 483: p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV6_H);
! 484: if (p == NULL)
! 485: {
! 486: return (-1);
! 487: }
! 488:
! 489: memset(&ip_hdr, 0, sizeof(ip_hdr));
! 490: ip_hdr.ip_flags[0] = 0x06 << 4;
! 491: ip_hdr.ip_flags[1] = ((tc & 0x0F) << 4) | ((fl & 0xF0000) >> 16);
! 492: ip_hdr.ip_flags[2] = fl & 0x0FF00 >> 8;
! 493: ip_hdr.ip_flags[3] = fl & 0x000FF;
! 494: ip_hdr.ip_len = htons(len);
! 495: ip_hdr.ip_nh = nh;
! 496: ip_hdr.ip_hl = hl;
! 497: ip_hdr.ip_src = src;
! 498: ip_hdr.ip_dst = dst;
! 499:
! 500: n = libnet_pblock_append(l, p, (u_int8_t *)&ip_hdr, LIBNET_IPV6_H);
! 501: if (n == -1)
! 502: {
! 503: goto bad;
! 504: }
! 505:
! 506: if ((payload && !payload_s) || (!payload && payload_s))
! 507: {
! 508: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
! 509: "%s(): payload inconsistency\n", __func__);
! 510: goto bad;
! 511: }
! 512:
! 513: if (payload && payload_s)
! 514: {
! 515: n = libnet_pblock_append(l, p, payload, payload_s);
! 516: if (n == -1)
! 517: {
! 518: goto bad;
! 519: }
! 520: }
! 521:
! 522: /* no checksum for IPv6 */
! 523: return (ptag ? ptag : libnet_pblock_update(l, p, LIBNET_IPV6_H,
! 524: LIBNET_PBLOCK_IPV6_H));
! 525: bad:
! 526: libnet_pblock_delete(l, p);
! 527: return (-1);
! 528: }
! 529:
! 530: libnet_ptag_t
! 531: libnet_build_ipv6_frag(u_int8_t nh, u_int8_t reserved, u_int16_t frag,
! 532: u_int32_t id, u_int8_t *payload, u_int32_t payload_s, libnet_t *l,
! 533: libnet_ptag_t ptag)
! 534: {
! 535: u_int32_t n;
! 536: u_int16_t h;
! 537: libnet_pblock_t *p;
! 538: struct libnet_ipv6_frag_hdr ipv6_frag_hdr;
! 539:
! 540: if (l == NULL)
! 541: {
! 542: return (-1);
! 543: }
! 544:
! 545: n = LIBNET_IPV6_FRAG_H + payload_s;
! 546: h = 0;
! 547:
! 548: if (LIBNET_IPV6_FRAG_H + payload_s > IP_MAXPACKET)
! 549: {
! 550: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
! 551: "%s(): IP packet too large\n", __func__);
! 552: return (-1);
! 553: }
! 554:
! 555: /*
! 556: * Find the existing protocol block if a ptag is specified, or create
! 557: * a new one.
! 558: */
! 559: p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV6_FRAG_H);
! 560: if (p == NULL)
! 561: {
! 562: return (-1);
! 563: }
! 564:
! 565: memset(&ipv6_frag_hdr, 0 , sizeof(ipv6_frag_hdr));
! 566: ipv6_frag_hdr.ip_nh = nh;
! 567: ipv6_frag_hdr.ip_reserved = reserved;
! 568: ipv6_frag_hdr.ip_frag = frag;
! 569: ipv6_frag_hdr.ip_id = id;
! 570:
! 571: /*
! 572: * Appened the protocol unit to the list.
! 573: */
! 574: n = libnet_pblock_append(l, p, (u_int8_t *)&ipv6_frag_hdr,
! 575: LIBNET_IPV6_FRAG_H);
! 576: if (n == -1)
! 577: {
! 578: goto bad;
! 579: }
! 580:
! 581: /*
! 582: * Sanity check the payload arguments.
! 583: */
! 584: if ((payload && !payload_s) || (!payload && payload_s))
! 585: {
! 586: sprintf(l->err_buf, "%s(): payload inconsistency\n", __func__);
! 587: goto bad;
! 588: }
! 589:
! 590: /*
! 591: * Append the payload to the list if it exists.
! 592: */
! 593: if (payload && payload_s)
! 594: {
! 595: n = libnet_pblock_append(l, p, payload, payload_s);
! 596: if (n == -1)
! 597: {
! 598: goto bad;
! 599: }
! 600: }
! 601:
! 602: /*
! 603: * Update the protocol block's meta information and return the protocol
! 604: * tag id of this pblock. This tag will be used to locate the pblock
! 605: * in order to modify the protocol header in subsequent calls.
! 606: */
! 607: return (ptag ? ptag : libnet_pblock_update(l, p, h,
! 608: LIBNET_PBLOCK_IPV6_FRAG_H));
! 609: bad:
! 610: libnet_pblock_delete(l, p);
! 611: return (-1);
! 612: }
! 613:
! 614: libnet_ptag_t
! 615: libnet_build_ipv6_routing(u_int8_t nh, u_int8_t len, u_int8_t rtype,
! 616: u_int8_t segments, u_int8_t *payload, u_int32_t payload_s, libnet_t *l,
! 617: libnet_ptag_t ptag)
! 618: {
! 619: u_int32_t n;
! 620: u_int16_t h;
! 621: libnet_pblock_t *p;
! 622: struct libnet_ipv6_routing_hdr ipv6_routing_hdr;
! 623:
! 624: if (l == NULL)
! 625: {
! 626: return (-1);
! 627: }
! 628:
! 629: /* Important: IPv6 routing header routes are specified using the payload
! 630: * interface!
! 631: */
! 632: n = LIBNET_IPV6_ROUTING_H + payload_s;
! 633: h = 0;
! 634:
! 635: if (LIBNET_IPV6_ROUTING_H + payload_s > IP_MAXPACKET)
! 636: {
! 637: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
! 638: "%s(): IP packet too large\n", __func__);
! 639: return (-1);
! 640: }
! 641:
! 642: /*
! 643: * Find the existing protocol block if a ptag is specified, or create
! 644: * a new one.
! 645: */
! 646: p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV6_ROUTING_H);
! 647: if (p == NULL)
! 648: {
! 649: return (-1);
! 650: }
! 651:
! 652: memset(&ipv6_routing_hdr, 0 , sizeof(ipv6_routing_hdr));
! 653: ipv6_routing_hdr.ip_nh = nh;
! 654: ipv6_routing_hdr.ip_len = len;
! 655: ipv6_routing_hdr.ip_rtype = rtype;
! 656: ipv6_routing_hdr.ip_segments = segments;
! 657:
! 658: /*
! 659: * Appened the protocol unit to the list.
! 660: */
! 661: n = libnet_pblock_append(l, p, (u_int8_t *)&ipv6_routing_hdr,
! 662: LIBNET_IPV6_ROUTING_H);
! 663: if (n == -1)
! 664: {
! 665: goto bad;
! 666: }
! 667:
! 668: /*
! 669: * Sanity check the payload arguments.
! 670: */
! 671: if ((payload && !payload_s) || (!payload && payload_s))
! 672: {
! 673: sprintf(l->err_buf, "%s(): payload inconsistency\n", __func__);
! 674: goto bad;
! 675: }
! 676:
! 677: /*
! 678: * Append the payload to the list if it exists.
! 679: */
! 680: if (payload && payload_s)
! 681: {
! 682: n = libnet_pblock_append(l, p, payload, payload_s);
! 683: if (n == -1)
! 684: {
! 685: goto bad;
! 686: }
! 687: }
! 688:
! 689: /*
! 690: * Update the protocol block's meta information and return the protocol
! 691: * tag id of this pblock. This tag will be used to locate the pblock
! 692: * in order to modify the protocol header in subsequent calls.
! 693: */
! 694: return (ptag ? ptag : libnet_pblock_update(l, p, h,
! 695: LIBNET_PBLOCK_IPV6_ROUTING_H));
! 696: bad:
! 697: libnet_pblock_delete(l, p);
! 698: return (-1);
! 699: }
! 700:
! 701: libnet_ptag_t
! 702: libnet_build_ipv6_destopts(u_int8_t nh, u_int8_t len, u_int8_t *payload,
! 703: u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
! 704: {
! 705: u_int32_t n;
! 706: u_int16_t h;
! 707: libnet_pblock_t *p;
! 708: struct libnet_ipv6_destopts_hdr ipv6_destopts_hdr;
! 709:
! 710: if (l == NULL)
! 711: {
! 712: return (-1);
! 713: }
! 714:
! 715: /* Important: IPv6 dest opts information is specified using the payload
! 716: * interface!
! 717: */
! 718: n = LIBNET_IPV6_DESTOPTS_H + payload_s;
! 719: h = 0;
! 720:
! 721: if (LIBNET_IPV6_DESTOPTS_H + payload_s > IP_MAXPACKET)
! 722: {
! 723: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
! 724: "%s(): IP packet too large\n", __func__);
! 725: return (-1);
! 726: }
! 727:
! 728: /*
! 729: * Find the existing protocol block if a ptag is specified, or create
! 730: * a new one.
! 731: */
! 732: p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV6_DESTOPTS_H);
! 733: if (p == NULL)
! 734: {
! 735: return (-1);
! 736: }
! 737:
! 738: memset(&ipv6_destopts_hdr, 0 , sizeof(ipv6_destopts_hdr));
! 739: ipv6_destopts_hdr.ip_nh = nh;
! 740: ipv6_destopts_hdr.ip_len = len;
! 741:
! 742: /*
! 743: * Appened the protocol unit to the list.
! 744: */
! 745: n = libnet_pblock_append(l, p, (u_int8_t *)&ipv6_destopts_hdr,
! 746: LIBNET_IPV6_DESTOPTS_H);
! 747: if (n == -1)
! 748: {
! 749: goto bad;
! 750: }
! 751:
! 752: /*
! 753: * Sanity check the payload arguments.
! 754: */
! 755: if ((payload && !payload_s) || (!payload && payload_s))
! 756: {
! 757: sprintf(l->err_buf, "%s(): payload inconsistency\n", __func__);
! 758: goto bad;
! 759: }
! 760:
! 761: /*
! 762: * Append the payload to the list if it exists.
! 763: */
! 764: if (payload && payload_s)
! 765: {
! 766: n = libnet_pblock_append(l, p, payload, payload_s);
! 767: if (n == -1)
! 768: {
! 769: goto bad;
! 770: }
! 771: }
! 772:
! 773: /*
! 774: * Update the protocol block's meta information and return the protocol
! 775: * tag id of this pblock. This tag will be used to locate the pblock
! 776: * in order to modify the protocol header in subsequent calls.
! 777: */
! 778: return (ptag ? ptag : libnet_pblock_update(l, p, h,
! 779: LIBNET_PBLOCK_IPV6_DESTOPTS_H));
! 780: bad:
! 781: libnet_pblock_delete(l, p);
! 782: return (-1);
! 783: }
! 784:
! 785: libnet_ptag_t
! 786: libnet_build_ipv6_hbhopts(u_int8_t nh, u_int8_t len, u_int8_t *payload,
! 787: u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
! 788: {
! 789: u_int32_t n;
! 790: u_int16_t h;
! 791: libnet_pblock_t *p;
! 792: struct libnet_ipv6_hbhopts_hdr ipv6_hbhopts_hdr;
! 793:
! 794: if (l == NULL)
! 795: {
! 796: return (-1);
! 797: }
! 798:
! 799: /* Important: IPv6 hop by hop opts information is specified using the
! 800: * payload interface!
! 801: */
! 802: n = LIBNET_IPV6_HBHOPTS_H + payload_s;
! 803: h = 0;
! 804:
! 805: if (LIBNET_IPV6_HBHOPTS_H + payload_s > IP_MAXPACKET)
! 806: {
! 807: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
! 808: "%s(): IP packet too large\n", __func__);
! 809: return (-1);
! 810: }
! 811:
! 812: /*
! 813: * Find the existing protocol block if a ptag is specified, or create
! 814: * a new one.
! 815: */
! 816: p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV6_HBHOPTS_H);
! 817: if (p == NULL)
! 818: {
! 819: return (-1);
! 820: }
! 821:
! 822: memset(&ipv6_hbhopts_hdr, 0 , sizeof(ipv6_hbhopts_hdr));
! 823: ipv6_hbhopts_hdr.ip_nh = nh;
! 824: ipv6_hbhopts_hdr.ip_len = len;
! 825:
! 826: /*
! 827: * Appened the protocol unit to the list.
! 828: */
! 829: n = libnet_pblock_append(l, p, (u_int8_t *)&ipv6_hbhopts_hdr,
! 830: LIBNET_IPV6_HBHOPTS_H);
! 831: if (n == -1)
! 832: {
! 833: goto bad;
! 834: }
! 835:
! 836: /*
! 837: * Sanity check the payload arguments.
! 838: */
! 839: if ((payload && !payload_s) || (!payload && payload_s))
! 840: {
! 841: sprintf(l->err_buf, "%s(): payload inconsistency\n", __func__);
! 842: goto bad;
! 843: }
! 844:
! 845: /*
! 846: * Append the payload to the list if it exists.
! 847: */
! 848: if (payload && payload_s)
! 849: {
! 850: n = libnet_pblock_append(l, p, payload, payload_s);
! 851: if (n == -1)
! 852: {
! 853: goto bad;
! 854: }
! 855: }
! 856:
! 857: /*
! 858: * Update the protocol block's meta information and return the protocol
! 859: * tag id of this pblock. This tag will be used to locate the pblock
! 860: * in order to modify the protocol header in subsequent calls.
! 861: */
! 862: return (ptag ? ptag : libnet_pblock_update(l, p, h,
! 863: LIBNET_PBLOCK_IPV6_HBHOPTS_H));
! 864: bad:
! 865: libnet_pblock_delete(l, p);
! 866: return (-1);
! 867: }
! 868:
! 869: libnet_ptag_t
! 870: libnet_autobuild_ipv6(u_int16_t len, u_int8_t nh, struct libnet_in6_addr dst,
! 871: libnet_t *l)
! 872: {
! 873:
! 874: /* NYI */
! 875: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
! 876: "%s(): not yet implemented\n", __func__);
! 877: return (-1);
! 878: }
! 879:
! 880: /* EOF */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>