1*36384Ssklower /*********************************************************** 2*36384Ssklower Copyright IBM Corporation 1987 3*36384Ssklower 4*36384Ssklower All Rights Reserved 5*36384Ssklower 6*36384Ssklower Permission to use, copy, modify, and distribute this software and its 7*36384Ssklower documentation for any purpose and without fee is hereby granted, 8*36384Ssklower provided that the above copyright notice appear in all copies and that 9*36384Ssklower both that copyright notice and this permission notice appear in 10*36384Ssklower supporting documentation, and that the name of IBM not be 11*36384Ssklower used in advertising or publicity pertaining to distribution of the 12*36384Ssklower software without specific, written prior permission. 13*36384Ssklower 14*36384Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 15*36384Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 16*36384Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 17*36384Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 18*36384Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 19*36384Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20*36384Ssklower SOFTWARE. 21*36384Ssklower 22*36384Ssklower ******************************************************************/ 23*36384Ssklower 24*36384Ssklower /* 25*36384Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 26*36384Ssklower */ 27*36384Ssklower /* 28*36384Ssklower * $Header: iso.c,v 4.11 88/09/19 14:58:35 root Exp $ 29*36384Ssklower * $Source: /usr/argo/sys/netiso/RCS/iso.c,v $ 30*36384Ssklower * 31*36384Ssklower * iso.c: miscellaneous routines to support the iso address family 32*36384Ssklower */ 33*36384Ssklower 34*36384Ssklower #ifndef lint 35*36384Ssklower static char *rcsid = "$Header: iso.c,v 4.11 88/09/19 14:58:35 root Exp $"; 36*36384Ssklower #endif 37*36384Ssklower 38*36384Ssklower 39*36384Ssklower #include "../h/types.h" 40*36384Ssklower #include "../h/param.h" 41*36384Ssklower #include "../h/ioctl.h" 42*36384Ssklower #include "../h/mbuf.h" 43*36384Ssklower #include "../h/domain.h" 44*36384Ssklower #include "../h/protosw.h" 45*36384Ssklower #include "../h/socket.h" 46*36384Ssklower #include "../h/socketvar.h" 47*36384Ssklower #include "../h/uio.h" 48*36384Ssklower #include "../h/dir.h" 49*36384Ssklower #include "../h/user.h" 50*36384Ssklower #include "../h/errno.h" 51*36384Ssklower 52*36384Ssklower #include "../net/if.h" 53*36384Ssklower #include "../net/route.h" 54*36384Ssklower #include "../net/af.h" 55*36384Ssklower 56*36384Ssklower #include "../netiso/iso.h" 57*36384Ssklower #include "../netiso/iso_var.h" 58*36384Ssklower #include "../netiso/iso_snpac.h" 59*36384Ssklower #include "../netiso/iso_pcb.h" 60*36384Ssklower #include "../netiso/clnp.h" 61*36384Ssklower #include "../netiso/argo_debug.h" 62*36384Ssklower 63*36384Ssklower #ifdef ISO 64*36384Ssklower 65*36384Ssklower int iso_interfaces = 0; /* number of external interfaces */ 66*36384Ssklower extern struct ifnet loif; /* loopback interface */ 67*36384Ssklower 68*36384Ssklower 69*36384Ssklower /* 70*36384Ssklower * FUNCTION: iso_init 71*36384Ssklower * 72*36384Ssklower * PURPOSE: initialize the iso address family 73*36384Ssklower * 74*36384Ssklower * RETURNS: nothing 75*36384Ssklower * 76*36384Ssklower * SIDE EFFECTS: 1) zeros the maptab table. 77*36384Ssklower * 78*36384Ssklower * NOTES: 79*36384Ssklower */ 80*36384Ssklower iso_init() 81*36384Ssklower { 82*36384Ssklower extern struct maptab iso_snpac[]; 83*36384Ssklower extern int iso_snpac_size; 84*36384Ssklower 85*36384Ssklower bzero((caddr_t)iso_snpac, iso_snpac_size * sizeof(struct snpa_cache)); 86*36384Ssklower } 87*36384Ssklower 88*36384Ssklower /* 89*36384Ssklower * FUNCTION: iso_addrmatch1 90*36384Ssklower * 91*36384Ssklower * PURPOSE: decide if the two iso_addrs passed are equal 92*36384Ssklower * 93*36384Ssklower * RETURNS: true if the addrs match, false if they do not 94*36384Ssklower * 95*36384Ssklower * SIDE EFFECTS: 96*36384Ssklower * 97*36384Ssklower * NOTES: 98*36384Ssklower */ 99*36384Ssklower iso_addrmatch1(isoaa, isoab) 100*36384Ssklower struct iso_addr *isoaa, *isoab; /* addresses to check */ 101*36384Ssklower { 102*36384Ssklower int compare_len; 103*36384Ssklower 104*36384Ssklower IFDEBUG(D_ROUTE) 105*36384Ssklower printf("iso_addrmatch1: comparing lengths: %d to %d\n", isoaa->isoa_len, 106*36384Ssklower isoab->isoa_len); 107*36384Ssklower printf("a:\n"); 108*36384Ssklower dump_buf((caddr_t)isoaa, isoaa->isoa_len); 109*36384Ssklower printf("b:\n"); 110*36384Ssklower dump_buf((caddr_t)isoab, isoab->isoa_len); 111*36384Ssklower ENDDEBUG 112*36384Ssklower 113*36384Ssklower if ((compare_len = isoaa->isoa_len) != isoab->isoa_len) { 114*36384Ssklower IFDEBUG(D_ROUTE) 115*36384Ssklower printf("iso_addrmatch1: returning false because of lengths\n"); 116*36384Ssklower ENDDEBUG 117*36384Ssklower return 0; 118*36384Ssklower } 119*36384Ssklower 120*36384Ssklower /* TODO : generalize this to all afis with masks */ 121*36384Ssklower if( isoaa->isoa_afi == AFI_37 ) { 122*36384Ssklower /* must not compare 2 least significant digits, or for 123*36384Ssklower * that matter, the DSP 124*36384Ssklower */ 125*36384Ssklower compare_len = ADDR37_IDI_LEN - 1; 126*36384Ssklower } 127*36384Ssklower 128*36384Ssklower IFDEBUG(D_ROUTE) 129*36384Ssklower int i; 130*36384Ssklower char *a, *b; 131*36384Ssklower 132*36384Ssklower a = (char *) isoaa; 133*36384Ssklower b = (char *) isoab; 134*36384Ssklower 135*36384Ssklower for (i=0; i<compare_len; i++) { 136*36384Ssklower printf("<%x=%x>", a[i]&0xff, b[i]&0xff); 137*36384Ssklower if (a[i] != b[i]) { 138*36384Ssklower printf("\naddrs are not equal at byte %d\n", i); 139*36384Ssklower return(0); 140*36384Ssklower } 141*36384Ssklower } 142*36384Ssklower printf("\n"); 143*36384Ssklower printf("addrs are equal\n"); 144*36384Ssklower return (1); 145*36384Ssklower ENDDEBUG 146*36384Ssklower return (!bcmp((caddr_t)isoaa, (caddr_t)isoab, compare_len)); 147*36384Ssklower } 148*36384Ssklower 149*36384Ssklower /* 150*36384Ssklower * FUNCTION: iso_addrmatch 151*36384Ssklower * 152*36384Ssklower * PURPOSE: decide if the two sockadrr_isos passed are equal 153*36384Ssklower * 154*36384Ssklower * RETURNS: true if the addrs match, false if they do not 155*36384Ssklower * 156*36384Ssklower * SIDE EFFECTS: 157*36384Ssklower * 158*36384Ssklower * NOTES: 159*36384Ssklower */ 160*36384Ssklower iso_addrmatch(sisoa, sisob) 161*36384Ssklower struct sockaddr_iso *sisoa, *sisob; /* addresses to check */ 162*36384Ssklower { 163*36384Ssklower return(iso_addrmatch1(&sisoa->siso_addr, &sisob->siso_addr)); 164*36384Ssklower } 165*36384Ssklower 166*36384Ssklower /* 167*36384Ssklower * FUNCTION: iso_netmatch 168*36384Ssklower * 169*36384Ssklower * PURPOSE: similar to iso_addrmatch but takes sockaddr_iso 170*36384Ssklower * as argument. 171*36384Ssklower * 172*36384Ssklower * RETURNS: true if same net, false if not 173*36384Ssklower * 174*36384Ssklower * SIDE EFFECTS: 175*36384Ssklower * 176*36384Ssklower * NOTES: 177*36384Ssklower */ 178*36384Ssklower iso_netmatch(sisoa, sisob) 179*36384Ssklower struct sockaddr_iso *sisoa, *sisob; 180*36384Ssklower { 181*36384Ssklower u_char bufa[sizeof(struct sockaddr_iso)]; 182*36384Ssklower u_char bufb[sizeof(struct sockaddr_iso)]; 183*36384Ssklower register int lena, lenb; 184*36384Ssklower 185*36384Ssklower lena = iso_netof(&sisoa->siso_addr, bufa); 186*36384Ssklower lenb = iso_netof(&sisob->siso_addr, bufb); 187*36384Ssklower 188*36384Ssklower IFDEBUG(D_ROUTE) 189*36384Ssklower printf("iso_netmatch: comparing lengths: %d to %d\n", lena, lenb); 190*36384Ssklower printf("a:\n"); 191*36384Ssklower dump_buf(bufa, lena); 192*36384Ssklower printf("b:\n"); 193*36384Ssklower dump_buf(bufb, lenb); 194*36384Ssklower ENDDEBUG 195*36384Ssklower 196*36384Ssklower return ((lena == lenb) && (!bcmp(bufa, bufb, lena))); 197*36384Ssklower } 198*36384Ssklower 199*36384Ssklower /* 200*36384Ssklower * FUNCTION: iso_hashchar 201*36384Ssklower * 202*36384Ssklower * PURPOSE: Hash all character in the buffer specified into 203*36384Ssklower * a long. Return the long. 204*36384Ssklower * 205*36384Ssklower * RETURNS: The hash value. 206*36384Ssklower * 207*36384Ssklower * SIDE EFFECTS: 208*36384Ssklower * 209*36384Ssklower * NOTES: The hash is achieved by exclusive ORing 4 byte 210*36384Ssklower * quantities. 211*36384Ssklower */ 212*36384Ssklower u_long 213*36384Ssklower iso_hashchar(buf, len) 214*36384Ssklower register caddr_t buf; /* buffer to pack from */ 215*36384Ssklower register int len; /* length of buffer */ 216*36384Ssklower { 217*36384Ssklower register u_long h = 0; 218*36384Ssklower register int i; 219*36384Ssklower 220*36384Ssklower for (i=0; i<len; i+=4) { 221*36384Ssklower register u_long l = 0; 222*36384Ssklower 223*36384Ssklower if ((len - i) < 4) { 224*36384Ssklower /* buffer not multiple of 4 */ 225*36384Ssklower switch (len - i) { 226*36384Ssklower case 3: 227*36384Ssklower l |= buf[i+2] << 8; 228*36384Ssklower case 2: 229*36384Ssklower l |= buf[i+1] << 16; 230*36384Ssklower case 1: 231*36384Ssklower l |= buf[i] << 24; 232*36384Ssklower break; 233*36384Ssklower default: 234*36384Ssklower printf("iso_hashchar: unexpected value x%x\n", len - i); 235*36384Ssklower break; 236*36384Ssklower } 237*36384Ssklower } else { 238*36384Ssklower l |= buf[i] << 24; 239*36384Ssklower l |= buf[i+1] << 16; 240*36384Ssklower l |= buf[i+2] << 8; 241*36384Ssklower l |= buf[i+3]; 242*36384Ssklower } 243*36384Ssklower 244*36384Ssklower h ^= l; 245*36384Ssklower } 246*36384Ssklower 247*36384Ssklower h ^= (u_long) (len % 4); 248*36384Ssklower 249*36384Ssklower return(h); 250*36384Ssklower } 251*36384Ssklower 252*36384Ssklower /* 253*36384Ssklower * FUNCTION: iso_hash 254*36384Ssklower * 255*36384Ssklower * PURPOSE: Fill in fields of afhash structure based upon addr passed. 256*36384Ssklower * 257*36384Ssklower * RETURNS: none 258*36384Ssklower * 259*36384Ssklower * SIDE EFFECTS: 260*36384Ssklower * 261*36384Ssklower * NOTES: 262*36384Ssklower */ 263*36384Ssklower iso_hash(siso, hp) 264*36384Ssklower struct sockaddr_iso *siso; /* address to perform hash on */ 265*36384Ssklower struct afhash *hp; /* RETURN: hash info here */ 266*36384Ssklower { 267*36384Ssklower u_long buf[sizeof(struct sockaddr_iso)+1/4]; 268*36384Ssklower register int bufsize; 269*36384Ssklower 270*36384Ssklower 271*36384Ssklower bzero(buf, sizeof(buf)); 272*36384Ssklower 273*36384Ssklower bufsize = iso_netof(&siso->siso_addr, buf); 274*36384Ssklower hp->afh_nethash = iso_hashchar((caddr_t)buf, bufsize); 275*36384Ssklower 276*36384Ssklower IFDEBUG(D_ROUTE) 277*36384Ssklower printf("iso_hash: iso_netof: bufsize = %d\n", bufsize); 278*36384Ssklower ENDDEBUG 279*36384Ssklower 280*36384Ssklower hp->afh_hosthash = iso_hashchar((caddr_t)&siso->siso_addr, 281*36384Ssklower siso->siso_addr.isoa_len); 282*36384Ssklower 283*36384Ssklower IFDEBUG(D_ROUTE) 284*36384Ssklower printf("iso_hash: %s: nethash = x%x, hosthash = x%x\n", 285*36384Ssklower clnp_iso_addrp(&siso->siso_addr), hp->afh_nethash, 286*36384Ssklower hp->afh_hosthash); 287*36384Ssklower ENDDEBUG 288*36384Ssklower } 289*36384Ssklower 290*36384Ssklower /* 291*36384Ssklower * FUNCTION: iso_netof 292*36384Ssklower * 293*36384Ssklower * PURPOSE: Extract the network portion of the iso address. 294*36384Ssklower * The network portion of the iso address varies depending 295*36384Ssklower * on the type of address. The network portion of the 296*36384Ssklower * address will include the IDP. The network portion is: 297*36384Ssklower * 298*36384Ssklower * TYPE DESC 299*36384Ssklower * t37 The AFI and x.121 (IDI) 300*36384Ssklower * osinet The AFI, orgid, snetid 301*36384Ssklower * rfc986 The AFI, vers and network part of 302*36384Ssklower * internet address. 303*36384Ssklower * 304*36384Ssklower * RETURNS: number of bytes placed into buf. 305*36384Ssklower * 306*36384Ssklower * SIDE EFFECTS: 307*36384Ssklower * 308*36384Ssklower * NOTES: Buf is assumed to be big enough 309*36384Ssklower */ 310*36384Ssklower iso_netof(isoa, buf) 311*36384Ssklower struct iso_addr *isoa; /* address */ 312*36384Ssklower caddr_t buf; /* RESULT: network portion of address here */ 313*36384Ssklower { 314*36384Ssklower u_int len = 1; /* length of afi */ 315*36384Ssklower 316*36384Ssklower switch (isoa->isoa_afi) { 317*36384Ssklower case AFI_37: 318*36384Ssklower /* 319*36384Ssklower * Due to classic x.25 tunnel vision, there is no 320*36384Ssklower * net portion of an x.121 address. For our purposes 321*36384Ssklower * the AFI will do, so that all x.25 -type addresses 322*36384Ssklower * map to the single x.25 SNPA. (Cannot have more than 323*36384Ssklower * one, obviously). 324*36384Ssklower */ 325*36384Ssklower 326*36384Ssklower break; 327*36384Ssklower 328*36384Ssklower /* case AFI_OSINET:*/ 329*36384Ssklower case AFI_RFC986: { 330*36384Ssklower u_short idi; /* value of idi */ 331*36384Ssklower 332*36384Ssklower /* osinet and rfc986 have idi in the same place */ 333*36384Ssklower CTOH(isoa->rfc986_idi[0], isoa->rfc986_idi[1], idi); 334*36384Ssklower 335*36384Ssklower if (idi == IDI_OSINET) 336*36384Ssklower /* 337*36384Ssklower * Network portion of OSINET address can only be the IDI. Clearly, 338*36384Ssklower * with one x25 interface, one could get to several orgids, and 339*36384Ssklower * several snetids. 340*36384Ssklower len += (ADDROSINET_IDI_LEN + OVLOSINET_ORGID_LEN + 341*36384Ssklower OVLOSINET_SNETID_LEN); 342*36384Ssklower */ 343*36384Ssklower len += ADDROSINET_IDI_LEN; 344*36384Ssklower else if (idi == IDI_RFC986) { 345*36384Ssklower u_long inetaddr; 346*36384Ssklower struct ovl_rfc986 *o986 = (struct ovl_rfc986 *)isoa; 347*36384Ssklower 348*36384Ssklower /* bump len to include idi and version (1 byte) */ 349*36384Ssklower len += ADDRRFC986_IDI_LEN + 1; 350*36384Ssklower 351*36384Ssklower /* get inet addr long aligned */ 352*36384Ssklower bcopy(o986->o986_inetaddr, &inetaddr, sizeof(inetaddr)); 353*36384Ssklower inetaddr = ntohl(inetaddr); /* convert to host byte order */ 354*36384Ssklower 355*36384Ssklower IFDEBUG(D_ROUTE) 356*36384Ssklower printf("iso_netof: isoa "); 357*36384Ssklower dump_buf(isoa, sizeof(*isoa)); 358*36384Ssklower printf("iso_netof: inetaddr 0x%x ", inetaddr); 359*36384Ssklower ENDDEBUG 360*36384Ssklower 361*36384Ssklower /* bump len by size of network portion of inet address */ 362*36384Ssklower if (IN_CLASSA(inetaddr)) { 363*36384Ssklower len += 4-IN_CLASSA_NSHIFT/8; 364*36384Ssklower IFDEBUG(D_ROUTE) 365*36384Ssklower printf("iso_netof: class A net len is now %d\n", len); 366*36384Ssklower ENDDEBUG 367*36384Ssklower } else if (IN_CLASSB(inetaddr)) { 368*36384Ssklower len += 4-IN_CLASSB_NSHIFT/8; 369*36384Ssklower IFDEBUG(D_ROUTE) 370*36384Ssklower printf("iso_netof: class B net len is now %d\n", len); 371*36384Ssklower ENDDEBUG 372*36384Ssklower } else { 373*36384Ssklower len += 4-IN_CLASSC_NSHIFT/8; 374*36384Ssklower IFDEBUG(D_ROUTE) 375*36384Ssklower printf("iso_netof: class C net len is now %d\n", len); 376*36384Ssklower ENDDEBUG 377*36384Ssklower } 378*36384Ssklower } else 379*36384Ssklower len = 0; 380*36384Ssklower } break; 381*36384Ssklower 382*36384Ssklower default: 383*36384Ssklower len = 0; 384*36384Ssklower } 385*36384Ssklower 386*36384Ssklower bcopy((caddr_t)isoa, buf, len); 387*36384Ssklower IFDEBUG(D_ROUTE) 388*36384Ssklower printf("in_netof: isoa "); 389*36384Ssklower dump_buf(isoa, len); 390*36384Ssklower printf("in_netof: net "); 391*36384Ssklower dump_buf(buf, len); 392*36384Ssklower ENDDEBUG 393*36384Ssklower return len; 394*36384Ssklower } 395*36384Ssklower 396*36384Ssklower /* 397*36384Ssklower * The following is a kludge until I figure something out. Since AFISO 398*36384Ssklower * allows >1 addr/ifp, SIOCGIFADDR can possibly return more than one 399*36384Ssklower * address. Rather than changing the ifreq structure, I have set up 400*36384Ssklower * the ioctl so it will return the address in sequential calls. When 401*36384Ssklower * all addresses have been read, EADDRNOTAVAIL will be returned. 402*36384Ssklower * 403*36384Ssklower * A call to delete or set an addr will cause a subsequent get to 404*36384Ssklower * retrieve the first addr, even if the first had already been read. 405*36384Ssklower * 406*36384Ssklower * The static pointer iso_ia keeps track of which addrs have been read. 407*36384Ssklower */ 408*36384Ssklower static struct iso_ifaddr *iso_iap = NULL; 409*36384Ssklower 410*36384Ssklower /* 411*36384Ssklower * FUNCTION: iso_control 412*36384Ssklower * 413*36384Ssklower * PURPOSE: Generic iso control operations (ioctl's). 414*36384Ssklower * Ifp is 0 if this is not an interface-specific ioctl. 415*36384Ssklower * 416*36384Ssklower * RETURNS: unix error code 417*36384Ssklower * 418*36384Ssklower * SIDE EFFECTS: 419*36384Ssklower * 420*36384Ssklower * NOTES: The iso address family will allow more than one 421*36384Ssklower * iso address per interface as long as they are different 422*36384Ssklower * iso address types. The three types currently supported 423*36384Ssklower * are rfc986, t37, and osinet. 424*36384Ssklower */ 425*36384Ssklower iso_control(so, cmd, data, ifp) 426*36384Ssklower struct socket *so; /* socket ioctl arrived on */ 427*36384Ssklower int cmd; /* ioctl to perform */ 428*36384Ssklower caddr_t data; /* data for the ioctl */ 429*36384Ssklower struct ifnet *ifp; /* optional interface ptr */ 430*36384Ssklower { 431*36384Ssklower register struct ifreq *ifr = (struct ifreq *)data; 432*36384Ssklower register struct iso_ifaddr *ia = 0; 433*36384Ssklower struct ifaddr *ifa; 434*36384Ssklower struct mbuf *m; 435*36384Ssklower 436*36384Ssklower 437*36384Ssklower switch (cmd) { 438*36384Ssklower case SIOCSIFADDR: 439*36384Ssklower if (!suser()) 440*36384Ssklower return (u.u_error); 441*36384Ssklower 442*36384Ssklower if (ifp == 0) 443*36384Ssklower panic("iso_control: SIOCSIFADDR"); 444*36384Ssklower 445*36384Ssklower /* 446*36384Ssklower * Check if a iso address of same type exists for ifp 447*36384Ssklower * If it does, then return an error. 448*36384Ssklower */ 449*36384Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 450*36384Ssklower if (ia->ia_ifp == ifp) { 451*36384Ssklower struct sockaddr_iso *siso; 452*36384Ssklower 453*36384Ssklower siso = (struct sockaddr_iso *)&ifr->ifr_addr; 454*36384Ssklower if (iso_eqtype(&IA_SIS(ia)->siso_addr, &siso->siso_addr)) 455*36384Ssklower return(EADDRNOTAVAIL); 456*36384Ssklower } 457*36384Ssklower } 458*36384Ssklower 459*36384Ssklower /* 460*36384Ssklower * Go ahead and create new ifaddr 461*36384Ssklower * 462*36384Ssklower * Link addr into list of iso addresses 463*36384Ssklower */ 464*36384Ssklower m = m_getclr(M_WAIT, MT_IFADDR); 465*36384Ssklower if (m == (struct mbuf *)NULL) 466*36384Ssklower return (ENOBUFS); 467*36384Ssklower if (ia = iso_ifaddr) { 468*36384Ssklower for ( ; ia->ia_next; ia = ia->ia_next) 469*36384Ssklower ; 470*36384Ssklower ia->ia_next = mtod(m, struct iso_ifaddr *); 471*36384Ssklower } else 472*36384Ssklower iso_ifaddr = mtod(m, struct iso_ifaddr *); 473*36384Ssklower iso_iap = iso_ifaddr; 474*36384Ssklower 475*36384Ssklower /* 476*36384Ssklower * Link addr into list on interface 477*36384Ssklower */ 478*36384Ssklower ia = mtod(m, struct iso_ifaddr *); 479*36384Ssklower if (ifa = ifp->if_addrlist) { 480*36384Ssklower for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 481*36384Ssklower ; 482*36384Ssklower ifa->ifa_next = (struct ifaddr *) ia; 483*36384Ssklower } else 484*36384Ssklower ifp->if_addrlist = (struct ifaddr *) ia; 485*36384Ssklower 486*36384Ssklower ia->ia_ifp = ifp; 487*36384Ssklower IA_SIS(ia)->siso_family = AF_ISO; 488*36384Ssklower if (ifp != &loif) 489*36384Ssklower iso_interfaces++; 490*36384Ssklower return (iso_ifinit(ifp, ia, &ifr->ifr_addr)); 491*36384Ssklower 492*36384Ssklower case SIOCGIFADDR: 493*36384Ssklower for (ia = iso_iap; ia; ia = ia->ia_next) { 494*36384Ssklower if (ia->ia_ifp == ifp) { 495*36384Ssklower ifr->ifr_addr = ia->ia_addr; 496*36384Ssklower iso_iap = ia->ia_next; 497*36384Ssklower return (0); 498*36384Ssklower } 499*36384Ssklower } 500*36384Ssklower iso_iap = iso_ifaddr; 501*36384Ssklower return(EADDRNOTAVAIL); 502*36384Ssklower 503*36384Ssklower case SIOCDIFADDR: /* TODO: what about this ioctl on other families */ 504*36384Ssklower if (!suser()) 505*36384Ssklower return (u.u_error); 506*36384Ssklower iso_iap = iso_ifaddr; 507*36384Ssklower 508*36384Ssklower if (ifp == 0) 509*36384Ssklower panic("iso_control: SIOCDIFADDR"); 510*36384Ssklower 511*36384Ssklower return (iso_ifdelete(ifp, &ifr->ifr_addr)); 512*36384Ssklower 513*36384Ssklower default: 514*36384Ssklower if (ifp == 0 || ifp->if_ioctl == 0) 515*36384Ssklower return (EOPNOTSUPP); 516*36384Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data)); 517*36384Ssklower } 518*36384Ssklower } 519*36384Ssklower 520*36384Ssklower struct ifaddr * 521*36384Ssklower iso_ifwithidi(addr) 522*36384Ssklower register struct sockaddr *addr; 523*36384Ssklower { 524*36384Ssklower register struct ifnet *ifp; 525*36384Ssklower register struct ifaddr *ifa; 526*36384Ssklower register u_int af = addr->sa_family; 527*36384Ssklower 528*36384Ssklower if (af != AF_ISO) 529*36384Ssklower return (0); 530*36384Ssklower IFDEBUG(D_ROUTE) 531*36384Ssklower printf(">>> iso_ifwithidi addr\n"); 532*36384Ssklower dump_isoaddr( (struct sockaddr_iso *)(addr)); 533*36384Ssklower printf("\n"); 534*36384Ssklower ENDDEBUG 535*36384Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) { 536*36384Ssklower IFDEBUG(D_ROUTE) 537*36384Ssklower printf("iso_ifwithidi ifnet %s\n", ifp->if_name); 538*36384Ssklower ENDDEBUG 539*36384Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 540*36384Ssklower IFDEBUG(D_ROUTE) 541*36384Ssklower printf("iso_ifwithidi address "); 542*36384Ssklower dump_isoaddr( (struct sockaddr_iso *)(&ifa->ifa_addr)); 543*36384Ssklower ENDDEBUG 544*36384Ssklower if (ifa->ifa_addr.sa_family != addr->sa_family) 545*36384Ssklower continue; 546*36384Ssklower 547*36384Ssklower #define IFA_SIS(ifa)\ 548*36384Ssklower ((struct sockaddr_iso *)&((ifa)->ifa_addr)) 549*36384Ssklower 550*36384Ssklower IFDEBUG(D_ROUTE) 551*36384Ssklower printf(" af same, args to iso_eqtype:\n"); 552*36384Ssklower printf("0x%x ", IFA_SIS(ifa)->siso_addr); 553*36384Ssklower printf(" 0x%x\n", 554*36384Ssklower &(((struct sockaddr_iso *)addr)->siso_addr)); 555*36384Ssklower ENDDEBUG 556*36384Ssklower 557*36384Ssklower if (iso_eqtype(&(IFA_SIS(ifa)->siso_addr), 558*36384Ssklower &(((struct sockaddr_iso *)addr)->siso_addr))) { 559*36384Ssklower IFDEBUG(D_ROUTE) 560*36384Ssklower printf("ifa_ifwithidi: ifa found\n"); 561*36384Ssklower ENDDEBUG 562*36384Ssklower return (ifa); 563*36384Ssklower } 564*36384Ssklower IFDEBUG(D_ROUTE) 565*36384Ssklower printf(" iso_eqtype failed\n"); 566*36384Ssklower ENDDEBUG 567*36384Ssklower } 568*36384Ssklower } 569*36384Ssklower return ((struct ifaddr *)0); 570*36384Ssklower } 571*36384Ssklower 572*36384Ssklower /* 573*36384Ssklower * FUNCTION: iso_ifinit 574*36384Ssklower * 575*36384Ssklower * PURPOSE: Initialize an interface's iso address and 576*36384Ssklower * routing table entry. 577*36384Ssklower * 578*36384Ssklower * RETURNS: unix error code 579*36384Ssklower * 580*36384Ssklower * SIDE EFFECTS: 581*36384Ssklower * 582*36384Ssklower * NOTES: 583*36384Ssklower */ 584*36384Ssklower iso_ifinit(ifp, ia, siso) 585*36384Ssklower register struct ifnet *ifp; /* interface to initialize */ 586*36384Ssklower register struct iso_ifaddr *ia; /* addr on ifnet list */ 587*36384Ssklower struct sockaddr_iso *siso; /* address to use */ 588*36384Ssklower { 589*36384Ssklower struct sockaddr oldaddr; 590*36384Ssklower struct sockaddr_iso netaddr; 591*36384Ssklower int s = splimp(), error; 592*36384Ssklower 593*36384Ssklower /* 594*36384Ssklower * Make sure the address make sense 595*36384Ssklower */ 596*36384Ssklower if (!iso_ck_addr(&siso->siso_addr)) 597*36384Ssklower return(EINVAL); 598*36384Ssklower IFDEBUG(D_ROUTE) 599*36384Ssklower int i; 600*36384Ssklower char *ptr; 601*36384Ssklower 602*36384Ssklower ptr = (char *) siso; 603*36384Ssklower printf("The size of sockaddr_iso is %d\n", 604*36384Ssklower sizeof(struct sockaddr_iso)); 605*36384Ssklower for(i=0; i< sizeof(struct sockaddr_iso); i++) { 606*36384Ssklower printf("sockaddr[%d] = 0x%x\n", i, *ptr++ & 0xff); 607*36384Ssklower } 608*36384Ssklower ENDDEBUG 609*36384Ssklower 610*36384Ssklower oldaddr = ia->ia_addr; 611*36384Ssklower ia->ia_addr = *(struct sockaddr *)siso; 612*36384Ssklower bzero((caddr_t)&netaddr, sizeof (netaddr)); 613*36384Ssklower netaddr.siso_family = AF_ISO; 614*36384Ssklower 615*36384Ssklower /* 616*36384Ssklower * Give the interface a chance to initialize 617*36384Ssklower */ 618*36384Ssklower if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 619*36384Ssklower splx(s); 620*36384Ssklower ia->ia_addr = oldaddr; 621*36384Ssklower return (error); 622*36384Ssklower } 623*36384Ssklower splx(s); 624*36384Ssklower 625*36384Ssklower /* 626*36384Ssklower * Add route for the network. 627*36384Ssklower */ 628*36384Ssklower if (ifp->if_flags & IFF_LOOPBACK) 629*36384Ssklower rtinit(&ia->ia_addr, &ia->ia_addr, (int)SIOCADDRT, RTF_HOST|RTF_UP); 630*36384Ssklower else { 631*36384Ssklower int len; 632*36384Ssklower 633*36384Ssklower len = iso_netof(&siso->siso_addr, (caddr_t)&netaddr.siso_addr); 634*36384Ssklower netaddr.siso_addr.isoa_len = len; 635*36384Ssklower rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, 636*36384Ssklower (int)SIOCADDRT, RTF_UP); 637*36384Ssklower } 638*36384Ssklower ia->ia_flags |= IFA_ROUTE; 639*36384Ssklower return (0); 640*36384Ssklower } 641*36384Ssklower 642*36384Ssklower 643*36384Ssklower /* 644*36384Ssklower * FUNCTION: iso_ifdelete 645*36384Ssklower * 646*36384Ssklower * PURPOSE: Delete an iso address from an interface. 647*36384Ssklower * 648*36384Ssklower * RETURNS: 0 or unix error code 649*36384Ssklower * 650*36384Ssklower * SIDE EFFECTS: 651*36384Ssklower * 652*36384Ssklower * NOTES: 653*36384Ssklower */ 654*36384Ssklower iso_ifdelete(ifp, siso) 655*36384Ssklower struct ifnet *ifp; /* interface to delete addr from */ 656*36384Ssklower struct sockaddr_iso *siso; /* address to delete */ 657*36384Ssklower { 658*36384Ssklower struct iso_addr *isoa = &siso->siso_addr; 659*36384Ssklower register struct iso_ifaddr *ia, *prev = 0; 660*36384Ssklower register struct ifaddr *ifa; 661*36384Ssklower int s; 662*36384Ssklower struct sockaddr_iso netaddr; 663*36384Ssklower 664*36384Ssklower /* 665*36384Ssklower * Find the iso address of same type as specified and delete it. 666*36384Ssklower */ 667*36384Ssklower for (ia = iso_ifaddr; ia; prev = ia, ia = ia->ia_next) { 668*36384Ssklower if (ia->ia_ifp == ifp) { 669*36384Ssklower if (iso_eqtype(&IA_SIS(ia)->siso_addr, isoa)) { 670*36384Ssklower /* 671*36384Ssklower * Delete any previous route for the address. 672*36384Ssklower */ 673*36384Ssklower IFDEBUG(D_IOCTL) 674*36384Ssklower printf("iso_ifdelete: delete %s\n", clnp_iso_addrp(isoa)) 675*36384Ssklower ENDDEBUG 676*36384Ssklower s = splimp(); 677*36384Ssklower bzero((caddr_t)&netaddr, sizeof (netaddr)); 678*36384Ssklower netaddr.siso_family = AF_ISO; 679*36384Ssklower if (ia->ia_flags & IFA_ROUTE) { 680*36384Ssklower if (ifp->if_flags & IFF_LOOPBACK) 681*36384Ssklower rtinit(&ia->ia_addr, &ia->ia_addr, (int)SIOCDELRT, 682*36384Ssklower RTF_HOST); 683*36384Ssklower else { 684*36384Ssklower (void) iso_netof(&siso->siso_addr, 685*36384Ssklower (caddr_t)&netaddr.siso_addr); 686*36384Ssklower rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, 687*36384Ssklower (int)SIOCDELRT, 0); 688*36384Ssklower } 689*36384Ssklower ia->ia_flags &= ~IFA_ROUTE; 690*36384Ssklower } 691*36384Ssklower splx(s); 692*36384Ssklower 693*36384Ssklower /* 694*36384Ssklower * Remove from list of iso addresses 695*36384Ssklower */ 696*36384Ssklower if (prev == 0) 697*36384Ssklower iso_ifaddr = ia->ia_next; 698*36384Ssklower else 699*36384Ssklower prev->ia_next = ia->ia_next; 700*36384Ssklower if (ifp != &loif) 701*36384Ssklower iso_interfaces--; 702*36384Ssklower 703*36384Ssklower /* 704*36384Ssklower * Remove from list of addrs on ifnet structure 705*36384Ssklower */ 706*36384Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 707*36384Ssklower ifp->if_addrlist = ia->ia_ifa.ifa_next; 708*36384Ssklower else { 709*36384Ssklower for (; ifa; ifa = ifa->ifa_next) { 710*36384Ssklower if (ifa->ifa_next == (struct ifaddr *)ia) { 711*36384Ssklower ifa->ifa_next = ia->ia_ifa.ifa_next; 712*36384Ssklower break; 713*36384Ssklower } 714*36384Ssklower } 715*36384Ssklower } 716*36384Ssklower 717*36384Ssklower /* 718*36384Ssklower * Free the iso_ifaddr mbuf 719*36384Ssklower */ 720*36384Ssklower m_free(dtom(ia)); 721*36384Ssklower return (0); 722*36384Ssklower } 723*36384Ssklower } 724*36384Ssklower } 725*36384Ssklower return(EADDRNOTAVAIL); 726*36384Ssklower } 727*36384Ssklower 728*36384Ssklower /* 729*36384Ssklower * FUNCTION: iso_ck_addr 730*36384Ssklower * 731*36384Ssklower * PURPOSE: return true if the iso_addr passed is 732*36384Ssklower * within the legal size limit for an iso address. 733*36384Ssklower * 734*36384Ssklower * RETURNS: true or false 735*36384Ssklower * 736*36384Ssklower * SIDE EFFECTS: 737*36384Ssklower * 738*36384Ssklower */ 739*36384Ssklower iso_ck_addr(isoa) 740*36384Ssklower struct iso_addr *isoa; /* address to check */ 741*36384Ssklower { 742*36384Ssklower return (isoa->isoa_len <= 20); 743*36384Ssklower 744*36384Ssklower } 745*36384Ssklower 746*36384Ssklower 747*36384Ssklower /* 748*36384Ssklower * FUNCTION: iso_eqtype 749*36384Ssklower * 750*36384Ssklower * PURPOSE: Determine if two iso addresses are of the same type. 751*36384Ssklower * This is flaky. Really we should consider all type 47 addrs to be the 752*36384Ssklower * same - but there do exist different structures for 47 addrs. 753*36384Ssklower * Gosip adds a 3rd. 754*36384Ssklower * 755*36384Ssklower * RETURNS: true if the addresses are the same type 756*36384Ssklower * 757*36384Ssklower * SIDE EFFECTS: 758*36384Ssklower * 759*36384Ssklower * NOTES: By type, I mean rfc986, t37, or osinet 760*36384Ssklower * 761*36384Ssklower * This will first compare afis. If they match, then 762*36384Ssklower * if the addr is not t37, the idis must be compared. 763*36384Ssklower */ 764*36384Ssklower iso_eqtype(isoaa, isoab) 765*36384Ssklower struct iso_addr *isoaa; /* first addr to check */ 766*36384Ssklower struct iso_addr *isoab; /* other addr to check */ 767*36384Ssklower { 768*36384Ssklower if (isoaa->isoa_afi == isoab->isoa_afi) { 769*36384Ssklower if (isoaa->isoa_afi == AFI_37) 770*36384Ssklower return(1); 771*36384Ssklower else 772*36384Ssklower return (!bcmp(&isoaa->isoa_u, &isoab->isoa_u, 2)); 773*36384Ssklower } 774*36384Ssklower return(0); 775*36384Ssklower } 776*36384Ssklower 777*36384Ssklower /* 778*36384Ssklower * FUNCTION: iso_iaonnetof() 779*36384Ssklower * 780*36384Ssklower * PURPOSE: Find and interface addresss based on the network 781*36384Ssklower * portion of an address. 782*36384Ssklower * 783*36384Ssklower * RETURNS: ptr to an interface address 784*36384Ssklower * 785*36384Ssklower * SIDE EFFECTS: 786*36384Ssklower * 787*36384Ssklower * NOTES: 788*36384Ssklower */ 789*36384Ssklower struct iso_ifaddr * 790*36384Ssklower iso_iaonnetof(siso) 791*36384Ssklower struct sockaddr_iso *siso; 792*36384Ssklower { 793*36384Ssklower register struct iso_ifaddr *ia; 794*36384Ssklower 795*36384Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) 796*36384Ssklower if (iso_netmatch( (struct sockaddr_iso *)(&ia->ia_ifa.ifa_addr), siso) ) 797*36384Ssklower return (ia); 798*36384Ssklower return ((struct iso_ifaddr *)0); 799*36384Ssklower } 800*36384Ssklower 801*36384Ssklower #ifdef NARGOXTWENTYFIVE > 0 802*36384Ssklower #include "cons.h" 803*36384Ssklower #endif NARGOXTWENTYFIVE > 0 804*36384Ssklower /* 805*36384Ssklower * FUNCTION: iso_nlctloutput 806*36384Ssklower * 807*36384Ssklower * PURPOSE: Set options at the network level 808*36384Ssklower * 809*36384Ssklower * RETURNS: E* 810*36384Ssklower * 811*36384Ssklower * SIDE EFFECTS: 812*36384Ssklower * 813*36384Ssklower * NOTES: This could embody some of the functions of 814*36384Ssklower * rclnp_ctloutput and cons_ctloutput. 815*36384Ssklower */ 816*36384Ssklower iso_nlctloutput(cmd, optname, pcb, m) 817*36384Ssklower int cmd; /* command:set or get */ 818*36384Ssklower int optname; /* option of interest */ 819*36384Ssklower caddr_t pcb; /* nl pcb */ 820*36384Ssklower struct mbuf *m; /* data for set, buffer for get */ 821*36384Ssklower { 822*36384Ssklower struct isopcb *isop = (struct isopcb *)pcb; 823*36384Ssklower int error = 0; /* return value */ 824*36384Ssklower caddr_t data; /* data for option */ 825*36384Ssklower int data_len; /* data's length */ 826*36384Ssklower 827*36384Ssklower IFDEBUG(D_ISO) 828*36384Ssklower printf("iso_nlctloutput: cmd %x, opt %x, pcb %x, m %x\n", 829*36384Ssklower cmd, optname, pcb, m); 830*36384Ssklower ENDDEBUG 831*36384Ssklower 832*36384Ssklower if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT)) 833*36384Ssklower return(EOPNOTSUPP); 834*36384Ssklower 835*36384Ssklower data = mtod(m, caddr_t); 836*36384Ssklower data_len = (m)->m_len; 837*36384Ssklower 838*36384Ssklower IFDEBUG(D_ISO) 839*36384Ssklower printf("iso_nlctloutput: data is:\n"); 840*36384Ssklower dump_buf(data, data_len); 841*36384Ssklower ENDDEBUG 842*36384Ssklower 843*36384Ssklower switch (optname) { 844*36384Ssklower 845*36384Ssklower #ifdef NARGOXTWENTYFIVE > 0 846*36384Ssklower case CONSOPT_X25CRUD: 847*36384Ssklower if (cmd == PRCO_GETOPT) { 848*36384Ssklower error = EOPNOTSUPP; 849*36384Ssklower break; 850*36384Ssklower } 851*36384Ssklower 852*36384Ssklower if (data_len > MAXX25CRUDLEN) { 853*36384Ssklower error = EINVAL; 854*36384Ssklower break; 855*36384Ssklower } 856*36384Ssklower 857*36384Ssklower IFDEBUG(D_ISO) 858*36384Ssklower printf("iso_nlctloutput: setting x25 crud\n"); 859*36384Ssklower ENDDEBUG 860*36384Ssklower 861*36384Ssklower bcopy(data, (caddr_t)&isop->isop_x25crud, data_len); 862*36384Ssklower isop->isop_x25crud_len = data_len; 863*36384Ssklower break; 864*36384Ssklower #endif NARGOXTWENTYFIVE > 0 865*36384Ssklower 866*36384Ssklower default: 867*36384Ssklower error = EOPNOTSUPP; 868*36384Ssklower } 869*36384Ssklower 870*36384Ssklower return error; 871*36384Ssklower } 872*36384Ssklower 873*36384Ssklower /* 874*36384Ssklower * FUNCTION: iso_routeifp 875*36384Ssklower * 876*36384Ssklower * PURPOSE: Route on a sockaddr and return ifp 877*36384Ssklower * 878*36384Ssklower * RETURNS: ifp of outgoing interface, or null 879*36384Ssklower * 880*36384Ssklower * SIDE EFFECTS: 881*36384Ssklower * 882*36384Ssklower * NOTES: 883*36384Ssklower */ 884*36384Ssklower struct ifnet * 885*36384Ssklower iso_routeifp(dst) 886*36384Ssklower struct sockaddr *dst; /* destination to route to */ 887*36384Ssklower { 888*36384Ssklower struct route ro; 889*36384Ssklower struct ifnet *ifp = NULL; 890*36384Ssklower 891*36384Ssklower ro.ro_dst = *dst; 892*36384Ssklower ro.ro_rt = NULL; 893*36384Ssklower 894*36384Ssklower IFDEBUG(D_ROUTE) 895*36384Ssklower printf("iso_routeifp: dst:"); 896*36384Ssklower dump_isoaddr(dst); 897*36384Ssklower ENDDEBUG 898*36384Ssklower 899*36384Ssklower rtalloc(&ro); 900*36384Ssklower 901*36384Ssklower if (ro.ro_rt) { 902*36384Ssklower ifp = ro.ro_rt->rt_ifp; 903*36384Ssklower RTFREE(ro.ro_rt); 904*36384Ssklower } 905*36384Ssklower 906*36384Ssklower IFDEBUG(D_ROUTE) 907*36384Ssklower printf("iso_routeifp: ifp x%x", ifp); 908*36384Ssklower if (ifp) 909*36384Ssklower printf(" (%s%d)\n", ifp->if_name, ifp->if_unit); 910*36384Ssklower else 911*36384Ssklower printf("\n"); 912*36384Ssklower ENDDEBUG 913*36384Ssklower 914*36384Ssklower return(ifp); 915*36384Ssklower } 916*36384Ssklower #endif ISO 917*36384Ssklower 918*36384Ssklower #ifdef ARGO_DEBUG 919*36384Ssklower 920*36384Ssklower /* 921*36384Ssklower * FUNCTION: dump_isoaddr 922*36384Ssklower * 923*36384Ssklower * PURPOSE: debugging 924*36384Ssklower * 925*36384Ssklower * RETURNS: nada 926*36384Ssklower * 927*36384Ssklower */ 928*36384Ssklower dump_isoaddr(s) 929*36384Ssklower struct sockaddr_iso *s; 930*36384Ssklower { 931*36384Ssklower caddr_t c = (caddr_t)&(s->siso_addr.isoa_u); 932*36384Ssklower register int i; 933*36384Ssklower 934*36384Ssklower if( s->siso_family == AF_ISO) { 935*36384Ssklower printf("len %d family: 0x%x suffix 0x%x, afi 0x%x,", 936*36384Ssklower (int)s->siso_addr.isoa_len, 937*36384Ssklower (int)s->siso_family, 938*36384Ssklower s->siso_tsuffix, (int)s->siso_addr.isoa_afi); 939*36384Ssklower if( s->siso_addr.isoa_len > sizeof(struct sockaddr) ) 940*36384Ssklower printf("ERROR-ADDR TOO BIG %d\n", s->siso_addr.isoa_len); 941*36384Ssklower else { 942*36384Ssklower if (s->siso_addr.isoa_len != 0) { 943*36384Ssklower /* -2 because we already skipped the afi */ 944*36384Ssklower for (i=0; i<s->siso_addr.isoa_len-2; i++) 945*36384Ssklower printf("0x%x.", *(c+i)&0xff); 946*36384Ssklower printf("0x%x\n", *(c+i)&0xff); 947*36384Ssklower } 948*36384Ssklower } 949*36384Ssklower } else if( s->siso_family == AF_INET) { 950*36384Ssklower /* hack */ 951*36384Ssklower struct sockaddr_in *sin = (struct sockaddr_in *)s; 952*36384Ssklower 953*36384Ssklower printf("%d.%d.%d.%d: %d", 954*36384Ssklower (sin->sin_addr.s_addr>>24)&0xff, 955*36384Ssklower (sin->sin_addr.s_addr>>16)&0xff, 956*36384Ssklower (sin->sin_addr.s_addr>>8)&0xff, 957*36384Ssklower (sin->sin_addr.s_addr)&0xff, 958*36384Ssklower sin->sin_port); 959*36384Ssklower } 960*36384Ssklower } 961*36384Ssklower 962*36384Ssklower #endif ARGO_DEBUG 963