Annotation of embedaddon/libnet/src/libnet_build_gre.c, revision 1.1.1.2
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: */
1.1.1.2 ! misho 110: #if 0
! 111: static void
! 112: __libnet_print_gre_flags_ver(uint16_t fv)
1.1 misho 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: }
1.1.1.2 ! misho 138: #endif
1.1 misho 139:
140: /* FIXME: what is the portability of the "((struct libnet_gre_hdr*)0)->" ? */
1.1.1.2 ! misho 141: uint32_t
! 142: libnet_getgre_length(uint16_t fv)
1.1 misho 143: {
144:
1.1.1.2 ! misho 145: uint32_t n = LIBNET_GRE_H;
1.1 misho 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
1.1.1.2 ! misho 175: libnet_build_gre(uint16_t fv, uint16_t type, uint16_t sum,
! 176: uint16_t offset, uint32_t key, uint32_t seq, uint16_t len,
! 177: const uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
1.1 misho 178: {
1.1.1.2 ! misho 179: uint32_t n;
1.1 misho 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);
1.1.1.2 ! misho 202: n = libnet_pblock_append(l, p, (uint8_t *)&gre_hdr, LIBNET_GRE_H);
1.1 misho 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);
1.1.1.2 ! misho 213: n = libnet_pblock_append(l, p, (uint8_t*)&sum,
1.1 misho 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);
1.1.1.2 ! misho 221: n = libnet_pblock_append(l, p, (uint8_t*)&offset,
1.1 misho 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);
1.1.1.2 ! misho 234: n = libnet_pblock_append(l, p, (uint8_t*)&key,
1.1 misho 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);
1.1.1.2 ! misho 247: n = libnet_pblock_append(l, p, (uint8_t*)&seq,
1.1 misho 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:
1.1.1.2 ! misho 256: /* boilerplate payload sanity check / append macro */
! 257: LIBNET_DO_PAYLOAD(l, p);
1.1 misho 258:
259: if ( (fv & GRE_CSUM) && (!sum) )
260: {
261: libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
262: }
263:
264: return (ptag ? ptag : libnet_pblock_update(l, p, len, LIBNET_PBLOCK_GRE_H));
265:
266: bad:
267: libnet_pblock_delete(l, p);
268: return (-1);
269: }
270:
271: libnet_ptag_t
1.1.1.2 ! misho 272: libnet_build_egre(uint16_t fv, uint16_t type, uint16_t sum,
! 273: uint16_t offset, uint32_t key, uint32_t seq, uint16_t len,
! 274: const uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
1.1 misho 275: {
276: return (libnet_build_gre(fv, type, sum, offset, key, seq, len,
277: payload, payload_s, l, ptag));
278: }
279:
280: /*
281: * Routing (variable)
282: *
283: * The Routing field is optional and is present only if the Routing
284: * Present bit is set to 1.
285: *
286: * The Routing field is a list of Source Route Entries (SREs). Each
287: * SRE has the form:
288: *
289: * 0 1 2 3
290: * 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
291: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
292: * | Address Family | SRE Offset | SRE Length |
293: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
294: * | Routing Information ...
295: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
296: *
297: */
298: libnet_ptag_t
1.1.1.2 ! misho 299: libnet_build_gre_sre(uint16_t af, uint8_t offset, uint8_t length,
! 300: uint8_t *routing, const uint8_t *payload, uint32_t payload_s, libnet_t *l,
1.1 misho 301: libnet_ptag_t ptag)
302: {
1.1.1.2 ! misho 303: uint32_t n;
1.1 misho 304: libnet_pblock_t *p;
305: struct libnet_gre_sre_hdr sre_hdr;
306:
307: if (l == NULL)
308: {
309: return (-1);
310: }
311:
312: n = LIBNET_GRE_SRE_H + length + payload_s;
313:
314: /*
315: * Find the existing protocol block if a ptag is specified, or create
316: * a new one.
317: */
318: p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_GRE_SRE_H);
319: if (p == NULL)
320: {
321: return (-1);
322: }
323: sre_hdr.af = htons(af);
324: sre_hdr.sre_offset = offset;
325: sre_hdr.sre_length = length;
1.1.1.2 ! misho 326: n = libnet_pblock_append(l, p, (uint8_t *)&sre_hdr, LIBNET_GRE_SRE_H);
1.1 misho 327: if (n == -1)
328: {
329: /* err msg set in libnet_pblock_append() */
330: goto bad;
331: }
332:
333: if ((routing && !length) || (!routing && length))
334: {
335: sprintf(l->err_buf, "%s(): routing inconsistency\n", __func__);
336: goto bad;
337: }
338:
339: if (routing && length)
340: {
341: n = libnet_pblock_append(l, p, routing, length);
342: if (n == -1)
343: {
344: /* err msg set in libnet_pblock_append() */
345: goto bad;
346: }
347: }
348:
1.1.1.2 ! misho 349: /* boilerplate payload sanity check / append macro */
! 350: LIBNET_DO_PAYLOAD(l, p);
1.1 misho 351:
352: return (ptag ? ptag : libnet_pblock_update(l, p, 0,
353: LIBNET_PBLOCK_GRE_SRE_H));
354:
355: bad:
356: libnet_pblock_delete(l, p);
357: return (-1);
358:
359: }
360:
361: libnet_ptag_t
362: libnet_build_gre_last_sre(libnet_t *l, libnet_ptag_t ptag)
363: {
1.1.1.2 ! misho 364: uint32_t n, zero = 0;
1.1 misho 365: libnet_pblock_t *p;
366:
367: if (l == NULL)
368: {
369: return (-1);
370: }
371:
372: n = LIBNET_GRE_SRE_H;
373:
374: /*
375: * Find the existing protocol block if a ptag is specified, or create
376: * a new one.
377: */
378: p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_GRE_H);
379: if (p == NULL)
380: {
381: return (-1);
382: }
383:
1.1.1.2 ! misho 384: n = libnet_pblock_append(l, p, (uint8_t *)&zero, LIBNET_GRE_SRE_H);
1.1 misho 385: if (n == -1)
386: {
387: /* err msg set in libnet_pblock_append() */
388: goto bad;
389: }
390:
391: return (ptag ? ptag : libnet_pblock_update(l, p, 0,
392: LIBNET_PBLOCK_GRE_SRE_H));
393:
394: bad:
395: libnet_pblock_delete(l, p);
396: return (-1);
397:
398: }
399: /* EOF */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>