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