136384Ssklower /*********************************************************** 236384Ssklower Copyright IBM Corporation 1987 336384Ssklower 436384Ssklower All Rights Reserved 536384Ssklower 636384Ssklower Permission to use, copy, modify, and distribute this software and its 736384Ssklower documentation for any purpose and without fee is hereby granted, 836384Ssklower provided that the above copyright notice appear in all copies and that 936384Ssklower both that copyright notice and this permission notice appear in 1036384Ssklower supporting documentation, and that the name of IBM not be 1136384Ssklower used in advertising or publicity pertaining to distribution of the 1236384Ssklower software without specific, written prior permission. 1336384Ssklower 1436384Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 1536384Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 1636384Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 1736384Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 1836384Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 1936384Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2036384Ssklower SOFTWARE. 2136384Ssklower 2236384Ssklower ******************************************************************/ 2336384Ssklower 2436384Ssklower /* 2536384Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 2636384Ssklower */ 2736384Ssklower /* 2836384Ssklower * $Header: iso.c,v 4.11 88/09/19 14:58:35 root Exp $ 2936384Ssklower * $Source: /usr/argo/sys/netiso/RCS/iso.c,v $ 30*43428Ssklower * @(#)iso.c 7.10 (Berkeley) 06/22/90 3136384Ssklower * 3236384Ssklower * iso.c: miscellaneous routines to support the iso address family 3336384Ssklower */ 3436384Ssklower 3536384Ssklower #ifndef lint 3636384Ssklower static char *rcsid = "$Header: iso.c,v 4.11 88/09/19 14:58:35 root Exp $"; 3736384Ssklower #endif 3836384Ssklower 3936384Ssklower 4037469Ssklower #include "types.h" 4137469Ssklower #include "param.h" 4237469Ssklower #include "ioctl.h" 4337469Ssklower #include "mbuf.h" 4437469Ssklower #include "domain.h" 4537469Ssklower #include "protosw.h" 4637469Ssklower #include "socket.h" 4737469Ssklower #include "socketvar.h" 4837469Ssklower #include "user.h" 4937469Ssklower #include "errno.h" 5036384Ssklower 5136384Ssklower #include "../net/if.h" 5236384Ssklower #include "../net/route.h" 5336384Ssklower #include "../net/af.h" 5436384Ssklower 5537469Ssklower #include "iso.h" 5637469Ssklower #include "iso_var.h" 5737469Ssklower #include "iso_snpac.h" 5837469Ssklower #include "iso_pcb.h" 5937469Ssklower #include "clnp.h" 6037469Ssklower #include "argo_debug.h" 6136384Ssklower 6236384Ssklower #ifdef ISO 6337469Ssklower #include "argoxtwentyfive.h" 6436384Ssklower 6536384Ssklower int iso_interfaces = 0; /* number of external interfaces */ 6636384Ssklower extern struct ifnet loif; /* loopback interface */ 6743333Ssklower int ether_output(), llc_rtrequest(); 6836384Ssklower 6936384Ssklower 7036384Ssklower /* 7136384Ssklower * FUNCTION: iso_init 7236384Ssklower * 7336384Ssklower * PURPOSE: initialize the iso address family 7436384Ssklower * 7536384Ssklower * RETURNS: nothing 7636384Ssklower * 7736384Ssklower * SIDE EFFECTS: 1) zeros the maptab table. 7837469Ssklower * 2) initializes the routing table. 7936384Ssklower * 8036384Ssklower * NOTES: 8136384Ssklower */ 8237469Ssklower struct radix_node_head *iso_rnhead; 8336384Ssklower iso_init() 8436384Ssklower { 8537469Ssklower static iso_init_done; 8636384Ssklower 8737469Ssklower if (iso_init_done == 0) { 8837469Ssklower iso_init_done++; 8937469Ssklower rn_inithead(&iso_rnhead, 40, AF_ISO); 9037469Ssklower } 9136384Ssklower } 9236384Ssklower 9336384Ssklower /* 9436384Ssklower * FUNCTION: iso_addrmatch1 9536384Ssklower * 9636384Ssklower * PURPOSE: decide if the two iso_addrs passed are equal 9736384Ssklower * 9836384Ssklower * RETURNS: true if the addrs match, false if they do not 9936384Ssklower * 10036384Ssklower * SIDE EFFECTS: 10136384Ssklower * 10236384Ssklower * NOTES: 10336384Ssklower */ 10436384Ssklower iso_addrmatch1(isoaa, isoab) 10537469Ssklower register struct iso_addr *isoaa, *isoab; /* addresses to check */ 10636384Ssklower { 10737469Ssklower u_int compare_len; 10836384Ssklower 10936384Ssklower IFDEBUG(D_ROUTE) 11036384Ssklower printf("iso_addrmatch1: comparing lengths: %d to %d\n", isoaa->isoa_len, 11136384Ssklower isoab->isoa_len); 11236384Ssklower printf("a:\n"); 11337469Ssklower dump_buf(isoaa->isoa_genaddr, isoaa->isoa_len); 11436384Ssklower printf("b:\n"); 11537469Ssklower dump_buf(isoab->isoa_genaddr, isoab->isoa_len); 11636384Ssklower ENDDEBUG 11736384Ssklower 11836384Ssklower if ((compare_len = isoaa->isoa_len) != isoab->isoa_len) { 11936384Ssklower IFDEBUG(D_ROUTE) 12036384Ssklower printf("iso_addrmatch1: returning false because of lengths\n"); 12136384Ssklower ENDDEBUG 12236384Ssklower return 0; 12336384Ssklower } 12436384Ssklower 12537469Ssklower #ifdef notdef 12636384Ssklower /* TODO : generalize this to all afis with masks */ 12736384Ssklower if( isoaa->isoa_afi == AFI_37 ) { 12836384Ssklower /* must not compare 2 least significant digits, or for 12936384Ssklower * that matter, the DSP 13036384Ssklower */ 13136384Ssklower compare_len = ADDR37_IDI_LEN - 1; 13236384Ssklower } 13337469Ssklower #endif 13436384Ssklower 13536384Ssklower IFDEBUG(D_ROUTE) 13636384Ssklower int i; 13736384Ssklower char *a, *b; 13836384Ssklower 13937469Ssklower a = isoaa->isoa_genaddr; 14037469Ssklower b = isoab->isoa_genaddr; 14136384Ssklower 14236384Ssklower for (i=0; i<compare_len; i++) { 14336384Ssklower printf("<%x=%x>", a[i]&0xff, b[i]&0xff); 14436384Ssklower if (a[i] != b[i]) { 14536384Ssklower printf("\naddrs are not equal at byte %d\n", i); 14636384Ssklower return(0); 14736384Ssklower } 14836384Ssklower } 14936384Ssklower printf("\n"); 15036384Ssklower printf("addrs are equal\n"); 15136384Ssklower return (1); 15236384Ssklower ENDDEBUG 15337469Ssklower return (!bcmp(isoaa->isoa_genaddr, isoab->isoa_genaddr, compare_len)); 15436384Ssklower } 15536384Ssklower 15636384Ssklower /* 15736384Ssklower * FUNCTION: iso_addrmatch 15836384Ssklower * 15936384Ssklower * PURPOSE: decide if the two sockadrr_isos passed are equal 16036384Ssklower * 16136384Ssklower * RETURNS: true if the addrs match, false if they do not 16236384Ssklower * 16336384Ssklower * SIDE EFFECTS: 16436384Ssklower * 16536384Ssklower * NOTES: 16636384Ssklower */ 16736384Ssklower iso_addrmatch(sisoa, sisob) 16836384Ssklower struct sockaddr_iso *sisoa, *sisob; /* addresses to check */ 16936384Ssklower { 17036384Ssklower return(iso_addrmatch1(&sisoa->siso_addr, &sisob->siso_addr)); 17136384Ssklower } 17237469Ssklower #ifdef notdef 17336384Ssklower /* 17436384Ssklower * FUNCTION: iso_netmatch 17536384Ssklower * 17636384Ssklower * PURPOSE: similar to iso_addrmatch but takes sockaddr_iso 17736384Ssklower * as argument. 17836384Ssklower * 17936384Ssklower * RETURNS: true if same net, false if not 18036384Ssklower * 18136384Ssklower * SIDE EFFECTS: 18236384Ssklower * 18336384Ssklower * NOTES: 18436384Ssklower */ 18536384Ssklower iso_netmatch(sisoa, sisob) 18636384Ssklower struct sockaddr_iso *sisoa, *sisob; 18736384Ssklower { 18836384Ssklower u_char bufa[sizeof(struct sockaddr_iso)]; 18936384Ssklower u_char bufb[sizeof(struct sockaddr_iso)]; 19036384Ssklower register int lena, lenb; 19136384Ssklower 19236384Ssklower lena = iso_netof(&sisoa->siso_addr, bufa); 19336384Ssklower lenb = iso_netof(&sisob->siso_addr, bufb); 19436384Ssklower 19536384Ssklower IFDEBUG(D_ROUTE) 19636384Ssklower printf("iso_netmatch: comparing lengths: %d to %d\n", lena, lenb); 19736384Ssklower printf("a:\n"); 19836384Ssklower dump_buf(bufa, lena); 19936384Ssklower printf("b:\n"); 20036384Ssklower dump_buf(bufb, lenb); 20136384Ssklower ENDDEBUG 20236384Ssklower 20336384Ssklower return ((lena == lenb) && (!bcmp(bufa, bufb, lena))); 20436384Ssklower } 20537469Ssklower #endif notdef 20636384Ssklower 20736384Ssklower /* 20836384Ssklower * FUNCTION: iso_hashchar 20936384Ssklower * 21036384Ssklower * PURPOSE: Hash all character in the buffer specified into 21136384Ssklower * a long. Return the long. 21236384Ssklower * 21336384Ssklower * RETURNS: The hash value. 21436384Ssklower * 21536384Ssklower * SIDE EFFECTS: 21636384Ssklower * 21736384Ssklower * NOTES: The hash is achieved by exclusive ORing 4 byte 21836384Ssklower * quantities. 21936384Ssklower */ 22036384Ssklower u_long 22136384Ssklower iso_hashchar(buf, len) 22236384Ssklower register caddr_t buf; /* buffer to pack from */ 22336384Ssklower register int len; /* length of buffer */ 22436384Ssklower { 22536384Ssklower register u_long h = 0; 22636384Ssklower register int i; 22736384Ssklower 22836384Ssklower for (i=0; i<len; i+=4) { 22936384Ssklower register u_long l = 0; 23036384Ssklower 23136384Ssklower if ((len - i) < 4) { 23236384Ssklower /* buffer not multiple of 4 */ 23336384Ssklower switch (len - i) { 23436384Ssklower case 3: 23536384Ssklower l |= buf[i+2] << 8; 23636384Ssklower case 2: 23736384Ssklower l |= buf[i+1] << 16; 23836384Ssklower case 1: 23936384Ssklower l |= buf[i] << 24; 24036384Ssklower break; 24136384Ssklower default: 24236384Ssklower printf("iso_hashchar: unexpected value x%x\n", len - i); 24336384Ssklower break; 24436384Ssklower } 24536384Ssklower } else { 24636384Ssklower l |= buf[i] << 24; 24736384Ssklower l |= buf[i+1] << 16; 24836384Ssklower l |= buf[i+2] << 8; 24936384Ssklower l |= buf[i+3]; 25036384Ssklower } 25136384Ssklower 25236384Ssklower h ^= l; 25336384Ssklower } 25436384Ssklower 25536384Ssklower h ^= (u_long) (len % 4); 25636384Ssklower 25736384Ssklower return(h); 25836384Ssklower } 25937469Ssklower #ifdef notdef 26036384Ssklower /* 26136384Ssklower * FUNCTION: iso_hash 26236384Ssklower * 26336384Ssklower * PURPOSE: Fill in fields of afhash structure based upon addr passed. 26436384Ssklower * 26536384Ssklower * RETURNS: none 26636384Ssklower * 26736384Ssklower * SIDE EFFECTS: 26836384Ssklower * 26936384Ssklower * NOTES: 27036384Ssklower */ 27136384Ssklower iso_hash(siso, hp) 27236384Ssklower struct sockaddr_iso *siso; /* address to perform hash on */ 27336384Ssklower struct afhash *hp; /* RETURN: hash info here */ 27436384Ssklower { 27536384Ssklower u_long buf[sizeof(struct sockaddr_iso)+1/4]; 27636384Ssklower register int bufsize; 27736384Ssklower 27836384Ssklower 27936384Ssklower bzero(buf, sizeof(buf)); 28036384Ssklower 28136384Ssklower bufsize = iso_netof(&siso->siso_addr, buf); 28236384Ssklower hp->afh_nethash = iso_hashchar((caddr_t)buf, bufsize); 28336384Ssklower 28436384Ssklower IFDEBUG(D_ROUTE) 28536384Ssklower printf("iso_hash: iso_netof: bufsize = %d\n", bufsize); 28636384Ssklower ENDDEBUG 28736384Ssklower 28836384Ssklower hp->afh_hosthash = iso_hashchar((caddr_t)&siso->siso_addr, 28936384Ssklower siso->siso_addr.isoa_len); 29036384Ssklower 29136384Ssklower IFDEBUG(D_ROUTE) 29236384Ssklower printf("iso_hash: %s: nethash = x%x, hosthash = x%x\n", 29336384Ssklower clnp_iso_addrp(&siso->siso_addr), hp->afh_nethash, 29436384Ssklower hp->afh_hosthash); 29536384Ssklower ENDDEBUG 29636384Ssklower } 29736384Ssklower /* 29836384Ssklower * FUNCTION: iso_netof 29936384Ssklower * 30036384Ssklower * PURPOSE: Extract the network portion of the iso address. 30136384Ssklower * The network portion of the iso address varies depending 30236384Ssklower * on the type of address. The network portion of the 30336384Ssklower * address will include the IDP. The network portion is: 30436384Ssklower * 30536384Ssklower * TYPE DESC 30636384Ssklower * t37 The AFI and x.121 (IDI) 30736384Ssklower * osinet The AFI, orgid, snetid 30836384Ssklower * rfc986 The AFI, vers and network part of 30936384Ssklower * internet address. 31036384Ssklower * 31136384Ssklower * RETURNS: number of bytes placed into buf. 31236384Ssklower * 31336384Ssklower * SIDE EFFECTS: 31436384Ssklower * 31536384Ssklower * NOTES: Buf is assumed to be big enough 31636384Ssklower */ 31736384Ssklower iso_netof(isoa, buf) 31836384Ssklower struct iso_addr *isoa; /* address */ 31936384Ssklower caddr_t buf; /* RESULT: network portion of address here */ 32036384Ssklower { 32136384Ssklower u_int len = 1; /* length of afi */ 32236384Ssklower 32336384Ssklower switch (isoa->isoa_afi) { 32436384Ssklower case AFI_37: 32536384Ssklower /* 32636384Ssklower * Due to classic x.25 tunnel vision, there is no 32736384Ssklower * net portion of an x.121 address. For our purposes 32836384Ssklower * the AFI will do, so that all x.25 -type addresses 32936384Ssklower * map to the single x.25 SNPA. (Cannot have more than 33036384Ssklower * one, obviously). 33136384Ssklower */ 33236384Ssklower 33336384Ssklower break; 33436384Ssklower 33536384Ssklower /* case AFI_OSINET:*/ 33636384Ssklower case AFI_RFC986: { 33736384Ssklower u_short idi; /* value of idi */ 33836384Ssklower 33936384Ssklower /* osinet and rfc986 have idi in the same place */ 34036384Ssklower CTOH(isoa->rfc986_idi[0], isoa->rfc986_idi[1], idi); 34136384Ssklower 34236384Ssklower if (idi == IDI_OSINET) 34336384Ssklower /* 34436384Ssklower * Network portion of OSINET address can only be the IDI. Clearly, 34536384Ssklower * with one x25 interface, one could get to several orgids, and 34636384Ssklower * several snetids. 34736384Ssklower len += (ADDROSINET_IDI_LEN + OVLOSINET_ORGID_LEN + 34836384Ssklower OVLOSINET_SNETID_LEN); 34936384Ssklower */ 35036384Ssklower len += ADDROSINET_IDI_LEN; 35136384Ssklower else if (idi == IDI_RFC986) { 35236384Ssklower u_long inetaddr; 35336384Ssklower struct ovl_rfc986 *o986 = (struct ovl_rfc986 *)isoa; 35436384Ssklower 35536384Ssklower /* bump len to include idi and version (1 byte) */ 35636384Ssklower len += ADDRRFC986_IDI_LEN + 1; 35736384Ssklower 35836384Ssklower /* get inet addr long aligned */ 35936384Ssklower bcopy(o986->o986_inetaddr, &inetaddr, sizeof(inetaddr)); 36036384Ssklower inetaddr = ntohl(inetaddr); /* convert to host byte order */ 36136384Ssklower 36236384Ssklower IFDEBUG(D_ROUTE) 36336384Ssklower printf("iso_netof: isoa "); 36436384Ssklower dump_buf(isoa, sizeof(*isoa)); 36536384Ssklower printf("iso_netof: inetaddr 0x%x ", inetaddr); 36636384Ssklower ENDDEBUG 36736384Ssklower 36836384Ssklower /* bump len by size of network portion of inet address */ 36936384Ssklower if (IN_CLASSA(inetaddr)) { 37036384Ssklower len += 4-IN_CLASSA_NSHIFT/8; 37136384Ssklower IFDEBUG(D_ROUTE) 37236384Ssklower printf("iso_netof: class A net len is now %d\n", len); 37336384Ssklower ENDDEBUG 37436384Ssklower } else if (IN_CLASSB(inetaddr)) { 37536384Ssklower len += 4-IN_CLASSB_NSHIFT/8; 37636384Ssklower IFDEBUG(D_ROUTE) 37736384Ssklower printf("iso_netof: class B net len is now %d\n", len); 37836384Ssklower ENDDEBUG 37936384Ssklower } else { 38036384Ssklower len += 4-IN_CLASSC_NSHIFT/8; 38136384Ssklower IFDEBUG(D_ROUTE) 38236384Ssklower printf("iso_netof: class C net len is now %d\n", len); 38336384Ssklower ENDDEBUG 38436384Ssklower } 38536384Ssklower } else 38636384Ssklower len = 0; 38736384Ssklower } break; 38836384Ssklower 38936384Ssklower default: 39036384Ssklower len = 0; 39136384Ssklower } 39236384Ssklower 39336384Ssklower bcopy((caddr_t)isoa, buf, len); 39436384Ssklower IFDEBUG(D_ROUTE) 39536384Ssklower printf("in_netof: isoa "); 39636384Ssklower dump_buf(isoa, len); 39736384Ssklower printf("in_netof: net "); 39836384Ssklower dump_buf(buf, len); 39936384Ssklower ENDDEBUG 40036384Ssklower return len; 40136384Ssklower } 40237469Ssklower #endif notdef 40336384Ssklower /* 40437469Ssklower * Generic iso control operations (ioctl's). 40537469Ssklower * Ifp is 0 if not an interface-specific ioctl. 40636384Ssklower */ 40737469Ssklower /* ARGSUSED */ 40836384Ssklower iso_control(so, cmd, data, ifp) 40937469Ssklower struct socket *so; 41037469Ssklower int cmd; 41137469Ssklower caddr_t data; 41237469Ssklower register struct ifnet *ifp; 41336384Ssklower { 41437469Ssklower register struct iso_ifreq *ifr = (struct iso_ifreq *)data; 41537469Ssklower register struct iso_ifaddr *ia = 0; 41637469Ssklower register struct ifaddr *ifa; 41737469Ssklower struct iso_ifaddr *oia; 41837469Ssklower struct iso_aliasreq *ifra = (struct iso_aliasreq *)data; 41937469Ssklower int error, hostIsNew, maskIsNew; 42036384Ssklower 42137469Ssklower /* 42237469Ssklower * Find address for this interface, if it exists. 42337469Ssklower */ 42437469Ssklower if (ifp) 42537469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) 42637469Ssklower if (ia->ia_ifp == ifp) 42737469Ssklower break; 42836384Ssklower 42936384Ssklower switch (cmd) { 43037469Ssklower 43137469Ssklower case SIOCAIFADDR_ISO: 43237469Ssklower case SIOCDIFADDR_ISO: 43337469Ssklower if (ifra->ifra_addr.siso_family == AF_ISO) 43437469Ssklower for (oia = ia; ia; ia = ia->ia_next) { 43537469Ssklower if (ia->ia_ifp == ifp && 43637469Ssklower SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr)) 43737469Ssklower break; 43837469Ssklower } 43937547Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 44037547Smckusick return (error); 44136384Ssklower if (ifp == 0) 44237469Ssklower panic("iso_control"); 44337469Ssklower if (ia == (struct iso_ifaddr *)0) { 44437469Ssklower struct iso_ifaddr *nia; 44537469Ssklower if (cmd == SIOCDIFADDR_ISO) 44637469Ssklower return (EADDRNOTAVAIL); 44737469Ssklower MALLOC(nia, struct iso_ifaddr *, sizeof(*nia), 44837469Ssklower M_IFADDR, M_WAITOK); 44937469Ssklower if (nia == (struct iso_ifaddr *)0) 45037469Ssklower return (ENOBUFS); 45137469Ssklower bzero((caddr_t)nia, sizeof(*nia)); 45237469Ssklower if (ia = iso_ifaddr) { 45337469Ssklower for ( ; ia->ia_next; ia = ia->ia_next) 45437469Ssklower ; 45537469Ssklower ia->ia_next = nia; 45637469Ssklower } else 45737469Ssklower iso_ifaddr = nia; 45837469Ssklower ia = nia; 45937469Ssklower if (ifa = ifp->if_addrlist) { 46037469Ssklower for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 46137469Ssklower ; 46237469Ssklower ifa->ifa_next = (struct ifaddr *) ia; 46337469Ssklower } else 46437469Ssklower ifp->if_addrlist = (struct ifaddr *) ia; 46537469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 46637469Ssklower ia->ia_ifa.ifa_dstaddr 46737469Ssklower = (struct sockaddr *)&ia->ia_dstaddr; 46837469Ssklower ia->ia_ifa.ifa_netmask 46937469Ssklower = (struct sockaddr *)&ia->ia_sockmask; 47037469Ssklower ia->ia_ifp = ifp; 47137469Ssklower if (ifp != &loif) 47237469Ssklower iso_interfaces++; 47337469Ssklower } 47437469Ssklower break; 47536384Ssklower 47637469Ssklower #define cmdbyte(x) (((x) >> 8) & 0xff) 47737469Ssklower default: 47837469Ssklower if (cmdbyte(cmd) == 'a') 47937469Ssklower return (snpac_ioctl(cmd, data)); 48037469Ssklower if (ia == (struct iso_ifaddr *)0) 48137469Ssklower return (EADDRNOTAVAIL); 48237469Ssklower break; 48337469Ssklower } 48437469Ssklower switch (cmd) { 48536384Ssklower 48637469Ssklower case SIOCGIFADDR_ISO: 48737469Ssklower ifr->ifr_Addr = ia->ia_addr; 48837469Ssklower break; 48936384Ssklower 49037469Ssklower case SIOCGIFDSTADDR_ISO: 49137469Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 49237469Ssklower return (EINVAL); 49337469Ssklower ifr->ifr_Addr = ia->ia_dstaddr; 49437469Ssklower break; 49536384Ssklower 49637469Ssklower case SIOCGIFNETMASK_ISO: 49737469Ssklower ifr->ifr_Addr = ia->ia_sockmask; 49837469Ssklower break; 49936384Ssklower 50037469Ssklower case SIOCAIFADDR_ISO: 501*43428Ssklower maskIsNew = 0; hostIsNew = 1; error = 0; 50237469Ssklower if (ia->ia_addr.siso_family == AF_ISO) { 50337469Ssklower if (ifra->ifra_addr.siso_len == 0) { 50437469Ssklower ifra->ifra_addr = ia->ia_addr; 50537469Ssklower hostIsNew = 0; 50637469Ssklower } else if (SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr)) 50737469Ssklower hostIsNew = 0; 50837469Ssklower } 50937469Ssklower if (ifra->ifra_mask.siso_len) { 51037469Ssklower iso_ifscrub(ifp, ia); 51137469Ssklower ia->ia_sockmask = ifra->ifra_mask; 51237469Ssklower maskIsNew = 1; 51337469Ssklower } 51437469Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) && 51537469Ssklower (ifra->ifra_dstaddr.siso_family == AF_ISO)) { 51637469Ssklower iso_ifscrub(ifp, ia); 51737469Ssklower ia->ia_dstaddr = ifra->ifra_dstaddr; 51837469Ssklower maskIsNew = 1; /* We lie; but the effect's the same */ 51937469Ssklower } 52037469Ssklower if (ifra->ifra_addr.siso_family == AF_ISO && 52137469Ssklower (hostIsNew || maskIsNew)) { 52237469Ssklower error = iso_ifinit(ifp, ia, &ifra->ifra_addr, 0); 52337469Ssklower } 52437469Ssklower if (ifra->ifra_snpaoffset) 52537469Ssklower ia->ia_snpaoffset = ifra->ifra_snpaoffset; 52637469Ssklower return (error); 52737469Ssklower 52837469Ssklower case SIOCDIFADDR_ISO: 52937469Ssklower iso_ifscrub(ifp, ia); 53037469Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 53137469Ssklower ifp->if_addrlist = ifa->ifa_next; 53237469Ssklower else { 53337469Ssklower while (ifa->ifa_next && 53437469Ssklower (ifa->ifa_next != (struct ifaddr *)ia)) 53537469Ssklower ifa = ifa->ifa_next; 53637469Ssklower if (ifa->ifa_next) 53737469Ssklower ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 53837469Ssklower else 53937469Ssklower printf("Couldn't unlink isoifaddr from ifp\n"); 54037469Ssklower } 54137469Ssklower oia = ia; 54237469Ssklower if (oia == (ia = iso_ifaddr)) { 54337469Ssklower iso_ifaddr = ia->ia_next; 54437469Ssklower } else { 54537469Ssklower while (ia->ia_next && (ia->ia_next != oia)) { 54637469Ssklower ia = ia->ia_next; 54736384Ssklower } 54837469Ssklower if (ia->ia_next) 54937469Ssklower ia->ia_next = oia->ia_next; 55037469Ssklower else 55137469Ssklower printf("Didn't unlink isoifadr from list\n"); 55236384Ssklower } 55337469Ssklower free((caddr_t)oia, M_IFADDR); 55437469Ssklower break; 55536384Ssklower 55636384Ssklower default: 55736384Ssklower if (ifp == 0 || ifp->if_ioctl == 0) 55836384Ssklower return (EOPNOTSUPP); 55936384Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data)); 56036384Ssklower } 56137469Ssklower return (0); 56236384Ssklower } 56336384Ssklower 56437469Ssklower /* 56537469Ssklower * Delete any existing route for an interface. 56637469Ssklower */ 56737469Ssklower iso_ifscrub(ifp, ia) 56837469Ssklower register struct ifnet *ifp; 56937469Ssklower register struct iso_ifaddr *ia; 57037469Ssklower { 57143333Ssklower int nsellength = ia->ia_addr.siso_tlen; 57237469Ssklower if ((ia->ia_flags & IFA_ROUTE) == 0) 57337469Ssklower return; 57443333Ssklower ia->ia_addr.siso_tlen = 0; 57537469Ssklower if (ifp->if_flags & IFF_LOOPBACK) 57637469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 57737469Ssklower else if (ifp->if_flags & IFF_POINTOPOINT) 57837469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 57937469Ssklower else { 58037469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 58137469Ssklower } 58243333Ssklower ia->ia_addr.siso_tlen = nsellength; 58337469Ssklower ia->ia_flags &= ~IFA_ROUTE; 58437469Ssklower } 58537469Ssklower 58637469Ssklower /* 58737469Ssklower * Initialize an interface's internet address 58837469Ssklower * and routing table entry. 58937469Ssklower */ 59037469Ssklower iso_ifinit(ifp, ia, siso, scrub) 59137469Ssklower register struct ifnet *ifp; 59237469Ssklower register struct iso_ifaddr *ia; 59337469Ssklower struct sockaddr_iso *siso; 59437469Ssklower { 59537469Ssklower struct sockaddr_iso oldaddr; 59643333Ssklower int s = splimp(), error, nsellength; 59737469Ssklower 59837469Ssklower oldaddr = ia->ia_addr; 59937469Ssklower ia->ia_addr = *siso; 60037469Ssklower /* 60137469Ssklower * Give the interface a chance to initialize 60237469Ssklower * if this is its first address, 60337469Ssklower * and to validate the address if necessary. 60437469Ssklower */ 60537469Ssklower if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 60637469Ssklower splx(s); 60737469Ssklower ia->ia_addr = oldaddr; 60837469Ssklower return (error); 60937469Ssklower } 61037469Ssklower if (scrub) { 61137469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 61237469Ssklower iso_ifscrub(ifp, ia); 61337469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 61437469Ssklower } 61543333Ssklower /* XXX -- The following is here temporarily out of laziness 61643333Ssklower in not changing every ethernet driver's if_ioctl routine */ 61743333Ssklower if (ifp->if_output == ether_output) { 61843333Ssklower ia->ia_ifa.ifa_rtrequest = llc_rtrequest; 61943333Ssklower ia->ia_ifa.ifa_flags |= RTF_CLONING; 62043333Ssklower ia->ia_ifa.ifa_llinfolen = sizeof(struct llinfo_llc); 62143333Ssklower } 62237469Ssklower /* 62337469Ssklower * Add route for the network. 62437469Ssklower */ 62543333Ssklower nsellength = ia->ia_addr.siso_tlen; 62643333Ssklower ia->ia_addr.siso_tlen = 0; 62737469Ssklower if (ifp->if_flags & IFF_LOOPBACK) { 62837469Ssklower ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 62940894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 63037469Ssklower } else if (ifp->if_flags & IFF_POINTOPOINT && 63137469Ssklower ia->ia_dstaddr.siso_family == AF_ISO) 63240894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 63337469Ssklower else { 63440894Ssklower rt_maskedcopy(ia->ia_ifa.ifa_addr, ia->ia_ifa.ifa_dstaddr, 63540894Ssklower ia->ia_ifa.ifa_netmask); 63640894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP); 63737469Ssklower } 63843333Ssklower ia->ia_addr.siso_tlen = nsellength; 63937469Ssklower ia->ia_flags |= IFA_ROUTE; 64037469Ssklower splx(s); 64140894Ssklower return (error); 64237469Ssklower } 64337469Ssklower #ifdef notdef 64437469Ssklower 64536384Ssklower struct ifaddr * 64636384Ssklower iso_ifwithidi(addr) 64736384Ssklower register struct sockaddr *addr; 64836384Ssklower { 64936384Ssklower register struct ifnet *ifp; 65036384Ssklower register struct ifaddr *ifa; 65136384Ssklower register u_int af = addr->sa_family; 65236384Ssklower 65336384Ssklower if (af != AF_ISO) 65436384Ssklower return (0); 65536384Ssklower IFDEBUG(D_ROUTE) 65636384Ssklower printf(">>> iso_ifwithidi addr\n"); 65736384Ssklower dump_isoaddr( (struct sockaddr_iso *)(addr)); 65836384Ssklower printf("\n"); 65936384Ssklower ENDDEBUG 66036384Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) { 66136384Ssklower IFDEBUG(D_ROUTE) 66236384Ssklower printf("iso_ifwithidi ifnet %s\n", ifp->if_name); 66336384Ssklower ENDDEBUG 66436384Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 66536384Ssklower IFDEBUG(D_ROUTE) 66636384Ssklower printf("iso_ifwithidi address "); 66737469Ssklower dump_isoaddr( (struct sockaddr_iso *)(ifa->ifa_addr)); 66836384Ssklower ENDDEBUG 66937469Ssklower if (ifa->ifa_addr->sa_family != addr->sa_family) 67036384Ssklower continue; 67136384Ssklower 67236384Ssklower #define IFA_SIS(ifa)\ 67337469Ssklower ((struct sockaddr_iso *)((ifa)->ifa_addr)) 67436384Ssklower 67536384Ssklower IFDEBUG(D_ROUTE) 67636384Ssklower printf(" af same, args to iso_eqtype:\n"); 67736384Ssklower printf("0x%x ", IFA_SIS(ifa)->siso_addr); 67836384Ssklower printf(" 0x%x\n", 67936384Ssklower &(((struct sockaddr_iso *)addr)->siso_addr)); 68036384Ssklower ENDDEBUG 68136384Ssklower 68236384Ssklower if (iso_eqtype(&(IFA_SIS(ifa)->siso_addr), 68336384Ssklower &(((struct sockaddr_iso *)addr)->siso_addr))) { 68436384Ssklower IFDEBUG(D_ROUTE) 68536384Ssklower printf("ifa_ifwithidi: ifa found\n"); 68636384Ssklower ENDDEBUG 68736384Ssklower return (ifa); 68836384Ssklower } 68936384Ssklower IFDEBUG(D_ROUTE) 69036384Ssklower printf(" iso_eqtype failed\n"); 69136384Ssklower ENDDEBUG 69236384Ssklower } 69336384Ssklower } 69436384Ssklower return ((struct ifaddr *)0); 69536384Ssklower } 69636384Ssklower 69737469Ssklower #endif notdef 69836384Ssklower /* 69936384Ssklower * FUNCTION: iso_ck_addr 70036384Ssklower * 70136384Ssklower * PURPOSE: return true if the iso_addr passed is 70236384Ssklower * within the legal size limit for an iso address. 70336384Ssklower * 70436384Ssklower * RETURNS: true or false 70536384Ssklower * 70636384Ssklower * SIDE EFFECTS: 70736384Ssklower * 70836384Ssklower */ 70936384Ssklower iso_ck_addr(isoa) 71036384Ssklower struct iso_addr *isoa; /* address to check */ 71136384Ssklower { 71236384Ssklower return (isoa->isoa_len <= 20); 71336384Ssklower 71436384Ssklower } 71536384Ssklower 71637469Ssklower #ifdef notdef 71736384Ssklower /* 71836384Ssklower * FUNCTION: iso_eqtype 71936384Ssklower * 72036384Ssklower * PURPOSE: Determine if two iso addresses are of the same type. 72136384Ssklower * This is flaky. Really we should consider all type 47 addrs to be the 72236384Ssklower * same - but there do exist different structures for 47 addrs. 72336384Ssklower * Gosip adds a 3rd. 72436384Ssklower * 72536384Ssklower * RETURNS: true if the addresses are the same type 72636384Ssklower * 72736384Ssklower * SIDE EFFECTS: 72836384Ssklower * 72936384Ssklower * NOTES: By type, I mean rfc986, t37, or osinet 73036384Ssklower * 73136384Ssklower * This will first compare afis. If they match, then 73236384Ssklower * if the addr is not t37, the idis must be compared. 73336384Ssklower */ 73436384Ssklower iso_eqtype(isoaa, isoab) 73536384Ssklower struct iso_addr *isoaa; /* first addr to check */ 73636384Ssklower struct iso_addr *isoab; /* other addr to check */ 73736384Ssklower { 73836384Ssklower if (isoaa->isoa_afi == isoab->isoa_afi) { 73936384Ssklower if (isoaa->isoa_afi == AFI_37) 74036384Ssklower return(1); 74136384Ssklower else 74236384Ssklower return (!bcmp(&isoaa->isoa_u, &isoab->isoa_u, 2)); 74336384Ssklower } 74436384Ssklower return(0); 74536384Ssklower } 74637469Ssklower #endif notdef 74736384Ssklower /* 74837469Ssklower * FUNCTION: iso_localifa() 74936384Ssklower * 75037469Ssklower * PURPOSE: Find an interface addresss having a given destination 75137469Ssklower * or at least matching the net. 75236384Ssklower * 75336384Ssklower * RETURNS: ptr to an interface address 75436384Ssklower * 75536384Ssklower * SIDE EFFECTS: 75636384Ssklower * 75736384Ssklower * NOTES: 75836384Ssklower */ 75936384Ssklower struct iso_ifaddr * 76037469Ssklower iso_localifa(siso) 76137469Ssklower register struct sockaddr_iso *siso; 76236384Ssklower { 76336384Ssklower register struct iso_ifaddr *ia; 76437469Ssklower register char *cp1, *cp2, *cp3; 76537469Ssklower register struct ifnet *ifp; 76637469Ssklower struct iso_ifaddr *ia_maybe = 0; 76737469Ssklower /* 76837469Ssklower * We make one pass looking for both net matches and an exact 76937469Ssklower * dst addr. 77037469Ssklower */ 77137469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 77237469Ssklower if ((ifp = ia->ia_ifp) == 0 || ((ifp->if_flags & IFF_UP) == 0)) 77337469Ssklower continue; 77437469Ssklower if (ifp->if_flags & IFF_POINTOPOINT) { 77537469Ssklower if ((ia->ia_dstaddr.siso_family == AF_ISO) && 77637469Ssklower SAME_ISOADDR(&ia->ia_dstaddr, siso)) 77737469Ssklower return (ia); 77837469Ssklower else 77937469Ssklower if (SAME_ISOADDR(&ia->ia_addr, siso)) 78037469Ssklower ia_maybe = ia; 78137469Ssklower continue; 78237469Ssklower } 78337469Ssklower if (ia->ia_sockmask.siso_len) { 78437469Ssklower char *cplim = ia->ia_sockmask.siso_len + (char *)&ia->ia_sockmask; 78537469Ssklower cp1 = ia->ia_sockmask.siso_data; 78637469Ssklower cp2 = siso->siso_data; 78737469Ssklower cp3 = ia->ia_addr.siso_data; 78839936Ssklower while (cp1 < cplim) 78937469Ssklower if (*cp1++ & (*cp2++ ^ *cp3++)) 79037469Ssklower goto next; 79137469Ssklower ia_maybe = ia; 79237469Ssklower } 79337469Ssklower if (SAME_ISOADDR(&ia->ia_addr, siso)) 79437469Ssklower return ia; 79537469Ssklower next:; 79637469Ssklower } 79737469Ssklower return ia_maybe; 79836384Ssklower } 79936384Ssklower 80036384Ssklower #ifdef NARGOXTWENTYFIVE > 0 80136384Ssklower #include "cons.h" 80236384Ssklower #endif NARGOXTWENTYFIVE > 0 80336384Ssklower /* 80436384Ssklower * FUNCTION: iso_nlctloutput 80536384Ssklower * 80636384Ssklower * PURPOSE: Set options at the network level 80736384Ssklower * 80836384Ssklower * RETURNS: E* 80936384Ssklower * 81036384Ssklower * SIDE EFFECTS: 81136384Ssklower * 81236384Ssklower * NOTES: This could embody some of the functions of 81336384Ssklower * rclnp_ctloutput and cons_ctloutput. 81436384Ssklower */ 81536384Ssklower iso_nlctloutput(cmd, optname, pcb, m) 81636384Ssklower int cmd; /* command:set or get */ 81736384Ssklower int optname; /* option of interest */ 81836384Ssklower caddr_t pcb; /* nl pcb */ 81936384Ssklower struct mbuf *m; /* data for set, buffer for get */ 82036384Ssklower { 82136384Ssklower struct isopcb *isop = (struct isopcb *)pcb; 82236384Ssklower int error = 0; /* return value */ 82336384Ssklower caddr_t data; /* data for option */ 82436384Ssklower int data_len; /* data's length */ 82536384Ssklower 82636384Ssklower IFDEBUG(D_ISO) 82736384Ssklower printf("iso_nlctloutput: cmd %x, opt %x, pcb %x, m %x\n", 82836384Ssklower cmd, optname, pcb, m); 82936384Ssklower ENDDEBUG 83036384Ssklower 83136384Ssklower if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT)) 83236384Ssklower return(EOPNOTSUPP); 83336384Ssklower 83436384Ssklower data = mtod(m, caddr_t); 83536384Ssklower data_len = (m)->m_len; 83636384Ssklower 83736384Ssklower IFDEBUG(D_ISO) 83836384Ssklower printf("iso_nlctloutput: data is:\n"); 83936384Ssklower dump_buf(data, data_len); 84036384Ssklower ENDDEBUG 84136384Ssklower 84236384Ssklower switch (optname) { 84336384Ssklower 84436384Ssklower #ifdef NARGOXTWENTYFIVE > 0 84536384Ssklower case CONSOPT_X25CRUD: 84636384Ssklower if (cmd == PRCO_GETOPT) { 84736384Ssklower error = EOPNOTSUPP; 84836384Ssklower break; 84936384Ssklower } 85036384Ssklower 85136384Ssklower if (data_len > MAXX25CRUDLEN) { 85236384Ssklower error = EINVAL; 85336384Ssklower break; 85436384Ssklower } 85536384Ssklower 85636384Ssklower IFDEBUG(D_ISO) 85736384Ssklower printf("iso_nlctloutput: setting x25 crud\n"); 85836384Ssklower ENDDEBUG 85936384Ssklower 86037469Ssklower bcopy(data, (caddr_t)isop->isop_x25crud, (unsigned)data_len); 86136384Ssklower isop->isop_x25crud_len = data_len; 86236384Ssklower break; 86336384Ssklower #endif NARGOXTWENTYFIVE > 0 86436384Ssklower 86536384Ssklower default: 86636384Ssklower error = EOPNOTSUPP; 86736384Ssklower } 86836384Ssklower 86936384Ssklower return error; 87036384Ssklower } 87136384Ssklower #endif ISO 87236384Ssklower 87336384Ssklower #ifdef ARGO_DEBUG 87436384Ssklower 87536384Ssklower /* 87636384Ssklower * FUNCTION: dump_isoaddr 87736384Ssklower * 87836384Ssklower * PURPOSE: debugging 87936384Ssklower * 88036384Ssklower * RETURNS: nada 88136384Ssklower * 88236384Ssklower */ 88336384Ssklower dump_isoaddr(s) 88436384Ssklower struct sockaddr_iso *s; 88536384Ssklower { 88637469Ssklower char *clnp_saddr_isop(); 88736384Ssklower register int i; 88836384Ssklower 88936384Ssklower if( s->siso_family == AF_ISO) { 89037469Ssklower printf("ISO address: suffixlen %d, %s\n", 89138841Ssklower s->siso_tlen, clnp_saddr_isop(s)); 89236384Ssklower } else if( s->siso_family == AF_INET) { 89336384Ssklower /* hack */ 89436384Ssklower struct sockaddr_in *sin = (struct sockaddr_in *)s; 89536384Ssklower 89636384Ssklower printf("%d.%d.%d.%d: %d", 89736384Ssklower (sin->sin_addr.s_addr>>24)&0xff, 89836384Ssklower (sin->sin_addr.s_addr>>16)&0xff, 89936384Ssklower (sin->sin_addr.s_addr>>8)&0xff, 90036384Ssklower (sin->sin_addr.s_addr)&0xff, 90136384Ssklower sin->sin_port); 90236384Ssklower } 90336384Ssklower } 90436384Ssklower 90536384Ssklower #endif ARGO_DEBUG 906