Annotation of embedaddon/libnet/src/libnet_build_gre.c, revision 1.1.1.3
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:
1.1.1.3 ! misho 31: #include "common.h"
1.1 misho 32:
33: /*
34: * Overall packet
35: *
36: * The entire encapsulated packet would then have the form:
37: *
38: * ---------------------------------
39: * | |
40: * | Delivery Header |
41: * | |
42: * ---------------------------------
43: * | |
44: * | GRE Header |
45: * | |
46: * ---------------------------------
47: * | |
48: * | Payload packet |
49: * | |
50: * ---------------------------------
51: *
52: * RFC 1701 defines a header.
53: * A new RFC (2784) has changed the header and proposed to remove the key
54: * and seqnum.
55: * A newer RFC (2890) has changed the header proposed in RFC 2784 by putting
56: * back key and seqnum.
57: * These will be supported the day IETF'guys stop this mess !
58: *
59: * FR
60: */
61:
62:
63: /*
64: * Generic Routing Encapsulation (GRE)
65: * RFC 1701 http://www.faqs.org/rfcs/rfc1701.html
66: *
67: *
68: * Packet header
69: *
70: * The GRE packet header has the form:
71: *
72: * 0 1 2 3
73: * 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
74: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
75: * |C|R|K|S|s|Recur| Flags | Ver | Protocol Type |
76: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
77: * | Checksum (optional) | Offset (optional) |
78: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
79: * | Key (optional) |
80: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
81: * | Sequence Number (optional) |
82: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
83: * | Routing (optional) |
84: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
85: *
86: * Enhanced GRE header
87: *
88: * See rfc 2637 for details. It is used for PPTP tunneling.
89: *
90: * 0 1 2 3
91: * 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
92: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
93: * |C|R|K|S|s|Recur|A| Flags | Ver | Protocol Type |
94: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
95: * | Key (HW) Payload Length | Key (LW) Call ID |
96: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
97: * | Sequence Number (Optional) |
98: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
99: * | Acknowledgment Number (Optional) |
100: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
101: *
102: */
1.1.1.2 misho 103: #if 0
104: static void
105: __libnet_print_gre_flags_ver(uint16_t fv)
1.1 misho 106: {
107: printf("version = %d (%d) -> ",
108: fv & GRE_VERSION_MASK, libnet_getgre_length(fv));
109: if (fv & GRE_CSUM)
110: {
111: printf("CSUM ");
112: }
113: if (fv & GRE_ROUTING)
114: {
115: printf("ROUTING ");
116: }
117: if (fv & GRE_KEY)
118: {
119: printf("KEY ");
120: }
121: if (fv & GRE_SEQ)
122: {
123: printf("SEQ ");
124: }
125: if (fv & GRE_ACK)
126: {
127: printf("ACK ");
128: }
129: printf("\n");
130: }
1.1.1.2 misho 131: #endif
1.1 misho 132:
133: /* FIXME: what is the portability of the "((struct libnet_gre_hdr*)0)->" ? */
1.1.1.2 misho 134: uint32_t
135: libnet_getgre_length(uint16_t fv)
1.1 misho 136: {
137:
1.1.1.2 misho 138: uint32_t n = LIBNET_GRE_H;
1.1 misho 139: /*
140: * If either the Checksum Present bit or the Routing Present bit are
141: * set, BOTH the Checksum and Offset fields are present in the GRE
142: * packet.
143: */
144:
145: if ((!(fv & GRE_VERSION_MASK) && (fv & (GRE_CSUM|GRE_ROUTING))) || /* v0 */
146: (fv & GRE_VERSION_MASK) ) /* v1 */
147: {
148: n += sizeof( ((struct libnet_gre_hdr *)0)->gre_sum) +
149: sizeof( ((struct libnet_gre_hdr *)0)->gre_offset);
150: }
151:
152: if ((!(fv & GRE_VERSION_MASK) && (fv & GRE_KEY)) || /* v0 */
153: ( (fv & GRE_VERSION_MASK) && (fv & GRE_SEQ)) ) /* v1 */
154: {
155: n += sizeof( ((struct libnet_gre_hdr *)0)->gre_key);
156: }
157:
158: if ((!(fv & GRE_VERSION_MASK) && (fv & GRE_SEQ)) || /* v0 */
159: ( (fv & GRE_VERSION_MASK) && (fv & GRE_ACK)) ) /* v1 */
160: {
161: n += sizeof( ((struct libnet_gre_hdr *)0)->gre_seq );
162: }
163:
164: return (n);
165: }
166:
167: libnet_ptag_t
1.1.1.2 misho 168: libnet_build_gre(uint16_t fv, uint16_t type, uint16_t sum,
169: uint16_t offset, uint32_t key, uint32_t seq, uint16_t len,
170: const uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
1.1 misho 171: {
1.1.1.2 misho 172: uint32_t n;
1.1 misho 173: libnet_pblock_t *p;
174: struct libnet_gre_hdr gre_hdr;
175:
176: if (l == NULL)
177: {
178: return (-1);
179: }
180:
181: n = libnet_getgre_length(fv) + payload_s;
182:
183: /*
184: * Find the existing protocol block if a ptag is specified, or create
185: * a new one.
186: */
187: p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_GRE_H);
188: if (p == NULL)
189: {
190: return (-1);
191: }
192:
193: gre_hdr.flags_ver = htons(fv);
194: gre_hdr.type = htons(type);
1.1.1.2 misho 195: n = libnet_pblock_append(l, p, (uint8_t *)&gre_hdr, LIBNET_GRE_H);
1.1 misho 196: if (n == -1)
197: {
198: /* err msg set in libnet_pblock_append() */
199: goto bad;
200: }
201:
202: if ((!(fv & GRE_VERSION_MASK) && (fv & (GRE_CSUM|GRE_ROUTING))) || /* v0 */
203: (fv & GRE_VERSION_MASK)) /* v1 */
204: {
205: sum = htons(sum);
1.1.1.2 misho 206: n = libnet_pblock_append(l, p, (uint8_t*)&sum,
1.1 misho 207: sizeof(gre_hdr.gre_sum));
208: if (n == -1)
209: {
210: /* err msg set in libnet_pblock_append() */
211: goto bad;
212: }
213: offset = htons(offset);
1.1.1.2 misho 214: n = libnet_pblock_append(l, p, (uint8_t*)&offset,
1.1 misho 215: sizeof(gre_hdr.gre_offset));
216: if (n == -1)
217: {
218: /* err msg set in libnet_pblock_append() */
219: goto bad;
220: }
221: }
222:
223: if ((!(fv & GRE_VERSION_MASK) && (fv & GRE_KEY)) || /* v0 */
224: ( (fv & GRE_VERSION_MASK) && (fv & GRE_SEQ)) ) /* v1 */
225: {
226: key = htonl(key);
1.1.1.2 misho 227: n = libnet_pblock_append(l, p, (uint8_t*)&key,
1.1 misho 228: sizeof(gre_hdr.gre_key));
229: if (n == -1)
230: {
231: /* err msg set in libnet_pblock_append() */
232: goto bad;
233: }
234: }
235:
236: if ((!(fv & GRE_VERSION_MASK) && (fv & GRE_SEQ)) || /* v0 */
237: ( (fv & GRE_VERSION_MASK) && (fv & GRE_ACK)) ) /* v1 */
238: {
239: seq = htonl(seq);
1.1.1.2 misho 240: n = libnet_pblock_append(l, p, (uint8_t*)&seq,
1.1 misho 241: sizeof(gre_hdr.gre_seq));
242: if (n == -1)
243: {
244: /* err msg set in libnet_pblock_append() */
245: goto bad;
246: }
247: }
248:
1.1.1.2 misho 249: /* boilerplate payload sanity check / append macro */
250: LIBNET_DO_PAYLOAD(l, p);
1.1 misho 251:
252: if ( (fv & GRE_CSUM) && (!sum) )
253: {
254: libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
255: }
256:
257: return (ptag ? ptag : libnet_pblock_update(l, p, len, LIBNET_PBLOCK_GRE_H));
258:
259: bad:
260: libnet_pblock_delete(l, p);
261: return (-1);
262: }
263:
264: libnet_ptag_t
1.1.1.2 misho 265: libnet_build_egre(uint16_t fv, uint16_t type, uint16_t sum,
266: uint16_t offset, uint32_t key, uint32_t seq, uint16_t len,
267: const uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
1.1 misho 268: {
269: return (libnet_build_gre(fv, type, sum, offset, key, seq, len,
270: payload, payload_s, l, ptag));
271: }
272:
273: /*
274: * Routing (variable)
275: *
276: * The Routing field is optional and is present only if the Routing
277: * Present bit is set to 1.
278: *
279: * The Routing field is a list of Source Route Entries (SREs). Each
280: * SRE has the form:
281: *
282: * 0 1 2 3
283: * 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
284: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
285: * | Address Family | SRE Offset | SRE Length |
286: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
287: * | Routing Information ...
288: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
289: *
290: */
291: libnet_ptag_t
1.1.1.2 misho 292: libnet_build_gre_sre(uint16_t af, uint8_t offset, uint8_t length,
293: uint8_t *routing, const uint8_t *payload, uint32_t payload_s, libnet_t *l,
1.1 misho 294: libnet_ptag_t ptag)
295: {
1.1.1.2 misho 296: uint32_t n;
1.1 misho 297: libnet_pblock_t *p;
298: struct libnet_gre_sre_hdr sre_hdr;
299:
300: if (l == NULL)
301: {
302: return (-1);
303: }
304:
305: n = LIBNET_GRE_SRE_H + length + payload_s;
306:
307: /*
308: * Find the existing protocol block if a ptag is specified, or create
309: * a new one.
310: */
311: p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_GRE_SRE_H);
312: if (p == NULL)
313: {
314: return (-1);
315: }
316: sre_hdr.af = htons(af);
317: sre_hdr.sre_offset = offset;
318: sre_hdr.sre_length = length;
1.1.1.2 misho 319: n = libnet_pblock_append(l, p, (uint8_t *)&sre_hdr, LIBNET_GRE_SRE_H);
1.1 misho 320: if (n == -1)
321: {
322: /* err msg set in libnet_pblock_append() */
323: goto bad;
324: }
325:
326: if ((routing && !length) || (!routing && length))
327: {
1.1.1.3 ! misho 328: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
! 329: "%s(): routing inconsistency", __func__);
1.1 misho 330: goto bad;
331: }
332:
333: if (routing && length)
334: {
335: n = libnet_pblock_append(l, p, routing, length);
336: if (n == -1)
337: {
338: /* err msg set in libnet_pblock_append() */
339: goto bad;
340: }
341: }
342:
1.1.1.2 misho 343: /* boilerplate payload sanity check / append macro */
344: LIBNET_DO_PAYLOAD(l, p);
1.1 misho 345:
346: return (ptag ? ptag : libnet_pblock_update(l, p, 0,
347: LIBNET_PBLOCK_GRE_SRE_H));
348:
349: bad:
350: libnet_pblock_delete(l, p);
351: return (-1);
352:
353: }
354:
355: libnet_ptag_t
356: libnet_build_gre_last_sre(libnet_t *l, libnet_ptag_t ptag)
357: {
1.1.1.2 misho 358: uint32_t n, zero = 0;
1.1 misho 359: libnet_pblock_t *p;
360:
361: if (l == NULL)
362: {
363: return (-1);
364: }
365:
366: n = LIBNET_GRE_SRE_H;
367:
368: /*
369: * Find the existing protocol block if a ptag is specified, or create
370: * a new one.
371: */
372: p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_GRE_H);
373: if (p == NULL)
374: {
375: return (-1);
376: }
377:
1.1.1.2 misho 378: n = libnet_pblock_append(l, p, (uint8_t *)&zero, LIBNET_GRE_SRE_H);
1.1 misho 379: if (n == -1)
380: {
381: /* err msg set in libnet_pblock_append() */
382: goto bad;
383: }
384:
385: return (ptag ? ptag : libnet_pblock_update(l, p, 0,
386: LIBNET_PBLOCK_GRE_SRE_H));
387:
388: bad:
389: libnet_pblock_delete(l, p);
390: return (-1);
391:
392: }
1.1.1.3 ! misho 393:
! 394: /**
! 395: * Local Variables:
! 396: * indent-tabs-mode: nil
! 397: * c-file-style: "stroustrup"
! 398: * End:
! 399: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>