149268Sbostic /*- 249268Sbostic * Copyright (c) 1991 The Regents of the University of California. 349268Sbostic * All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*58601Ssklower * @(#)iso.c 7.22 (Berkeley) 03/09/93 849268Sbostic */ 949268Sbostic 1036384Ssklower /*********************************************************** 1136384Ssklower Copyright IBM Corporation 1987 1236384Ssklower 1336384Ssklower All Rights Reserved 1436384Ssklower 1536384Ssklower Permission to use, copy, modify, and distribute this software and its 1636384Ssklower documentation for any purpose and without fee is hereby granted, 1736384Ssklower provided that the above copyright notice appear in all copies and that 1836384Ssklower both that copyright notice and this permission notice appear in 1936384Ssklower supporting documentation, and that the name of IBM not be 2036384Ssklower used in advertising or publicity pertaining to distribution of the 2136384Ssklower software without specific, written prior permission. 2236384Ssklower 2336384Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 2436384Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 2536384Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 2636384Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 2736384Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 2836384Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2936384Ssklower SOFTWARE. 3036384Ssklower 3136384Ssklower ******************************************************************/ 3236384Ssklower 3336384Ssklower /* 3436384Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 3536384Ssklower */ 3636384Ssklower /* 3736384Ssklower * $Header: iso.c,v 4.11 88/09/19 14:58:35 root Exp $ 3836384Ssklower * $Source: /usr/argo/sys/netiso/RCS/iso.c,v $ 3936384Ssklower * 4036384Ssklower * iso.c: miscellaneous routines to support the iso address family 4136384Ssklower */ 4236384Ssklower 4356533Sbostic #include <sys/param.h> 4456533Sbostic #include <sys/systm.h> 4556533Sbostic #include <sys/ioctl.h> 4656533Sbostic #include <sys/mbuf.h> 4756533Sbostic #include <sys/domain.h> 4856533Sbostic #include <sys/protosw.h> 4956533Sbostic #include <sys/socket.h> 5056533Sbostic #include <sys/socketvar.h> 5156533Sbostic #include <sys/errno.h> 5236384Ssklower 5356533Sbostic #include <net/if.h> 5456533Sbostic #include <net/route.h> 5556533Sbostic #include <net/af.h> 5636384Ssklower 5756533Sbostic #include <netiso/iso.h> 5856533Sbostic #include <netiso/iso_var.h> 5956533Sbostic #include <netiso/iso_snpac.h> 6056533Sbostic #include <netiso/iso_pcb.h> 6156533Sbostic #include <netiso/clnp.h> 6256533Sbostic #include <netiso/argo_debug.h> 6356913Ssklower #ifdef TUBA 6456913Ssklower #include <netiso/tuba_table.h> 6556913Ssklower #endif 6636384Ssklower 6736384Ssklower #ifdef ISO 6836384Ssklower 6936384Ssklower int iso_interfaces = 0; /* number of external interfaces */ 7036384Ssklower extern struct ifnet loif; /* loopback interface */ 7154823Ssklower int ether_output(); 7254823Ssklower void llc_rtrequest(); 7336384Ssklower 7436384Ssklower /* 7536384Ssklower * FUNCTION: iso_addrmatch1 7636384Ssklower * 7736384Ssklower * PURPOSE: decide if the two iso_addrs passed are equal 7836384Ssklower * 7936384Ssklower * RETURNS: true if the addrs match, false if they do not 8036384Ssklower * 8136384Ssklower * SIDE EFFECTS: 8236384Ssklower * 8336384Ssklower * NOTES: 8436384Ssklower */ 8536384Ssklower iso_addrmatch1(isoaa, isoab) 8637469Ssklower register struct iso_addr *isoaa, *isoab; /* addresses to check */ 8736384Ssklower { 8837469Ssklower u_int compare_len; 8936384Ssklower 9036384Ssklower IFDEBUG(D_ROUTE) 9136384Ssklower printf("iso_addrmatch1: comparing lengths: %d to %d\n", isoaa->isoa_len, 9236384Ssklower isoab->isoa_len); 9336384Ssklower printf("a:\n"); 9437469Ssklower dump_buf(isoaa->isoa_genaddr, isoaa->isoa_len); 9536384Ssklower printf("b:\n"); 9637469Ssklower dump_buf(isoab->isoa_genaddr, isoab->isoa_len); 9736384Ssklower ENDDEBUG 9836384Ssklower 9936384Ssklower if ((compare_len = isoaa->isoa_len) != isoab->isoa_len) { 10036384Ssklower IFDEBUG(D_ROUTE) 10136384Ssklower printf("iso_addrmatch1: returning false because of lengths\n"); 10236384Ssklower ENDDEBUG 10336384Ssklower return 0; 10436384Ssklower } 10536384Ssklower 10637469Ssklower #ifdef notdef 10736384Ssklower /* TODO : generalize this to all afis with masks */ 10836384Ssklower if( isoaa->isoa_afi == AFI_37 ) { 10936384Ssklower /* must not compare 2 least significant digits, or for 11036384Ssklower * that matter, the DSP 11136384Ssklower */ 11236384Ssklower compare_len = ADDR37_IDI_LEN - 1; 11336384Ssklower } 11437469Ssklower #endif 11536384Ssklower 11636384Ssklower IFDEBUG(D_ROUTE) 11736384Ssklower int i; 11836384Ssklower char *a, *b; 11936384Ssklower 12037469Ssklower a = isoaa->isoa_genaddr; 12137469Ssklower b = isoab->isoa_genaddr; 12236384Ssklower 12336384Ssklower for (i=0; i<compare_len; i++) { 12436384Ssklower printf("<%x=%x>", a[i]&0xff, b[i]&0xff); 12536384Ssklower if (a[i] != b[i]) { 12636384Ssklower printf("\naddrs are not equal at byte %d\n", i); 12736384Ssklower return(0); 12836384Ssklower } 12936384Ssklower } 13036384Ssklower printf("\n"); 13136384Ssklower printf("addrs are equal\n"); 13236384Ssklower return (1); 13336384Ssklower ENDDEBUG 13437469Ssklower return (!bcmp(isoaa->isoa_genaddr, isoab->isoa_genaddr, compare_len)); 13536384Ssklower } 13636384Ssklower 13736384Ssklower /* 13836384Ssklower * FUNCTION: iso_addrmatch 13936384Ssklower * 14036384Ssklower * PURPOSE: decide if the two sockadrr_isos passed are equal 14136384Ssklower * 14236384Ssklower * RETURNS: true if the addrs match, false if they do not 14336384Ssklower * 14436384Ssklower * SIDE EFFECTS: 14536384Ssklower * 14636384Ssklower * NOTES: 14736384Ssklower */ 14836384Ssklower iso_addrmatch(sisoa, sisob) 14936384Ssklower struct sockaddr_iso *sisoa, *sisob; /* addresses to check */ 15036384Ssklower { 15136384Ssklower return(iso_addrmatch1(&sisoa->siso_addr, &sisob->siso_addr)); 15236384Ssklower } 15337469Ssklower #ifdef notdef 15436384Ssklower /* 15536384Ssklower * FUNCTION: iso_netmatch 15636384Ssklower * 15736384Ssklower * PURPOSE: similar to iso_addrmatch but takes sockaddr_iso 15836384Ssklower * as argument. 15936384Ssklower * 16036384Ssklower * RETURNS: true if same net, false if not 16136384Ssklower * 16236384Ssklower * SIDE EFFECTS: 16336384Ssklower * 16436384Ssklower * NOTES: 16536384Ssklower */ 16636384Ssklower iso_netmatch(sisoa, sisob) 16736384Ssklower struct sockaddr_iso *sisoa, *sisob; 16836384Ssklower { 16936384Ssklower u_char bufa[sizeof(struct sockaddr_iso)]; 17036384Ssklower u_char bufb[sizeof(struct sockaddr_iso)]; 17136384Ssklower register int lena, lenb; 17236384Ssklower 17336384Ssklower lena = iso_netof(&sisoa->siso_addr, bufa); 17436384Ssklower lenb = iso_netof(&sisob->siso_addr, bufb); 17536384Ssklower 17636384Ssklower IFDEBUG(D_ROUTE) 17736384Ssklower printf("iso_netmatch: comparing lengths: %d to %d\n", lena, lenb); 17836384Ssklower printf("a:\n"); 17936384Ssklower dump_buf(bufa, lena); 18036384Ssklower printf("b:\n"); 18136384Ssklower dump_buf(bufb, lenb); 18236384Ssklower ENDDEBUG 18336384Ssklower 18436384Ssklower return ((lena == lenb) && (!bcmp(bufa, bufb, lena))); 18536384Ssklower } 18637469Ssklower #endif notdef 18736384Ssklower 18836384Ssklower /* 18936384Ssklower * FUNCTION: iso_hashchar 19036384Ssklower * 19136384Ssklower * PURPOSE: Hash all character in the buffer specified into 19236384Ssklower * a long. Return the long. 19336384Ssklower * 19436384Ssklower * RETURNS: The hash value. 19536384Ssklower * 19636384Ssklower * SIDE EFFECTS: 19736384Ssklower * 19836384Ssklower * NOTES: The hash is achieved by exclusive ORing 4 byte 19936384Ssklower * quantities. 20036384Ssklower */ 20136384Ssklower u_long 20236384Ssklower iso_hashchar(buf, len) 20336384Ssklower register caddr_t buf; /* buffer to pack from */ 20436384Ssklower register int len; /* length of buffer */ 20536384Ssklower { 20636384Ssklower register u_long h = 0; 20736384Ssklower register int i; 20836384Ssklower 20936384Ssklower for (i=0; i<len; i+=4) { 21036384Ssklower register u_long l = 0; 21136384Ssklower 21236384Ssklower if ((len - i) < 4) { 21336384Ssklower /* buffer not multiple of 4 */ 21436384Ssklower switch (len - i) { 21536384Ssklower case 3: 21636384Ssklower l |= buf[i+2] << 8; 21736384Ssklower case 2: 21836384Ssklower l |= buf[i+1] << 16; 21936384Ssklower case 1: 22036384Ssklower l |= buf[i] << 24; 22136384Ssklower break; 22236384Ssklower default: 22336384Ssklower printf("iso_hashchar: unexpected value x%x\n", len - i); 22436384Ssklower break; 22536384Ssklower } 22636384Ssklower } else { 22736384Ssklower l |= buf[i] << 24; 22836384Ssklower l |= buf[i+1] << 16; 22936384Ssklower l |= buf[i+2] << 8; 23036384Ssklower l |= buf[i+3]; 23136384Ssklower } 23236384Ssklower 23336384Ssklower h ^= l; 23436384Ssklower } 23536384Ssklower 23636384Ssklower h ^= (u_long) (len % 4); 23736384Ssklower 23836384Ssklower return(h); 23936384Ssklower } 24037469Ssklower #ifdef notdef 24136384Ssklower /* 24236384Ssklower * FUNCTION: iso_hash 24336384Ssklower * 24436384Ssklower * PURPOSE: Fill in fields of afhash structure based upon addr passed. 24536384Ssklower * 24636384Ssklower * RETURNS: none 24736384Ssklower * 24836384Ssklower * SIDE EFFECTS: 24936384Ssklower * 25036384Ssklower * NOTES: 25136384Ssklower */ 25236384Ssklower iso_hash(siso, hp) 25336384Ssklower struct sockaddr_iso *siso; /* address to perform hash on */ 25436384Ssklower struct afhash *hp; /* RETURN: hash info here */ 25536384Ssklower { 25636384Ssklower u_long buf[sizeof(struct sockaddr_iso)+1/4]; 25736384Ssklower register int bufsize; 25836384Ssklower 25936384Ssklower 26036384Ssklower bzero(buf, sizeof(buf)); 26136384Ssklower 26236384Ssklower bufsize = iso_netof(&siso->siso_addr, buf); 26336384Ssklower hp->afh_nethash = iso_hashchar((caddr_t)buf, bufsize); 26436384Ssklower 26536384Ssklower IFDEBUG(D_ROUTE) 26636384Ssklower printf("iso_hash: iso_netof: bufsize = %d\n", bufsize); 26736384Ssklower ENDDEBUG 26836384Ssklower 26936384Ssklower hp->afh_hosthash = iso_hashchar((caddr_t)&siso->siso_addr, 27036384Ssklower siso->siso_addr.isoa_len); 27136384Ssklower 27236384Ssklower IFDEBUG(D_ROUTE) 27336384Ssklower printf("iso_hash: %s: nethash = x%x, hosthash = x%x\n", 27436384Ssklower clnp_iso_addrp(&siso->siso_addr), hp->afh_nethash, 27536384Ssklower hp->afh_hosthash); 27636384Ssklower ENDDEBUG 27736384Ssklower } 27836384Ssklower /* 27936384Ssklower * FUNCTION: iso_netof 28036384Ssklower * 28136384Ssklower * PURPOSE: Extract the network portion of the iso address. 28236384Ssklower * The network portion of the iso address varies depending 28336384Ssklower * on the type of address. The network portion of the 28436384Ssklower * address will include the IDP. The network portion is: 28536384Ssklower * 28636384Ssklower * TYPE DESC 28736384Ssklower * t37 The AFI and x.121 (IDI) 28836384Ssklower * osinet The AFI, orgid, snetid 28936384Ssklower * rfc986 The AFI, vers and network part of 29036384Ssklower * internet address. 29136384Ssklower * 29236384Ssklower * RETURNS: number of bytes placed into buf. 29336384Ssklower * 29436384Ssklower * SIDE EFFECTS: 29536384Ssklower * 29636384Ssklower * NOTES: Buf is assumed to be big enough 29736384Ssklower */ 29836384Ssklower iso_netof(isoa, buf) 29936384Ssklower struct iso_addr *isoa; /* address */ 30036384Ssklower caddr_t buf; /* RESULT: network portion of address here */ 30136384Ssklower { 30236384Ssklower u_int len = 1; /* length of afi */ 30336384Ssklower 30436384Ssklower switch (isoa->isoa_afi) { 30536384Ssklower case AFI_37: 30636384Ssklower /* 30736384Ssklower * Due to classic x.25 tunnel vision, there is no 30836384Ssklower * net portion of an x.121 address. For our purposes 30936384Ssklower * the AFI will do, so that all x.25 -type addresses 31036384Ssklower * map to the single x.25 SNPA. (Cannot have more than 31136384Ssklower * one, obviously). 31236384Ssklower */ 31336384Ssklower 31436384Ssklower break; 31536384Ssklower 31636384Ssklower /* case AFI_OSINET:*/ 31736384Ssklower case AFI_RFC986: { 31836384Ssklower u_short idi; /* value of idi */ 31936384Ssklower 32036384Ssklower /* osinet and rfc986 have idi in the same place */ 32136384Ssklower CTOH(isoa->rfc986_idi[0], isoa->rfc986_idi[1], idi); 32236384Ssklower 32336384Ssklower if (idi == IDI_OSINET) 32436384Ssklower /* 32536384Ssklower * Network portion of OSINET address can only be the IDI. Clearly, 32636384Ssklower * with one x25 interface, one could get to several orgids, and 32736384Ssklower * several snetids. 32836384Ssklower len += (ADDROSINET_IDI_LEN + OVLOSINET_ORGID_LEN + 32936384Ssklower OVLOSINET_SNETID_LEN); 33036384Ssklower */ 33136384Ssklower len += ADDROSINET_IDI_LEN; 33236384Ssklower else if (idi == IDI_RFC986) { 33336384Ssklower u_long inetaddr; 33436384Ssklower struct ovl_rfc986 *o986 = (struct ovl_rfc986 *)isoa; 33536384Ssklower 33636384Ssklower /* bump len to include idi and version (1 byte) */ 33736384Ssklower len += ADDRRFC986_IDI_LEN + 1; 33836384Ssklower 33936384Ssklower /* get inet addr long aligned */ 34036384Ssklower bcopy(o986->o986_inetaddr, &inetaddr, sizeof(inetaddr)); 34136384Ssklower inetaddr = ntohl(inetaddr); /* convert to host byte order */ 34236384Ssklower 34336384Ssklower IFDEBUG(D_ROUTE) 34436384Ssklower printf("iso_netof: isoa "); 34536384Ssklower dump_buf(isoa, sizeof(*isoa)); 34636384Ssklower printf("iso_netof: inetaddr 0x%x ", inetaddr); 34736384Ssklower ENDDEBUG 34836384Ssklower 34936384Ssklower /* bump len by size of network portion of inet address */ 35036384Ssklower if (IN_CLASSA(inetaddr)) { 35136384Ssklower len += 4-IN_CLASSA_NSHIFT/8; 35236384Ssklower IFDEBUG(D_ROUTE) 35336384Ssklower printf("iso_netof: class A net len is now %d\n", len); 35436384Ssklower ENDDEBUG 35536384Ssklower } else if (IN_CLASSB(inetaddr)) { 35636384Ssklower len += 4-IN_CLASSB_NSHIFT/8; 35736384Ssklower IFDEBUG(D_ROUTE) 35836384Ssklower printf("iso_netof: class B net len is now %d\n", len); 35936384Ssklower ENDDEBUG 36036384Ssklower } else { 36136384Ssklower len += 4-IN_CLASSC_NSHIFT/8; 36236384Ssklower IFDEBUG(D_ROUTE) 36336384Ssklower printf("iso_netof: class C net len is now %d\n", len); 36436384Ssklower ENDDEBUG 36536384Ssklower } 36636384Ssklower } else 36736384Ssklower len = 0; 36836384Ssklower } break; 36936384Ssklower 37036384Ssklower default: 37136384Ssklower len = 0; 37236384Ssklower } 37336384Ssklower 37436384Ssklower bcopy((caddr_t)isoa, buf, len); 37536384Ssklower IFDEBUG(D_ROUTE) 376*58601Ssklower printf("iso_netof: isoa "); 37736384Ssklower dump_buf(isoa, len); 378*58601Ssklower printf("iso_netof: net "); 37936384Ssklower dump_buf(buf, len); 38036384Ssklower ENDDEBUG 38136384Ssklower return len; 38236384Ssklower } 38337469Ssklower #endif notdef 38436384Ssklower /* 38537469Ssklower * Generic iso control operations (ioctl's). 38637469Ssklower * Ifp is 0 if not an interface-specific ioctl. 38736384Ssklower */ 38837469Ssklower /* ARGSUSED */ 38936384Ssklower iso_control(so, cmd, data, ifp) 39037469Ssklower struct socket *so; 39137469Ssklower int cmd; 39237469Ssklower caddr_t data; 39337469Ssklower register struct ifnet *ifp; 39436384Ssklower { 39537469Ssklower register struct iso_ifreq *ifr = (struct iso_ifreq *)data; 39637469Ssklower register struct iso_ifaddr *ia = 0; 39737469Ssklower register struct ifaddr *ifa; 39837469Ssklower struct iso_ifaddr *oia; 39937469Ssklower struct iso_aliasreq *ifra = (struct iso_aliasreq *)data; 40037469Ssklower int error, hostIsNew, maskIsNew; 40136384Ssklower 40237469Ssklower /* 40337469Ssklower * Find address for this interface, if it exists. 40437469Ssklower */ 40537469Ssklower if (ifp) 40637469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) 40737469Ssklower if (ia->ia_ifp == ifp) 40837469Ssklower break; 40936384Ssklower 41036384Ssklower switch (cmd) { 41137469Ssklower 41237469Ssklower case SIOCAIFADDR_ISO: 41337469Ssklower case SIOCDIFADDR_ISO: 41437469Ssklower if (ifra->ifra_addr.siso_family == AF_ISO) 41537469Ssklower for (oia = ia; ia; ia = ia->ia_next) { 41637469Ssklower if (ia->ia_ifp == ifp && 41737469Ssklower SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr)) 41837469Ssklower break; 41937469Ssklower } 42050232Ssklower if ((so->so_state & SS_PRIV) == 0) 42150232Ssklower return (EPERM); 42236384Ssklower if (ifp == 0) 42337469Ssklower panic("iso_control"); 42437469Ssklower if (ia == (struct iso_ifaddr *)0) { 42537469Ssklower struct iso_ifaddr *nia; 42637469Ssklower if (cmd == SIOCDIFADDR_ISO) 42737469Ssklower return (EADDRNOTAVAIL); 42856913Ssklower #ifdef TUBA 42956913Ssklower /* XXXXXX can't be done in the proto init routines */ 43056913Ssklower if (tuba_tree == 0) 43156913Ssklower tuba_table_init(); 43256913Ssklower #endif 43337469Ssklower MALLOC(nia, struct iso_ifaddr *, sizeof(*nia), 43437469Ssklower M_IFADDR, M_WAITOK); 43537469Ssklower if (nia == (struct iso_ifaddr *)0) 43637469Ssklower return (ENOBUFS); 43737469Ssklower bzero((caddr_t)nia, sizeof(*nia)); 43837469Ssklower if (ia = iso_ifaddr) { 43937469Ssklower for ( ; ia->ia_next; ia = ia->ia_next) 44037469Ssklower ; 44137469Ssklower ia->ia_next = nia; 44237469Ssklower } else 44337469Ssklower iso_ifaddr = nia; 44437469Ssklower ia = nia; 44537469Ssklower if (ifa = ifp->if_addrlist) { 44637469Ssklower for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 44737469Ssklower ; 44837469Ssklower ifa->ifa_next = (struct ifaddr *) ia; 44937469Ssklower } else 45037469Ssklower ifp->if_addrlist = (struct ifaddr *) ia; 45137469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 45237469Ssklower ia->ia_ifa.ifa_dstaddr 45337469Ssklower = (struct sockaddr *)&ia->ia_dstaddr; 45437469Ssklower ia->ia_ifa.ifa_netmask 45537469Ssklower = (struct sockaddr *)&ia->ia_sockmask; 45637469Ssklower ia->ia_ifp = ifp; 45737469Ssklower if (ifp != &loif) 45837469Ssklower iso_interfaces++; 45937469Ssklower } 46037469Ssklower break; 46136384Ssklower 46237469Ssklower #define cmdbyte(x) (((x) >> 8) & 0xff) 46337469Ssklower default: 46437469Ssklower if (cmdbyte(cmd) == 'a') 46550232Ssklower return (snpac_ioctl(so, cmd, data)); 46637469Ssklower if (ia == (struct iso_ifaddr *)0) 46737469Ssklower return (EADDRNOTAVAIL); 46837469Ssklower break; 46937469Ssklower } 47037469Ssklower switch (cmd) { 47136384Ssklower 47237469Ssklower case SIOCGIFADDR_ISO: 47337469Ssklower ifr->ifr_Addr = ia->ia_addr; 47437469Ssklower break; 47536384Ssklower 47637469Ssklower case SIOCGIFDSTADDR_ISO: 47737469Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 47837469Ssklower return (EINVAL); 47937469Ssklower ifr->ifr_Addr = ia->ia_dstaddr; 48037469Ssklower break; 48136384Ssklower 48237469Ssklower case SIOCGIFNETMASK_ISO: 48337469Ssklower ifr->ifr_Addr = ia->ia_sockmask; 48437469Ssklower break; 48536384Ssklower 48637469Ssklower case SIOCAIFADDR_ISO: 48743428Ssklower maskIsNew = 0; hostIsNew = 1; error = 0; 48837469Ssklower if (ia->ia_addr.siso_family == AF_ISO) { 48937469Ssklower if (ifra->ifra_addr.siso_len == 0) { 49037469Ssklower ifra->ifra_addr = ia->ia_addr; 49137469Ssklower hostIsNew = 0; 49237469Ssklower } else if (SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr)) 49337469Ssklower hostIsNew = 0; 49437469Ssklower } 49537469Ssklower if (ifra->ifra_mask.siso_len) { 49637469Ssklower iso_ifscrub(ifp, ia); 49737469Ssklower ia->ia_sockmask = ifra->ifra_mask; 49837469Ssklower maskIsNew = 1; 49937469Ssklower } 50037469Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) && 50137469Ssklower (ifra->ifra_dstaddr.siso_family == AF_ISO)) { 50237469Ssklower iso_ifscrub(ifp, ia); 50337469Ssklower ia->ia_dstaddr = ifra->ifra_dstaddr; 50437469Ssklower maskIsNew = 1; /* We lie; but the effect's the same */ 50537469Ssklower } 50637469Ssklower if (ifra->ifra_addr.siso_family == AF_ISO && 50737469Ssklower (hostIsNew || maskIsNew)) { 50837469Ssklower error = iso_ifinit(ifp, ia, &ifra->ifra_addr, 0); 50937469Ssklower } 51037469Ssklower if (ifra->ifra_snpaoffset) 51137469Ssklower ia->ia_snpaoffset = ifra->ifra_snpaoffset; 51237469Ssklower return (error); 51337469Ssklower 51437469Ssklower case SIOCDIFADDR_ISO: 51537469Ssklower iso_ifscrub(ifp, ia); 51637469Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 51737469Ssklower ifp->if_addrlist = ifa->ifa_next; 51837469Ssklower else { 51937469Ssklower while (ifa->ifa_next && 52037469Ssklower (ifa->ifa_next != (struct ifaddr *)ia)) 52137469Ssklower ifa = ifa->ifa_next; 52237469Ssklower if (ifa->ifa_next) 52337469Ssklower ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 52437469Ssklower else 52537469Ssklower printf("Couldn't unlink isoifaddr from ifp\n"); 52637469Ssklower } 52737469Ssklower oia = ia; 52837469Ssklower if (oia == (ia = iso_ifaddr)) { 52937469Ssklower iso_ifaddr = ia->ia_next; 53037469Ssklower } else { 53137469Ssklower while (ia->ia_next && (ia->ia_next != oia)) { 53237469Ssklower ia = ia->ia_next; 53336384Ssklower } 53437469Ssklower if (ia->ia_next) 53537469Ssklower ia->ia_next = oia->ia_next; 53637469Ssklower else 53737469Ssklower printf("Didn't unlink isoifadr from list\n"); 53836384Ssklower } 53952030Ssklower IFAFREE((&oia->ia_ifa)); 54037469Ssklower break; 54136384Ssklower 54236384Ssklower default: 54336384Ssklower if (ifp == 0 || ifp->if_ioctl == 0) 54436384Ssklower return (EOPNOTSUPP); 54536384Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data)); 54636384Ssklower } 54737469Ssklower return (0); 54836384Ssklower } 54936384Ssklower 55037469Ssklower /* 55137469Ssklower * Delete any existing route for an interface. 55237469Ssklower */ 55337469Ssklower iso_ifscrub(ifp, ia) 55437469Ssklower register struct ifnet *ifp; 55537469Ssklower register struct iso_ifaddr *ia; 55637469Ssklower { 55743333Ssklower int nsellength = ia->ia_addr.siso_tlen; 55837469Ssklower if ((ia->ia_flags & IFA_ROUTE) == 0) 55937469Ssklower return; 56043333Ssklower ia->ia_addr.siso_tlen = 0; 56137469Ssklower if (ifp->if_flags & IFF_LOOPBACK) 56237469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 56337469Ssklower else if (ifp->if_flags & IFF_POINTOPOINT) 56437469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 56537469Ssklower else { 56637469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 56737469Ssklower } 56843333Ssklower ia->ia_addr.siso_tlen = nsellength; 56937469Ssklower ia->ia_flags &= ~IFA_ROUTE; 57037469Ssklower } 57137469Ssklower 57237469Ssklower /* 57337469Ssklower * Initialize an interface's internet address 57437469Ssklower * and routing table entry. 57537469Ssklower */ 57637469Ssklower iso_ifinit(ifp, ia, siso, scrub) 57737469Ssklower register struct ifnet *ifp; 57837469Ssklower register struct iso_ifaddr *ia; 57937469Ssklower struct sockaddr_iso *siso; 58037469Ssklower { 58137469Ssklower struct sockaddr_iso oldaddr; 58243333Ssklower int s = splimp(), error, nsellength; 58337469Ssklower 58437469Ssklower oldaddr = ia->ia_addr; 58537469Ssklower ia->ia_addr = *siso; 58637469Ssklower /* 58737469Ssklower * Give the interface a chance to initialize 58837469Ssklower * if this is its first address, 58937469Ssklower * and to validate the address if necessary. 59037469Ssklower */ 59154823Ssklower if (ifp->if_ioctl && 59254823Ssklower (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) { 59337469Ssklower splx(s); 59437469Ssklower ia->ia_addr = oldaddr; 59537469Ssklower return (error); 59637469Ssklower } 59737469Ssklower if (scrub) { 59837469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 59937469Ssklower iso_ifscrub(ifp, ia); 60037469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 60137469Ssklower } 60243333Ssklower /* XXX -- The following is here temporarily out of laziness 60343333Ssklower in not changing every ethernet driver's if_ioctl routine */ 60443333Ssklower if (ifp->if_output == ether_output) { 60543333Ssklower ia->ia_ifa.ifa_rtrequest = llc_rtrequest; 60643333Ssklower ia->ia_ifa.ifa_flags |= RTF_CLONING; 60743333Ssklower } 60837469Ssklower /* 60937469Ssklower * Add route for the network. 61037469Ssklower */ 61143333Ssklower nsellength = ia->ia_addr.siso_tlen; 61243333Ssklower ia->ia_addr.siso_tlen = 0; 61337469Ssklower if (ifp->if_flags & IFF_LOOPBACK) { 61437469Ssklower ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 61540894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 61637469Ssklower } else if (ifp->if_flags & IFF_POINTOPOINT && 61737469Ssklower ia->ia_dstaddr.siso_family == AF_ISO) 61840894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 61937469Ssklower else { 62040894Ssklower rt_maskedcopy(ia->ia_ifa.ifa_addr, ia->ia_ifa.ifa_dstaddr, 62140894Ssklower ia->ia_ifa.ifa_netmask); 62249936Ssklower ia->ia_dstaddr.siso_nlen = 62349936Ssklower min(ia->ia_addr.siso_nlen, (ia->ia_sockmask.siso_len - 6)); 62440894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP); 62537469Ssklower } 62643333Ssklower ia->ia_addr.siso_tlen = nsellength; 62737469Ssklower ia->ia_flags |= IFA_ROUTE; 62837469Ssklower splx(s); 62940894Ssklower return (error); 63037469Ssklower } 63137469Ssklower #ifdef notdef 63237469Ssklower 63336384Ssklower struct ifaddr * 63436384Ssklower iso_ifwithidi(addr) 63536384Ssklower register struct sockaddr *addr; 63636384Ssklower { 63736384Ssklower register struct ifnet *ifp; 63836384Ssklower register struct ifaddr *ifa; 63936384Ssklower register u_int af = addr->sa_family; 64036384Ssklower 64136384Ssklower if (af != AF_ISO) 64236384Ssklower return (0); 64336384Ssklower IFDEBUG(D_ROUTE) 64436384Ssklower printf(">>> iso_ifwithidi addr\n"); 64536384Ssklower dump_isoaddr( (struct sockaddr_iso *)(addr)); 64636384Ssklower printf("\n"); 64736384Ssklower ENDDEBUG 64836384Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) { 64936384Ssklower IFDEBUG(D_ROUTE) 65036384Ssklower printf("iso_ifwithidi ifnet %s\n", ifp->if_name); 65136384Ssklower ENDDEBUG 65236384Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 65336384Ssklower IFDEBUG(D_ROUTE) 65436384Ssklower printf("iso_ifwithidi address "); 65537469Ssklower dump_isoaddr( (struct sockaddr_iso *)(ifa->ifa_addr)); 65636384Ssklower ENDDEBUG 65737469Ssklower if (ifa->ifa_addr->sa_family != addr->sa_family) 65836384Ssklower continue; 65936384Ssklower 66036384Ssklower #define IFA_SIS(ifa)\ 66137469Ssklower ((struct sockaddr_iso *)((ifa)->ifa_addr)) 66236384Ssklower 66336384Ssklower IFDEBUG(D_ROUTE) 66436384Ssklower printf(" af same, args to iso_eqtype:\n"); 66536384Ssklower printf("0x%x ", IFA_SIS(ifa)->siso_addr); 66636384Ssklower printf(" 0x%x\n", 66736384Ssklower &(((struct sockaddr_iso *)addr)->siso_addr)); 66836384Ssklower ENDDEBUG 66936384Ssklower 67036384Ssklower if (iso_eqtype(&(IFA_SIS(ifa)->siso_addr), 67136384Ssklower &(((struct sockaddr_iso *)addr)->siso_addr))) { 67236384Ssklower IFDEBUG(D_ROUTE) 67336384Ssklower printf("ifa_ifwithidi: ifa found\n"); 67436384Ssklower ENDDEBUG 67536384Ssklower return (ifa); 67636384Ssklower } 67736384Ssklower IFDEBUG(D_ROUTE) 67836384Ssklower printf(" iso_eqtype failed\n"); 67936384Ssklower ENDDEBUG 68036384Ssklower } 68136384Ssklower } 68236384Ssklower return ((struct ifaddr *)0); 68336384Ssklower } 68436384Ssklower 68537469Ssklower #endif notdef 68636384Ssklower /* 68736384Ssklower * FUNCTION: iso_ck_addr 68836384Ssklower * 68936384Ssklower * PURPOSE: return true if the iso_addr passed is 69036384Ssklower * within the legal size limit for an iso address. 69136384Ssklower * 69236384Ssklower * RETURNS: true or false 69336384Ssklower * 69436384Ssklower * SIDE EFFECTS: 69536384Ssklower * 69636384Ssklower */ 69736384Ssklower iso_ck_addr(isoa) 69836384Ssklower struct iso_addr *isoa; /* address to check */ 69936384Ssklower { 70036384Ssklower return (isoa->isoa_len <= 20); 70136384Ssklower 70236384Ssklower } 70336384Ssklower 70437469Ssklower #ifdef notdef 70536384Ssklower /* 70636384Ssklower * FUNCTION: iso_eqtype 70736384Ssklower * 70836384Ssklower * PURPOSE: Determine if two iso addresses are of the same type. 70936384Ssklower * This is flaky. Really we should consider all type 47 addrs to be the 71036384Ssklower * same - but there do exist different structures for 47 addrs. 71136384Ssklower * Gosip adds a 3rd. 71236384Ssklower * 71336384Ssklower * RETURNS: true if the addresses are the same type 71436384Ssklower * 71536384Ssklower * SIDE EFFECTS: 71636384Ssklower * 71736384Ssklower * NOTES: By type, I mean rfc986, t37, or osinet 71836384Ssklower * 71936384Ssklower * This will first compare afis. If they match, then 72036384Ssklower * if the addr is not t37, the idis must be compared. 72136384Ssklower */ 72236384Ssklower iso_eqtype(isoaa, isoab) 72336384Ssklower struct iso_addr *isoaa; /* first addr to check */ 72436384Ssklower struct iso_addr *isoab; /* other addr to check */ 72536384Ssklower { 72636384Ssklower if (isoaa->isoa_afi == isoab->isoa_afi) { 72736384Ssklower if (isoaa->isoa_afi == AFI_37) 72836384Ssklower return(1); 72936384Ssklower else 73036384Ssklower return (!bcmp(&isoaa->isoa_u, &isoab->isoa_u, 2)); 73136384Ssklower } 73236384Ssklower return(0); 73336384Ssklower } 73437469Ssklower #endif notdef 73536384Ssklower /* 73637469Ssklower * FUNCTION: iso_localifa() 73736384Ssklower * 73837469Ssklower * PURPOSE: Find an interface addresss having a given destination 73937469Ssklower * or at least matching the net. 74036384Ssklower * 74136384Ssklower * RETURNS: ptr to an interface address 74236384Ssklower * 74336384Ssklower * SIDE EFFECTS: 74436384Ssklower * 74536384Ssklower * NOTES: 74636384Ssklower */ 74736384Ssklower struct iso_ifaddr * 74837469Ssklower iso_localifa(siso) 74937469Ssklower register struct sockaddr_iso *siso; 75036384Ssklower { 75136384Ssklower register struct iso_ifaddr *ia; 75237469Ssklower register char *cp1, *cp2, *cp3; 75337469Ssklower register struct ifnet *ifp; 75437469Ssklower struct iso_ifaddr *ia_maybe = 0; 75537469Ssklower /* 75637469Ssklower * We make one pass looking for both net matches and an exact 75737469Ssklower * dst addr. 75837469Ssklower */ 75937469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 76037469Ssklower if ((ifp = ia->ia_ifp) == 0 || ((ifp->if_flags & IFF_UP) == 0)) 76137469Ssklower continue; 76237469Ssklower if (ifp->if_flags & IFF_POINTOPOINT) { 76337469Ssklower if ((ia->ia_dstaddr.siso_family == AF_ISO) && 76437469Ssklower SAME_ISOADDR(&ia->ia_dstaddr, siso)) 76537469Ssklower return (ia); 76637469Ssklower else 76737469Ssklower if (SAME_ISOADDR(&ia->ia_addr, siso)) 76837469Ssklower ia_maybe = ia; 76937469Ssklower continue; 77037469Ssklower } 77137469Ssklower if (ia->ia_sockmask.siso_len) { 77237469Ssklower char *cplim = ia->ia_sockmask.siso_len + (char *)&ia->ia_sockmask; 77337469Ssklower cp1 = ia->ia_sockmask.siso_data; 77437469Ssklower cp2 = siso->siso_data; 77537469Ssklower cp3 = ia->ia_addr.siso_data; 77639936Ssklower while (cp1 < cplim) 77737469Ssklower if (*cp1++ & (*cp2++ ^ *cp3++)) 77837469Ssklower goto next; 77937469Ssklower ia_maybe = ia; 78037469Ssklower } 78137469Ssklower if (SAME_ISOADDR(&ia->ia_addr, siso)) 78237469Ssklower return ia; 78337469Ssklower next:; 78437469Ssklower } 78537469Ssklower return ia_maybe; 78636384Ssklower } 78736384Ssklower 78847272Ssklower #ifdef TPCONS 78956533Sbostic #include <netiso/cons.h> 79047272Ssklower #endif TPCONS 79136384Ssklower /* 79236384Ssklower * FUNCTION: iso_nlctloutput 79336384Ssklower * 79436384Ssklower * PURPOSE: Set options at the network level 79536384Ssklower * 79636384Ssklower * RETURNS: E* 79736384Ssklower * 79836384Ssklower * SIDE EFFECTS: 79936384Ssklower * 80036384Ssklower * NOTES: This could embody some of the functions of 80136384Ssklower * rclnp_ctloutput and cons_ctloutput. 80236384Ssklower */ 80336384Ssklower iso_nlctloutput(cmd, optname, pcb, m) 80436384Ssklower int cmd; /* command:set or get */ 80536384Ssklower int optname; /* option of interest */ 80636384Ssklower caddr_t pcb; /* nl pcb */ 80736384Ssklower struct mbuf *m; /* data for set, buffer for get */ 80836384Ssklower { 80936384Ssklower struct isopcb *isop = (struct isopcb *)pcb; 81036384Ssklower int error = 0; /* return value */ 81136384Ssklower caddr_t data; /* data for option */ 81236384Ssklower int data_len; /* data's length */ 81336384Ssklower 81436384Ssklower IFDEBUG(D_ISO) 81536384Ssklower printf("iso_nlctloutput: cmd %x, opt %x, pcb %x, m %x\n", 81636384Ssklower cmd, optname, pcb, m); 81736384Ssklower ENDDEBUG 81836384Ssklower 81936384Ssklower if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT)) 82036384Ssklower return(EOPNOTSUPP); 82136384Ssklower 82236384Ssklower data = mtod(m, caddr_t); 82336384Ssklower data_len = (m)->m_len; 82436384Ssklower 82536384Ssklower IFDEBUG(D_ISO) 82636384Ssklower printf("iso_nlctloutput: data is:\n"); 82736384Ssklower dump_buf(data, data_len); 82836384Ssklower ENDDEBUG 82936384Ssklower 83036384Ssklower switch (optname) { 83136384Ssklower 83247272Ssklower #ifdef TPCONS 83336384Ssklower case CONSOPT_X25CRUD: 83436384Ssklower if (cmd == PRCO_GETOPT) { 83536384Ssklower error = EOPNOTSUPP; 83636384Ssklower break; 83736384Ssklower } 83836384Ssklower 83936384Ssklower if (data_len > MAXX25CRUDLEN) { 84036384Ssklower error = EINVAL; 84136384Ssklower break; 84236384Ssklower } 84336384Ssklower 84436384Ssklower IFDEBUG(D_ISO) 84536384Ssklower printf("iso_nlctloutput: setting x25 crud\n"); 84636384Ssklower ENDDEBUG 84736384Ssklower 84837469Ssklower bcopy(data, (caddr_t)isop->isop_x25crud, (unsigned)data_len); 84936384Ssklower isop->isop_x25crud_len = data_len; 85036384Ssklower break; 85147272Ssklower #endif TPCONS 85236384Ssklower 85336384Ssklower default: 85436384Ssklower error = EOPNOTSUPP; 85536384Ssklower } 85650972Ssklower if (cmd == PRCO_SETOPT) 85750972Ssklower m_freem(m); 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