]>
git.ipfire.org Git - thirdparty/dhcp.git/blob - common/tr.c
3 token ring interface support
4 Contributed in May of 1999 by Andrew Chittenden */
7 * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
8 * Copyright (c) 1996-2003 by Internet Software Consortium
10 * This Source Code Form is subject to the terms of the Mozilla Public
11 * License, v. 2.0. If a copy of the MPL was not distributed with this
12 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
14 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 * Internet Systems Consortium, Inc.
24 * Newmarket, NH 03857 USA
26 * https://www.isc.org/
31 #if defined (HAVE_TR_SUPPORT) && \
32 (defined (PACKET_ASSEMBLY) || defined (PACKET_DECODING))
33 #include "includes/netinet/ip.h"
34 #include "includes/netinet/udp.h"
35 #include "includes/netinet/if_ether.h"
36 #include "netinet/if_tr.h"
40 * token ring device handling subroutines. These are required as token-ring
41 * does not have a simple on-the-wire header but requires the use of
45 static int insert_source_routing (struct trh_hdr
*trh
, struct interface_info
* interface
);
46 static void save_source_routing (struct trh_hdr
*trh
, struct interface_info
* interface
);
47 static void expire_routes (void);
50 * As we keep a list of interesting routing information only, a singly
51 * linked list is all we need
53 struct routing_entry
{
54 struct routing_entry
*next
;
55 unsigned char addr
[TR_ALEN
];
56 unsigned char iface
[5];
57 u_int16_t rcf
; /* route control field */
58 u_int16_t rseg
[8]; /* routing registers */
59 unsigned long access_time
; /* time we last used this entry */
62 static struct routing_entry
*routing_info
= NULL
;
64 static int routing_timeout
= 10;
65 static struct timeval routing_timer
;
67 void assemble_tr_header (interface
, buf
, bufix
, to
)
68 struct interface_info
*interface
;
78 /* set up the token header */
79 trh
= (struct trh_hdr
*) &buf
[*bufix
];
80 if (interface
-> hw_address
.hlen
- 1 == sizeof (trh
->saddr
))
81 memcpy (trh
->saddr
, &interface
-> hw_address
.hbuf
[1],
84 memset (trh
->saddr
, 0x00, sizeof (trh
->saddr
));
86 if (to
&& to
-> hlen
== 7) /* XXX */
87 memcpy (trh
->daddr
, &to
-> hbuf
[1], sizeof trh
->daddr
);
89 memset (trh
->daddr
, 0xff, sizeof (trh
->daddr
));
91 hdr_len
= insert_source_routing (trh
, interface
);
96 /* set up the llc header for snap encoding after the tr header */
97 llc
= (struct trllc
*)(buf
+ *bufix
+ hdr_len
);
98 llc
->dsap
= EXTENDED_SAP
;
99 llc
->ssap
= EXTENDED_SAP
;
104 llc
->ethertype
= htons(ETHERTYPE_IP
);
106 hdr_len
+= sizeof(struct trllc
);
112 static unsigned char tr_broadcast
[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
115 * decoding the token header is a bit complex as you can see here. It is
116 * further complicated by the linux kernel stripping off some valuable
117 * information (see comment below) even though we've asked for the raw
120 ssize_t
decode_tr_header (interface
, buf
, bufix
, from
)
121 struct interface_info
*interface
;
124 struct hardware
*from
;
126 struct trh_hdr
*trh
= (struct trh_hdr
*) buf
+ bufix
;
130 unsigned int route_len
= 0;
134 /* see whether any source routing information has expired */
135 gettimeofday(&now
, NULL
);
137 if (routing_timer
.tv_sec
== 0)
138 routing_timer
.tv_sec
= now
.tv_sec
+ routing_timeout
;
139 else if ((now
.tv_sec
- routing_timer
.tv_sec
) > 0)
142 /* the kernel might have stripped off the source
143 * routing bit. We try a heuristic to determine whether
144 * this is the case and put it back on if so
146 route_len
= (ntohs(trh
->rcf
) & TR_RCF_LEN_MASK
) >> 8;
147 llc
= (struct trllc
*)(buf
+ bufix
+ sizeof(struct trh_hdr
)-TR_MAXRIFLEN
+route_len
);
148 if (llc
->dsap
== EXTENDED_SAP
149 && llc
->ssap
== EXTENDED_SAP
150 && llc
->llc
== UI_CMD
151 && llc
->protid
[0] == 0
152 && llc
->protid
[1] == 0
153 && llc
->protid
[2] == 0) {
154 /* say there is source routing information present */
155 trh
->saddr
[0] |= TR_RII
;
158 if (trh
->saddr
[0] & TR_RII
)
159 route_len
= (ntohs(trh
->rcf
) & TR_RCF_LEN_MASK
) >> 8;
163 hdr_len
= sizeof (struct trh_hdr
) - TR_MAXRIFLEN
+ route_len
;
165 /* now filter out unwanted packets: this is based on the packet
166 * filter code in bpf.c */
167 llc
= (struct trllc
*)(buf
+ bufix
+ hdr_len
);
168 ip
= (struct ip
*) (llc
+ 1);
169 udp
= (struct udphdr
*) ((unsigned char*) ip
+ IP_HL (ip
));
171 /* make sure it is a snap encoded, IP, UDP, unfragmented packet sent
173 if (llc
->dsap
!= EXTENDED_SAP
174 || ntohs(llc
->ethertype
) != ETHERTYPE_IP
175 || ip
->ip_p
!= IPPROTO_UDP
176 || (ntohs (ip
->ip_off
) & IP_OFFMASK
) != 0
177 || udp
->uh_dport
!= local_port
)
180 /* only save source routing information for packets from valued hosts */
181 save_source_routing(trh
, interface
);
183 return hdr_len
+ sizeof (struct trllc
);
186 /* insert_source_routing inserts source route information into the token ring
189 static int insert_source_routing (trh
, interface
)
191 struct interface_info
* interface
;
193 struct routing_entry
*rover
;
195 unsigned int route_len
= 0;
197 gettimeofday(&now
, NULL
);
199 /* single route broadcasts as per rfc 1042 */
200 if (memcmp(trh
->daddr
, tr_broadcast
,TR_ALEN
) == 0) {
201 trh
->saddr
[0] |= TR_RII
;
202 trh
->rcf
= ((sizeof(trh
->rcf
)) << 8) & TR_RCF_LEN_MASK
;
203 trh
->rcf
|= (TR_RCF_FRAME2K
| TR_RCF_LIMITED_BROADCAST
);
204 trh
->rcf
= htons(trh
->rcf
);
206 /* look for a routing entry */
207 for (rover
= routing_info
; rover
!= NULL
; rover
= rover
->next
) {
208 if (memcmp(rover
->addr
, trh
->daddr
, TR_ALEN
) == 0)
213 /* success: route that frame */
214 if ((rover
->rcf
& TR_RCF_LEN_MASK
) >> 8) {
215 u_int16_t rcf
= rover
->rcf
;
216 memcpy(trh
->rseg
,rover
->rseg
,sizeof(trh
->rseg
));
217 rcf
^= TR_RCF_DIR_BIT
;
218 rcf
&= ~TR_RCF_BROADCAST_MASK
;
219 trh
->rcf
= htons(rcf
);
220 trh
->saddr
[0] |= TR_RII
;
222 rover
->access_time
= now
.tv_sec
;
224 /* we don't have any routing information so send a
225 * limited broadcast */
226 trh
->saddr
[0] |= TR_RII
;
227 trh
->rcf
= ((sizeof(trh
->rcf
)) << 8) & TR_RCF_LEN_MASK
;
228 trh
->rcf
|= (TR_RCF_FRAME2K
| TR_RCF_LIMITED_BROADCAST
);
229 trh
->rcf
= htons(trh
->rcf
);
233 /* return how much of the header we've actually used */
234 if (trh
->saddr
[0] & TR_RII
)
235 route_len
= (ntohs(trh
->rcf
) & TR_RCF_LEN_MASK
) >> 8;
239 return sizeof (struct trh_hdr
) - TR_MAXRIFLEN
+ route_len
;
243 * save any source routing information
245 static void save_source_routing(trh
, interface
)
247 struct interface_info
*interface
;
249 struct routing_entry
*rover
;
251 unsigned char saddr
[TR_ALEN
];
254 gettimeofday(&now
, NULL
);
256 memcpy(saddr
, trh
->saddr
, sizeof(saddr
));
257 saddr
[0] &= 0x7f; /* strip off source routing present flag */
259 /* scan our table to see if we've got it */
260 for (rover
= routing_info
; rover
!= NULL
; rover
= rover
->next
) {
261 if (memcmp(&rover
->addr
[0], &saddr
[0], TR_ALEN
) == 0)
265 /* found an entry so update it with fresh information */
267 if ((trh
->saddr
[0] & TR_RII
) &&
268 ((ntohs(trh
->rcf
) & TR_RCF_LEN_MASK
) >> 8) > 2) {
269 rcf
= ntohs(trh
->rcf
);
270 rcf
&= ~TR_RCF_BROADCAST_MASK
;
271 memcpy(rover
->rseg
, trh
->rseg
, sizeof(rover
->rseg
));
274 rover
->access_time
= now
.tv_sec
;
275 return; /* that's all folks */
278 /* no entry found, so create one */
279 rover
= dmalloc (sizeof (struct routing_entry
), MDL
);
282 "%s: unable to save source routing information\n",
287 memcpy(rover
->addr
, saddr
, sizeof(rover
->addr
));
288 memcpy(rover
->iface
, interface
->name
, 5);
289 rover
->access_time
= now
.tv_sec
;
290 if (trh
->saddr
[0] & TR_RII
) {
291 if (((ntohs(trh
->rcf
) & TR_RCF_LEN_MASK
) >> 8) > 2) {
292 rcf
= ntohs(trh
->rcf
);
293 rcf
&= ~TR_RCF_BROADCAST_MASK
;
294 memcpy(rover
->rseg
, trh
->rseg
, sizeof(rover
->rseg
));
299 /* insert into list */
300 rover
->next
= routing_info
;
301 routing_info
= rover
;
307 * get rid of old routes
309 static void expire_routes()
311 struct routing_entry
*rover
;
312 struct routing_entry
**prover
= &routing_info
;
315 gettimeofday(&now
, NULL
);
317 while((rover
= *prover
) != NULL
) {
318 if ((now
.tv_sec
- rover
->access_time
) > routing_timeout
) {
319 *prover
= rover
->next
;
322 prover
= &rover
->next
;
325 /* Reset the timer */
326 routing_timer
.tv_sec
= now
.tv_sec
+ routing_timeout
;
327 routing_timer
.tv_usec
= now
.tv_usec
;