1 /* $NetBSD: pk_llcsubr.c,v 1.15 2003/08/07 16:33:04 agc Exp $ */
2
3 /*
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Dirk Husemann and the Computer Science Department (IV) of
9 * the University of Erlangen-Nuremberg, Germany.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)pk_llcsubr.c 8.2 (Berkeley) 2/9/95
36 */
37
38 /*
39 * Copyright (c) 1990, 1991, 1992
40 * Dirk Husemann, Computer Science Department IV,
41 * University of Erlangen-Nuremberg, Germany.
42 *
43 * This code is derived from software contributed to Berkeley by
44 * Dirk Husemann and the Computer Science Department (IV) of
45 * the University of Erlangen-Nuremberg, Germany.
46 *
47 * Redistribution and use in source and binary forms, with or without
48 * modification, are permitted provided that the following conditions
49 * are met:
50 * 1. Redistributions of source code must retain the above copyright
51 * notice, this list of conditions and the following disclaimer.
52 * 2. Redistributions in binary form must reproduce the above copyright
53 * notice, this list of conditions and the following disclaimer in the
54 * documentation and/or other materials provided with the distribution.
55 * 3. All advertising materials mentioning features or use of this software
56 * must display the following acknowledgement:
57 * This product includes software developed by the University of
58 * California, Berkeley and its contributors.
59 * 4. Neither the name of the University nor the names of its contributors
60 * may be used to endorse or promote products derived from this software
61 * without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
64 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
67 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
69 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73 * SUCH DAMAGE.
74 *
75 * @(#)pk_llcsubr.c 8.2 (Berkeley) 2/9/95
76 */
77
78 #include <sys/cdefs.h>
79 __KERNEL_RCSID(0, "$NetBSD: pk_llcsubr.c,v 1.15 2003/08/07 16:33:04 agc Exp $");
80
81 #include "opt_llc.h"
82
83 #include <sys/param.h>
84 #include <sys/systm.h>
85 #include <sys/mbuf.h>
86 #include <sys/domain.h>
87 #include <sys/socket.h>
88 #include <sys/socketvar.h>
89 #include <sys/protosw.h>
90 #include <sys/errno.h>
91 #include <sys/time.h>
92 #include <sys/kernel.h>
93
94 #include <net/if.h>
95 #include <net/if_dl.h>
96 #include <net/if_llc.h>
97 #include <net/if_types.h>
98 #include <net/route.h>
99
100 #include <netccitt/dll.h>
101 #include <netccitt/x25.h>
102 #include <netccitt/pk.h>
103 #include <netccitt/pk_var.h>
104 #include <netccitt/pk_extern.h>
105 #include <netccitt/llc_var.h>
106
107
108 /*
109 * Routing support for X.25
110 *
111 * We distinguish between two cases:
112 * RTF_HOST:
113 * rt_key(rt) X.25 address of host
114 * rt_gateway SNPA (MAC+DLSAP) address of host
115 * rt_llinfo pkcb for rt_key(rt)
116 *
117 * RTF_GATEWAY
118 * rt_key(rt) X.25 address of host or suitably masked network
119 * rt_gateway X.25 address of next X.25 gateway (switch)
120 * rt_llinfo rtentry for rt_gateway address
121 * ought to be of type RTF_HOST
122 *
123 *
124 * Mapping of X.121 to pkcbs:
125 *
126 * HDLC uses the DTE-DCE model of X.25, therefore we need a many-to-one
127 * relationship, i.e.:
128 *
129 * {X.121_a, X.121_b, X.121_c, ..., X.121_i} -> pkcb_0
130 *
131 * LLC2 uses the DTE-DTE model of X.25, resulting effectively in a
132 * one-to-one relationship, i.e.:
133 *
134 * {X.121_j} -> pkcb_1a
135 * {X.121_k} -> pkcb_1b
136 * ...
137 * {X.121_q} -> pkcb_1q
138 *
139 * It might make sense to allow a many-to-one relation for LLC2 also,
140 *
141 * {X.121_r, X.121_s, X.121_t, X.121_u} -> pkcb_2a
142 *
143 * This would make addresses X.121_[r-u] essentially aliases of one
144 * address ({X.121_[r-u]} would constitute a representative set).
145 *
146 * Each one-to-one relation must obviously be entered individually with
147 * a route add command, whereas a many-to-one relationship can be
148 * either entered individually or generated by using a netmask.
149 *
150 * To facilitate dealings the many-to-one case for LLC2 can only be
151 * established via a netmask.
152 *
153 */
154
155 #define XTRACTPKP(rt) ((rt)->rt_flags & RTF_GATEWAY ? \
156 ((rt)->rt_llinfo ? \
157 (struct pkcb *) ((struct rtentry *)((rt)->rt_llinfo))->rt_llinfo : \
158 (struct pkcb *) NULL) : \
159 (struct pkcb *)((rt)->rt_llinfo))
160
161 #define equal(a1, a2) (bcmp((caddr_t)(a1), \
162 (caddr_t)(a2), \
163 (a1)->sa_len) == 0)
164 #define XIFA(rt) ((struct x25_ifaddr *)((rt)->rt_ifa))
165 #define SA(s) ((struct sockaddr *)s)
166
167 static int cons_rtrequest_internal __P((int, struct rtentry *,
168 struct rt_addrinfo *));
169
170 /*
171 * ifa_rtrequest currently does not check the error from the rtrequest call
172 * so we use a void version of the cons_rtrequest routine.
173 */
174 void
175 cons_rtrequest(cmd, rt, info)
176 int cmd;
177 struct rtentry *rt;
178 struct rt_addrinfo *info;
179 {
180 cons_rtrequest_internal(cmd, rt, info);
181 }
182
183
184 static int
185 cons_rtrequest_internal(cmd, rt, info)
186 int cmd;
187 struct rtentry *rt;
188 struct rt_addrinfo *info;
189 {
190 struct pkcb *pkp;
191 char one_to_one;
192
193 pkp = XTRACTPKP(rt);
194
195 switch (cmd) {
196 case RTM_RESOLVE:
197 case RTM_ADD:
198 if (pkp)
199 return (EEXIST);
200
201 if (rt->rt_flags & RTF_GATEWAY) {
202 if (rt->rt_llinfo)
203 RTFREE((struct rtentry *) rt->rt_llinfo);
204 rt->rt_llinfo = (caddr_t) rtalloc1(rt->rt_gateway, 1);
205 return (0);
206 }
207 /*
208 * Assumptions: (1) ifnet structure is filled in
209 * (2) at least the pkcb created via
210 * x25config (ifconfig?) has been
211 * set up already.
212 * (3) HDLC interfaces have an if_type of
213 * IFT_X25{,DDN}, LLC2 interfaces
214 * anything else (any better way to
215 * do this?)
216 *
217 */
218 if (!rt->rt_ifa)
219 return (ENETDOWN);
220
221 /*
222 * We differentiate between dealing with a many-to-one (HDLC:
223 * DTE-DCE) and a one-to-one (LLC2: DTE-DTE) relationship (by
224 * looking at the if type).
225 *
226 * Only in case of the many-to-one relationship (HDLC) we set
227 * the ia->ia_pkcb pointer to the pkcb allocated via
228 * pk_newlink() as we will use just that one pkcb for future
229 * route additions (the rtentry->rt_llinfo pointer points to
230 * the pkcb allocated for that route).
231 *
232 * In case of the one-to-one relationship (LLC2) we create a new
233 * pkcb (via pk_newlink()) for each new rtentry.
234 *
235 * NOTE: Only in case of HDLC does ia->ia_pkcb point to a pkcb,
236 * in the LLC2 case it doesn't (as we don't need it here)!
237 */
238 one_to_one = ISISO8802(rt->rt_ifp);
239
240 if (!(pkp = XIFA(rt)->ia_pkcb) && !one_to_one)
241 XIFA(rt)->ia_pkcb = pkp =
242 pk_newlink(XIFA(rt), (caddr_t) 0);
243 else if (one_to_one &&
244 !equal(rt->rt_gateway, rt->rt_ifa->ifa_addr)) {
245 pkp = pk_newlink(XIFA(rt), (caddr_t) 0);
246 /*
247 * We also need another route entry for mapping
248 * MAC+LSAP->X.25 address
249 */
250 pkp->pk_llrt = npaidb_enter((struct sockaddr_dl *)
251 rt->rt_gateway, rt_key(rt),
252 rt, 0);
253 }
254 if (pkp) {
255 if (!pkp->pk_rt)
256 pkp->pk_rt = rt;
257 pkp->pk_refcount++;
258 }
259 rt->rt_llinfo = (caddr_t) pkp;
260
261 return (0);
262
263 case RTM_DELETE:
264 {
265 /*
266 * The pkp might be empty if we are dealing
267 * with an interface route entry for LLC2, in this
268 * case we don't need to do anything ...
269 */
270 if (pkp) {
271 if (rt->rt_flags & RTF_GATEWAY) {
272 if (rt->rt_llinfo)
273 RTFREE((struct rtentry *) rt->rt_llinfo);
274 return (0);
275 }
276 if (pkp->pk_llrt)
277 npaidb_destroy(pkp->pk_llrt);
278
279 pk_dellink(pkp);
280
281 return (0);
282 }
283 }
284 }
285 return 0;
286 }
287
288 /*
289 * Network Protocol Addressing Information DataBase (npaidb)
290 *
291 * To speed up locating the entity dealing with an LLC packet use is made
292 * of a routing tree. This npaidb routing tree is handled
293 * by the normal rn_*() routines just like (almost) any other routing tree.
294 *
295 * The mapping being done by the npaidb_*() routines is as follows:
296 *
297 * Key: MAC,LSAP (enhancing struct sockaddr_dl)
298 * Gateway: sockaddr_x25 (i.e. X.25 address - X.121 or NSAP)
299 * Llinfo: npaidbentry {
300 * struct llc_linkcb *npaidb_linkp;
301 * struct rtentry *npaidb_rt;
302 * }
303 *
304 * Using the npaidbentry provided by llinfo we can then access
305 *
306 * o the pkcb by using (struct pkcb *) (npaidb_rt->rt_llinfo)
307 * o the linkcb via npaidb_linkp
308 *
309 * The following functions are provided
310 *
311 * o npaidb_enter(struct sockaddr_dl *sdl, struct sockaddr_x25 *sx25,
312 * struct struct llc_linkcb *link, struct rtentry *rt)
313 *
314 * o npaidb_enrich(short type, caddr_t info)
315 *
316 */
317
318 struct sockaddr_dl npdl_netmask = {
319 sizeof(struct sockaddr_dl), /* _len */
320 0, /* _family */
321 0, /* _index */
322 0, /* _type */
323 -1, /* _nlen */
324 -1, /* _alen */
325 -1, /* _slen */
326 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* _data */
327 };
328 struct sockaddr npdl_dummy;
329
330 int npdl_datasize = sizeof(struct sockaddr_dl) -
331 ((int) ((unsigned long)&((struct sockaddr_dl *) 0)->sdl_data[0]));
332
333 struct rtentry *
334 npaidb_enter(key, value, rt, link)
335 struct sockaddr_dl *key;
336 struct sockaddr *value;
337 struct rtentry *rt;
338 struct llc_linkcb *link;
339 {
340 struct rtentry *nprt;
341 int i;
342
343 USES_AF_LINK_RTS;
344
345 if ((nprt = rtalloc1(SA(key), 0)) == 0) {
346 u_int size = sizeof(struct npaidbentry);
347 u_char saploc = LLSAPLOC(key, rt->rt_ifp);
348
349 /*
350 * set up netmask: LLC2 packets have the lowest bit set in
351 * response packets (e.g. 0x7e for command packets, 0x7f for
352 * response packets), to facilitate the lookup we use a
353 * netmask of 11111110 for the SAP position. The remaining
354 * positions are zeroed out.
355 */
356 npdl_netmask.sdl_data[saploc] = NPDL_SAPNETMASK;
357 bzero((caddr_t) & npdl_netmask.sdl_data[saploc + 1],
358 npdl_datasize - saploc - 1);
359
360 if (value == 0)
361 value = &npdl_dummy;
362
363 /* now enter it */
364 rtrequest(RTM_ADD, SA(key), SA(value),
365 SA(&npdl_netmask), 0, &nprt);
366
367 /* and reset npdl_netmask */
368 for (i = saploc; i < npdl_datasize; i++)
369 npdl_netmask.sdl_data[i] = -1;
370
371 nprt->rt_llinfo = malloc(size, M_PCB, M_WAITOK);
372 if (nprt->rt_llinfo) {
373 bzero(nprt->rt_llinfo, size);
374 ((struct npaidbentry *) (nprt->rt_llinfo))->np_rt = rt;
375 }
376 } else
377 nprt->rt_refcnt--;
378 return nprt;
379 }
380
381 struct rtentry *
382 npaidb_enrich(type, info, sdl)
383 short type;
384 caddr_t info;
385 struct sockaddr_dl *sdl;
386 {
387 struct rtentry *rt;
388
389 USES_AF_LINK_RTS;
390
391 if ((rt = rtalloc1((struct sockaddr *) sdl, 0)) != NULL) {
392 rt->rt_refcnt--;
393 switch (type) {
394 case NPAIDB_LINK:
395 ((struct npaidbentry *) (rt->rt_llinfo))->np_link =
396 (struct llc_linkcb *) info;
397 break;
398 }
399 return rt;
400 }
401 return ((struct rtentry *) 0);
402
403 }
404
405 int
406 npaidb_destroy(rt)
407 struct rtentry *rt;
408 {
409 USES_AF_LINK_RTS;
410
411 if (rt->rt_llinfo)
412 free((caddr_t) rt->rt_llinfo, M_PCB);
413 return (rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt),
414 0, 0));
415 }
416
417
418 #ifdef LLC
419 /*
420 * Glue between X.25 and LLC2
421 */
422 long
423 x25_llcglue(prc, addr)
424 int prc;
425 struct sockaddr *addr;
426 {
427 struct x25_ifaddr *x25ifa;
428 struct dll_ctlinfo ctlinfo;
429 long rv;
430
431 if ((x25ifa = (struct x25_ifaddr *) ifa_ifwithaddr(addr)) == 0)
432 return 0;
433
434 ctlinfo.dlcti_cfg = (struct dllconfig *)
435 (((struct sockaddr_x25 *) (&x25ifa->ia_xc)) + 1);
436 ctlinfo.dlcti_lsap = LLC_X25_LSAP;
437
438 rv = (long) llc_ctlinput(prc, addr, &ctlinfo);
439
440 return (rv);
441 }
442 #endif /* LLC */
Cache object: a227505f47eeafb2b646663e53b85885
|