Annotation of embedaddon/dhcp/common/tr.c, revision 1.1.1.1
1.1 misho 1: /* tr.c
2:
3: token ring interface support
4: Contributed in May of 1999 by Andrew Chittenden */
5:
6: /*
7: * Copyright (c) 2011 by Internet Systems Consortium, Inc. ("ISC")
8: * Copyright (c) 2004-2007,2009 by Internet Systems Consortium, Inc. ("ISC")
9: * Copyright (c) 1996-2003 by Internet Software Consortium
10: *
11: * Permission to use, copy, modify, and distribute this software for any
12: * purpose with or without fee is hereby granted, provided that the above
13: * copyright notice and this permission notice appear in all copies.
14: *
15: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
16: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
18: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21: * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22: *
23: * Internet Systems Consortium, Inc.
24: * 950 Charter Street
25: * Redwood City, CA 94063
26: * <info@isc.org>
27: * https://www.isc.org/
28: */
29:
30: #include "dhcpd.h"
31:
32: #if defined (HAVE_TR_SUPPORT) && \
33: (defined (PACKET_ASSEMBLY) || defined (PACKET_DECODING))
34: #include "includes/netinet/ip.h"
35: #include "includes/netinet/udp.h"
36: #include "includes/netinet/if_ether.h"
37: #include "netinet/if_tr.h"
38: #include <sys/time.h>
39:
40: /*
41: * token ring device handling subroutines. These are required as token-ring
42: * does not have a simple on-the-wire header but requires the use of
43: * source routing
44: */
45:
46: static int insert_source_routing (struct trh_hdr *trh, struct interface_info* interface);
47: static void save_source_routing (struct trh_hdr *trh, struct interface_info* interface);
48: static void expire_routes (void);
49:
50: /*
51: * As we keep a list of interesting routing information only, a singly
52: * linked list is all we need
53: */
54: struct routing_entry {
55: struct routing_entry *next;
56: unsigned char addr[TR_ALEN];
57: unsigned char iface[5];
58: u_int16_t rcf; /* route control field */
59: u_int16_t rseg[8]; /* routing registers */
60: unsigned long access_time; /* time we last used this entry */
61: };
62:
63: static struct routing_entry *routing_info = NULL;
64:
65: static int routing_timeout = 10;
66: static struct timeval routing_timer;
67:
68: void assemble_tr_header (interface, buf, bufix, to)
69: struct interface_info *interface;
70: unsigned char *buf;
71: unsigned *bufix;
72: struct hardware *to;
73: {
74: struct trh_hdr *trh;
75: int hdr_len;
76: struct trllc *llc;
77:
78:
79: /* set up the token header */
80: trh = (struct trh_hdr *) &buf[*bufix];
81: if (interface -> hw_address.hlen - 1 == sizeof (trh->saddr))
82: memcpy (trh->saddr, &interface -> hw_address.hbuf [1],
83: sizeof (trh->saddr));
84: else
85: memset (trh->saddr, 0x00, sizeof (trh->saddr));
86:
87: if (to && to -> hlen == 7) /* XXX */
88: memcpy (trh->daddr, &to -> hbuf [1], sizeof trh->daddr);
89: else
90: memset (trh->daddr, 0xff, sizeof (trh->daddr));
91:
92: hdr_len = insert_source_routing (trh, interface);
93:
94: trh->ac = AC;
95: trh->fc = LLC_FRAME;
96:
97: /* set up the llc header for snap encoding after the tr header */
98: llc = (struct trllc *)(buf + *bufix + hdr_len);
99: llc->dsap = EXTENDED_SAP;
100: llc->ssap = EXTENDED_SAP;
101: llc->llc = UI_CMD;
102: llc->protid[0] = 0;
103: llc->protid[1] = 0;
104: llc->protid[2] = 0;
105: llc->ethertype = htons(ETHERTYPE_IP);
106:
107: hdr_len += sizeof(struct trllc);
108:
109: *bufix += hdr_len;
110: }
111:
112:
113: static unsigned char tr_broadcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
114:
115: /*
116: * decoding the token header is a bit complex as you can see here. It is
117: * further complicated by the linux kernel stripping off some valuable
118: * information (see comment below) even though we've asked for the raw
119: * packets.
120: */
121: ssize_t decode_tr_header (interface, buf, bufix, from)
122: struct interface_info *interface;
123: unsigned char *buf;
124: unsigned bufix;
125: struct hardware *from;
126: {
127: struct trh_hdr *trh = (struct trh_hdr *) buf + bufix;
128: struct trllc *llc;
129: struct ip *ip;
130: struct udphdr *udp;
131: unsigned int route_len = 0;
132: ssize_t hdr_len;
133: struct timeval now;
134:
135: /* see whether any source routing information has expired */
136: gettimeofday(&now, NULL);
137:
138: if (routing_timer.tv_sec == 0)
139: routing_timer.tv_sec = now.tv_sec + routing_timeout;
140: else if ((now.tv_sec - routing_timer.tv_sec) > 0)
141: expire_routes();
142:
143: /* the kernel might have stripped off the source
144: * routing bit. We try a heuristic to determine whether
145: * this is the case and put it back on if so
146: */
147: route_len = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8;
148: llc = (struct trllc *)(buf + bufix + sizeof(struct trh_hdr)-TR_MAXRIFLEN+route_len);
149: if (llc->dsap == EXTENDED_SAP
150: && llc->ssap == EXTENDED_SAP
151: && llc->llc == UI_CMD
152: && llc->protid[0] == 0
153: && llc->protid[1] == 0
154: && llc->protid[2] == 0) {
155: /* say there is source routing information present */
156: trh->saddr[0] |= TR_RII;
157: }
158:
159: if (trh->saddr[0] & TR_RII)
160: route_len = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8;
161: else
162: route_len = 0;
163:
164: hdr_len = sizeof (struct trh_hdr) - TR_MAXRIFLEN + route_len;
165:
166: /* now filter out unwanted packets: this is based on the packet
167: * filter code in bpf.c */
168: llc = (struct trllc *)(buf + bufix + hdr_len);
169: ip = (struct ip *) (llc + 1);
170: udp = (struct udphdr *) ((unsigned char*) ip + IP_HL (ip));
171:
172: /* make sure it is a snap encoded, IP, UDP, unfragmented packet sent
173: * to our port */
174: if (llc->dsap != EXTENDED_SAP
175: || ntohs(llc->ethertype) != ETHERTYPE_IP
176: || ip->ip_p != IPPROTO_UDP
177: || (ntohs (ip->ip_off) & IP_OFFMASK) != 0
178: || udp->uh_dport != local_port)
179: return -1;
180:
181: /* only save source routing information for packets from valued hosts */
182: save_source_routing(trh, interface);
183:
184: return hdr_len + sizeof (struct trllc);
185: }
186:
187: /* insert_source_routing inserts source route information into the token ring
188: * header
189: */
190: static int insert_source_routing (trh, interface)
191: struct trh_hdr *trh;
192: struct interface_info* interface;
193: {
194: struct routing_entry *rover;
195: struct timeval now;
196: unsigned int route_len = 0;
197:
198: gettimeofday(&now, NULL);
199:
200: /* single route broadcasts as per rfc 1042 */
201: if (memcmp(trh->daddr, tr_broadcast,TR_ALEN) == 0) {
202: trh->saddr[0] |= TR_RII;
203: trh->rcf = ((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK;
204: trh->rcf |= (TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST);
205: trh->rcf = htons(trh->rcf);
206: } else {
207: /* look for a routing entry */
208: for (rover = routing_info; rover != NULL; rover = rover->next) {
209: if (memcmp(rover->addr, trh->daddr, TR_ALEN) == 0)
210: break;
211: }
212:
213: if (rover != NULL) {
214: /* success: route that frame */
215: if ((rover->rcf & TR_RCF_LEN_MASK) >> 8) {
216: u_int16_t rcf = rover->rcf;
217: memcpy(trh->rseg,rover->rseg,sizeof(trh->rseg));
218: rcf ^= TR_RCF_DIR_BIT;
219: rcf &= ~TR_RCF_BROADCAST_MASK;
220: trh->rcf = htons(rcf);
221: trh->saddr[0] |= TR_RII;
222: }
223: rover->access_time = now.tv_sec;
224: } else {
225: /* we don't have any routing information so send a
226: * limited broadcast */
227: trh->saddr[0] |= TR_RII;
228: trh->rcf = ((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK;
229: trh->rcf |= (TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST);
230: trh->rcf = htons(trh->rcf);
231: }
232: }
233:
234: /* return how much of the header we've actually used */
235: if (trh->saddr[0] & TR_RII)
236: route_len = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8;
237: else
238: route_len = 0;
239:
240: return sizeof (struct trh_hdr) - TR_MAXRIFLEN + route_len;
241: }
242:
243: /*
244: * save any source routing information
245: */
246: static void save_source_routing(trh, interface)
247: struct trh_hdr *trh;
248: struct interface_info *interface;
249: {
250: struct routing_entry *rover;
251: struct timeval now;
252: unsigned char saddr[TR_ALEN];
253: u_int16_t rcf = 0;
254:
255: gettimeofday(&now, NULL);
256:
257: memcpy(saddr, trh->saddr, sizeof(saddr));
258: saddr[0] &= 0x7f; /* strip off source routing present flag */
259:
260: /* scan our table to see if we've got it */
261: for (rover = routing_info; rover != NULL; rover = rover->next) {
262: if (memcmp(&rover->addr[0], &saddr[0], TR_ALEN) == 0)
263: break;
264: }
265:
266: /* found an entry so update it with fresh information */
267: if (rover != NULL) {
268: if ((trh->saddr[0] & TR_RII) &&
269: ((ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8) > 2) {
270: rcf = ntohs(trh->rcf);
271: rcf &= ~TR_RCF_BROADCAST_MASK;
272: memcpy(rover->rseg, trh->rseg, sizeof(rover->rseg));
273: }
274: rover->rcf = rcf;
275: rover->access_time = now.tv_sec;
276: return; /* that's all folks */
277: }
278:
279: /* no entry found, so create one */
280: rover = dmalloc (sizeof (struct routing_entry), MDL);
281: if (rover == NULL) {
282: fprintf(stderr,
283: "%s: unable to save source routing information\n",
284: __FILE__);
285: return;
286: }
287:
288: memcpy(rover->addr, saddr, sizeof(rover->addr));
289: memcpy(rover->iface, interface->name, 5);
290: rover->access_time = now.tv_sec;
291: if (trh->saddr[0] & TR_RII) {
292: if (((ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8) > 2) {
293: rcf = ntohs(trh->rcf);
294: rcf &= ~TR_RCF_BROADCAST_MASK;
295: memcpy(rover->rseg, trh->rseg, sizeof(rover->rseg));
296: }
297: rover->rcf = rcf;
298: }
299:
300: /* insert into list */
301: rover->next = routing_info;
302: routing_info = rover;
303:
304: return;
305: }
306:
307: /*
308: * get rid of old routes
309: */
310: static void expire_routes()
311: {
312: struct routing_entry *rover;
313: struct routing_entry **prover = &routing_info;
314: struct timeval now;
315:
316: gettimeofday(&now, NULL);
317:
318: while((rover = *prover) != NULL) {
319: if ((now.tv_sec - rover->access_time) > routing_timeout) {
320: *prover = rover->next;
321: dfree (rover, MDL);
322: } else
323: prover = &rover->next;
324: }
325:
326: /* Reset the timer */
327: routing_timer.tv_sec = now.tv_sec + routing_timeout;
328: routing_timer.tv_usec = now.tv_usec;
329: }
330:
331: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>