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*40894Ssklower * @(#)iso.c 7.8 (Berkeley) 04/12/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 */ 6736384Ssklower 6836384Ssklower 6936384Ssklower /* 7036384Ssklower * FUNCTION: iso_init 7136384Ssklower * 7236384Ssklower * PURPOSE: initialize the iso address family 7336384Ssklower * 7436384Ssklower * RETURNS: nothing 7536384Ssklower * 7636384Ssklower * SIDE EFFECTS: 1) zeros the maptab table. 7737469Ssklower * 2) initializes the routing table. 7836384Ssklower * 7936384Ssklower * NOTES: 8036384Ssklower */ 8137469Ssklower struct radix_node_head *iso_rnhead; 8236384Ssklower iso_init() 8336384Ssklower { 8437469Ssklower extern struct spna_cache iso_snpac[]; 8537469Ssklower extern u_int iso_snpac_size; 8637469Ssklower static iso_init_done; 8736384Ssklower 8837469Ssklower if (iso_init_done == 0) { 8937469Ssklower iso_init_done++; 9037469Ssklower bzero((caddr_t)iso_snpac, iso_snpac_size * sizeof(struct snpa_cache)); 9137469Ssklower rn_inithead(&iso_rnhead, 40, AF_ISO); 9237469Ssklower } 9336384Ssklower } 9436384Ssklower 9536384Ssklower /* 9636384Ssklower * FUNCTION: iso_addrmatch1 9736384Ssklower * 9836384Ssklower * PURPOSE: decide if the two iso_addrs passed are equal 9936384Ssklower * 10036384Ssklower * RETURNS: true if the addrs match, false if they do not 10136384Ssklower * 10236384Ssklower * SIDE EFFECTS: 10336384Ssklower * 10436384Ssklower * NOTES: 10536384Ssklower */ 10636384Ssklower iso_addrmatch1(isoaa, isoab) 10737469Ssklower register struct iso_addr *isoaa, *isoab; /* addresses to check */ 10836384Ssklower { 10937469Ssklower u_int compare_len; 11036384Ssklower 11136384Ssklower IFDEBUG(D_ROUTE) 11236384Ssklower printf("iso_addrmatch1: comparing lengths: %d to %d\n", isoaa->isoa_len, 11336384Ssklower isoab->isoa_len); 11436384Ssklower printf("a:\n"); 11537469Ssklower dump_buf(isoaa->isoa_genaddr, isoaa->isoa_len); 11636384Ssklower printf("b:\n"); 11737469Ssklower dump_buf(isoab->isoa_genaddr, isoab->isoa_len); 11836384Ssklower ENDDEBUG 11936384Ssklower 12036384Ssklower if ((compare_len = isoaa->isoa_len) != isoab->isoa_len) { 12136384Ssklower IFDEBUG(D_ROUTE) 12236384Ssklower printf("iso_addrmatch1: returning false because of lengths\n"); 12336384Ssklower ENDDEBUG 12436384Ssklower return 0; 12536384Ssklower } 12636384Ssklower 12737469Ssklower #ifdef notdef 12836384Ssklower /* TODO : generalize this to all afis with masks */ 12936384Ssklower if( isoaa->isoa_afi == AFI_37 ) { 13036384Ssklower /* must not compare 2 least significant digits, or for 13136384Ssklower * that matter, the DSP 13236384Ssklower */ 13336384Ssklower compare_len = ADDR37_IDI_LEN - 1; 13436384Ssklower } 13537469Ssklower #endif 13636384Ssklower 13736384Ssklower IFDEBUG(D_ROUTE) 13836384Ssklower int i; 13936384Ssklower char *a, *b; 14036384Ssklower 14137469Ssklower a = isoaa->isoa_genaddr; 14237469Ssklower b = isoab->isoa_genaddr; 14336384Ssklower 14436384Ssklower for (i=0; i<compare_len; i++) { 14536384Ssklower printf("<%x=%x>", a[i]&0xff, b[i]&0xff); 14636384Ssklower if (a[i] != b[i]) { 14736384Ssklower printf("\naddrs are not equal at byte %d\n", i); 14836384Ssklower return(0); 14936384Ssklower } 15036384Ssklower } 15136384Ssklower printf("\n"); 15236384Ssklower printf("addrs are equal\n"); 15336384Ssklower return (1); 15436384Ssklower ENDDEBUG 15537469Ssklower return (!bcmp(isoaa->isoa_genaddr, isoab->isoa_genaddr, compare_len)); 15636384Ssklower } 15736384Ssklower 15836384Ssklower /* 15936384Ssklower * FUNCTION: iso_addrmatch 16036384Ssklower * 16136384Ssklower * PURPOSE: decide if the two sockadrr_isos passed are equal 16236384Ssklower * 16336384Ssklower * RETURNS: true if the addrs match, false if they do not 16436384Ssklower * 16536384Ssklower * SIDE EFFECTS: 16636384Ssklower * 16736384Ssklower * NOTES: 16836384Ssklower */ 16936384Ssklower iso_addrmatch(sisoa, sisob) 17036384Ssklower struct sockaddr_iso *sisoa, *sisob; /* addresses to check */ 17136384Ssklower { 17236384Ssklower return(iso_addrmatch1(&sisoa->siso_addr, &sisob->siso_addr)); 17336384Ssklower } 17437469Ssklower #ifdef notdef 17536384Ssklower /* 17636384Ssklower * FUNCTION: iso_netmatch 17736384Ssklower * 17836384Ssklower * PURPOSE: similar to iso_addrmatch but takes sockaddr_iso 17936384Ssklower * as argument. 18036384Ssklower * 18136384Ssklower * RETURNS: true if same net, false if not 18236384Ssklower * 18336384Ssklower * SIDE EFFECTS: 18436384Ssklower * 18536384Ssklower * NOTES: 18636384Ssklower */ 18736384Ssklower iso_netmatch(sisoa, sisob) 18836384Ssklower struct sockaddr_iso *sisoa, *sisob; 18936384Ssklower { 19036384Ssklower u_char bufa[sizeof(struct sockaddr_iso)]; 19136384Ssklower u_char bufb[sizeof(struct sockaddr_iso)]; 19236384Ssklower register int lena, lenb; 19336384Ssklower 19436384Ssklower lena = iso_netof(&sisoa->siso_addr, bufa); 19536384Ssklower lenb = iso_netof(&sisob->siso_addr, bufb); 19636384Ssklower 19736384Ssklower IFDEBUG(D_ROUTE) 19836384Ssklower printf("iso_netmatch: comparing lengths: %d to %d\n", lena, lenb); 19936384Ssklower printf("a:\n"); 20036384Ssklower dump_buf(bufa, lena); 20136384Ssklower printf("b:\n"); 20236384Ssklower dump_buf(bufb, lenb); 20336384Ssklower ENDDEBUG 20436384Ssklower 20536384Ssklower return ((lena == lenb) && (!bcmp(bufa, bufb, lena))); 20636384Ssklower } 20737469Ssklower #endif notdef 20836384Ssklower 20936384Ssklower /* 21036384Ssklower * FUNCTION: iso_hashchar 21136384Ssklower * 21236384Ssklower * PURPOSE: Hash all character in the buffer specified into 21336384Ssklower * a long. Return the long. 21436384Ssklower * 21536384Ssklower * RETURNS: The hash value. 21636384Ssklower * 21736384Ssklower * SIDE EFFECTS: 21836384Ssklower * 21936384Ssklower * NOTES: The hash is achieved by exclusive ORing 4 byte 22036384Ssklower * quantities. 22136384Ssklower */ 22236384Ssklower u_long 22336384Ssklower iso_hashchar(buf, len) 22436384Ssklower register caddr_t buf; /* buffer to pack from */ 22536384Ssklower register int len; /* length of buffer */ 22636384Ssklower { 22736384Ssklower register u_long h = 0; 22836384Ssklower register int i; 22936384Ssklower 23036384Ssklower for (i=0; i<len; i+=4) { 23136384Ssklower register u_long l = 0; 23236384Ssklower 23336384Ssklower if ((len - i) < 4) { 23436384Ssklower /* buffer not multiple of 4 */ 23536384Ssklower switch (len - i) { 23636384Ssklower case 3: 23736384Ssklower l |= buf[i+2] << 8; 23836384Ssklower case 2: 23936384Ssklower l |= buf[i+1] << 16; 24036384Ssklower case 1: 24136384Ssklower l |= buf[i] << 24; 24236384Ssklower break; 24336384Ssklower default: 24436384Ssklower printf("iso_hashchar: unexpected value x%x\n", len - i); 24536384Ssklower break; 24636384Ssklower } 24736384Ssklower } else { 24836384Ssklower l |= buf[i] << 24; 24936384Ssklower l |= buf[i+1] << 16; 25036384Ssklower l |= buf[i+2] << 8; 25136384Ssklower l |= buf[i+3]; 25236384Ssklower } 25336384Ssklower 25436384Ssklower h ^= l; 25536384Ssklower } 25636384Ssklower 25736384Ssklower h ^= (u_long) (len % 4); 25836384Ssklower 25936384Ssklower return(h); 26036384Ssklower } 26137469Ssklower #ifdef notdef 26236384Ssklower /* 26336384Ssklower * FUNCTION: iso_hash 26436384Ssklower * 26536384Ssklower * PURPOSE: Fill in fields of afhash structure based upon addr passed. 26636384Ssklower * 26736384Ssklower * RETURNS: none 26836384Ssklower * 26936384Ssklower * SIDE EFFECTS: 27036384Ssklower * 27136384Ssklower * NOTES: 27236384Ssklower */ 27336384Ssklower iso_hash(siso, hp) 27436384Ssklower struct sockaddr_iso *siso; /* address to perform hash on */ 27536384Ssklower struct afhash *hp; /* RETURN: hash info here */ 27636384Ssklower { 27736384Ssklower u_long buf[sizeof(struct sockaddr_iso)+1/4]; 27836384Ssklower register int bufsize; 27936384Ssklower 28036384Ssklower 28136384Ssklower bzero(buf, sizeof(buf)); 28236384Ssklower 28336384Ssklower bufsize = iso_netof(&siso->siso_addr, buf); 28436384Ssklower hp->afh_nethash = iso_hashchar((caddr_t)buf, bufsize); 28536384Ssklower 28636384Ssklower IFDEBUG(D_ROUTE) 28736384Ssklower printf("iso_hash: iso_netof: bufsize = %d\n", bufsize); 28836384Ssklower ENDDEBUG 28936384Ssklower 29036384Ssklower hp->afh_hosthash = iso_hashchar((caddr_t)&siso->siso_addr, 29136384Ssklower siso->siso_addr.isoa_len); 29236384Ssklower 29336384Ssklower IFDEBUG(D_ROUTE) 29436384Ssklower printf("iso_hash: %s: nethash = x%x, hosthash = x%x\n", 29536384Ssklower clnp_iso_addrp(&siso->siso_addr), hp->afh_nethash, 29636384Ssklower hp->afh_hosthash); 29736384Ssklower ENDDEBUG 29836384Ssklower } 29936384Ssklower /* 30036384Ssklower * FUNCTION: iso_netof 30136384Ssklower * 30236384Ssklower * PURPOSE: Extract the network portion of the iso address. 30336384Ssklower * The network portion of the iso address varies depending 30436384Ssklower * on the type of address. The network portion of the 30536384Ssklower * address will include the IDP. The network portion is: 30636384Ssklower * 30736384Ssklower * TYPE DESC 30836384Ssklower * t37 The AFI and x.121 (IDI) 30936384Ssklower * osinet The AFI, orgid, snetid 31036384Ssklower * rfc986 The AFI, vers and network part of 31136384Ssklower * internet address. 31236384Ssklower * 31336384Ssklower * RETURNS: number of bytes placed into buf. 31436384Ssklower * 31536384Ssklower * SIDE EFFECTS: 31636384Ssklower * 31736384Ssklower * NOTES: Buf is assumed to be big enough 31836384Ssklower */ 31936384Ssklower iso_netof(isoa, buf) 32036384Ssklower struct iso_addr *isoa; /* address */ 32136384Ssklower caddr_t buf; /* RESULT: network portion of address here */ 32236384Ssklower { 32336384Ssklower u_int len = 1; /* length of afi */ 32436384Ssklower 32536384Ssklower switch (isoa->isoa_afi) { 32636384Ssklower case AFI_37: 32736384Ssklower /* 32836384Ssklower * Due to classic x.25 tunnel vision, there is no 32936384Ssklower * net portion of an x.121 address. For our purposes 33036384Ssklower * the AFI will do, so that all x.25 -type addresses 33136384Ssklower * map to the single x.25 SNPA. (Cannot have more than 33236384Ssklower * one, obviously). 33336384Ssklower */ 33436384Ssklower 33536384Ssklower break; 33636384Ssklower 33736384Ssklower /* case AFI_OSINET:*/ 33836384Ssklower case AFI_RFC986: { 33936384Ssklower u_short idi; /* value of idi */ 34036384Ssklower 34136384Ssklower /* osinet and rfc986 have idi in the same place */ 34236384Ssklower CTOH(isoa->rfc986_idi[0], isoa->rfc986_idi[1], idi); 34336384Ssklower 34436384Ssklower if (idi == IDI_OSINET) 34536384Ssklower /* 34636384Ssklower * Network portion of OSINET address can only be the IDI. Clearly, 34736384Ssklower * with one x25 interface, one could get to several orgids, and 34836384Ssklower * several snetids. 34936384Ssklower len += (ADDROSINET_IDI_LEN + OVLOSINET_ORGID_LEN + 35036384Ssklower OVLOSINET_SNETID_LEN); 35136384Ssklower */ 35236384Ssklower len += ADDROSINET_IDI_LEN; 35336384Ssklower else if (idi == IDI_RFC986) { 35436384Ssklower u_long inetaddr; 35536384Ssklower struct ovl_rfc986 *o986 = (struct ovl_rfc986 *)isoa; 35636384Ssklower 35736384Ssklower /* bump len to include idi and version (1 byte) */ 35836384Ssklower len += ADDRRFC986_IDI_LEN + 1; 35936384Ssklower 36036384Ssklower /* get inet addr long aligned */ 36136384Ssklower bcopy(o986->o986_inetaddr, &inetaddr, sizeof(inetaddr)); 36236384Ssklower inetaddr = ntohl(inetaddr); /* convert to host byte order */ 36336384Ssklower 36436384Ssklower IFDEBUG(D_ROUTE) 36536384Ssklower printf("iso_netof: isoa "); 36636384Ssklower dump_buf(isoa, sizeof(*isoa)); 36736384Ssklower printf("iso_netof: inetaddr 0x%x ", inetaddr); 36836384Ssklower ENDDEBUG 36936384Ssklower 37036384Ssklower /* bump len by size of network portion of inet address */ 37136384Ssklower if (IN_CLASSA(inetaddr)) { 37236384Ssklower len += 4-IN_CLASSA_NSHIFT/8; 37336384Ssklower IFDEBUG(D_ROUTE) 37436384Ssklower printf("iso_netof: class A net len is now %d\n", len); 37536384Ssklower ENDDEBUG 37636384Ssklower } else if (IN_CLASSB(inetaddr)) { 37736384Ssklower len += 4-IN_CLASSB_NSHIFT/8; 37836384Ssklower IFDEBUG(D_ROUTE) 37936384Ssklower printf("iso_netof: class B net len is now %d\n", len); 38036384Ssklower ENDDEBUG 38136384Ssklower } else { 38236384Ssklower len += 4-IN_CLASSC_NSHIFT/8; 38336384Ssklower IFDEBUG(D_ROUTE) 38436384Ssklower printf("iso_netof: class C net len is now %d\n", len); 38536384Ssklower ENDDEBUG 38636384Ssklower } 38736384Ssklower } else 38836384Ssklower len = 0; 38936384Ssklower } break; 39036384Ssklower 39136384Ssklower default: 39236384Ssklower len = 0; 39336384Ssklower } 39436384Ssklower 39536384Ssklower bcopy((caddr_t)isoa, buf, len); 39636384Ssklower IFDEBUG(D_ROUTE) 39736384Ssklower printf("in_netof: isoa "); 39836384Ssklower dump_buf(isoa, len); 39936384Ssklower printf("in_netof: net "); 40036384Ssklower dump_buf(buf, len); 40136384Ssklower ENDDEBUG 40236384Ssklower return len; 40336384Ssklower } 40437469Ssklower #endif notdef 40536384Ssklower /* 40637469Ssklower * Generic iso control operations (ioctl's). 40737469Ssklower * Ifp is 0 if not an interface-specific ioctl. 40836384Ssklower */ 40937469Ssklower /* ARGSUSED */ 41036384Ssklower iso_control(so, cmd, data, ifp) 41137469Ssklower struct socket *so; 41237469Ssklower int cmd; 41337469Ssklower caddr_t data; 41437469Ssklower register struct ifnet *ifp; 41536384Ssklower { 41637469Ssklower register struct iso_ifreq *ifr = (struct iso_ifreq *)data; 41737469Ssklower register struct iso_ifaddr *ia = 0; 41837469Ssklower register struct ifaddr *ifa; 41937469Ssklower struct iso_ifaddr *oia; 42037469Ssklower struct iso_aliasreq *ifra = (struct iso_aliasreq *)data; 42137469Ssklower int error, hostIsNew, maskIsNew; 42236384Ssklower 42337469Ssklower /* 42437469Ssklower * Find address for this interface, if it exists. 42537469Ssklower */ 42637469Ssklower if (ifp) 42737469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) 42837469Ssklower if (ia->ia_ifp == ifp) 42937469Ssklower break; 43036384Ssklower 43136384Ssklower switch (cmd) { 43237469Ssklower 43337469Ssklower case SIOCAIFADDR_ISO: 43437469Ssklower case SIOCDIFADDR_ISO: 43537469Ssklower if (ifra->ifra_addr.siso_family == AF_ISO) 43637469Ssklower for (oia = ia; ia; ia = ia->ia_next) { 43737469Ssklower if (ia->ia_ifp == ifp && 43837469Ssklower SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr)) 43937469Ssklower break; 44037469Ssklower } 44137547Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 44237547Smckusick return (error); 44336384Ssklower if (ifp == 0) 44437469Ssklower panic("iso_control"); 44537469Ssklower if (ia == (struct iso_ifaddr *)0) { 44637469Ssklower struct iso_ifaddr *nia; 44737469Ssklower if (cmd == SIOCDIFADDR_ISO) 44837469Ssklower return (EADDRNOTAVAIL); 44937469Ssklower MALLOC(nia, struct iso_ifaddr *, sizeof(*nia), 45037469Ssklower M_IFADDR, M_WAITOK); 45137469Ssklower if (nia == (struct iso_ifaddr *)0) 45237469Ssklower return (ENOBUFS); 45337469Ssklower bzero((caddr_t)nia, sizeof(*nia)); 45437469Ssklower if (ia = iso_ifaddr) { 45537469Ssklower for ( ; ia->ia_next; ia = ia->ia_next) 45637469Ssklower ; 45737469Ssklower ia->ia_next = nia; 45837469Ssklower } else 45937469Ssklower iso_ifaddr = nia; 46037469Ssklower ia = nia; 46137469Ssklower if (ifa = ifp->if_addrlist) { 46237469Ssklower for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 46337469Ssklower ; 46437469Ssklower ifa->ifa_next = (struct ifaddr *) ia; 46537469Ssklower } else 46637469Ssklower ifp->if_addrlist = (struct ifaddr *) ia; 46737469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 46837469Ssklower ia->ia_ifa.ifa_dstaddr 46937469Ssklower = (struct sockaddr *)&ia->ia_dstaddr; 47037469Ssklower ia->ia_ifa.ifa_netmask 47137469Ssklower = (struct sockaddr *)&ia->ia_sockmask; 47237469Ssklower ia->ia_ifp = ifp; 47337469Ssklower if (ifp != &loif) 47437469Ssklower iso_interfaces++; 47537469Ssklower } 47637469Ssklower break; 47736384Ssklower 47837469Ssklower #define cmdbyte(x) (((x) >> 8) & 0xff) 47937469Ssklower default: 48037469Ssklower if (cmdbyte(cmd) == 'a') 48137469Ssklower return (snpac_ioctl(cmd, data)); 48237469Ssklower if (ia == (struct iso_ifaddr *)0) 48337469Ssklower return (EADDRNOTAVAIL); 48437469Ssklower break; 48537469Ssklower } 48637469Ssklower switch (cmd) { 48736384Ssklower 48837469Ssklower case SIOCGIFADDR_ISO: 48937469Ssklower ifr->ifr_Addr = ia->ia_addr; 49037469Ssklower break; 49136384Ssklower 49237469Ssklower case SIOCGIFDSTADDR_ISO: 49337469Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 49437469Ssklower return (EINVAL); 49537469Ssklower ifr->ifr_Addr = ia->ia_dstaddr; 49637469Ssklower break; 49736384Ssklower 49837469Ssklower case SIOCGIFNETMASK_ISO: 49937469Ssklower ifr->ifr_Addr = ia->ia_sockmask; 50037469Ssklower break; 50136384Ssklower 50237469Ssklower case SIOCAIFADDR_ISO: 50337469Ssklower maskIsNew = 0; hostIsNew = 1; error = u.u_error; 50437469Ssklower if (ia->ia_addr.siso_family == AF_ISO) { 50537469Ssklower if (ifra->ifra_addr.siso_len == 0) { 50637469Ssklower ifra->ifra_addr = ia->ia_addr; 50737469Ssklower hostIsNew = 0; 50837469Ssklower } else if (SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr)) 50937469Ssklower hostIsNew = 0; 51037469Ssklower } 51137469Ssklower if (ifra->ifra_mask.siso_len) { 51237469Ssklower iso_ifscrub(ifp, ia); 51337469Ssklower ia->ia_sockmask = ifra->ifra_mask; 51437469Ssklower maskIsNew = 1; 51537469Ssklower } 51637469Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) && 51737469Ssklower (ifra->ifra_dstaddr.siso_family == AF_ISO)) { 51837469Ssklower iso_ifscrub(ifp, ia); 51937469Ssklower ia->ia_dstaddr = ifra->ifra_dstaddr; 52037469Ssklower maskIsNew = 1; /* We lie; but the effect's the same */ 52137469Ssklower } 52237469Ssklower if (ifra->ifra_addr.siso_family == AF_ISO && 52337469Ssklower (hostIsNew || maskIsNew)) { 52437469Ssklower error = iso_ifinit(ifp, ia, &ifra->ifra_addr, 0); 52537469Ssklower } 52637469Ssklower if (ifra->ifra_snpaoffset) 52737469Ssklower ia->ia_snpaoffset = ifra->ifra_snpaoffset; 52837469Ssklower return (error); 52937469Ssklower 53037469Ssklower case SIOCDIFADDR_ISO: 53137469Ssklower iso_ifscrub(ifp, ia); 53237469Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 53337469Ssklower ifp->if_addrlist = ifa->ifa_next; 53437469Ssklower else { 53537469Ssklower while (ifa->ifa_next && 53637469Ssklower (ifa->ifa_next != (struct ifaddr *)ia)) 53737469Ssklower ifa = ifa->ifa_next; 53837469Ssklower if (ifa->ifa_next) 53937469Ssklower ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 54037469Ssklower else 54137469Ssklower printf("Couldn't unlink isoifaddr from ifp\n"); 54237469Ssklower } 54337469Ssklower oia = ia; 54437469Ssklower if (oia == (ia = iso_ifaddr)) { 54537469Ssklower iso_ifaddr = ia->ia_next; 54637469Ssklower } else { 54737469Ssklower while (ia->ia_next && (ia->ia_next != oia)) { 54837469Ssklower ia = ia->ia_next; 54936384Ssklower } 55037469Ssklower if (ia->ia_next) 55137469Ssklower ia->ia_next = oia->ia_next; 55237469Ssklower else 55337469Ssklower printf("Didn't unlink isoifadr from list\n"); 55436384Ssklower } 55537469Ssklower free((caddr_t)oia, M_IFADDR); 55637469Ssklower break; 55736384Ssklower 55836384Ssklower default: 55936384Ssklower if (ifp == 0 || ifp->if_ioctl == 0) 56036384Ssklower return (EOPNOTSUPP); 56136384Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data)); 56236384Ssklower } 56337469Ssklower return (0); 56436384Ssklower } 56536384Ssklower 56637469Ssklower /* 56737469Ssklower * Delete any existing route for an interface. 56837469Ssklower */ 56937469Ssklower iso_ifscrub(ifp, ia) 57037469Ssklower register struct ifnet *ifp; 57137469Ssklower register struct iso_ifaddr *ia; 57237469Ssklower { 57337469Ssklower if ((ia->ia_flags & IFA_ROUTE) == 0) 57437469Ssklower return; 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 } 58237469Ssklower ia->ia_flags &= ~IFA_ROUTE; 58337469Ssklower } 58437469Ssklower 58537469Ssklower /* 58637469Ssklower * Initialize an interface's internet address 58737469Ssklower * and routing table entry. 58837469Ssklower */ 58937469Ssklower iso_ifinit(ifp, ia, siso, scrub) 59037469Ssklower register struct ifnet *ifp; 59137469Ssklower register struct iso_ifaddr *ia; 59237469Ssklower struct sockaddr_iso *siso; 59337469Ssklower { 59437469Ssklower struct sockaddr_iso oldaddr; 59537469Ssklower int s = splimp(), error; 59637469Ssklower 59737469Ssklower oldaddr = ia->ia_addr; 59837469Ssklower ia->ia_addr = *siso; 59937469Ssklower /* 60037469Ssklower * Give the interface a chance to initialize 60137469Ssklower * if this is its first address, 60237469Ssklower * and to validate the address if necessary. 60337469Ssklower */ 60437469Ssklower if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 60537469Ssklower splx(s); 60637469Ssklower ia->ia_addr = oldaddr; 60737469Ssklower return (error); 60837469Ssklower } 60937469Ssklower if (scrub) { 61037469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 61137469Ssklower iso_ifscrub(ifp, ia); 61237469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 61337469Ssklower } 61437469Ssklower /* 61537469Ssklower * Add route for the network. 61637469Ssklower */ 61737469Ssklower if (ifp->if_flags & IFF_LOOPBACK) { 61837469Ssklower ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 619*40894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 62037469Ssklower } else if (ifp->if_flags & IFF_POINTOPOINT && 62137469Ssklower ia->ia_dstaddr.siso_family == AF_ISO) 622*40894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 62337469Ssklower else { 624*40894Ssklower rt_maskedcopy(ia->ia_ifa.ifa_addr, ia->ia_ifa.ifa_dstaddr, 625*40894Ssklower ia->ia_ifa.ifa_netmask); 626*40894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP); 62737469Ssklower } 62837469Ssklower ia->ia_flags |= IFA_ROUTE; 62937469Ssklower splx(s); 630*40894Ssklower return (error); 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; 77739936Ssklower while (cp1 < 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 #endif ISO 86136384Ssklower 86236384Ssklower #ifdef ARGO_DEBUG 86336384Ssklower 86436384Ssklower /* 86536384Ssklower * FUNCTION: dump_isoaddr 86636384Ssklower * 86736384Ssklower * PURPOSE: debugging 86836384Ssklower * 86936384Ssklower * RETURNS: nada 87036384Ssklower * 87136384Ssklower */ 87236384Ssklower dump_isoaddr(s) 87336384Ssklower struct sockaddr_iso *s; 87436384Ssklower { 87537469Ssklower char *clnp_saddr_isop(); 87636384Ssklower register int i; 87736384Ssklower 87836384Ssklower if( s->siso_family == AF_ISO) { 87937469Ssklower printf("ISO address: suffixlen %d, %s\n", 88038841Ssklower s->siso_tlen, clnp_saddr_isop(s)); 88136384Ssklower } else if( s->siso_family == AF_INET) { 88236384Ssklower /* hack */ 88336384Ssklower struct sockaddr_in *sin = (struct sockaddr_in *)s; 88436384Ssklower 88536384Ssklower printf("%d.%d.%d.%d: %d", 88636384Ssklower (sin->sin_addr.s_addr>>24)&0xff, 88736384Ssklower (sin->sin_addr.s_addr>>16)&0xff, 88836384Ssklower (sin->sin_addr.s_addr>>8)&0xff, 88936384Ssklower (sin->sin_addr.s_addr)&0xff, 89036384Ssklower sin->sin_port); 89136384Ssklower } 89236384Ssklower } 89336384Ssklower 89436384Ssklower #endif ARGO_DEBUG 895