Annotation of embedaddon/libnet/src/libnet_build_icmp.c, revision 1.1.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>