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