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*37547Smckusick * @(#)iso.c 7.3 (Berkeley) 04/26/89 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 "uio.h" 4937469Ssklower #include "dir.h" 5037469Ssklower #include "user.h" 5137469Ssklower #include "errno.h" 5236384Ssklower 5336384Ssklower #include "../net/if.h" 5436384Ssklower #include "../net/route.h" 5536384Ssklower #include "../net/af.h" 5636384Ssklower 5737469Ssklower #include "iso.h" 5837469Ssklower #include "iso_var.h" 5937469Ssklower #include "iso_snpac.h" 6037469Ssklower #include "iso_pcb.h" 6137469Ssklower #include "clnp.h" 6237469Ssklower #include "argo_debug.h" 6336384Ssklower 6436384Ssklower #ifdef ISO 6537469Ssklower #include "argoxtwentyfive.h" 6636384Ssklower 6736384Ssklower int iso_interfaces = 0; /* number of external interfaces */ 6836384Ssklower extern struct ifnet loif; /* loopback interface */ 6936384Ssklower 7036384Ssklower 7136384Ssklower /* 7236384Ssklower * FUNCTION: iso_init 7336384Ssklower * 7436384Ssklower * PURPOSE: initialize the iso address family 7536384Ssklower * 7636384Ssklower * RETURNS: nothing 7736384Ssklower * 7836384Ssklower * SIDE EFFECTS: 1) zeros the maptab table. 7937469Ssklower * 2) initializes the routing table. 8036384Ssklower * 8136384Ssklower * NOTES: 8236384Ssklower */ 8337469Ssklower struct radix_node_head *iso_rnhead; 8436384Ssklower iso_init() 8536384Ssklower { 8637469Ssklower extern struct spna_cache iso_snpac[]; 8737469Ssklower extern u_int iso_snpac_size; 8837469Ssklower static iso_init_done; 8936384Ssklower 9037469Ssklower if (iso_init_done == 0) { 9137469Ssklower iso_init_done++; 9237469Ssklower bzero((caddr_t)iso_snpac, iso_snpac_size * sizeof(struct snpa_cache)); 9337469Ssklower rn_inithead(&iso_rnhead, 40, AF_ISO); 9437469Ssklower } 9536384Ssklower } 9636384Ssklower 9736384Ssklower /* 9836384Ssklower * FUNCTION: iso_addrmatch1 9936384Ssklower * 10036384Ssklower * PURPOSE: decide if the two iso_addrs passed are equal 10136384Ssklower * 10236384Ssklower * RETURNS: true if the addrs match, false if they do not 10336384Ssklower * 10436384Ssklower * SIDE EFFECTS: 10536384Ssklower * 10636384Ssklower * NOTES: 10736384Ssklower */ 10836384Ssklower iso_addrmatch1(isoaa, isoab) 10937469Ssklower register struct iso_addr *isoaa, *isoab; /* addresses to check */ 11036384Ssklower { 11137469Ssklower u_int compare_len; 11236384Ssklower 11336384Ssklower IFDEBUG(D_ROUTE) 11436384Ssklower printf("iso_addrmatch1: comparing lengths: %d to %d\n", isoaa->isoa_len, 11536384Ssklower isoab->isoa_len); 11636384Ssklower printf("a:\n"); 11737469Ssklower dump_buf(isoaa->isoa_genaddr, isoaa->isoa_len); 11836384Ssklower printf("b:\n"); 11937469Ssklower dump_buf(isoab->isoa_genaddr, isoab->isoa_len); 12036384Ssklower ENDDEBUG 12136384Ssklower 12236384Ssklower if ((compare_len = isoaa->isoa_len) != isoab->isoa_len) { 12336384Ssklower IFDEBUG(D_ROUTE) 12436384Ssklower printf("iso_addrmatch1: returning false because of lengths\n"); 12536384Ssklower ENDDEBUG 12636384Ssklower return 0; 12736384Ssklower } 12836384Ssklower 12937469Ssklower #ifdef notdef 13036384Ssklower /* TODO : generalize this to all afis with masks */ 13136384Ssklower if( isoaa->isoa_afi == AFI_37 ) { 13236384Ssklower /* must not compare 2 least significant digits, or for 13336384Ssklower * that matter, the DSP 13436384Ssklower */ 13536384Ssklower compare_len = ADDR37_IDI_LEN - 1; 13636384Ssklower } 13737469Ssklower #endif 13836384Ssklower 13936384Ssklower IFDEBUG(D_ROUTE) 14036384Ssklower int i; 14136384Ssklower char *a, *b; 14236384Ssklower 14337469Ssklower a = isoaa->isoa_genaddr; 14437469Ssklower b = isoab->isoa_genaddr; 14536384Ssklower 14636384Ssklower for (i=0; i<compare_len; i++) { 14736384Ssklower printf("<%x=%x>", a[i]&0xff, b[i]&0xff); 14836384Ssklower if (a[i] != b[i]) { 14936384Ssklower printf("\naddrs are not equal at byte %d\n", i); 15036384Ssklower return(0); 15136384Ssklower } 15236384Ssklower } 15336384Ssklower printf("\n"); 15436384Ssklower printf("addrs are equal\n"); 15536384Ssklower return (1); 15636384Ssklower ENDDEBUG 15737469Ssklower return (!bcmp(isoaa->isoa_genaddr, isoab->isoa_genaddr, compare_len)); 15836384Ssklower } 15936384Ssklower 16036384Ssklower /* 16136384Ssklower * FUNCTION: iso_addrmatch 16236384Ssklower * 16336384Ssklower * PURPOSE: decide if the two sockadrr_isos passed are equal 16436384Ssklower * 16536384Ssklower * RETURNS: true if the addrs match, false if they do not 16636384Ssklower * 16736384Ssklower * SIDE EFFECTS: 16836384Ssklower * 16936384Ssklower * NOTES: 17036384Ssklower */ 17136384Ssklower iso_addrmatch(sisoa, sisob) 17236384Ssklower struct sockaddr_iso *sisoa, *sisob; /* addresses to check */ 17336384Ssklower { 17436384Ssklower return(iso_addrmatch1(&sisoa->siso_addr, &sisob->siso_addr)); 17536384Ssklower } 17637469Ssklower #ifdef notdef 17736384Ssklower /* 17836384Ssklower * FUNCTION: iso_netmatch 17936384Ssklower * 18036384Ssklower * PURPOSE: similar to iso_addrmatch but takes sockaddr_iso 18136384Ssklower * as argument. 18236384Ssklower * 18336384Ssklower * RETURNS: true if same net, false if not 18436384Ssklower * 18536384Ssklower * SIDE EFFECTS: 18636384Ssklower * 18736384Ssklower * NOTES: 18836384Ssklower */ 18936384Ssklower iso_netmatch(sisoa, sisob) 19036384Ssklower struct sockaddr_iso *sisoa, *sisob; 19136384Ssklower { 19236384Ssklower u_char bufa[sizeof(struct sockaddr_iso)]; 19336384Ssklower u_char bufb[sizeof(struct sockaddr_iso)]; 19436384Ssklower register int lena, lenb; 19536384Ssklower 19636384Ssklower lena = iso_netof(&sisoa->siso_addr, bufa); 19736384Ssklower lenb = iso_netof(&sisob->siso_addr, bufb); 19836384Ssklower 19936384Ssklower IFDEBUG(D_ROUTE) 20036384Ssklower printf("iso_netmatch: comparing lengths: %d to %d\n", lena, lenb); 20136384Ssklower printf("a:\n"); 20236384Ssklower dump_buf(bufa, lena); 20336384Ssklower printf("b:\n"); 20436384Ssklower dump_buf(bufb, lenb); 20536384Ssklower ENDDEBUG 20636384Ssklower 20736384Ssklower return ((lena == lenb) && (!bcmp(bufa, bufb, lena))); 20836384Ssklower } 20937469Ssklower #endif notdef 21036384Ssklower 21136384Ssklower /* 21236384Ssklower * FUNCTION: iso_hashchar 21336384Ssklower * 21436384Ssklower * PURPOSE: Hash all character in the buffer specified into 21536384Ssklower * a long. Return the long. 21636384Ssklower * 21736384Ssklower * RETURNS: The hash value. 21836384Ssklower * 21936384Ssklower * SIDE EFFECTS: 22036384Ssklower * 22136384Ssklower * NOTES: The hash is achieved by exclusive ORing 4 byte 22236384Ssklower * quantities. 22336384Ssklower */ 22436384Ssklower u_long 22536384Ssklower iso_hashchar(buf, len) 22636384Ssklower register caddr_t buf; /* buffer to pack from */ 22736384Ssklower register int len; /* length of buffer */ 22836384Ssklower { 22936384Ssklower register u_long h = 0; 23036384Ssklower register int i; 23136384Ssklower 23236384Ssklower for (i=0; i<len; i+=4) { 23336384Ssklower register u_long l = 0; 23436384Ssklower 23536384Ssklower if ((len - i) < 4) { 23636384Ssklower /* buffer not multiple of 4 */ 23736384Ssklower switch (len - i) { 23836384Ssklower case 3: 23936384Ssklower l |= buf[i+2] << 8; 24036384Ssklower case 2: 24136384Ssklower l |= buf[i+1] << 16; 24236384Ssklower case 1: 24336384Ssklower l |= buf[i] << 24; 24436384Ssklower break; 24536384Ssklower default: 24636384Ssklower printf("iso_hashchar: unexpected value x%x\n", len - i); 24736384Ssklower break; 24836384Ssklower } 24936384Ssklower } else { 25036384Ssklower l |= buf[i] << 24; 25136384Ssklower l |= buf[i+1] << 16; 25236384Ssklower l |= buf[i+2] << 8; 25336384Ssklower l |= buf[i+3]; 25436384Ssklower } 25536384Ssklower 25636384Ssklower h ^= l; 25736384Ssklower } 25836384Ssklower 25936384Ssklower h ^= (u_long) (len % 4); 26036384Ssklower 26136384Ssklower return(h); 26236384Ssklower } 26337469Ssklower #ifdef notdef 26436384Ssklower /* 26536384Ssklower * FUNCTION: iso_hash 26636384Ssklower * 26736384Ssklower * PURPOSE: Fill in fields of afhash structure based upon addr passed. 26836384Ssklower * 26936384Ssklower * RETURNS: none 27036384Ssklower * 27136384Ssklower * SIDE EFFECTS: 27236384Ssklower * 27336384Ssklower * NOTES: 27436384Ssklower */ 27536384Ssklower iso_hash(siso, hp) 27636384Ssklower struct sockaddr_iso *siso; /* address to perform hash on */ 27736384Ssklower struct afhash *hp; /* RETURN: hash info here */ 27836384Ssklower { 27936384Ssklower u_long buf[sizeof(struct sockaddr_iso)+1/4]; 28036384Ssklower register int bufsize; 28136384Ssklower 28236384Ssklower 28336384Ssklower bzero(buf, sizeof(buf)); 28436384Ssklower 28536384Ssklower bufsize = iso_netof(&siso->siso_addr, buf); 28636384Ssklower hp->afh_nethash = iso_hashchar((caddr_t)buf, bufsize); 28736384Ssklower 28836384Ssklower IFDEBUG(D_ROUTE) 28936384Ssklower printf("iso_hash: iso_netof: bufsize = %d\n", bufsize); 29036384Ssklower ENDDEBUG 29136384Ssklower 29236384Ssklower hp->afh_hosthash = iso_hashchar((caddr_t)&siso->siso_addr, 29336384Ssklower siso->siso_addr.isoa_len); 29436384Ssklower 29536384Ssklower IFDEBUG(D_ROUTE) 29636384Ssklower printf("iso_hash: %s: nethash = x%x, hosthash = x%x\n", 29736384Ssklower clnp_iso_addrp(&siso->siso_addr), hp->afh_nethash, 29836384Ssklower hp->afh_hosthash); 29936384Ssklower ENDDEBUG 30036384Ssklower } 30136384Ssklower /* 30236384Ssklower * FUNCTION: iso_netof 30336384Ssklower * 30436384Ssklower * PURPOSE: Extract the network portion of the iso address. 30536384Ssklower * The network portion of the iso address varies depending 30636384Ssklower * on the type of address. The network portion of the 30736384Ssklower * address will include the IDP. The network portion is: 30836384Ssklower * 30936384Ssklower * TYPE DESC 31036384Ssklower * t37 The AFI and x.121 (IDI) 31136384Ssklower * osinet The AFI, orgid, snetid 31236384Ssklower * rfc986 The AFI, vers and network part of 31336384Ssklower * internet address. 31436384Ssklower * 31536384Ssklower * RETURNS: number of bytes placed into buf. 31636384Ssklower * 31736384Ssklower * SIDE EFFECTS: 31836384Ssklower * 31936384Ssklower * NOTES: Buf is assumed to be big enough 32036384Ssklower */ 32136384Ssklower iso_netof(isoa, buf) 32236384Ssklower struct iso_addr *isoa; /* address */ 32336384Ssklower caddr_t buf; /* RESULT: network portion of address here */ 32436384Ssklower { 32536384Ssklower u_int len = 1; /* length of afi */ 32636384Ssklower 32736384Ssklower switch (isoa->isoa_afi) { 32836384Ssklower case AFI_37: 32936384Ssklower /* 33036384Ssklower * Due to classic x.25 tunnel vision, there is no 33136384Ssklower * net portion of an x.121 address. For our purposes 33236384Ssklower * the AFI will do, so that all x.25 -type addresses 33336384Ssklower * map to the single x.25 SNPA. (Cannot have more than 33436384Ssklower * one, obviously). 33536384Ssklower */ 33636384Ssklower 33736384Ssklower break; 33836384Ssklower 33936384Ssklower /* case AFI_OSINET:*/ 34036384Ssklower case AFI_RFC986: { 34136384Ssklower u_short idi; /* value of idi */ 34236384Ssklower 34336384Ssklower /* osinet and rfc986 have idi in the same place */ 34436384Ssklower CTOH(isoa->rfc986_idi[0], isoa->rfc986_idi[1], idi); 34536384Ssklower 34636384Ssklower if (idi == IDI_OSINET) 34736384Ssklower /* 34836384Ssklower * Network portion of OSINET address can only be the IDI. Clearly, 34936384Ssklower * with one x25 interface, one could get to several orgids, and 35036384Ssklower * several snetids. 35136384Ssklower len += (ADDROSINET_IDI_LEN + OVLOSINET_ORGID_LEN + 35236384Ssklower OVLOSINET_SNETID_LEN); 35336384Ssklower */ 35436384Ssklower len += ADDROSINET_IDI_LEN; 35536384Ssklower else if (idi == IDI_RFC986) { 35636384Ssklower u_long inetaddr; 35736384Ssklower struct ovl_rfc986 *o986 = (struct ovl_rfc986 *)isoa; 35836384Ssklower 35936384Ssklower /* bump len to include idi and version (1 byte) */ 36036384Ssklower len += ADDRRFC986_IDI_LEN + 1; 36136384Ssklower 36236384Ssklower /* get inet addr long aligned */ 36336384Ssklower bcopy(o986->o986_inetaddr, &inetaddr, sizeof(inetaddr)); 36436384Ssklower inetaddr = ntohl(inetaddr); /* convert to host byte order */ 36536384Ssklower 36636384Ssklower IFDEBUG(D_ROUTE) 36736384Ssklower printf("iso_netof: isoa "); 36836384Ssklower dump_buf(isoa, sizeof(*isoa)); 36936384Ssklower printf("iso_netof: inetaddr 0x%x ", inetaddr); 37036384Ssklower ENDDEBUG 37136384Ssklower 37236384Ssklower /* bump len by size of network portion of inet address */ 37336384Ssklower if (IN_CLASSA(inetaddr)) { 37436384Ssklower len += 4-IN_CLASSA_NSHIFT/8; 37536384Ssklower IFDEBUG(D_ROUTE) 37636384Ssklower printf("iso_netof: class A net len is now %d\n", len); 37736384Ssklower ENDDEBUG 37836384Ssklower } else if (IN_CLASSB(inetaddr)) { 37936384Ssklower len += 4-IN_CLASSB_NSHIFT/8; 38036384Ssklower IFDEBUG(D_ROUTE) 38136384Ssklower printf("iso_netof: class B net len is now %d\n", len); 38236384Ssklower ENDDEBUG 38336384Ssklower } else { 38436384Ssklower len += 4-IN_CLASSC_NSHIFT/8; 38536384Ssklower IFDEBUG(D_ROUTE) 38636384Ssklower printf("iso_netof: class C net len is now %d\n", len); 38736384Ssklower ENDDEBUG 38836384Ssklower } 38936384Ssklower } else 39036384Ssklower len = 0; 39136384Ssklower } break; 39236384Ssklower 39336384Ssklower default: 39436384Ssklower len = 0; 39536384Ssklower } 39636384Ssklower 39736384Ssklower bcopy((caddr_t)isoa, buf, len); 39836384Ssklower IFDEBUG(D_ROUTE) 39936384Ssklower printf("in_netof: isoa "); 40036384Ssklower dump_buf(isoa, len); 40136384Ssklower printf("in_netof: net "); 40236384Ssklower dump_buf(buf, len); 40336384Ssklower ENDDEBUG 40436384Ssklower return len; 40536384Ssklower } 40637469Ssklower #endif notdef 40736384Ssklower /* 40837469Ssklower * Generic iso control operations (ioctl's). 40937469Ssklower * Ifp is 0 if not an interface-specific ioctl. 41036384Ssklower */ 41137469Ssklower /* ARGSUSED */ 41236384Ssklower iso_control(so, cmd, data, ifp) 41337469Ssklower struct socket *so; 41437469Ssklower int cmd; 41537469Ssklower caddr_t data; 41637469Ssklower register struct ifnet *ifp; 41736384Ssklower { 41837469Ssklower register struct iso_ifreq *ifr = (struct iso_ifreq *)data; 41937469Ssklower register struct iso_ifaddr *ia = 0; 42037469Ssklower register struct ifaddr *ifa; 42137469Ssklower struct iso_ifaddr *oia; 42237469Ssklower struct iso_aliasreq *ifra = (struct iso_aliasreq *)data; 42337469Ssklower int error, hostIsNew, maskIsNew; 42436384Ssklower 42537469Ssklower /* 42637469Ssklower * Find address for this interface, if it exists. 42737469Ssklower */ 42837469Ssklower if (ifp) 42937469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) 43037469Ssklower if (ia->ia_ifp == ifp) 43137469Ssklower break; 43236384Ssklower 43336384Ssklower switch (cmd) { 43437469Ssklower 43537469Ssklower case SIOCAIFADDR_ISO: 43637469Ssklower case SIOCDIFADDR_ISO: 43737469Ssklower if (ifra->ifra_addr.siso_family == AF_ISO) 43837469Ssklower for (oia = ia; ia; ia = ia->ia_next) { 43937469Ssklower if (ia->ia_ifp == ifp && 44037469Ssklower SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr)) 44137469Ssklower break; 44237469Ssklower } 443*37547Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 444*37547Smckusick return (error); 44536384Ssklower if (ifp == 0) 44637469Ssklower panic("iso_control"); 44737469Ssklower if (ia == (struct iso_ifaddr *)0) { 44837469Ssklower struct iso_ifaddr *nia; 44937469Ssklower if (cmd == SIOCDIFADDR_ISO) 45037469Ssklower return (EADDRNOTAVAIL); 45137469Ssklower MALLOC(nia, struct iso_ifaddr *, sizeof(*nia), 45237469Ssklower M_IFADDR, M_WAITOK); 45337469Ssklower if (nia == (struct iso_ifaddr *)0) 45437469Ssklower return (ENOBUFS); 45537469Ssklower bzero((caddr_t)nia, sizeof(*nia)); 45637469Ssklower if (ia = iso_ifaddr) { 45737469Ssklower for ( ; ia->ia_next; ia = ia->ia_next) 45837469Ssklower ; 45937469Ssklower ia->ia_next = nia; 46037469Ssklower } else 46137469Ssklower iso_ifaddr = nia; 46237469Ssklower ia = nia; 46337469Ssklower if (ifa = ifp->if_addrlist) { 46437469Ssklower for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 46537469Ssklower ; 46637469Ssklower ifa->ifa_next = (struct ifaddr *) ia; 46737469Ssklower } else 46837469Ssklower ifp->if_addrlist = (struct ifaddr *) ia; 46937469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 47037469Ssklower ia->ia_ifa.ifa_dstaddr 47137469Ssklower = (struct sockaddr *)&ia->ia_dstaddr; 47237469Ssklower ia->ia_ifa.ifa_netmask 47337469Ssklower = (struct sockaddr *)&ia->ia_sockmask; 47437469Ssklower ia->ia_ifp = ifp; 47537469Ssklower if (ifp != &loif) 47637469Ssklower iso_interfaces++; 47737469Ssklower } 47837469Ssklower break; 47936384Ssklower 48037469Ssklower #define cmdbyte(x) (((x) >> 8) & 0xff) 48137469Ssklower default: 48237469Ssklower if (cmdbyte(cmd) == 'a') 48337469Ssklower return (snpac_ioctl(cmd, data)); 48437469Ssklower if (ia == (struct iso_ifaddr *)0) 48537469Ssklower return (EADDRNOTAVAIL); 48637469Ssklower break; 48737469Ssklower } 48837469Ssklower switch (cmd) { 48936384Ssklower 49037469Ssklower case SIOCGIFADDR_ISO: 49137469Ssklower ifr->ifr_Addr = ia->ia_addr; 49237469Ssklower break; 49336384Ssklower 49437469Ssklower case SIOCGIFDSTADDR_ISO: 49537469Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 49637469Ssklower return (EINVAL); 49737469Ssklower ifr->ifr_Addr = ia->ia_dstaddr; 49837469Ssklower break; 49936384Ssklower 50037469Ssklower case SIOCGIFNETMASK_ISO: 50137469Ssklower ifr->ifr_Addr = ia->ia_sockmask; 50237469Ssklower break; 50336384Ssklower 50437469Ssklower case SIOCAIFADDR_ISO: 50537469Ssklower maskIsNew = 0; hostIsNew = 1; error = u.u_error; 50637469Ssklower if (ia->ia_addr.siso_family == AF_ISO) { 50737469Ssklower if (ifra->ifra_addr.siso_len == 0) { 50837469Ssklower ifra->ifra_addr = ia->ia_addr; 50937469Ssklower hostIsNew = 0; 51037469Ssklower } else if (SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr)) 51137469Ssklower hostIsNew = 0; 51237469Ssklower } 51337469Ssklower if (ifra->ifra_mask.siso_len) { 51437469Ssklower iso_ifscrub(ifp, ia); 51537469Ssklower ia->ia_sockmask = ifra->ifra_mask; 51637469Ssklower maskIsNew = 1; 51737469Ssklower } 51837469Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) && 51937469Ssklower (ifra->ifra_dstaddr.siso_family == AF_ISO)) { 52037469Ssklower iso_ifscrub(ifp, ia); 52137469Ssklower ia->ia_dstaddr = ifra->ifra_dstaddr; 52237469Ssklower maskIsNew = 1; /* We lie; but the effect's the same */ 52337469Ssklower } 52437469Ssklower if (ifra->ifra_addr.siso_family == AF_ISO && 52537469Ssklower (hostIsNew || maskIsNew)) { 52637469Ssklower error = iso_ifinit(ifp, ia, &ifra->ifra_addr, 0); 52737469Ssklower } 52837469Ssklower if (ifra->ifra_snpaoffset) 52937469Ssklower ia->ia_snpaoffset = ifra->ifra_snpaoffset; 53037469Ssklower return (error); 53137469Ssklower 53237469Ssklower case SIOCDIFADDR_ISO: 53337469Ssklower iso_ifscrub(ifp, ia); 53437469Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 53537469Ssklower ifp->if_addrlist = ifa->ifa_next; 53637469Ssklower else { 53737469Ssklower while (ifa->ifa_next && 53837469Ssklower (ifa->ifa_next != (struct ifaddr *)ia)) 53937469Ssklower ifa = ifa->ifa_next; 54037469Ssklower if (ifa->ifa_next) 54137469Ssklower ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 54237469Ssklower else 54337469Ssklower printf("Couldn't unlink isoifaddr from ifp\n"); 54437469Ssklower } 54537469Ssklower oia = ia; 54637469Ssklower if (oia == (ia = iso_ifaddr)) { 54737469Ssklower iso_ifaddr = ia->ia_next; 54837469Ssklower } else { 54937469Ssklower while (ia->ia_next && (ia->ia_next != oia)) { 55037469Ssklower ia = ia->ia_next; 55136384Ssklower } 55237469Ssklower if (ia->ia_next) 55337469Ssklower ia->ia_next = oia->ia_next; 55437469Ssklower else 55537469Ssklower printf("Didn't unlink isoifadr from list\n"); 55636384Ssklower } 55737469Ssklower free((caddr_t)oia, M_IFADDR); 55837469Ssklower break; 55936384Ssklower 56036384Ssklower default: 56136384Ssklower if (ifp == 0 || ifp->if_ioctl == 0) 56236384Ssklower return (EOPNOTSUPP); 56336384Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data)); 56436384Ssklower } 56537469Ssklower return (0); 56636384Ssklower } 56736384Ssklower 56837469Ssklower /* 56937469Ssklower * Delete any existing route for an interface. 57037469Ssklower */ 57137469Ssklower iso_ifscrub(ifp, ia) 57237469Ssklower register struct ifnet *ifp; 57337469Ssklower register struct iso_ifaddr *ia; 57437469Ssklower { 57537469Ssklower if ((ia->ia_flags & IFA_ROUTE) == 0) 57637469Ssklower return; 57737469Ssklower if (ifp->if_flags & IFF_LOOPBACK) 57837469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 57937469Ssklower else if (ifp->if_flags & IFF_POINTOPOINT) 58037469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 58137469Ssklower else { 58237469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 58337469Ssklower } 58437469Ssklower ia->ia_flags &= ~IFA_ROUTE; 58537469Ssklower } 58637469Ssklower 58737469Ssklower /* 58837469Ssklower * Initialize an interface's internet address 58937469Ssklower * and routing table entry. 59037469Ssklower */ 59137469Ssklower iso_ifinit(ifp, ia, siso, scrub) 59237469Ssklower register struct ifnet *ifp; 59337469Ssklower register struct iso_ifaddr *ia; 59437469Ssklower struct sockaddr_iso *siso; 59537469Ssklower { 59637469Ssklower struct sockaddr_iso oldaddr; 59737469Ssklower int s = splimp(), error; 59837469Ssklower 59937469Ssklower oldaddr = ia->ia_addr; 60037469Ssklower ia->ia_addr = *siso; 60137469Ssklower /* 60237469Ssklower * Give the interface a chance to initialize 60337469Ssklower * if this is its first address, 60437469Ssklower * and to validate the address if necessary. 60537469Ssklower */ 60637469Ssklower if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 60737469Ssklower splx(s); 60837469Ssklower ia->ia_addr = oldaddr; 60937469Ssklower return (error); 61037469Ssklower } 61137469Ssklower if (scrub) { 61237469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 61337469Ssklower iso_ifscrub(ifp, ia); 61437469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 61537469Ssklower } 61637469Ssklower /* 61737469Ssklower * Add route for the network. 61837469Ssklower */ 61937469Ssklower if (ifp->if_flags & IFF_LOOPBACK) { 62037469Ssklower ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 62137469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 62237469Ssklower } else if (ifp->if_flags & IFF_POINTOPOINT && 62337469Ssklower ia->ia_dstaddr.siso_family == AF_ISO) 62437469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 62537469Ssklower else { 62637469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP); 62737469Ssklower } 62837469Ssklower ia->ia_flags |= IFA_ROUTE; 62937469Ssklower splx(s); 63037469Ssklower return (0); 63137469Ssklower } 63237469Ssklower #ifdef notdef 63337469Ssklower 63436384Ssklower struct ifaddr * 63536384Ssklower iso_ifwithidi(addr) 63636384Ssklower register struct sockaddr *addr; 63736384Ssklower { 63836384Ssklower register struct ifnet *ifp; 63936384Ssklower register struct ifaddr *ifa; 64036384Ssklower register u_int af = addr->sa_family; 64136384Ssklower 64236384Ssklower if (af != AF_ISO) 64336384Ssklower return (0); 64436384Ssklower IFDEBUG(D_ROUTE) 64536384Ssklower printf(">>> iso_ifwithidi addr\n"); 64636384Ssklower dump_isoaddr( (struct sockaddr_iso *)(addr)); 64736384Ssklower printf("\n"); 64836384Ssklower ENDDEBUG 64936384Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) { 65036384Ssklower IFDEBUG(D_ROUTE) 65136384Ssklower printf("iso_ifwithidi ifnet %s\n", ifp->if_name); 65236384Ssklower ENDDEBUG 65336384Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 65436384Ssklower IFDEBUG(D_ROUTE) 65536384Ssklower printf("iso_ifwithidi address "); 65637469Ssklower dump_isoaddr( (struct sockaddr_iso *)(ifa->ifa_addr)); 65736384Ssklower ENDDEBUG 65837469Ssklower if (ifa->ifa_addr->sa_family != addr->sa_family) 65936384Ssklower continue; 66036384Ssklower 66136384Ssklower #define IFA_SIS(ifa)\ 66237469Ssklower ((struct sockaddr_iso *)((ifa)->ifa_addr)) 66336384Ssklower 66436384Ssklower IFDEBUG(D_ROUTE) 66536384Ssklower printf(" af same, args to iso_eqtype:\n"); 66636384Ssklower printf("0x%x ", IFA_SIS(ifa)->siso_addr); 66736384Ssklower printf(" 0x%x\n", 66836384Ssklower &(((struct sockaddr_iso *)addr)->siso_addr)); 66936384Ssklower ENDDEBUG 67036384Ssklower 67136384Ssklower if (iso_eqtype(&(IFA_SIS(ifa)->siso_addr), 67236384Ssklower &(((struct sockaddr_iso *)addr)->siso_addr))) { 67336384Ssklower IFDEBUG(D_ROUTE) 67436384Ssklower printf("ifa_ifwithidi: ifa found\n"); 67536384Ssklower ENDDEBUG 67636384Ssklower return (ifa); 67736384Ssklower } 67836384Ssklower IFDEBUG(D_ROUTE) 67936384Ssklower printf(" iso_eqtype failed\n"); 68036384Ssklower ENDDEBUG 68136384Ssklower } 68236384Ssklower } 68336384Ssklower return ((struct ifaddr *)0); 68436384Ssklower } 68536384Ssklower 68637469Ssklower #endif notdef 68736384Ssklower /* 68836384Ssklower * FUNCTION: iso_ck_addr 68936384Ssklower * 69036384Ssklower * PURPOSE: return true if the iso_addr passed is 69136384Ssklower * within the legal size limit for an iso address. 69236384Ssklower * 69336384Ssklower * RETURNS: true or false 69436384Ssklower * 69536384Ssklower * SIDE EFFECTS: 69636384Ssklower * 69736384Ssklower */ 69836384Ssklower iso_ck_addr(isoa) 69936384Ssklower struct iso_addr *isoa; /* address to check */ 70036384Ssklower { 70136384Ssklower return (isoa->isoa_len <= 20); 70236384Ssklower 70336384Ssklower } 70436384Ssklower 70537469Ssklower #ifdef notdef 70636384Ssklower /* 70736384Ssklower * FUNCTION: iso_eqtype 70836384Ssklower * 70936384Ssklower * PURPOSE: Determine if two iso addresses are of the same type. 71036384Ssklower * This is flaky. Really we should consider all type 47 addrs to be the 71136384Ssklower * same - but there do exist different structures for 47 addrs. 71236384Ssklower * Gosip adds a 3rd. 71336384Ssklower * 71436384Ssklower * RETURNS: true if the addresses are the same type 71536384Ssklower * 71636384Ssklower * SIDE EFFECTS: 71736384Ssklower * 71836384Ssklower * NOTES: By type, I mean rfc986, t37, or osinet 71936384Ssklower * 72036384Ssklower * This will first compare afis. If they match, then 72136384Ssklower * if the addr is not t37, the idis must be compared. 72236384Ssklower */ 72336384Ssklower iso_eqtype(isoaa, isoab) 72436384Ssklower struct iso_addr *isoaa; /* first addr to check */ 72536384Ssklower struct iso_addr *isoab; /* other addr to check */ 72636384Ssklower { 72736384Ssklower if (isoaa->isoa_afi == isoab->isoa_afi) { 72836384Ssklower if (isoaa->isoa_afi == AFI_37) 72936384Ssklower return(1); 73036384Ssklower else 73136384Ssklower return (!bcmp(&isoaa->isoa_u, &isoab->isoa_u, 2)); 73236384Ssklower } 73336384Ssklower return(0); 73436384Ssklower } 73537469Ssklower #endif notdef 73636384Ssklower /* 73737469Ssklower * FUNCTION: iso_localifa() 73836384Ssklower * 73937469Ssklower * PURPOSE: Find an interface addresss having a given destination 74037469Ssklower * or at least matching the net. 74136384Ssklower * 74236384Ssklower * RETURNS: ptr to an interface address 74336384Ssklower * 74436384Ssklower * SIDE EFFECTS: 74536384Ssklower * 74636384Ssklower * NOTES: 74736384Ssklower */ 74836384Ssklower struct iso_ifaddr * 74937469Ssklower iso_localifa(siso) 75037469Ssklower register struct sockaddr_iso *siso; 75136384Ssklower { 75236384Ssklower register struct iso_ifaddr *ia; 75337469Ssklower register char *cp1, *cp2, *cp3; 75437469Ssklower register struct ifnet *ifp; 75537469Ssklower struct iso_ifaddr *ia_maybe = 0; 75637469Ssklower /* 75737469Ssklower * We make one pass looking for both net matches and an exact 75837469Ssklower * dst addr. 75937469Ssklower */ 76037469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 76137469Ssklower if ((ifp = ia->ia_ifp) == 0 || ((ifp->if_flags & IFF_UP) == 0)) 76237469Ssklower continue; 76337469Ssklower if (ifp->if_flags & IFF_POINTOPOINT) { 76437469Ssklower if ((ia->ia_dstaddr.siso_family == AF_ISO) && 76537469Ssklower SAME_ISOADDR(&ia->ia_dstaddr, siso)) 76637469Ssklower return (ia); 76737469Ssklower else 76837469Ssklower if (SAME_ISOADDR(&ia->ia_addr, siso)) 76937469Ssklower ia_maybe = ia; 77037469Ssklower continue; 77137469Ssklower } 77237469Ssklower if (ia->ia_sockmask.siso_len) { 77337469Ssklower char *cplim = ia->ia_sockmask.siso_len + (char *)&ia->ia_sockmask; 77437469Ssklower cp1 = ia->ia_sockmask.siso_data; 77537469Ssklower cp2 = siso->siso_data; 77637469Ssklower cp3 = ia->ia_addr.siso_data; 77737469Ssklower while (cp2 < cplim) 77837469Ssklower if (*cp1++ & (*cp2++ ^ *cp3++)) 77937469Ssklower goto next; 78037469Ssklower ia_maybe = ia; 78137469Ssklower } 78237469Ssklower if (SAME_ISOADDR(&ia->ia_addr, siso)) 78337469Ssklower return ia; 78437469Ssklower next:; 78537469Ssklower } 78637469Ssklower return ia_maybe; 78736384Ssklower } 78836384Ssklower 78936384Ssklower #ifdef NARGOXTWENTYFIVE > 0 79036384Ssklower #include "cons.h" 79136384Ssklower #endif NARGOXTWENTYFIVE > 0 79236384Ssklower /* 79336384Ssklower * FUNCTION: iso_nlctloutput 79436384Ssklower * 79536384Ssklower * PURPOSE: Set options at the network level 79636384Ssklower * 79736384Ssklower * RETURNS: E* 79836384Ssklower * 79936384Ssklower * SIDE EFFECTS: 80036384Ssklower * 80136384Ssklower * NOTES: This could embody some of the functions of 80236384Ssklower * rclnp_ctloutput and cons_ctloutput. 80336384Ssklower */ 80436384Ssklower iso_nlctloutput(cmd, optname, pcb, m) 80536384Ssklower int cmd; /* command:set or get */ 80636384Ssklower int optname; /* option of interest */ 80736384Ssklower caddr_t pcb; /* nl pcb */ 80836384Ssklower struct mbuf *m; /* data for set, buffer for get */ 80936384Ssklower { 81036384Ssklower struct isopcb *isop = (struct isopcb *)pcb; 81136384Ssklower int error = 0; /* return value */ 81236384Ssklower caddr_t data; /* data for option */ 81336384Ssklower int data_len; /* data's length */ 81436384Ssklower 81536384Ssklower IFDEBUG(D_ISO) 81636384Ssklower printf("iso_nlctloutput: cmd %x, opt %x, pcb %x, m %x\n", 81736384Ssklower cmd, optname, pcb, m); 81836384Ssklower ENDDEBUG 81936384Ssklower 82036384Ssklower if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT)) 82136384Ssklower return(EOPNOTSUPP); 82236384Ssklower 82336384Ssklower data = mtod(m, caddr_t); 82436384Ssklower data_len = (m)->m_len; 82536384Ssklower 82636384Ssklower IFDEBUG(D_ISO) 82736384Ssklower printf("iso_nlctloutput: data is:\n"); 82836384Ssklower dump_buf(data, data_len); 82936384Ssklower ENDDEBUG 83036384Ssklower 83136384Ssklower switch (optname) { 83236384Ssklower 83336384Ssklower #ifdef NARGOXTWENTYFIVE > 0 83436384Ssklower case CONSOPT_X25CRUD: 83536384Ssklower if (cmd == PRCO_GETOPT) { 83636384Ssklower error = EOPNOTSUPP; 83736384Ssklower break; 83836384Ssklower } 83936384Ssklower 84036384Ssklower if (data_len > MAXX25CRUDLEN) { 84136384Ssklower error = EINVAL; 84236384Ssklower break; 84336384Ssklower } 84436384Ssklower 84536384Ssklower IFDEBUG(D_ISO) 84636384Ssklower printf("iso_nlctloutput: setting x25 crud\n"); 84736384Ssklower ENDDEBUG 84836384Ssklower 84937469Ssklower bcopy(data, (caddr_t)isop->isop_x25crud, (unsigned)data_len); 85036384Ssklower isop->isop_x25crud_len = data_len; 85136384Ssklower break; 85236384Ssklower #endif NARGOXTWENTYFIVE > 0 85336384Ssklower 85436384Ssklower default: 85536384Ssklower error = EOPNOTSUPP; 85636384Ssklower } 85736384Ssklower 85836384Ssklower return error; 85936384Ssklower } 86036384Ssklower 86136384Ssklower /* 86236384Ssklower * FUNCTION: iso_routeifp 86336384Ssklower * 86436384Ssklower * PURPOSE: Route on a sockaddr and return ifp 86536384Ssklower * 86636384Ssklower * RETURNS: ifp of outgoing interface, or null 86736384Ssklower * 86836384Ssklower * SIDE EFFECTS: 86936384Ssklower * 87036384Ssklower * NOTES: 87136384Ssklower */ 87237469Ssklower struct iso_ifaddr * 87337469Ssklower iso_routeifa(dst) 87436384Ssklower struct sockaddr *dst; /* destination to route to */ 87536384Ssklower { 87637469Ssklower struct rtentry *rt; 87737469Ssklower struct ifaddr *ifa = 0; 87837469Ssklower struct ifnet *ifp = 0; 87936384Ssklower 88036384Ssklower 88136384Ssklower IFDEBUG(D_ROUTE) 88236384Ssklower printf("iso_routeifp: dst:"); 88337469Ssklower dump_isoaddr((struct sockaddr_iso *)dst); 88436384Ssklower ENDDEBUG 88536384Ssklower 88637469Ssklower rt = rtalloc1(dst, 0); 88736384Ssklower 88837469Ssklower if (rt) { 88937469Ssklower ifa = rt->rt_ifa; 89037469Ssklower ifp = rt->rt_ifp; 89137469Ssklower RTFREE(rt); 89236384Ssklower } 89336384Ssklower 89436384Ssklower IFDEBUG(D_ROUTE) 89537469Ssklower printf("iso_routeifp: ifa x%x", ifa); 89636384Ssklower if (ifp) 89736384Ssklower printf(" (%s%d)\n", ifp->if_name, ifp->if_unit); 89836384Ssklower else 89936384Ssklower printf("\n"); 90036384Ssklower ENDDEBUG 90136384Ssklower 90237469Ssklower return((struct iso_ifaddr *)ifa); 90336384Ssklower } 90436384Ssklower #endif ISO 90536384Ssklower 90636384Ssklower #ifdef ARGO_DEBUG 90736384Ssklower 90836384Ssklower /* 90936384Ssklower * FUNCTION: dump_isoaddr 91036384Ssklower * 91136384Ssklower * PURPOSE: debugging 91236384Ssklower * 91336384Ssklower * RETURNS: nada 91436384Ssklower * 91536384Ssklower */ 91636384Ssklower dump_isoaddr(s) 91736384Ssklower struct sockaddr_iso *s; 91836384Ssklower { 91937469Ssklower char *clnp_saddr_isop(); 92036384Ssklower register int i; 92136384Ssklower 92236384Ssklower if( s->siso_family == AF_ISO) { 92337469Ssklower printf("ISO address: suffixlen %d, %s\n", 92437469Ssklower s->siso_tsuffixlen, clnp_saddr_isop(s)); 92536384Ssklower } else if( s->siso_family == AF_INET) { 92636384Ssklower /* hack */ 92736384Ssklower struct sockaddr_in *sin = (struct sockaddr_in *)s; 92836384Ssklower 92936384Ssklower printf("%d.%d.%d.%d: %d", 93036384Ssklower (sin->sin_addr.s_addr>>24)&0xff, 93136384Ssklower (sin->sin_addr.s_addr>>16)&0xff, 93236384Ssklower (sin->sin_addr.s_addr>>8)&0xff, 93336384Ssklower (sin->sin_addr.s_addr)&0xff, 93436384Ssklower sin->sin_port); 93536384Ssklower } 93636384Ssklower } 93736384Ssklower 93836384Ssklower #endif ARGO_DEBUG 939