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