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