|
|
1.1 root 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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.