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*47272Ssklower * @(#)iso.c 7.11 (Berkeley) 03/12/91 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 6336384Ssklower 6436384Ssklower int iso_interfaces = 0; /* number of external interfaces */ 6536384Ssklower extern struct ifnet loif; /* loopback interface */ 6643333Ssklower int ether_output(), llc_rtrequest(); 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 static iso_init_done; 8536384Ssklower 8637469Ssklower if (iso_init_done == 0) { 8737469Ssklower iso_init_done++; 8837469Ssklower rn_inithead(&iso_rnhead, 40, AF_ISO); 8937469Ssklower } 9036384Ssklower } 9136384Ssklower 9236384Ssklower /* 9336384Ssklower * FUNCTION: iso_addrmatch1 9436384Ssklower * 9536384Ssklower * PURPOSE: decide if the two iso_addrs passed are equal 9636384Ssklower * 9736384Ssklower * RETURNS: true if the addrs match, false if they do not 9836384Ssklower * 9936384Ssklower * SIDE EFFECTS: 10036384Ssklower * 10136384Ssklower * NOTES: 10236384Ssklower */ 10336384Ssklower iso_addrmatch1(isoaa, isoab) 10437469Ssklower register struct iso_addr *isoaa, *isoab; /* addresses to check */ 10536384Ssklower { 10637469Ssklower u_int compare_len; 10736384Ssklower 10836384Ssklower IFDEBUG(D_ROUTE) 10936384Ssklower printf("iso_addrmatch1: comparing lengths: %d to %d\n", isoaa->isoa_len, 11036384Ssklower isoab->isoa_len); 11136384Ssklower printf("a:\n"); 11237469Ssklower dump_buf(isoaa->isoa_genaddr, isoaa->isoa_len); 11336384Ssklower printf("b:\n"); 11437469Ssklower dump_buf(isoab->isoa_genaddr, isoab->isoa_len); 11536384Ssklower ENDDEBUG 11636384Ssklower 11736384Ssklower if ((compare_len = isoaa->isoa_len) != isoab->isoa_len) { 11836384Ssklower IFDEBUG(D_ROUTE) 11936384Ssklower printf("iso_addrmatch1: returning false because of lengths\n"); 12036384Ssklower ENDDEBUG 12136384Ssklower return 0; 12236384Ssklower } 12336384Ssklower 12437469Ssklower #ifdef notdef 12536384Ssklower /* TODO : generalize this to all afis with masks */ 12636384Ssklower if( isoaa->isoa_afi == AFI_37 ) { 12736384Ssklower /* must not compare 2 least significant digits, or for 12836384Ssklower * that matter, the DSP 12936384Ssklower */ 13036384Ssklower compare_len = ADDR37_IDI_LEN - 1; 13136384Ssklower } 13237469Ssklower #endif 13336384Ssklower 13436384Ssklower IFDEBUG(D_ROUTE) 13536384Ssklower int i; 13636384Ssklower char *a, *b; 13736384Ssklower 13837469Ssklower a = isoaa->isoa_genaddr; 13937469Ssklower b = isoab->isoa_genaddr; 14036384Ssklower 14136384Ssklower for (i=0; i<compare_len; i++) { 14236384Ssklower printf("<%x=%x>", a[i]&0xff, b[i]&0xff); 14336384Ssklower if (a[i] != b[i]) { 14436384Ssklower printf("\naddrs are not equal at byte %d\n", i); 14536384Ssklower return(0); 14636384Ssklower } 14736384Ssklower } 14836384Ssklower printf("\n"); 14936384Ssklower printf("addrs are equal\n"); 15036384Ssklower return (1); 15136384Ssklower ENDDEBUG 15237469Ssklower return (!bcmp(isoaa->isoa_genaddr, isoab->isoa_genaddr, compare_len)); 15336384Ssklower } 15436384Ssklower 15536384Ssklower /* 15636384Ssklower * FUNCTION: iso_addrmatch 15736384Ssklower * 15836384Ssklower * PURPOSE: decide if the two sockadrr_isos passed are equal 15936384Ssklower * 16036384Ssklower * RETURNS: true if the addrs match, false if they do not 16136384Ssklower * 16236384Ssklower * SIDE EFFECTS: 16336384Ssklower * 16436384Ssklower * NOTES: 16536384Ssklower */ 16636384Ssklower iso_addrmatch(sisoa, sisob) 16736384Ssklower struct sockaddr_iso *sisoa, *sisob; /* addresses to check */ 16836384Ssklower { 16936384Ssklower return(iso_addrmatch1(&sisoa->siso_addr, &sisob->siso_addr)); 17036384Ssklower } 17137469Ssklower #ifdef notdef 17236384Ssklower /* 17336384Ssklower * FUNCTION: iso_netmatch 17436384Ssklower * 17536384Ssklower * PURPOSE: similar to iso_addrmatch but takes sockaddr_iso 17636384Ssklower * as argument. 17736384Ssklower * 17836384Ssklower * RETURNS: true if same net, false if not 17936384Ssklower * 18036384Ssklower * SIDE EFFECTS: 18136384Ssklower * 18236384Ssklower * NOTES: 18336384Ssklower */ 18436384Ssklower iso_netmatch(sisoa, sisob) 18536384Ssklower struct sockaddr_iso *sisoa, *sisob; 18636384Ssklower { 18736384Ssklower u_char bufa[sizeof(struct sockaddr_iso)]; 18836384Ssklower u_char bufb[sizeof(struct sockaddr_iso)]; 18936384Ssklower register int lena, lenb; 19036384Ssklower 19136384Ssklower lena = iso_netof(&sisoa->siso_addr, bufa); 19236384Ssklower lenb = iso_netof(&sisob->siso_addr, bufb); 19336384Ssklower 19436384Ssklower IFDEBUG(D_ROUTE) 19536384Ssklower printf("iso_netmatch: comparing lengths: %d to %d\n", lena, lenb); 19636384Ssklower printf("a:\n"); 19736384Ssklower dump_buf(bufa, lena); 19836384Ssklower printf("b:\n"); 19936384Ssklower dump_buf(bufb, lenb); 20036384Ssklower ENDDEBUG 20136384Ssklower 20236384Ssklower return ((lena == lenb) && (!bcmp(bufa, bufb, lena))); 20336384Ssklower } 20437469Ssklower #endif notdef 20536384Ssklower 20636384Ssklower /* 20736384Ssklower * FUNCTION: iso_hashchar 20836384Ssklower * 20936384Ssklower * PURPOSE: Hash all character in the buffer specified into 21036384Ssklower * a long. Return the long. 21136384Ssklower * 21236384Ssklower * RETURNS: The hash value. 21336384Ssklower * 21436384Ssklower * SIDE EFFECTS: 21536384Ssklower * 21636384Ssklower * NOTES: The hash is achieved by exclusive ORing 4 byte 21736384Ssklower * quantities. 21836384Ssklower */ 21936384Ssklower u_long 22036384Ssklower iso_hashchar(buf, len) 22136384Ssklower register caddr_t buf; /* buffer to pack from */ 22236384Ssklower register int len; /* length of buffer */ 22336384Ssklower { 22436384Ssklower register u_long h = 0; 22536384Ssklower register int i; 22636384Ssklower 22736384Ssklower for (i=0; i<len; i+=4) { 22836384Ssklower register u_long l = 0; 22936384Ssklower 23036384Ssklower if ((len - i) < 4) { 23136384Ssklower /* buffer not multiple of 4 */ 23236384Ssklower switch (len - i) { 23336384Ssklower case 3: 23436384Ssklower l |= buf[i+2] << 8; 23536384Ssklower case 2: 23636384Ssklower l |= buf[i+1] << 16; 23736384Ssklower case 1: 23836384Ssklower l |= buf[i] << 24; 23936384Ssklower break; 24036384Ssklower default: 24136384Ssklower printf("iso_hashchar: unexpected value x%x\n", len - i); 24236384Ssklower break; 24336384Ssklower } 24436384Ssklower } else { 24536384Ssklower l |= buf[i] << 24; 24636384Ssklower l |= buf[i+1] << 16; 24736384Ssklower l |= buf[i+2] << 8; 24836384Ssklower l |= buf[i+3]; 24936384Ssklower } 25036384Ssklower 25136384Ssklower h ^= l; 25236384Ssklower } 25336384Ssklower 25436384Ssklower h ^= (u_long) (len % 4); 25536384Ssklower 25636384Ssklower return(h); 25736384Ssklower } 25837469Ssklower #ifdef notdef 25936384Ssklower /* 26036384Ssklower * FUNCTION: iso_hash 26136384Ssklower * 26236384Ssklower * PURPOSE: Fill in fields of afhash structure based upon addr passed. 26336384Ssklower * 26436384Ssklower * RETURNS: none 26536384Ssklower * 26636384Ssklower * SIDE EFFECTS: 26736384Ssklower * 26836384Ssklower * NOTES: 26936384Ssklower */ 27036384Ssklower iso_hash(siso, hp) 27136384Ssklower struct sockaddr_iso *siso; /* address to perform hash on */ 27236384Ssklower struct afhash *hp; /* RETURN: hash info here */ 27336384Ssklower { 27436384Ssklower u_long buf[sizeof(struct sockaddr_iso)+1/4]; 27536384Ssklower register int bufsize; 27636384Ssklower 27736384Ssklower 27836384Ssklower bzero(buf, sizeof(buf)); 27936384Ssklower 28036384Ssklower bufsize = iso_netof(&siso->siso_addr, buf); 28136384Ssklower hp->afh_nethash = iso_hashchar((caddr_t)buf, bufsize); 28236384Ssklower 28336384Ssklower IFDEBUG(D_ROUTE) 28436384Ssklower printf("iso_hash: iso_netof: bufsize = %d\n", bufsize); 28536384Ssklower ENDDEBUG 28636384Ssklower 28736384Ssklower hp->afh_hosthash = iso_hashchar((caddr_t)&siso->siso_addr, 28836384Ssklower siso->siso_addr.isoa_len); 28936384Ssklower 29036384Ssklower IFDEBUG(D_ROUTE) 29136384Ssklower printf("iso_hash: %s: nethash = x%x, hosthash = x%x\n", 29236384Ssklower clnp_iso_addrp(&siso->siso_addr), hp->afh_nethash, 29336384Ssklower hp->afh_hosthash); 29436384Ssklower ENDDEBUG 29536384Ssklower } 29636384Ssklower /* 29736384Ssklower * FUNCTION: iso_netof 29836384Ssklower * 29936384Ssklower * PURPOSE: Extract the network portion of the iso address. 30036384Ssklower * The network portion of the iso address varies depending 30136384Ssklower * on the type of address. The network portion of the 30236384Ssklower * address will include the IDP. The network portion is: 30336384Ssklower * 30436384Ssklower * TYPE DESC 30536384Ssklower * t37 The AFI and x.121 (IDI) 30636384Ssklower * osinet The AFI, orgid, snetid 30736384Ssklower * rfc986 The AFI, vers and network part of 30836384Ssklower * internet address. 30936384Ssklower * 31036384Ssklower * RETURNS: number of bytes placed into buf. 31136384Ssklower * 31236384Ssklower * SIDE EFFECTS: 31336384Ssklower * 31436384Ssklower * NOTES: Buf is assumed to be big enough 31536384Ssklower */ 31636384Ssklower iso_netof(isoa, buf) 31736384Ssklower struct iso_addr *isoa; /* address */ 31836384Ssklower caddr_t buf; /* RESULT: network portion of address here */ 31936384Ssklower { 32036384Ssklower u_int len = 1; /* length of afi */ 32136384Ssklower 32236384Ssklower switch (isoa->isoa_afi) { 32336384Ssklower case AFI_37: 32436384Ssklower /* 32536384Ssklower * Due to classic x.25 tunnel vision, there is no 32636384Ssklower * net portion of an x.121 address. For our purposes 32736384Ssklower * the AFI will do, so that all x.25 -type addresses 32836384Ssklower * map to the single x.25 SNPA. (Cannot have more than 32936384Ssklower * one, obviously). 33036384Ssklower */ 33136384Ssklower 33236384Ssklower break; 33336384Ssklower 33436384Ssklower /* case AFI_OSINET:*/ 33536384Ssklower case AFI_RFC986: { 33636384Ssklower u_short idi; /* value of idi */ 33736384Ssklower 33836384Ssklower /* osinet and rfc986 have idi in the same place */ 33936384Ssklower CTOH(isoa->rfc986_idi[0], isoa->rfc986_idi[1], idi); 34036384Ssklower 34136384Ssklower if (idi == IDI_OSINET) 34236384Ssklower /* 34336384Ssklower * Network portion of OSINET address can only be the IDI. Clearly, 34436384Ssklower * with one x25 interface, one could get to several orgids, and 34536384Ssklower * several snetids. 34636384Ssklower len += (ADDROSINET_IDI_LEN + OVLOSINET_ORGID_LEN + 34736384Ssklower OVLOSINET_SNETID_LEN); 34836384Ssklower */ 34936384Ssklower len += ADDROSINET_IDI_LEN; 35036384Ssklower else if (idi == IDI_RFC986) { 35136384Ssklower u_long inetaddr; 35236384Ssklower struct ovl_rfc986 *o986 = (struct ovl_rfc986 *)isoa; 35336384Ssklower 35436384Ssklower /* bump len to include idi and version (1 byte) */ 35536384Ssklower len += ADDRRFC986_IDI_LEN + 1; 35636384Ssklower 35736384Ssklower /* get inet addr long aligned */ 35836384Ssklower bcopy(o986->o986_inetaddr, &inetaddr, sizeof(inetaddr)); 35936384Ssklower inetaddr = ntohl(inetaddr); /* convert to host byte order */ 36036384Ssklower 36136384Ssklower IFDEBUG(D_ROUTE) 36236384Ssklower printf("iso_netof: isoa "); 36336384Ssklower dump_buf(isoa, sizeof(*isoa)); 36436384Ssklower printf("iso_netof: inetaddr 0x%x ", inetaddr); 36536384Ssklower ENDDEBUG 36636384Ssklower 36736384Ssklower /* bump len by size of network portion of inet address */ 36836384Ssklower if (IN_CLASSA(inetaddr)) { 36936384Ssklower len += 4-IN_CLASSA_NSHIFT/8; 37036384Ssklower IFDEBUG(D_ROUTE) 37136384Ssklower printf("iso_netof: class A net len is now %d\n", len); 37236384Ssklower ENDDEBUG 37336384Ssklower } else if (IN_CLASSB(inetaddr)) { 37436384Ssklower len += 4-IN_CLASSB_NSHIFT/8; 37536384Ssklower IFDEBUG(D_ROUTE) 37636384Ssklower printf("iso_netof: class B net len is now %d\n", len); 37736384Ssklower ENDDEBUG 37836384Ssklower } else { 37936384Ssklower len += 4-IN_CLASSC_NSHIFT/8; 38036384Ssklower IFDEBUG(D_ROUTE) 38136384Ssklower printf("iso_netof: class C net len is now %d\n", len); 38236384Ssklower ENDDEBUG 38336384Ssklower } 38436384Ssklower } else 38536384Ssklower len = 0; 38636384Ssklower } break; 38736384Ssklower 38836384Ssklower default: 38936384Ssklower len = 0; 39036384Ssklower } 39136384Ssklower 39236384Ssklower bcopy((caddr_t)isoa, buf, len); 39336384Ssklower IFDEBUG(D_ROUTE) 39436384Ssklower printf("in_netof: isoa "); 39536384Ssklower dump_buf(isoa, len); 39636384Ssklower printf("in_netof: net "); 39736384Ssklower dump_buf(buf, len); 39836384Ssklower ENDDEBUG 39936384Ssklower return len; 40036384Ssklower } 40137469Ssklower #endif notdef 40236384Ssklower /* 40337469Ssklower * Generic iso control operations (ioctl's). 40437469Ssklower * Ifp is 0 if not an interface-specific ioctl. 40536384Ssklower */ 40637469Ssklower /* ARGSUSED */ 40736384Ssklower iso_control(so, cmd, data, ifp) 40837469Ssklower struct socket *so; 40937469Ssklower int cmd; 41037469Ssklower caddr_t data; 41137469Ssklower register struct ifnet *ifp; 41236384Ssklower { 41337469Ssklower register struct iso_ifreq *ifr = (struct iso_ifreq *)data; 41437469Ssklower register struct iso_ifaddr *ia = 0; 41537469Ssklower register struct ifaddr *ifa; 41637469Ssklower struct iso_ifaddr *oia; 41737469Ssklower struct iso_aliasreq *ifra = (struct iso_aliasreq *)data; 41837469Ssklower int error, hostIsNew, maskIsNew; 41936384Ssklower 42037469Ssklower /* 42137469Ssklower * Find address for this interface, if it exists. 42237469Ssklower */ 42337469Ssklower if (ifp) 42437469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) 42537469Ssklower if (ia->ia_ifp == ifp) 42637469Ssklower break; 42736384Ssklower 42836384Ssklower switch (cmd) { 42937469Ssklower 43037469Ssklower case SIOCAIFADDR_ISO: 43137469Ssklower case SIOCDIFADDR_ISO: 43237469Ssklower if (ifra->ifra_addr.siso_family == AF_ISO) 43337469Ssklower for (oia = ia; ia; ia = ia->ia_next) { 43437469Ssklower if (ia->ia_ifp == ifp && 43537469Ssklower SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr)) 43637469Ssklower break; 43737469Ssklower } 43837547Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 43937547Smckusick return (error); 44036384Ssklower if (ifp == 0) 44137469Ssklower panic("iso_control"); 44237469Ssklower if (ia == (struct iso_ifaddr *)0) { 44337469Ssklower struct iso_ifaddr *nia; 44437469Ssklower if (cmd == SIOCDIFADDR_ISO) 44537469Ssklower return (EADDRNOTAVAIL); 44637469Ssklower MALLOC(nia, struct iso_ifaddr *, sizeof(*nia), 44737469Ssklower M_IFADDR, M_WAITOK); 44837469Ssklower if (nia == (struct iso_ifaddr *)0) 44937469Ssklower return (ENOBUFS); 45037469Ssklower bzero((caddr_t)nia, sizeof(*nia)); 45137469Ssklower if (ia = iso_ifaddr) { 45237469Ssklower for ( ; ia->ia_next; ia = ia->ia_next) 45337469Ssklower ; 45437469Ssklower ia->ia_next = nia; 45537469Ssklower } else 45637469Ssklower iso_ifaddr = nia; 45737469Ssklower ia = nia; 45837469Ssklower if (ifa = ifp->if_addrlist) { 45937469Ssklower for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 46037469Ssklower ; 46137469Ssklower ifa->ifa_next = (struct ifaddr *) ia; 46237469Ssklower } else 46337469Ssklower ifp->if_addrlist = (struct ifaddr *) ia; 46437469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 46537469Ssklower ia->ia_ifa.ifa_dstaddr 46637469Ssklower = (struct sockaddr *)&ia->ia_dstaddr; 46737469Ssklower ia->ia_ifa.ifa_netmask 46837469Ssklower = (struct sockaddr *)&ia->ia_sockmask; 46937469Ssklower ia->ia_ifp = ifp; 47037469Ssklower if (ifp != &loif) 47137469Ssklower iso_interfaces++; 47237469Ssklower } 47337469Ssklower break; 47436384Ssklower 47537469Ssklower #define cmdbyte(x) (((x) >> 8) & 0xff) 47637469Ssklower default: 47737469Ssklower if (cmdbyte(cmd) == 'a') 47837469Ssklower return (snpac_ioctl(cmd, data)); 47937469Ssklower if (ia == (struct iso_ifaddr *)0) 48037469Ssklower return (EADDRNOTAVAIL); 48137469Ssklower break; 48237469Ssklower } 48337469Ssklower switch (cmd) { 48436384Ssklower 48537469Ssklower case SIOCGIFADDR_ISO: 48637469Ssklower ifr->ifr_Addr = ia->ia_addr; 48737469Ssklower break; 48836384Ssklower 48937469Ssklower case SIOCGIFDSTADDR_ISO: 49037469Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 49137469Ssklower return (EINVAL); 49237469Ssklower ifr->ifr_Addr = ia->ia_dstaddr; 49337469Ssklower break; 49436384Ssklower 49537469Ssklower case SIOCGIFNETMASK_ISO: 49637469Ssklower ifr->ifr_Addr = ia->ia_sockmask; 49737469Ssklower break; 49836384Ssklower 49937469Ssklower case SIOCAIFADDR_ISO: 50043428Ssklower maskIsNew = 0; hostIsNew = 1; error = 0; 50137469Ssklower if (ia->ia_addr.siso_family == AF_ISO) { 50237469Ssklower if (ifra->ifra_addr.siso_len == 0) { 50337469Ssklower ifra->ifra_addr = ia->ia_addr; 50437469Ssklower hostIsNew = 0; 50537469Ssklower } else if (SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr)) 50637469Ssklower hostIsNew = 0; 50737469Ssklower } 50837469Ssklower if (ifra->ifra_mask.siso_len) { 50937469Ssklower iso_ifscrub(ifp, ia); 51037469Ssklower ia->ia_sockmask = ifra->ifra_mask; 51137469Ssklower maskIsNew = 1; 51237469Ssklower } 51337469Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) && 51437469Ssklower (ifra->ifra_dstaddr.siso_family == AF_ISO)) { 51537469Ssklower iso_ifscrub(ifp, ia); 51637469Ssklower ia->ia_dstaddr = ifra->ifra_dstaddr; 51737469Ssklower maskIsNew = 1; /* We lie; but the effect's the same */ 51837469Ssklower } 51937469Ssklower if (ifra->ifra_addr.siso_family == AF_ISO && 52037469Ssklower (hostIsNew || maskIsNew)) { 52137469Ssklower error = iso_ifinit(ifp, ia, &ifra->ifra_addr, 0); 52237469Ssklower } 52337469Ssklower if (ifra->ifra_snpaoffset) 52437469Ssklower ia->ia_snpaoffset = ifra->ifra_snpaoffset; 52537469Ssklower return (error); 52637469Ssklower 52737469Ssklower case SIOCDIFADDR_ISO: 52837469Ssklower iso_ifscrub(ifp, ia); 52937469Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 53037469Ssklower ifp->if_addrlist = ifa->ifa_next; 53137469Ssklower else { 53237469Ssklower while (ifa->ifa_next && 53337469Ssklower (ifa->ifa_next != (struct ifaddr *)ia)) 53437469Ssklower ifa = ifa->ifa_next; 53537469Ssklower if (ifa->ifa_next) 53637469Ssklower ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 53737469Ssklower else 53837469Ssklower printf("Couldn't unlink isoifaddr from ifp\n"); 53937469Ssklower } 54037469Ssklower oia = ia; 54137469Ssklower if (oia == (ia = iso_ifaddr)) { 54237469Ssklower iso_ifaddr = ia->ia_next; 54337469Ssklower } else { 54437469Ssklower while (ia->ia_next && (ia->ia_next != oia)) { 54537469Ssklower ia = ia->ia_next; 54636384Ssklower } 54737469Ssklower if (ia->ia_next) 54837469Ssklower ia->ia_next = oia->ia_next; 54937469Ssklower else 55037469Ssklower printf("Didn't unlink isoifadr from list\n"); 55136384Ssklower } 55237469Ssklower free((caddr_t)oia, M_IFADDR); 55337469Ssklower break; 55436384Ssklower 55536384Ssklower default: 55636384Ssklower if (ifp == 0 || ifp->if_ioctl == 0) 55736384Ssklower return (EOPNOTSUPP); 55836384Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data)); 55936384Ssklower } 56037469Ssklower return (0); 56136384Ssklower } 56236384Ssklower 56337469Ssklower /* 56437469Ssklower * Delete any existing route for an interface. 56537469Ssklower */ 56637469Ssklower iso_ifscrub(ifp, ia) 56737469Ssklower register struct ifnet *ifp; 56837469Ssklower register struct iso_ifaddr *ia; 56937469Ssklower { 57043333Ssklower int nsellength = ia->ia_addr.siso_tlen; 57137469Ssklower if ((ia->ia_flags & IFA_ROUTE) == 0) 57237469Ssklower return; 57343333Ssklower ia->ia_addr.siso_tlen = 0; 57437469Ssklower if (ifp->if_flags & IFF_LOOPBACK) 57537469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 57637469Ssklower else if (ifp->if_flags & IFF_POINTOPOINT) 57737469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 57837469Ssklower else { 57937469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 58037469Ssklower } 58143333Ssklower ia->ia_addr.siso_tlen = nsellength; 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; 59543333Ssklower int s = splimp(), error, nsellength; 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 } 61443333Ssklower /* XXX -- The following is here temporarily out of laziness 61543333Ssklower in not changing every ethernet driver's if_ioctl routine */ 61643333Ssklower if (ifp->if_output == ether_output) { 61743333Ssklower ia->ia_ifa.ifa_rtrequest = llc_rtrequest; 61843333Ssklower ia->ia_ifa.ifa_flags |= RTF_CLONING; 61943333Ssklower ia->ia_ifa.ifa_llinfolen = sizeof(struct llinfo_llc); 62043333Ssklower } 62137469Ssklower /* 62237469Ssklower * Add route for the network. 62337469Ssklower */ 62443333Ssklower nsellength = ia->ia_addr.siso_tlen; 62543333Ssklower ia->ia_addr.siso_tlen = 0; 62637469Ssklower if (ifp->if_flags & IFF_LOOPBACK) { 62737469Ssklower ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 62840894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 62937469Ssklower } else if (ifp->if_flags & IFF_POINTOPOINT && 63037469Ssklower ia->ia_dstaddr.siso_family == AF_ISO) 63140894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 63237469Ssklower else { 63340894Ssklower rt_maskedcopy(ia->ia_ifa.ifa_addr, ia->ia_ifa.ifa_dstaddr, 63440894Ssklower ia->ia_ifa.ifa_netmask); 63540894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP); 63637469Ssklower } 63743333Ssklower ia->ia_addr.siso_tlen = nsellength; 63837469Ssklower ia->ia_flags |= IFA_ROUTE; 63937469Ssklower splx(s); 64040894Ssklower return (error); 64137469Ssklower } 64237469Ssklower #ifdef notdef 64337469Ssklower 64436384Ssklower struct ifaddr * 64536384Ssklower iso_ifwithidi(addr) 64636384Ssklower register struct sockaddr *addr; 64736384Ssklower { 64836384Ssklower register struct ifnet *ifp; 64936384Ssklower register struct ifaddr *ifa; 65036384Ssklower register u_int af = addr->sa_family; 65136384Ssklower 65236384Ssklower if (af != AF_ISO) 65336384Ssklower return (0); 65436384Ssklower IFDEBUG(D_ROUTE) 65536384Ssklower printf(">>> iso_ifwithidi addr\n"); 65636384Ssklower dump_isoaddr( (struct sockaddr_iso *)(addr)); 65736384Ssklower printf("\n"); 65836384Ssklower ENDDEBUG 65936384Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) { 66036384Ssklower IFDEBUG(D_ROUTE) 66136384Ssklower printf("iso_ifwithidi ifnet %s\n", ifp->if_name); 66236384Ssklower ENDDEBUG 66336384Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 66436384Ssklower IFDEBUG(D_ROUTE) 66536384Ssklower printf("iso_ifwithidi address "); 66637469Ssklower dump_isoaddr( (struct sockaddr_iso *)(ifa->ifa_addr)); 66736384Ssklower ENDDEBUG 66837469Ssklower if (ifa->ifa_addr->sa_family != addr->sa_family) 66936384Ssklower continue; 67036384Ssklower 67136384Ssklower #define IFA_SIS(ifa)\ 67237469Ssklower ((struct sockaddr_iso *)((ifa)->ifa_addr)) 67336384Ssklower 67436384Ssklower IFDEBUG(D_ROUTE) 67536384Ssklower printf(" af same, args to iso_eqtype:\n"); 67636384Ssklower printf("0x%x ", IFA_SIS(ifa)->siso_addr); 67736384Ssklower printf(" 0x%x\n", 67836384Ssklower &(((struct sockaddr_iso *)addr)->siso_addr)); 67936384Ssklower ENDDEBUG 68036384Ssklower 68136384Ssklower if (iso_eqtype(&(IFA_SIS(ifa)->siso_addr), 68236384Ssklower &(((struct sockaddr_iso *)addr)->siso_addr))) { 68336384Ssklower IFDEBUG(D_ROUTE) 68436384Ssklower printf("ifa_ifwithidi: ifa found\n"); 68536384Ssklower ENDDEBUG 68636384Ssklower return (ifa); 68736384Ssklower } 68836384Ssklower IFDEBUG(D_ROUTE) 68936384Ssklower printf(" iso_eqtype failed\n"); 69036384Ssklower ENDDEBUG 69136384Ssklower } 69236384Ssklower } 69336384Ssklower return ((struct ifaddr *)0); 69436384Ssklower } 69536384Ssklower 69637469Ssklower #endif notdef 69736384Ssklower /* 69836384Ssklower * FUNCTION: iso_ck_addr 69936384Ssklower * 70036384Ssklower * PURPOSE: return true if the iso_addr passed is 70136384Ssklower * within the legal size limit for an iso address. 70236384Ssklower * 70336384Ssklower * RETURNS: true or false 70436384Ssklower * 70536384Ssklower * SIDE EFFECTS: 70636384Ssklower * 70736384Ssklower */ 70836384Ssklower iso_ck_addr(isoa) 70936384Ssklower struct iso_addr *isoa; /* address to check */ 71036384Ssklower { 71136384Ssklower return (isoa->isoa_len <= 20); 71236384Ssklower 71336384Ssklower } 71436384Ssklower 71537469Ssklower #ifdef notdef 71636384Ssklower /* 71736384Ssklower * FUNCTION: iso_eqtype 71836384Ssklower * 71936384Ssklower * PURPOSE: Determine if two iso addresses are of the same type. 72036384Ssklower * This is flaky. Really we should consider all type 47 addrs to be the 72136384Ssklower * same - but there do exist different structures for 47 addrs. 72236384Ssklower * Gosip adds a 3rd. 72336384Ssklower * 72436384Ssklower * RETURNS: true if the addresses are the same type 72536384Ssklower * 72636384Ssklower * SIDE EFFECTS: 72736384Ssklower * 72836384Ssklower * NOTES: By type, I mean rfc986, t37, or osinet 72936384Ssklower * 73036384Ssklower * This will first compare afis. If they match, then 73136384Ssklower * if the addr is not t37, the idis must be compared. 73236384Ssklower */ 73336384Ssklower iso_eqtype(isoaa, isoab) 73436384Ssklower struct iso_addr *isoaa; /* first addr to check */ 73536384Ssklower struct iso_addr *isoab; /* other addr to check */ 73636384Ssklower { 73736384Ssklower if (isoaa->isoa_afi == isoab->isoa_afi) { 73836384Ssklower if (isoaa->isoa_afi == AFI_37) 73936384Ssklower return(1); 74036384Ssklower else 74136384Ssklower return (!bcmp(&isoaa->isoa_u, &isoab->isoa_u, 2)); 74236384Ssklower } 74336384Ssklower return(0); 74436384Ssklower } 74537469Ssklower #endif notdef 74636384Ssklower /* 74737469Ssklower * FUNCTION: iso_localifa() 74836384Ssklower * 74937469Ssklower * PURPOSE: Find an interface addresss having a given destination 75037469Ssklower * or at least matching the net. 75136384Ssklower * 75236384Ssklower * RETURNS: ptr to an interface address 75336384Ssklower * 75436384Ssklower * SIDE EFFECTS: 75536384Ssklower * 75636384Ssklower * NOTES: 75736384Ssklower */ 75836384Ssklower struct iso_ifaddr * 75937469Ssklower iso_localifa(siso) 76037469Ssklower register struct sockaddr_iso *siso; 76136384Ssklower { 76236384Ssklower register struct iso_ifaddr *ia; 76337469Ssklower register char *cp1, *cp2, *cp3; 76437469Ssklower register struct ifnet *ifp; 76537469Ssklower struct iso_ifaddr *ia_maybe = 0; 76637469Ssklower /* 76737469Ssklower * We make one pass looking for both net matches and an exact 76837469Ssklower * dst addr. 76937469Ssklower */ 77037469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 77137469Ssklower if ((ifp = ia->ia_ifp) == 0 || ((ifp->if_flags & IFF_UP) == 0)) 77237469Ssklower continue; 77337469Ssklower if (ifp->if_flags & IFF_POINTOPOINT) { 77437469Ssklower if ((ia->ia_dstaddr.siso_family == AF_ISO) && 77537469Ssklower SAME_ISOADDR(&ia->ia_dstaddr, siso)) 77637469Ssklower return (ia); 77737469Ssklower else 77837469Ssklower if (SAME_ISOADDR(&ia->ia_addr, siso)) 77937469Ssklower ia_maybe = ia; 78037469Ssklower continue; 78137469Ssklower } 78237469Ssklower if (ia->ia_sockmask.siso_len) { 78337469Ssklower char *cplim = ia->ia_sockmask.siso_len + (char *)&ia->ia_sockmask; 78437469Ssklower cp1 = ia->ia_sockmask.siso_data; 78537469Ssklower cp2 = siso->siso_data; 78637469Ssklower cp3 = ia->ia_addr.siso_data; 78739936Ssklower while (cp1 < cplim) 78837469Ssklower if (*cp1++ & (*cp2++ ^ *cp3++)) 78937469Ssklower goto next; 79037469Ssklower ia_maybe = ia; 79137469Ssklower } 79237469Ssklower if (SAME_ISOADDR(&ia->ia_addr, siso)) 79337469Ssklower return ia; 79437469Ssklower next:; 79537469Ssklower } 79637469Ssklower return ia_maybe; 79736384Ssklower } 79836384Ssklower 799*47272Ssklower #ifdef TPCONS 80036384Ssklower #include "cons.h" 801*47272Ssklower #endif TPCONS 80236384Ssklower /* 80336384Ssklower * FUNCTION: iso_nlctloutput 80436384Ssklower * 80536384Ssklower * PURPOSE: Set options at the network level 80636384Ssklower * 80736384Ssklower * RETURNS: E* 80836384Ssklower * 80936384Ssklower * SIDE EFFECTS: 81036384Ssklower * 81136384Ssklower * NOTES: This could embody some of the functions of 81236384Ssklower * rclnp_ctloutput and cons_ctloutput. 81336384Ssklower */ 81436384Ssklower iso_nlctloutput(cmd, optname, pcb, m) 81536384Ssklower int cmd; /* command:set or get */ 81636384Ssklower int optname; /* option of interest */ 81736384Ssklower caddr_t pcb; /* nl pcb */ 81836384Ssklower struct mbuf *m; /* data for set, buffer for get */ 81936384Ssklower { 82036384Ssklower struct isopcb *isop = (struct isopcb *)pcb; 82136384Ssklower int error = 0; /* return value */ 82236384Ssklower caddr_t data; /* data for option */ 82336384Ssklower int data_len; /* data's length */ 82436384Ssklower 82536384Ssklower IFDEBUG(D_ISO) 82636384Ssklower printf("iso_nlctloutput: cmd %x, opt %x, pcb %x, m %x\n", 82736384Ssklower cmd, optname, pcb, m); 82836384Ssklower ENDDEBUG 82936384Ssklower 83036384Ssklower if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT)) 83136384Ssklower return(EOPNOTSUPP); 83236384Ssklower 83336384Ssklower data = mtod(m, caddr_t); 83436384Ssklower data_len = (m)->m_len; 83536384Ssklower 83636384Ssklower IFDEBUG(D_ISO) 83736384Ssklower printf("iso_nlctloutput: data is:\n"); 83836384Ssklower dump_buf(data, data_len); 83936384Ssklower ENDDEBUG 84036384Ssklower 84136384Ssklower switch (optname) { 84236384Ssklower 843*47272Ssklower #ifdef TPCONS 84436384Ssklower case CONSOPT_X25CRUD: 84536384Ssklower if (cmd == PRCO_GETOPT) { 84636384Ssklower error = EOPNOTSUPP; 84736384Ssklower break; 84836384Ssklower } 84936384Ssklower 85036384Ssklower if (data_len > MAXX25CRUDLEN) { 85136384Ssklower error = EINVAL; 85236384Ssklower break; 85336384Ssklower } 85436384Ssklower 85536384Ssklower IFDEBUG(D_ISO) 85636384Ssklower printf("iso_nlctloutput: setting x25 crud\n"); 85736384Ssklower ENDDEBUG 85836384Ssklower 85937469Ssklower bcopy(data, (caddr_t)isop->isop_x25crud, (unsigned)data_len); 86036384Ssklower isop->isop_x25crud_len = data_len; 86136384Ssklower break; 862*47272Ssklower #endif TPCONS 86336384Ssklower 86436384Ssklower default: 86536384Ssklower error = EOPNOTSUPP; 86636384Ssklower } 86736384Ssklower 86836384Ssklower return error; 86936384Ssklower } 87036384Ssklower #endif ISO 87136384Ssklower 87236384Ssklower #ifdef ARGO_DEBUG 87336384Ssklower 87436384Ssklower /* 87536384Ssklower * FUNCTION: dump_isoaddr 87636384Ssklower * 87736384Ssklower * PURPOSE: debugging 87836384Ssklower * 87936384Ssklower * RETURNS: nada 88036384Ssklower * 88136384Ssklower */ 88236384Ssklower dump_isoaddr(s) 88336384Ssklower struct sockaddr_iso *s; 88436384Ssklower { 88537469Ssklower char *clnp_saddr_isop(); 88636384Ssklower register int i; 88736384Ssklower 88836384Ssklower if( s->siso_family == AF_ISO) { 88937469Ssklower printf("ISO address: suffixlen %d, %s\n", 89038841Ssklower s->siso_tlen, clnp_saddr_isop(s)); 89136384Ssklower } else if( s->siso_family == AF_INET) { 89236384Ssklower /* hack */ 89336384Ssklower struct sockaddr_in *sin = (struct sockaddr_in *)s; 89436384Ssklower 89536384Ssklower printf("%d.%d.%d.%d: %d", 89636384Ssklower (sin->sin_addr.s_addr>>24)&0xff, 89736384Ssklower (sin->sin_addr.s_addr>>16)&0xff, 89836384Ssklower (sin->sin_addr.s_addr>>8)&0xff, 89936384Ssklower (sin->sin_addr.s_addr)&0xff, 90036384Ssklower sin->sin_port); 90136384Ssklower } 90236384Ssklower } 90336384Ssklower 90436384Ssklower #endif ARGO_DEBUG 905