xref: /csrg-svn/sys/netccitt/pk_llcsubr.c (revision 57029)
1*57029Ssklower /*
2*57029Ssklower  * Copyright (C) Dirk Husemann, Computer Science Department IV,
3*57029Ssklower  * 		 University of Erlangen-Nuremberg, Germany, 1990, 1991, 1992
4*57029Ssklower  * Copyright (c) 1992   Regents of the University of California.
5*57029Ssklower  * All rights reserved.
6*57029Ssklower  *
7*57029Ssklower  * This code is derived from software contributed to Berkeley by
8*57029Ssklower  * Dirk Husemann and the Computer Science Department (IV) of
9*57029Ssklower  * the University of Erlangen-Nuremberg, Germany.
10*57029Ssklower  *
11*57029Ssklower  * %sccs.include.redist.c%
12*57029Ssklower  *
13*57029Ssklower  *	@(#)pk_llcsubr.c	7.1 (Berkeley) 12/08/92
14*57029Ssklower  */
15*57029Ssklower 
16*57029Ssklower #include <sys/param.h>
17*57029Ssklower #include <sys/systm.h>
18*57029Ssklower #include <sys/mbuf.h>
19*57029Ssklower #include <sys/domain.h>
20*57029Ssklower #include <sys/socket.h>
21*57029Ssklower #include <sys/socketvar.h>
22*57029Ssklower #include <sys/protosw.h>
23*57029Ssklower #include <sys/errno.h>
24*57029Ssklower #include <sys/time.h>
25*57029Ssklower #include <sys/kernel.h>
26*57029Ssklower 
27*57029Ssklower #include <net/if.h>
28*57029Ssklower #include <net/if_dl.h>
29*57029Ssklower #include <net/if_llc.h>
30*57029Ssklower #include <net/if_types.h>
31*57029Ssklower #include <net/route.h>
32*57029Ssklower 
33*57029Ssklower #include <netccitt/dll.h>
34*57029Ssklower #include <netccitt/x25.h>
35*57029Ssklower #include <netccitt/pk.h>
36*57029Ssklower #include <netccitt/pk_var.h>
37*57029Ssklower #include <netccitt/llc_var.h>
38*57029Ssklower 
39*57029Ssklower 
40*57029Ssklower /*
41*57029Ssklower  * Routing support for X.25
42*57029Ssklower  *
43*57029Ssklower  * We distinguish between two cases:
44*57029Ssklower  * RTF_HOST:
45*57029Ssklower  * 	rt_key(rt)	X.25 address of host
46*57029Ssklower  *	rt_gateway	SNPA (MAC+DLSAP) address of host
47*57029Ssklower  *	rt_llinfo	pkcb for rt_key(rt)
48*57029Ssklower  *
49*57029Ssklower  * RTF_GATEWAY
50*57029Ssklower  *	rt_key(rt)	X.25 address of host or suitably masked network
51*57029Ssklower  *	rt_gateway	X.25 address of next X.25 gateway (switch)
52*57029Ssklower  *	rt_llinfo	rtentry for rt_gateway address
53*57029Ssklower  *			ought to be of type RTF_HOST
54*57029Ssklower  *
55*57029Ssklower  *
56*57029Ssklower  * Mapping of X.121 to pkcbs:
57*57029Ssklower  *
58*57029Ssklower  * HDLC uses the DTE-DCE model of X.25, therefore we need a many-to-one
59*57029Ssklower  * relationship, i.e.:
60*57029Ssklower  *
61*57029Ssklower  * 	{X.121_a, X.121_b, X.121_c, ..., X.121_i} -> pkcb_0
62*57029Ssklower  *
63*57029Ssklower  * LLC2 utilizes the DTE-DTE model of X.25, resulting effectively in a
64*57029Ssklower  * one-to-one relationship, i.e.:
65*57029Ssklower  *
66*57029Ssklower  *	{X.121_j} 	->	pkcb_1a
67*57029Ssklower  *	{X.121_k}	->	pkcb_1b
68*57029Ssklower  *	...
69*57029Ssklower  *	{X.121_q}	->	pkcb_1q
70*57029Ssklower  *
71*57029Ssklower  * It might make sense to allow a many-to-one relation for LLC2 also,
72*57029Ssklower  *
73*57029Ssklower  *	{X.121_r, X.121_s, X.121_t, X.121_u} -> pkcb_2a
74*57029Ssklower  *
75*57029Ssklower  * This would make addresses X.121_[r-u] essentially aliases of one
76*57029Ssklower  * address ({X.121_[r-u]} would constitute a representative set).
77*57029Ssklower  *
78*57029Ssklower  * Each one-to-one relation must obviously be entered individually with
79*57029Ssklower  * a route add command, whereas a many-to-one relationship can be
80*57029Ssklower  * either entered individually or generated by using a netmask.
81*57029Ssklower  *
82*57029Ssklower  * To facilitate dealings the many-to-one case for LLC2 can only be
83*57029Ssklower  * established via a netmask.
84*57029Ssklower  *
85*57029Ssklower  */
86*57029Ssklower 
87*57029Ssklower #define XTRACTPKP(rt)	((rt)->rt_flags & RTF_GATEWAY ? \
88*57029Ssklower 			 ((rt)->rt_llinfo ? \
89*57029Ssklower 			  (struct pkcb *) ((struct rtentry *)((rt)->rt_llinfo))->rt_llinfo : \
90*57029Ssklower 			  (struct pkcb *) NULL) : \
91*57029Ssklower 			 (struct pkcb *)((rt)->rt_llinfo))
92*57029Ssklower 
93*57029Ssklower #define equal(a1, a2) (bcmp((caddr_t)(a1), \
94*57029Ssklower 			       (caddr_t)(a2), \
95*57029Ssklower 			       (a1)->sa_len) == 0)
96*57029Ssklower #define XIFA(rt) ((struct x25_ifaddr *)((rt)->rt_ifa))
97*57029Ssklower 
98*57029Ssklower int
99*57029Ssklower cons_rtrequest(int cmd, struct rtentry *rt, struct sockaddr *dst)
100*57029Ssklower {
101*57029Ssklower 	register struct pkcb *pkp;
102*57029Ssklower 	register int i;
103*57029Ssklower 	register char one_to_one;
104*57029Ssklower 	struct pkcb *pk_newlink();
105*57029Ssklower 	struct rtentry *npaidb_enter();
106*57029Ssklower 
107*57029Ssklower 	pkp = XTRACTPKP(rt);
108*57029Ssklower 
109*57029Ssklower 	switch(cmd) {
110*57029Ssklower 	case RTM_RESOLVE:
111*57029Ssklower 	case RTM_ADD:
112*57029Ssklower 		if (pkp)
113*57029Ssklower 			return(EEXIST);
114*57029Ssklower 
115*57029Ssklower 		if (rt->rt_flags & RTF_GATEWAY) {
116*57029Ssklower 			if (rt->rt_llinfo)
117*57029Ssklower 				RTFREE((struct rtentry *)rt->rt_llinfo);
118*57029Ssklower 			rt->rt_llinfo = (caddr_t) rtalloc1(rt->rt_gateway, 1);
119*57029Ssklower 			return(0);
120*57029Ssklower 		}
121*57029Ssklower 		/*
122*57029Ssklower 		 * Assumptions:	(1) ifnet structure is filled in
123*57029Ssklower 		 *		(2) at least the pkcb created via
124*57029Ssklower 		 *		    x25config (ifconfig?) has been
125*57029Ssklower 		 *		    set up already.
126*57029Ssklower 		 *		(3) HDLC interfaces have an if_type of
127*57029Ssklower 		 *		    IFT_X25{,DDN}, LLC2 interfaces
128*57029Ssklower 		 *		    anything else (any better way to
129*57029Ssklower 		 *		    do this?)
130*57029Ssklower 		 *
131*57029Ssklower 		 */
132*57029Ssklower 		if (!rt->rt_ifa)
133*57029Ssklower 			return (ENETDOWN);
134*57029Ssklower 
135*57029Ssklower 		/*
136*57029Ssklower 		 * We differentiate between dealing with a many-to-one
137*57029Ssklower 		 * (HDLC: DTE-DCE) and a one-to-one (LLC2: DTE-DTE)
138*57029Ssklower 		 * relationship (by looking at the if type).
139*57029Ssklower 		 *
140*57029Ssklower 		 * Only in case of the many-to-one relationship (HDLC)
141*57029Ssklower 		 * we set the ia->ia_pkcb pointer to the pkcb allocated
142*57029Ssklower 		 * via pk_newlink() as we will use just that one pkcb for
143*57029Ssklower 		 * future route additions (the rtentry->rt_llinfo pointer
144*57029Ssklower 		 * points to the pkcb allocated for that route).
145*57029Ssklower 		 *
146*57029Ssklower 		 * In case of the one-to-one relationship (LLC2) we
147*57029Ssklower 		 * create a new pkcb (via pk_newlink()) for each new rtentry.
148*57029Ssklower 		 *
149*57029Ssklower 		 * NOTE: Only in case of HDLC does ia->ia_pkcb point
150*57029Ssklower 		 * to a pkcb, in the LLC2 case it doesn't (as we don't
151*57029Ssklower 		 * need it here)!
152*57029Ssklower 		 */
153*57029Ssklower 		one_to_one = ISISO8802(rt->rt_ifp);
154*57029Ssklower 
155*57029Ssklower 		if (!(pkp = XIFA(rt)->ia_pkcb) && !one_to_one)
156*57029Ssklower 			XIFA(rt)->ia_pkcb = pkp =
157*57029Ssklower 				pk_newlink(XIFA(rt), (caddr_t) 0);
158*57029Ssklower 		else if (one_to_one &&
159*57029Ssklower 			 !equal(rt->rt_gateway, rt->rt_ifa->ifa_addr)) {
160*57029Ssklower 			pkp = pk_newlink(XIFA(rt), (caddr_t) 0);
161*57029Ssklower 			/*
162*57029Ssklower 			 * We also need another route entry for mapping
163*57029Ssklower 			 * MAC+LSAP->X.25 address
164*57029Ssklower 			 */
165*57029Ssklower 			pkp->pk_llrt = npaidb_enter(rt->rt_gateway, rt_key(rt), rt, 0);
166*57029Ssklower 		}
167*57029Ssklower 		if (pkp) {
168*57029Ssklower 			if (!pkp->pk_rt)
169*57029Ssklower 				pkp->pk_rt = rt;
170*57029Ssklower 			pkp->pk_refcount++;
171*57029Ssklower 		}
172*57029Ssklower 		rt->rt_llinfo = (caddr_t) pkp;
173*57029Ssklower 
174*57029Ssklower 		return(0);
175*57029Ssklower 
176*57029Ssklower 	case RTM_DELETE:
177*57029Ssklower 	{
178*57029Ssklower 		/*
179*57029Ssklower 		 * The pkp might be empty if we are dealing
180*57029Ssklower 		 * with an interface route entry for LLC2, in this
181*57029Ssklower 		 * case we don't need to do anything ...
182*57029Ssklower 		 */
183*57029Ssklower 		if (pkp) {
184*57029Ssklower 			if ( rt->rt_flags & RTF_GATEWAY ) {
185*57029Ssklower 				if (rt->rt_llinfo)
186*57029Ssklower 					RTFREE((struct rtentry *)rt->rt_llinfo);
187*57029Ssklower 				return(0);
188*57029Ssklower 			}
189*57029Ssklower 
190*57029Ssklower 			if (pkp->pk_llrt)
191*57029Ssklower 				npaidb_destroy(pkp->pk_llrt);
192*57029Ssklower 
193*57029Ssklower 			pk_dellink (pkp);
194*57029Ssklower 
195*57029Ssklower 			return(0);
196*57029Ssklower 		}
197*57029Ssklower 	}
198*57029Ssklower 	}
199*57029Ssklower }
200*57029Ssklower 
201*57029Ssklower 
202*57029Ssklower /*
203*57029Ssklower  * Glue between X.25 and LLC2
204*57029Ssklower  */
205*57029Ssklower int
206*57029Ssklower x25_llcglue(int prc, struct sockaddr *addr)
207*57029Ssklower {
208*57029Ssklower 	register struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)addr;
209*57029Ssklower 	register struct x25_ifaddr *x25ifa;
210*57029Ssklower 	struct dll_ctlinfo ctlinfo;
211*57029Ssklower 
212*57029Ssklower 	if((x25ifa = (struct x25_ifaddr *)ifa_ifwithaddr(addr)) == 0)
213*57029Ssklower 		return 0;
214*57029Ssklower 
215*57029Ssklower 	ctlinfo.dlcti_cfg  =
216*57029Ssklower 	    (struct dllconfig *)(((struct sockaddr_x25 *)(&x25ifa->ia_xc))+1);
217*57029Ssklower 	ctlinfo.dlcti_lsap = LLC_X25_LSAP;
218*57029Ssklower 
219*57029Ssklower 	return ((int)llc_ctlinput(prc, addr, (caddr_t)&ctlinfo));
220*57029Ssklower }
221