Annotation of embedaddon/libnet/src/libnet_build_gre.c, revision 1.1.1.1
1.1 misho 1: /*
2: * libnet
3: * libnet_build_gre.c - GRE packet assembler
4: *
5: * Copyright (c) 2003 Frédéric Raynal <pappy@security-labs.org>
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27: * SUCH DAMAGE.
28: *
29: */
30:
31: #if (HAVE_CONFIG_H)
32: #include "../include/config.h"
33: #endif
34: #if (!(_WIN32) || (__CYGWIN__))
35: #include "../include/libnet.h"
36: #else
37: #include "../include/win32/libnet.h"
38: #endif
39:
40: /*
41: * Overall packet
42: *
43: * The entire encapsulated packet would then have the form:
44: *
45: * ---------------------------------
46: * | |
47: * | Delivery Header |
48: * | |
49: * ---------------------------------
50: * | |
51: * | GRE Header |
52: * | |
53: * ---------------------------------
54: * | |
55: * | Payload packet |
56: * | |
57: * ---------------------------------
58: *
59: * RFC 1701 defines a header.
60: * A new RFC (2784) has changed the header and proposed to remove the key
61: * and seqnum.
62: * A newer RFC (2890) has changed the header proposed in RFC 2784 by putting
63: * back key and seqnum.
64: * These will be supported the day IETF'guys stop this mess !
65: *
66: * FR
67: */
68:
69:
70: /*
71: * Generic Routing Encapsulation (GRE)
72: * RFC 1701 http://www.faqs.org/rfcs/rfc1701.html
73: *
74: *
75: * Packet header
76: *
77: * The GRE packet header has the form:
78: *
79: * 0 1 2 3
80: * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
81: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
82: * |C|R|K|S|s|Recur| Flags | Ver | Protocol Type |
83: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
84: * | Checksum (optional) | Offset (optional) |
85: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
86: * | Key (optional) |
87: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
88: * | Sequence Number (optional) |
89: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
90: * | Routing (optional) |
91: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
92: *
93: * Enhanced GRE header
94: *
95: * See rfc 2637 for details. It is used for PPTP tunneling.
96: *
97: * 0 1 2 3
98: * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
99: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
100: * |C|R|K|S|s|Recur|A| Flags | Ver | Protocol Type |
101: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
102: * | Key (HW) Payload Length | Key (LW) Call ID |
103: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
104: * | Sequence Number (Optional) |
105: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
106: * | Acknowledgment Number (Optional) |
107: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
108: *
109: */
110:
111: static inline void
112: __libnet_print_gre_flags_ver(u_int16_t fv)
113: {
114: printf("version = %d (%d) -> ",
115: fv & GRE_VERSION_MASK, libnet_getgre_length(fv));
116: if (fv & GRE_CSUM)
117: {
118: printf("CSUM ");
119: }
120: if (fv & GRE_ROUTING)
121: {
122: printf("ROUTING ");
123: }
124: if (fv & GRE_KEY)
125: {
126: printf("KEY ");
127: }
128: if (fv & GRE_SEQ)
129: {
130: printf("SEQ ");
131: }
132: if (fv & GRE_ACK)
133: {
134: printf("ACK ");
135: }
136: printf("\n");
137: }
138:
139:
140: /* FIXME: what is the portability of the "((struct libnet_gre_hdr*)0)->" ? */
141: inline u_int32_t
142: libnet_getgre_length(u_int16_t fv)
143: {
144:
145: u_int32_t n = LIBNET_GRE_H;
146: /*
147: * If either the Checksum Present bit or the Routing Present bit are
148: * set, BOTH the Checksum and Offset fields are present in the GRE
149: * packet.
150: */
151:
152: if ((!(fv & GRE_VERSION_MASK) && (fv & (GRE_CSUM|GRE_ROUTING))) || /* v0 */
153: (fv & GRE_VERSION_MASK) ) /* v1 */
154: {
155: n += sizeof( ((struct libnet_gre_hdr *)0)->gre_sum) +
156: sizeof( ((struct libnet_gre_hdr *)0)->gre_offset);
157: }
158:
159: if ((!(fv & GRE_VERSION_MASK) && (fv & GRE_KEY)) || /* v0 */
160: ( (fv & GRE_VERSION_MASK) && (fv & GRE_SEQ)) ) /* v1 */
161: {
162: n += sizeof( ((struct libnet_gre_hdr *)0)->gre_key);
163: }
164:
165: if ((!(fv & GRE_VERSION_MASK) && (fv & GRE_SEQ)) || /* v0 */
166: ( (fv & GRE_VERSION_MASK) && (fv & GRE_ACK)) ) /* v1 */
167: {
168: n += sizeof( ((struct libnet_gre_hdr *)0)->gre_seq );
169: }
170:
171: return (n);
172: }
173:
174: libnet_ptag_t
175: libnet_build_gre(u_int16_t fv, u_int16_t type, u_int16_t sum,
176: u_int16_t offset, u_int32_t key, u_int32_t seq, u_int16_t len,
177: u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
178: {
179: u_int32_t n;
180: libnet_pblock_t *p;
181: struct libnet_gre_hdr gre_hdr;
182:
183: if (l == NULL)
184: {
185: return (-1);
186: }
187:
188: n = libnet_getgre_length(fv) + payload_s;
189:
190: /*
191: * Find the existing protocol block if a ptag is specified, or create
192: * a new one.
193: */
194: p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_GRE_H);
195: if (p == NULL)
196: {
197: return (-1);
198: }
199:
200: gre_hdr.flags_ver = htons(fv);
201: gre_hdr.type = htons(type);
202: n = libnet_pblock_append(l, p, (u_int8_t *)&gre_hdr, LIBNET_GRE_H);
203: if (n == -1)
204: {
205: /* err msg set in libnet_pblock_append() */
206: goto bad;
207: }
208:
209: if ((!(fv & GRE_VERSION_MASK) && (fv & (GRE_CSUM|GRE_ROUTING))) || /* v0 */
210: (fv & GRE_VERSION_MASK)) /* v1 */
211: {
212: sum = htons(sum);
213: n = libnet_pblock_append(l, p, (u_int8_t*)&sum,
214: sizeof(gre_hdr.gre_sum));
215: if (n == -1)
216: {
217: /* err msg set in libnet_pblock_append() */
218: goto bad;
219: }
220: offset = htons(offset);
221: n = libnet_pblock_append(l, p, (u_int8_t*)&offset,
222: sizeof(gre_hdr.gre_offset));
223: if (n == -1)
224: {
225: /* err msg set in libnet_pblock_append() */
226: goto bad;
227: }
228: }
229:
230: if ((!(fv & GRE_VERSION_MASK) && (fv & GRE_KEY)) || /* v0 */
231: ( (fv & GRE_VERSION_MASK) && (fv & GRE_SEQ)) ) /* v1 */
232: {
233: key = htonl(key);
234: n = libnet_pblock_append(l, p, (u_int8_t*)&key,
235: sizeof(gre_hdr.gre_key));
236: if (n == -1)
237: {
238: /* err msg set in libnet_pblock_append() */
239: goto bad;
240: }
241: }
242:
243: if ((!(fv & GRE_VERSION_MASK) && (fv & GRE_SEQ)) || /* v0 */
244: ( (fv & GRE_VERSION_MASK) && (fv & GRE_ACK)) ) /* v1 */
245: {
246: seq = htonl(seq);
247: n = libnet_pblock_append(l, p, (u_int8_t*)&seq,
248: sizeof(gre_hdr.gre_seq));
249: if (n == -1)
250: {
251: /* err msg set in libnet_pblock_append() */
252: goto bad;
253: }
254: }
255:
256: if ((payload && !payload_s) || (!payload && payload_s))
257: {
258: sprintf(l->err_buf, "%s(): payload inconsistency\n", __func__);
259: goto bad;
260: }
261:
262: if (payload && payload_s)
263: {
264: n = libnet_pblock_append(l, p, payload, payload_s);
265: if (n == -1)
266: {
267: /* err msg set in libnet_pblock_append() */
268: goto bad;
269: }
270: }
271:
272: if ( (fv & GRE_CSUM) && (!sum) )
273: {
274: libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
275: }
276:
277: return (ptag ? ptag : libnet_pblock_update(l, p, len, LIBNET_PBLOCK_GRE_H));
278:
279: bad:
280: libnet_pblock_delete(l, p);
281: return (-1);
282: }
283:
284: libnet_ptag_t
285: libnet_build_egre(u_int16_t fv, u_int16_t type, u_int16_t sum,
286: u_int16_t offset, u_int32_t key, u_int32_t seq, u_int16_t len,
287: u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
288: {
289: return (libnet_build_gre(fv, type, sum, offset, key, seq, len,
290: payload, payload_s, l, ptag));
291: }
292:
293: /*
294: * Routing (variable)
295: *
296: * The Routing field is optional and is present only if the Routing
297: * Present bit is set to 1.
298: *
299: * The Routing field is a list of Source Route Entries (SREs). Each
300: * SRE has the form:
301: *
302: * 0 1 2 3
303: * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
304: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
305: * | Address Family | SRE Offset | SRE Length |
306: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
307: * | Routing Information ...
308: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
309: *
310: */
311: libnet_ptag_t
312: libnet_build_gre_sre(u_int16_t af, u_int8_t offset, u_int8_t length,
313: u_int8_t *routing, u_int8_t *payload, u_int32_t payload_s, libnet_t *l,
314: libnet_ptag_t ptag)
315: {
316: u_int32_t n;
317: libnet_pblock_t *p;
318: struct libnet_gre_sre_hdr sre_hdr;
319:
320: if (l == NULL)
321: {
322: return (-1);
323: }
324:
325: n = LIBNET_GRE_SRE_H + length + payload_s;
326:
327: /*
328: * Find the existing protocol block if a ptag is specified, or create
329: * a new one.
330: */
331: p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_GRE_SRE_H);
332: if (p == NULL)
333: {
334: return (-1);
335: }
336: sre_hdr.af = htons(af);
337: sre_hdr.sre_offset = offset;
338: sre_hdr.sre_length = length;
339: n = libnet_pblock_append(l, p, (u_int8_t *)&sre_hdr, LIBNET_GRE_SRE_H);
340: if (n == -1)
341: {
342: /* err msg set in libnet_pblock_append() */
343: goto bad;
344: }
345:
346: if ((routing && !length) || (!routing && length))
347: {
348: sprintf(l->err_buf, "%s(): routing inconsistency\n", __func__);
349: goto bad;
350: }
351:
352: if (routing && length)
353: {
354: n = libnet_pblock_append(l, p, routing, length);
355: if (n == -1)
356: {
357: /* err msg set in libnet_pblock_append() */
358: goto bad;
359: }
360: }
361:
362: if ((payload && !payload_s) || (!payload && payload_s))
363: {
364: sprintf(l->err_buf, "%s(): payload inconsistency\n", __func__);
365: goto bad;
366: }
367:
368: if (payload && payload_s)
369: {
370: n = libnet_pblock_append(l, p, payload, payload_s);
371: if (n == -1)
372: {
373: /* err msg set in libnet_pblock_append() */
374: goto bad;
375: }
376: }
377:
378: return (ptag ? ptag : libnet_pblock_update(l, p, 0,
379: LIBNET_PBLOCK_GRE_SRE_H));
380:
381: bad:
382: libnet_pblock_delete(l, p);
383: return (-1);
384:
385: }
386:
387: libnet_ptag_t
388: libnet_build_gre_last_sre(libnet_t *l, libnet_ptag_t ptag)
389: {
390: u_int32_t n, zero = 0;
391: libnet_pblock_t *p;
392:
393: if (l == NULL)
394: {
395: return (-1);
396: }
397:
398: n = LIBNET_GRE_SRE_H;
399:
400: /*
401: * Find the existing protocol block if a ptag is specified, or create
402: * a new one.
403: */
404: p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_GRE_H);
405: if (p == NULL)
406: {
407: return (-1);
408: }
409:
410: n = libnet_pblock_append(l, p, (u_int8_t *)&zero, LIBNET_GRE_SRE_H);
411: if (n == -1)
412: {
413: /* err msg set in libnet_pblock_append() */
414: goto bad;
415: }
416:
417: return (ptag ? ptag : libnet_pblock_update(l, p, 0,
418: LIBNET_PBLOCK_GRE_SRE_H));
419:
420: bad:
421: libnet_pblock_delete(l, p);
422: return (-1);
423:
424: }
425:
426:
427: /* EOF */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>