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