Annotation of embedaddon/libnet/src/libnet_build_icmp.c, revision 1.1.1.2
1.1 misho 1: /*
1.1.1.2 ! misho 2: * $Id: libnet_build_icmp.c,v 1.17 2004/04/13 17:32:28 mike Exp $
1.1 misho 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:
1.1.1.2 ! misho 42: #include <assert.h>
! 43:
1.1 misho 44: /* some common cruft for completing ICMP error packets */
45: #define LIBNET_BUILD_ICMP_ERR_FINISH(len) \
46: do \
47: { \
1.1.1.2 ! misho 48: n = libnet_pblock_append(l, p, (uint8_t *)&icmp_hdr, len); \
1.1 misho 49: if (n == -1) \
50: { \
51: goto bad; \
52: } \
53: \
1.1.1.2 ! misho 54: if (payload_s && !payload) \
1.1 misho 55: { \
56: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, \
57: "%s(): payload inconsistency\n", __func__); \
58: goto bad; \
59: } \
60: \
1.1.1.2 ! misho 61: if (payload_s) \
1.1 misho 62: { \
63: n = libnet_pblock_append(l, p, payload, payload_s); \
64: if (n == -1) \
65: { \
66: goto bad; \
67: } \
68: } \
69: \
70: if (sum == 0) \
71: { \
72: libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM); \
73: } \
74: } while (0)
75:
76: libnet_ptag_t
1.1.1.2 ! misho 77: libnet_build_icmpv4_echo(uint8_t type, uint8_t code, uint16_t sum,
! 78: uint16_t id, uint16_t seq, const uint8_t *payload, uint32_t payload_s,
1.1 misho 79: libnet_t *l, libnet_ptag_t ptag)
80: {
1.1.1.2 ! misho 81: uint32_t n, h;
1.1 misho 82: libnet_pblock_t *p;
83: struct libnet_icmpv4_hdr icmp_hdr;
84:
85: if (l == NULL)
86: {
87: return (-1);
88: }
89:
90: n = LIBNET_ICMPV4_ECHO_H + payload_s; /* size of memory block */
91: h = LIBNET_ICMPV4_ECHO_H + payload_s; /* hl for checksum */
92:
93: /*
94: * Find the existing protocol block if a ptag is specified, or create
95: * a new one.
96: */
97: p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV4_ECHO_H);
98: if (p == NULL)
99: {
100: return (-1);
101: }
102:
103: memset(&icmp_hdr, 0, sizeof(icmp_hdr));
104: icmp_hdr.icmp_type = type; /* packet type */
105: icmp_hdr.icmp_code = code; /* packet code */
106: icmp_hdr.icmp_sum = (sum ? htons(sum) : 0); /* checksum */
107: icmp_hdr.icmp_id = htons(id); /* packet id */
108: icmp_hdr.icmp_seq = htons(seq); /* packet seq */
109:
1.1.1.2 ! misho 110: n = libnet_pblock_append(l, p, (uint8_t *)&icmp_hdr, LIBNET_ICMPV4_ECHO_H);
1.1 misho 111: if (n == -1)
112: {
113: goto bad;
114: }
115:
1.1.1.2 ! misho 116: /* boilerplate payload sanity check / append macro */
! 117: LIBNET_DO_PAYLOAD(l, p);
1.1 misho 118:
119: if (sum == 0)
120: {
121: /*
122: * If checksum is zero, by default libnet will compute a checksum
123: * for the user. The programmer can override this by calling
124: * libnet_toggle_checksum(l, ptag, 1);
125: */
126: libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
127: }
128: return (ptag ? ptag : libnet_pblock_update(l, p, h,
129: LIBNET_PBLOCK_ICMPV4_ECHO_H));
130: bad:
131: libnet_pblock_delete(l, p);
132: return (-1);
133: }
134:
135: libnet_ptag_t
1.1.1.2 ! misho 136: libnet_build_icmpv4_mask(uint8_t type, uint8_t code, uint16_t sum,
! 137: uint16_t id, uint16_t seq, uint32_t mask, const uint8_t *payload,
! 138: uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
1.1 misho 139: {
1.1.1.2 ! misho 140: uint32_t n, h;
1.1 misho 141: libnet_pblock_t *p;
142: struct libnet_icmpv4_hdr icmp_hdr;
143:
144: if (l == NULL)
145: {
146: return (-1);
147: }
148:
149: n = LIBNET_ICMPV4_MASK_H + payload_s; /* size of memory block */
150: h = LIBNET_ICMPV4_MASK_H + payload_s; /* hl for checksum */
151:
152: /*
153: * Find the existing protocol block if a ptag is specified, or create
154: * a new one.
155: */
156: p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV4_MASK_H);
157: if (p == NULL)
158: {
159: return (-1);
160: }
161:
162: memset(&icmp_hdr, 0, sizeof(icmp_hdr));
163: icmp_hdr.icmp_type = type; /* packet type */
164: icmp_hdr.icmp_code = code; /* packet code */
165: icmp_hdr.icmp_sum = (sum ? htons(sum) : 0); /* checksum */
166: icmp_hdr.icmp_id = htons(id); /* packet id */
167: icmp_hdr.icmp_seq = htons(seq); /* packet seq */
168: icmp_hdr.icmp_mask = htonl(mask); /* address mask */
169:
1.1.1.2 ! misho 170: n = libnet_pblock_append(l, p, (uint8_t *)&icmp_hdr, LIBNET_ICMPV4_MASK_H);
1.1 misho 171: if (n == -1)
172: {
173: goto bad;
174: }
175:
1.1.1.2 ! misho 176: /* boilerplate payload sanity check / append macro */
! 177: LIBNET_DO_PAYLOAD(l, p);
1.1 misho 178:
179: if (sum == 0)
180: {
181: /*
182: * If checksum is zero, by default libnet will compute a checksum
183: * for the user. The programmer can override this by calling
184: * libnet_toggle_checksum(l, ptag, 1);
185: */
186: libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
187: }
188: return (ptag ? ptag : libnet_pblock_update(l, p, h,
189: LIBNET_PBLOCK_ICMPV4_MASK_H));
190: bad:
191: libnet_pblock_delete(l, p);
192: return (-1);
193: }
194:
195: libnet_ptag_t
1.1.1.2 ! misho 196: libnet_build_icmpv4_timestamp(uint8_t type, uint8_t code, uint16_t sum,
! 197: uint16_t id, uint16_t seq, uint32_t otime, uint32_t rtime, uint32_t ttime,
! 198: const uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
1.1 misho 199: {
1.1.1.2 ! misho 200: uint32_t n, h;
1.1 misho 201: libnet_pblock_t *p;
202: struct libnet_icmpv4_hdr icmp_hdr;
203:
204: if (l == NULL)
205: {
206: return (-1);
207: }
208:
209: n = LIBNET_ICMPV4_TS_H + payload_s; /* size of memory block */
210: h = LIBNET_ICMPV4_TS_H + payload_s; /* hl for checksum */
211:
212: /*
213: * Find the existing protocol block if a ptag is specified, or create
214: * a new one.
215: */
216: p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV4_TS_H);
217: if (p == NULL)
218: {
219: return (-1);
220: }
221:
222: memset(&icmp_hdr, 0, sizeof(icmp_hdr));
223: icmp_hdr.icmp_type = type; /* packet type */
224: icmp_hdr.icmp_code = code; /* packet code */
225: icmp_hdr.icmp_sum = (sum ? htons(sum) : 0); /* checksum */
226: icmp_hdr.icmp_id = htons(id); /* packet id */
227: icmp_hdr.icmp_seq = htons(seq); /* packet seq */
228: icmp_hdr.icmp_otime = htonl(otime); /* original timestamp */
229: icmp_hdr.icmp_rtime = htonl(rtime); /* receive timestamp */
230: icmp_hdr.icmp_ttime = htonl(ttime); /* transmit timestamp */
231:
1.1.1.2 ! misho 232: n = libnet_pblock_append(l, p, (uint8_t *)&icmp_hdr, LIBNET_ICMPV4_TS_H);
1.1 misho 233: if (n == -1)
234: {
235: goto bad;
236: }
237:
1.1.1.2 ! misho 238: /* boilerplate payload sanity check / append macro */
! 239: LIBNET_DO_PAYLOAD(l, p);
1.1 misho 240:
241: if (sum == 0)
242: {
243: /*
244: * If checksum is zero, by default libnet will compute a checksum
245: * for the user. The programmer can override this by calling
246: * libnet_toggle_checksum(l, ptag, 1);
247: */
248: libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
249: }
250: return (ptag ? ptag : libnet_pblock_update(l, p, h,
251: LIBNET_PBLOCK_ICMPV4_TS_H));
252: bad:
253: libnet_pblock_delete(l, p);
254: return (-1);
255: }
256:
257: libnet_ptag_t
1.1.1.2 ! misho 258: libnet_build_icmpv4_unreach(uint8_t type, uint8_t code, uint16_t sum,
! 259: const uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
1.1 misho 260: {
1.1.1.2 ! misho 261: uint32_t n, h;
1.1 misho 262: libnet_pblock_t *p;
263: struct libnet_icmpv4_hdr icmp_hdr;
264:
265: if (l == NULL)
266: {
267: return (-1);
268: }
269: n = LIBNET_ICMPV4_UNREACH_H + payload_s; /* size of memory block */
270:
271: /*
272: * FREDRAYNAL: as ICMP checksum includes what is embedded in
273: * the payload, and what is after the ICMP header, we need to include
274: * those 2 sizes.
275: */
276: h = LIBNET_ICMPV4_UNREACH_H + payload_s + l->total_size;
277:
278: /*
279: * Find the existing protocol block if a ptag is specified, or create
280: * a new one.
281: */
282: p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV4_UNREACH_H);
283: if (p == NULL)
284: {
285: return (-1);
286: }
287:
288: memset(&icmp_hdr, 0, sizeof(icmp_hdr));
289: icmp_hdr.icmp_type = type; /* packet type */
290: icmp_hdr.icmp_code = code; /* packet code */
291: icmp_hdr.icmp_sum = (sum ? htons(sum) : 0); /* checksum */
292: icmp_hdr.icmp_id = 0; /* must be 0 */
293: icmp_hdr.icmp_seq = 0; /* must be 0 */
294:
295: LIBNET_BUILD_ICMP_ERR_FINISH(LIBNET_ICMPV4_UNREACH_H);
296:
297: return (ptag ? ptag : libnet_pblock_update(l, p, h,
298: LIBNET_PBLOCK_ICMPV4_UNREACH_H));
299: bad:
300: libnet_pblock_delete(l, p);
301: return (-1);
302: }
303:
304: libnet_ptag_t
1.1.1.2 ! misho 305: libnet_build_icmpv4_timeexceed(uint8_t type, uint8_t code, uint16_t sum,
! 306: const uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
1.1 misho 307: {
1.1.1.2 ! misho 308: uint32_t n, h;
1.1 misho 309: libnet_pblock_t *p;
310: struct libnet_icmpv4_hdr icmp_hdr;
311:
312: if (l == NULL)
313: {
314: return (-1);
315: }
316:
317: /* size of memory block */
1.1.1.2 ! misho 318: n = LIBNET_ICMPV4_TIMXCEED_H + payload_s;
1.1 misho 319: /*
320: * FREDRAYNAL: as ICMP checksum includes what is embedded in
321: * the payload, and what is after the ICMP header, we need to include
322: * those 2 sizes.
323: */
324: h = LIBNET_ICMPV4_TIMXCEED_H + payload_s + l->total_size;
325:
326: /*
327: * Find the existing protocol block if a ptag is specified, or create
328: * a new one.
329: */
330: p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV4_TIMXCEED_H);
331: if (p == NULL)
332: {
333: return (-1);
334: }
335:
336: memset(&icmp_hdr, 0, sizeof(icmp_hdr));
337: icmp_hdr.icmp_type = type; /* packet type */
338: icmp_hdr.icmp_code = code; /* packet code */
339: icmp_hdr.icmp_sum = (sum ? htons(sum) : 0); /* checksum */
340: icmp_hdr.icmp_id = 0; /* must be 0 */
341: icmp_hdr.icmp_seq = 0; /* must be 0 */
342:
343: LIBNET_BUILD_ICMP_ERR_FINISH(LIBNET_ICMPV4_TIMXCEED_H);
344:
345: return (ptag ? ptag : libnet_pblock_update(l, p, h,
346: LIBNET_PBLOCK_ICMPV4_TIMXCEED_H));
347: bad:
348: libnet_pblock_delete(l, p);
349: return (-1);
350: }
351:
352: libnet_ptag_t
1.1.1.2 ! misho 353: libnet_build_icmpv4_redirect(uint8_t type, uint8_t code, uint16_t sum,
! 354: uint32_t gateway, const uint8_t *payload, uint32_t payload_s, libnet_t *l,
1.1 misho 355: libnet_ptag_t ptag)
356:
357: {
1.1.1.2 ! misho 358: uint32_t n, h;
1.1 misho 359: libnet_pblock_t *p;
360: struct libnet_icmpv4_hdr icmp_hdr;
361:
362: if (l == NULL)
363: {
364: return (-1);
365: }
366:
1.1.1.2 ! misho 367: n = LIBNET_ICMPV4_REDIRECT_H + payload_s; /* size of memory block */
1.1 misho 368: /*
369: * FREDRAYNAL: as ICMP checksum includes what is embedded in
370: * the payload, and what is after the ICMP header, we need to include
371: * those 2 sizes.
372: */
373: h = LIBNET_ICMPV4_REDIRECT_H + payload_s + l->total_size;
374:
375: /*
376: * Find the existing protocol block if a ptag is specified, or create
377: * a new one.
378: */
379: p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV4_REDIRECT_H);
380: if (p == NULL)
381: {
382: return (-1);
383: }
384:
385: memset(&icmp_hdr, 0, sizeof(icmp_hdr));
386: icmp_hdr.icmp_type = type; /* packet type */
387: icmp_hdr.icmp_code = code; /* packet code */
388: icmp_hdr.icmp_sum = (sum ? htons(sum) : 0); /* checksum */
389: icmp_hdr.hun.gateway = gateway;
390:
391: LIBNET_BUILD_ICMP_ERR_FINISH(LIBNET_ICMPV4_REDIRECT_H);
392:
393: return (ptag ? ptag : libnet_pblock_update(l, p, h,
394: LIBNET_PBLOCK_ICMPV4_REDIRECT_H));
395: bad:
396: libnet_pblock_delete(l, p);
397: return (-1);
398: }
399:
1.1.1.2 ! misho 400:
! 401: libnet_ptag_t
! 402: libnet_build_icmpv6_common(
! 403: uint8_t type, uint8_t code, uint16_t sum,
! 404: const void* specific, uint32_t specific_s, uint8_t pblock_type,
! 405: uint8_t *payload, uint32_t payload_s,
! 406: libnet_t *l, libnet_ptag_t ptag
! 407: )
! 408: {
! 409: uint32_t n;
! 410: libnet_pblock_t *p;
! 411: struct libnet_icmpv6_hdr icmp_hdr;
! 412:
! 413: if (l == NULL)
! 414: {
! 415: return (-1);
! 416: }
! 417:
! 418: n = LIBNET_ICMPV6_COMMON_H + specific_s + payload_s;
! 419:
! 420: p = libnet_pblock_probe(l, ptag, n, pblock_type);
! 421:
! 422: if (p == NULL)
! 423: {
! 424: return (-1);
! 425: }
! 426:
! 427: memset(&icmp_hdr, 0, sizeof(icmp_hdr));
! 428: icmp_hdr.icmp_type = type;
! 429: icmp_hdr.icmp_code = code;
! 430: icmp_hdr.icmp_sum = htons(sum);
! 431:
! 432: if (libnet_pblock_append(l, p, (uint8_t *)&icmp_hdr, LIBNET_ICMPV6_COMMON_H) < 0)
! 433: {
! 434: goto bad;
! 435: }
! 436:
! 437: if (libnet_pblock_append(l, p, specific, specific_s) < 0)
! 438: {
! 439: goto bad;
! 440: }
! 441:
! 442: if (libnet_pblock_append(l, p, payload, payload_s) < 0)
! 443: {
! 444: goto bad;
! 445: }
! 446:
! 447: if (sum == 0)
! 448: {
! 449: libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
! 450: }
! 451:
! 452: return ptag ? ptag : libnet_pblock_update(l, p, 0, pblock_type);
! 453:
! 454: bad:
! 455: libnet_pblock_delete(l, p);
! 456:
! 457: return -1;
! 458: }
! 459:
! 460: libnet_ptag_t libnet_build_icmpv6(uint8_t type, uint8_t code, uint16_t sum,
! 461: uint8_t* payload, uint32_t payload_s,
! 462: libnet_t* l, libnet_ptag_t ptag)
! 463: {
! 464: return libnet_build_icmpv6_common(
! 465: type, code, sum,
! 466: NULL, 0, LIBNET_PBLOCK_ICMPV6_UNREACH_H,
! 467: payload, payload_s,
! 468: l, ptag);
! 469: }
! 470:
! 471: libnet_ptag_t
! 472: libnet_build_icmpv6_unreach(
! 473: uint8_t type, uint8_t code, uint16_t sum,
! 474: uint8_t *payload, uint32_t payload_s,
! 475: libnet_t *l, libnet_ptag_t ptag
! 476: )
! 477: {
! 478: struct libnet_icmpv6_unreach specific;
! 479:
! 480: memset(&specific, 0, sizeof(specific));
! 481:
! 482: return libnet_build_icmpv6_common(
! 483: type, code, sum,
! 484: &specific, sizeof(specific), LIBNET_PBLOCK_ICMPV6_UNREACH_H,
! 485: payload, payload_s,
! 486: l, ptag);
! 487: }
! 488:
! 489: libnet_ptag_t
! 490: libnet_build_icmpv6_echo(
! 491: uint8_t type, uint8_t code, uint16_t sum,
! 492: uint16_t id, uint16_t seq,
! 493: uint8_t *payload, uint32_t payload_s,
! 494: libnet_t *l, libnet_ptag_t ptag
! 495: )
! 496: {
! 497: struct libnet_icmpv6_echo specific;
! 498:
! 499: memset(&specific, 0, sizeof(specific));
! 500: specific.id = htons(id);
! 501: specific.seq = htons(seq);
! 502:
! 503: return libnet_build_icmpv6_common(
! 504: type, code, sum,
! 505: &specific, sizeof(specific), LIBNET_PBLOCK_ICMPV6_ECHO_H,
! 506: payload, payload_s,
! 507: l, ptag);
! 508: }
! 509:
! 510:
! 511: libnet_ptag_t libnet_build_icmpv6_ndp_nsol(
! 512: uint8_t type, uint8_t code, uint16_t sum,
! 513: struct libnet_in6_addr target,
! 514: uint8_t *payload, uint32_t payload_s,
! 515: libnet_t* l, libnet_ptag_t ptag)
! 516: {
! 517: struct libnet_icmpv6_ndp_nsol specific;
! 518:
! 519: memset(&specific, 0, sizeof(specific));
! 520: specific.reserved = 0;
! 521: specific.target_addr = target;
! 522:
! 523: return libnet_build_icmpv6_common(
! 524: type, code, sum,
! 525: &specific, sizeof(specific), LIBNET_PBLOCK_ICMPV6_NDP_NSOL_H,
! 526: payload, payload_s,
! 527: l, ptag);
! 528: }
! 529:
! 530:
! 531: libnet_ptag_t libnet_build_icmpv6_ndp_nadv(
! 532: uint8_t type, uint8_t code, uint16_t sum,
! 533: uint32_t flags, struct libnet_in6_addr target,
! 534: uint8_t *payload, uint32_t payload_s,
! 535: libnet_t* l, libnet_ptag_t ptag)
! 536: {
! 537:
! 538: struct libnet_icmpv6_ndp_nadv specific;
! 539:
! 540: memset(&specific, 0, sizeof(specific));
! 541: specific.flags = htonl(flags);
! 542: specific.target_addr = target;
! 543:
! 544: return libnet_build_icmpv6_common(
! 545: type, code, sum,
! 546: &specific, sizeof(specific), LIBNET_PBLOCK_ICMPV6_NDP_NADV_H,
! 547: payload, payload_s,
! 548: l, ptag);
! 549: }
! 550:
! 551: libnet_ptag_t libnet_build_icmpv6_ndp_opt(
! 552: uint8_t type, uint8_t* option, uint32_t option_s,
! 553: libnet_t* l, libnet_ptag_t ptag)
! 554: {
! 555: struct libnet_icmpv6_ndp_opt opt;
! 556: uint32_t n;
! 557: static uint8_t pad[8] = { 0 };
! 558: uint32_t pad_s = 0;
! 559: libnet_pblock_t* p;
! 560:
! 561: if(l == NULL)
! 562: return -1;
! 563:
! 564: if(!option)
! 565: option_s = 0;
! 566:
! 567: /* options need to be padded to a multiple of 8-bytes, and opts.len is in units of 8-bytes */
! 568: n = sizeof(opt) + option_s;
! 569:
! 570: if(n % 8)
! 571: {
! 572: n += 8 - (n % 8);
! 573: }
! 574:
! 575: if(n > (0xff * 8))
! 576: {
! 577: return -1;
! 578: }
! 579:
! 580: pad_s = n - option_s - sizeof(opt);
! 581:
! 582: assert((n % 8) == 0);
! 583: assert(pad_s < sizeof(pad));
! 584:
! 585: p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV6_NDP_OPT_H);
! 586: if(p == NULL)
! 587: return -1;
! 588:
! 589: memset(&opt, 0, sizeof(opt));
! 590: opt.type = type;
! 591: opt.len = n / 8;
! 592:
! 593: if(libnet_pblock_append(l, p, &opt, sizeof(opt)) == -1)
! 594: goto bad;
! 595:
! 596: if(libnet_pblock_append(l, p, option, option_s) == -1)
! 597: goto bad;
! 598:
! 599: if(libnet_pblock_append(l, p, pad, pad_s) == -1)
! 600: goto bad;
! 601:
! 602: return ptag ? ptag : libnet_pblock_update(l, p, n, LIBNET_PBLOCK_ICMPV6_NDP_OPT_H);
! 603:
! 604: bad:
! 605: libnet_pblock_delete(l, p);
! 606: return -1;
! 607: }
! 608:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>