149268Sbostic /*- 249268Sbostic * Copyright (c) 1991 The Regents of the University of California. 349268Sbostic * All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*54823Ssklower * @(#)iso.c 7.18 (Berkeley) 07/09/92 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 4337469Ssklower #include "types.h" 4437469Ssklower #include "param.h" 4537469Ssklower #include "ioctl.h" 4637469Ssklower #include "mbuf.h" 4737469Ssklower #include "domain.h" 4837469Ssklower #include "protosw.h" 4937469Ssklower #include "socket.h" 5037469Ssklower #include "socketvar.h" 5137469Ssklower #include "errno.h" 5236384Ssklower 5336384Ssklower #include "../net/if.h" 5436384Ssklower #include "../net/route.h" 5536384Ssklower #include "../net/af.h" 5636384Ssklower 5737469Ssklower #include "iso.h" 5837469Ssklower #include "iso_var.h" 5937469Ssklower #include "iso_snpac.h" 6037469Ssklower #include "iso_pcb.h" 6137469Ssklower #include "clnp.h" 6237469Ssklower #include "argo_debug.h" 6336384Ssklower 6436384Ssklower #ifdef ISO 6536384Ssklower 6636384Ssklower int iso_interfaces = 0; /* number of external interfaces */ 6736384Ssklower extern struct ifnet loif; /* loopback interface */ 68*54823Ssklower int ether_output(); 69*54823Ssklower void llc_rtrequest(); 7036384Ssklower 7136384Ssklower /* 7236384Ssklower * FUNCTION: iso_addrmatch1 7336384Ssklower * 7436384Ssklower * PURPOSE: decide if the two iso_addrs passed are equal 7536384Ssklower * 7636384Ssklower * RETURNS: true if the addrs match, false if they do not 7736384Ssklower * 7836384Ssklower * SIDE EFFECTS: 7936384Ssklower * 8036384Ssklower * NOTES: 8136384Ssklower */ 8236384Ssklower iso_addrmatch1(isoaa, isoab) 8337469Ssklower register struct iso_addr *isoaa, *isoab; /* addresses to check */ 8436384Ssklower { 8537469Ssklower u_int compare_len; 8636384Ssklower 8736384Ssklower IFDEBUG(D_ROUTE) 8836384Ssklower printf("iso_addrmatch1: comparing lengths: %d to %d\n", isoaa->isoa_len, 8936384Ssklower isoab->isoa_len); 9036384Ssklower printf("a:\n"); 9137469Ssklower dump_buf(isoaa->isoa_genaddr, isoaa->isoa_len); 9236384Ssklower printf("b:\n"); 9337469Ssklower dump_buf(isoab->isoa_genaddr, isoab->isoa_len); 9436384Ssklower ENDDEBUG 9536384Ssklower 9636384Ssklower if ((compare_len = isoaa->isoa_len) != isoab->isoa_len) { 9736384Ssklower IFDEBUG(D_ROUTE) 9836384Ssklower printf("iso_addrmatch1: returning false because of lengths\n"); 9936384Ssklower ENDDEBUG 10036384Ssklower return 0; 10136384Ssklower } 10236384Ssklower 10337469Ssklower #ifdef notdef 10436384Ssklower /* TODO : generalize this to all afis with masks */ 10536384Ssklower if( isoaa->isoa_afi == AFI_37 ) { 10636384Ssklower /* must not compare 2 least significant digits, or for 10736384Ssklower * that matter, the DSP 10836384Ssklower */ 10936384Ssklower compare_len = ADDR37_IDI_LEN - 1; 11036384Ssklower } 11137469Ssklower #endif 11236384Ssklower 11336384Ssklower IFDEBUG(D_ROUTE) 11436384Ssklower int i; 11536384Ssklower char *a, *b; 11636384Ssklower 11737469Ssklower a = isoaa->isoa_genaddr; 11837469Ssklower b = isoab->isoa_genaddr; 11936384Ssklower 12036384Ssklower for (i=0; i<compare_len; i++) { 12136384Ssklower printf("<%x=%x>", a[i]&0xff, b[i]&0xff); 12236384Ssklower if (a[i] != b[i]) { 12336384Ssklower printf("\naddrs are not equal at byte %d\n", i); 12436384Ssklower return(0); 12536384Ssklower } 12636384Ssklower } 12736384Ssklower printf("\n"); 12836384Ssklower printf("addrs are equal\n"); 12936384Ssklower return (1); 13036384Ssklower ENDDEBUG 13137469Ssklower return (!bcmp(isoaa->isoa_genaddr, isoab->isoa_genaddr, compare_len)); 13236384Ssklower } 13336384Ssklower 13436384Ssklower /* 13536384Ssklower * FUNCTION: iso_addrmatch 13636384Ssklower * 13736384Ssklower * PURPOSE: decide if the two sockadrr_isos passed are equal 13836384Ssklower * 13936384Ssklower * RETURNS: true if the addrs match, false if they do not 14036384Ssklower * 14136384Ssklower * SIDE EFFECTS: 14236384Ssklower * 14336384Ssklower * NOTES: 14436384Ssklower */ 14536384Ssklower iso_addrmatch(sisoa, sisob) 14636384Ssklower struct sockaddr_iso *sisoa, *sisob; /* addresses to check */ 14736384Ssklower { 14836384Ssklower return(iso_addrmatch1(&sisoa->siso_addr, &sisob->siso_addr)); 14936384Ssklower } 15037469Ssklower #ifdef notdef 15136384Ssklower /* 15236384Ssklower * FUNCTION: iso_netmatch 15336384Ssklower * 15436384Ssklower * PURPOSE: similar to iso_addrmatch but takes sockaddr_iso 15536384Ssklower * as argument. 15636384Ssklower * 15736384Ssklower * RETURNS: true if same net, false if not 15836384Ssklower * 15936384Ssklower * SIDE EFFECTS: 16036384Ssklower * 16136384Ssklower * NOTES: 16236384Ssklower */ 16336384Ssklower iso_netmatch(sisoa, sisob) 16436384Ssklower struct sockaddr_iso *sisoa, *sisob; 16536384Ssklower { 16636384Ssklower u_char bufa[sizeof(struct sockaddr_iso)]; 16736384Ssklower u_char bufb[sizeof(struct sockaddr_iso)]; 16836384Ssklower register int lena, lenb; 16936384Ssklower 17036384Ssklower lena = iso_netof(&sisoa->siso_addr, bufa); 17136384Ssklower lenb = iso_netof(&sisob->siso_addr, bufb); 17236384Ssklower 17336384Ssklower IFDEBUG(D_ROUTE) 17436384Ssklower printf("iso_netmatch: comparing lengths: %d to %d\n", lena, lenb); 17536384Ssklower printf("a:\n"); 17636384Ssklower dump_buf(bufa, lena); 17736384Ssklower printf("b:\n"); 17836384Ssklower dump_buf(bufb, lenb); 17936384Ssklower ENDDEBUG 18036384Ssklower 18136384Ssklower return ((lena == lenb) && (!bcmp(bufa, bufb, lena))); 18236384Ssklower } 18337469Ssklower #endif notdef 18436384Ssklower 18536384Ssklower /* 18636384Ssklower * FUNCTION: iso_hashchar 18736384Ssklower * 18836384Ssklower * PURPOSE: Hash all character in the buffer specified into 18936384Ssklower * a long. Return the long. 19036384Ssklower * 19136384Ssklower * RETURNS: The hash value. 19236384Ssklower * 19336384Ssklower * SIDE EFFECTS: 19436384Ssklower * 19536384Ssklower * NOTES: The hash is achieved by exclusive ORing 4 byte 19636384Ssklower * quantities. 19736384Ssklower */ 19836384Ssklower u_long 19936384Ssklower iso_hashchar(buf, len) 20036384Ssklower register caddr_t buf; /* buffer to pack from */ 20136384Ssklower register int len; /* length of buffer */ 20236384Ssklower { 20336384Ssklower register u_long h = 0; 20436384Ssklower register int i; 20536384Ssklower 20636384Ssklower for (i=0; i<len; i+=4) { 20736384Ssklower register u_long l = 0; 20836384Ssklower 20936384Ssklower if ((len - i) < 4) { 21036384Ssklower /* buffer not multiple of 4 */ 21136384Ssklower switch (len - i) { 21236384Ssklower case 3: 21336384Ssklower l |= buf[i+2] << 8; 21436384Ssklower case 2: 21536384Ssklower l |= buf[i+1] << 16; 21636384Ssklower case 1: 21736384Ssklower l |= buf[i] << 24; 21836384Ssklower break; 21936384Ssklower default: 22036384Ssklower printf("iso_hashchar: unexpected value x%x\n", len - i); 22136384Ssklower break; 22236384Ssklower } 22336384Ssklower } else { 22436384Ssklower l |= buf[i] << 24; 22536384Ssklower l |= buf[i+1] << 16; 22636384Ssklower l |= buf[i+2] << 8; 22736384Ssklower l |= buf[i+3]; 22836384Ssklower } 22936384Ssklower 23036384Ssklower h ^= l; 23136384Ssklower } 23236384Ssklower 23336384Ssklower h ^= (u_long) (len % 4); 23436384Ssklower 23536384Ssklower return(h); 23636384Ssklower } 23737469Ssklower #ifdef notdef 23836384Ssklower /* 23936384Ssklower * FUNCTION: iso_hash 24036384Ssklower * 24136384Ssklower * PURPOSE: Fill in fields of afhash structure based upon addr passed. 24236384Ssklower * 24336384Ssklower * RETURNS: none 24436384Ssklower * 24536384Ssklower * SIDE EFFECTS: 24636384Ssklower * 24736384Ssklower * NOTES: 24836384Ssklower */ 24936384Ssklower iso_hash(siso, hp) 25036384Ssklower struct sockaddr_iso *siso; /* address to perform hash on */ 25136384Ssklower struct afhash *hp; /* RETURN: hash info here */ 25236384Ssklower { 25336384Ssklower u_long buf[sizeof(struct sockaddr_iso)+1/4]; 25436384Ssklower register int bufsize; 25536384Ssklower 25636384Ssklower 25736384Ssklower bzero(buf, sizeof(buf)); 25836384Ssklower 25936384Ssklower bufsize = iso_netof(&siso->siso_addr, buf); 26036384Ssklower hp->afh_nethash = iso_hashchar((caddr_t)buf, bufsize); 26136384Ssklower 26236384Ssklower IFDEBUG(D_ROUTE) 26336384Ssklower printf("iso_hash: iso_netof: bufsize = %d\n", bufsize); 26436384Ssklower ENDDEBUG 26536384Ssklower 26636384Ssklower hp->afh_hosthash = iso_hashchar((caddr_t)&siso->siso_addr, 26736384Ssklower siso->siso_addr.isoa_len); 26836384Ssklower 26936384Ssklower IFDEBUG(D_ROUTE) 27036384Ssklower printf("iso_hash: %s: nethash = x%x, hosthash = x%x\n", 27136384Ssklower clnp_iso_addrp(&siso->siso_addr), hp->afh_nethash, 27236384Ssklower hp->afh_hosthash); 27336384Ssklower ENDDEBUG 27436384Ssklower } 27536384Ssklower /* 27636384Ssklower * FUNCTION: iso_netof 27736384Ssklower * 27836384Ssklower * PURPOSE: Extract the network portion of the iso address. 27936384Ssklower * The network portion of the iso address varies depending 28036384Ssklower * on the type of address. The network portion of the 28136384Ssklower * address will include the IDP. The network portion is: 28236384Ssklower * 28336384Ssklower * TYPE DESC 28436384Ssklower * t37 The AFI and x.121 (IDI) 28536384Ssklower * osinet The AFI, orgid, snetid 28636384Ssklower * rfc986 The AFI, vers and network part of 28736384Ssklower * internet address. 28836384Ssklower * 28936384Ssklower * RETURNS: number of bytes placed into buf. 29036384Ssklower * 29136384Ssklower * SIDE EFFECTS: 29236384Ssklower * 29336384Ssklower * NOTES: Buf is assumed to be big enough 29436384Ssklower */ 29536384Ssklower iso_netof(isoa, buf) 29636384Ssklower struct iso_addr *isoa; /* address */ 29736384Ssklower caddr_t buf; /* RESULT: network portion of address here */ 29836384Ssklower { 29936384Ssklower u_int len = 1; /* length of afi */ 30036384Ssklower 30136384Ssklower switch (isoa->isoa_afi) { 30236384Ssklower case AFI_37: 30336384Ssklower /* 30436384Ssklower * Due to classic x.25 tunnel vision, there is no 30536384Ssklower * net portion of an x.121 address. For our purposes 30636384Ssklower * the AFI will do, so that all x.25 -type addresses 30736384Ssklower * map to the single x.25 SNPA. (Cannot have more than 30836384Ssklower * one, obviously). 30936384Ssklower */ 31036384Ssklower 31136384Ssklower break; 31236384Ssklower 31336384Ssklower /* case AFI_OSINET:*/ 31436384Ssklower case AFI_RFC986: { 31536384Ssklower u_short idi; /* value of idi */ 31636384Ssklower 31736384Ssklower /* osinet and rfc986 have idi in the same place */ 31836384Ssklower CTOH(isoa->rfc986_idi[0], isoa->rfc986_idi[1], idi); 31936384Ssklower 32036384Ssklower if (idi == IDI_OSINET) 32136384Ssklower /* 32236384Ssklower * Network portion of OSINET address can only be the IDI. Clearly, 32336384Ssklower * with one x25 interface, one could get to several orgids, and 32436384Ssklower * several snetids. 32536384Ssklower len += (ADDROSINET_IDI_LEN + OVLOSINET_ORGID_LEN + 32636384Ssklower OVLOSINET_SNETID_LEN); 32736384Ssklower */ 32836384Ssklower len += ADDROSINET_IDI_LEN; 32936384Ssklower else if (idi == IDI_RFC986) { 33036384Ssklower u_long inetaddr; 33136384Ssklower struct ovl_rfc986 *o986 = (struct ovl_rfc986 *)isoa; 33236384Ssklower 33336384Ssklower /* bump len to include idi and version (1 byte) */ 33436384Ssklower len += ADDRRFC986_IDI_LEN + 1; 33536384Ssklower 33636384Ssklower /* get inet addr long aligned */ 33736384Ssklower bcopy(o986->o986_inetaddr, &inetaddr, sizeof(inetaddr)); 33836384Ssklower inetaddr = ntohl(inetaddr); /* convert to host byte order */ 33936384Ssklower 34036384Ssklower IFDEBUG(D_ROUTE) 34136384Ssklower printf("iso_netof: isoa "); 34236384Ssklower dump_buf(isoa, sizeof(*isoa)); 34336384Ssklower printf("iso_netof: inetaddr 0x%x ", inetaddr); 34436384Ssklower ENDDEBUG 34536384Ssklower 34636384Ssklower /* bump len by size of network portion of inet address */ 34736384Ssklower if (IN_CLASSA(inetaddr)) { 34836384Ssklower len += 4-IN_CLASSA_NSHIFT/8; 34936384Ssklower IFDEBUG(D_ROUTE) 35036384Ssklower printf("iso_netof: class A net len is now %d\n", len); 35136384Ssklower ENDDEBUG 35236384Ssklower } else if (IN_CLASSB(inetaddr)) { 35336384Ssklower len += 4-IN_CLASSB_NSHIFT/8; 35436384Ssklower IFDEBUG(D_ROUTE) 35536384Ssklower printf("iso_netof: class B net len is now %d\n", len); 35636384Ssklower ENDDEBUG 35736384Ssklower } else { 35836384Ssklower len += 4-IN_CLASSC_NSHIFT/8; 35936384Ssklower IFDEBUG(D_ROUTE) 36036384Ssklower printf("iso_netof: class C net len is now %d\n", len); 36136384Ssklower ENDDEBUG 36236384Ssklower } 36336384Ssklower } else 36436384Ssklower len = 0; 36536384Ssklower } break; 36636384Ssklower 36736384Ssklower default: 36836384Ssklower len = 0; 36936384Ssklower } 37036384Ssklower 37136384Ssklower bcopy((caddr_t)isoa, buf, len); 37236384Ssklower IFDEBUG(D_ROUTE) 37336384Ssklower printf("in_netof: isoa "); 37436384Ssklower dump_buf(isoa, len); 37536384Ssklower printf("in_netof: net "); 37636384Ssklower dump_buf(buf, len); 37736384Ssklower ENDDEBUG 37836384Ssklower return len; 37936384Ssklower } 38037469Ssklower #endif notdef 38136384Ssklower /* 38237469Ssklower * Generic iso control operations (ioctl's). 38337469Ssklower * Ifp is 0 if not an interface-specific ioctl. 38436384Ssklower */ 38537469Ssklower /* ARGSUSED */ 38636384Ssklower iso_control(so, cmd, data, ifp) 38737469Ssklower struct socket *so; 38837469Ssklower int cmd; 38937469Ssklower caddr_t data; 39037469Ssklower register struct ifnet *ifp; 39136384Ssklower { 39237469Ssklower register struct iso_ifreq *ifr = (struct iso_ifreq *)data; 39337469Ssklower register struct iso_ifaddr *ia = 0; 39437469Ssklower register struct ifaddr *ifa; 39537469Ssklower struct iso_ifaddr *oia; 39637469Ssklower struct iso_aliasreq *ifra = (struct iso_aliasreq *)data; 39737469Ssklower int error, hostIsNew, maskIsNew; 39836384Ssklower 39937469Ssklower /* 40037469Ssklower * Find address for this interface, if it exists. 40137469Ssklower */ 40237469Ssklower if (ifp) 40337469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) 40437469Ssklower if (ia->ia_ifp == ifp) 40537469Ssklower break; 40636384Ssklower 40736384Ssklower switch (cmd) { 40837469Ssklower 40937469Ssklower case SIOCAIFADDR_ISO: 41037469Ssklower case SIOCDIFADDR_ISO: 41137469Ssklower if (ifra->ifra_addr.siso_family == AF_ISO) 41237469Ssklower for (oia = ia; ia; ia = ia->ia_next) { 41337469Ssklower if (ia->ia_ifp == ifp && 41437469Ssklower SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr)) 41537469Ssklower break; 41637469Ssklower } 41750232Ssklower if ((so->so_state & SS_PRIV) == 0) 41850232Ssklower return (EPERM); 41936384Ssklower if (ifp == 0) 42037469Ssklower panic("iso_control"); 42137469Ssklower if (ia == (struct iso_ifaddr *)0) { 42237469Ssklower struct iso_ifaddr *nia; 42337469Ssklower if (cmd == SIOCDIFADDR_ISO) 42437469Ssklower return (EADDRNOTAVAIL); 42537469Ssklower MALLOC(nia, struct iso_ifaddr *, sizeof(*nia), 42637469Ssklower M_IFADDR, M_WAITOK); 42737469Ssklower if (nia == (struct iso_ifaddr *)0) 42837469Ssklower return (ENOBUFS); 42937469Ssklower bzero((caddr_t)nia, sizeof(*nia)); 43037469Ssklower if (ia = iso_ifaddr) { 43137469Ssklower for ( ; ia->ia_next; ia = ia->ia_next) 43237469Ssklower ; 43337469Ssklower ia->ia_next = nia; 43437469Ssklower } else 43537469Ssklower iso_ifaddr = nia; 43637469Ssklower ia = nia; 43737469Ssklower if (ifa = ifp->if_addrlist) { 43837469Ssklower for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 43937469Ssklower ; 44037469Ssklower ifa->ifa_next = (struct ifaddr *) ia; 44137469Ssklower } else 44237469Ssklower ifp->if_addrlist = (struct ifaddr *) ia; 44337469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 44437469Ssklower ia->ia_ifa.ifa_dstaddr 44537469Ssklower = (struct sockaddr *)&ia->ia_dstaddr; 44637469Ssklower ia->ia_ifa.ifa_netmask 44737469Ssklower = (struct sockaddr *)&ia->ia_sockmask; 44837469Ssklower ia->ia_ifp = ifp; 44937469Ssklower if (ifp != &loif) 45037469Ssklower iso_interfaces++; 45137469Ssklower } 45237469Ssklower break; 45336384Ssklower 45437469Ssklower #define cmdbyte(x) (((x) >> 8) & 0xff) 45537469Ssklower default: 45637469Ssklower if (cmdbyte(cmd) == 'a') 45750232Ssklower return (snpac_ioctl(so, cmd, data)); 45837469Ssklower if (ia == (struct iso_ifaddr *)0) 45937469Ssklower return (EADDRNOTAVAIL); 46037469Ssklower break; 46137469Ssklower } 46237469Ssklower switch (cmd) { 46336384Ssklower 46437469Ssklower case SIOCGIFADDR_ISO: 46537469Ssklower ifr->ifr_Addr = ia->ia_addr; 46637469Ssklower break; 46736384Ssklower 46837469Ssklower case SIOCGIFDSTADDR_ISO: 46937469Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 47037469Ssklower return (EINVAL); 47137469Ssklower ifr->ifr_Addr = ia->ia_dstaddr; 47237469Ssklower break; 47336384Ssklower 47437469Ssklower case SIOCGIFNETMASK_ISO: 47537469Ssklower ifr->ifr_Addr = ia->ia_sockmask; 47637469Ssklower break; 47736384Ssklower 47837469Ssklower case SIOCAIFADDR_ISO: 47943428Ssklower maskIsNew = 0; hostIsNew = 1; error = 0; 48037469Ssklower if (ia->ia_addr.siso_family == AF_ISO) { 48137469Ssklower if (ifra->ifra_addr.siso_len == 0) { 48237469Ssklower ifra->ifra_addr = ia->ia_addr; 48337469Ssklower hostIsNew = 0; 48437469Ssklower } else if (SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr)) 48537469Ssklower hostIsNew = 0; 48637469Ssklower } 48737469Ssklower if (ifra->ifra_mask.siso_len) { 48837469Ssklower iso_ifscrub(ifp, ia); 48937469Ssklower ia->ia_sockmask = ifra->ifra_mask; 49037469Ssklower maskIsNew = 1; 49137469Ssklower } 49237469Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) && 49337469Ssklower (ifra->ifra_dstaddr.siso_family == AF_ISO)) { 49437469Ssklower iso_ifscrub(ifp, ia); 49537469Ssklower ia->ia_dstaddr = ifra->ifra_dstaddr; 49637469Ssklower maskIsNew = 1; /* We lie; but the effect's the same */ 49737469Ssklower } 49837469Ssklower if (ifra->ifra_addr.siso_family == AF_ISO && 49937469Ssklower (hostIsNew || maskIsNew)) { 50037469Ssklower error = iso_ifinit(ifp, ia, &ifra->ifra_addr, 0); 50137469Ssklower } 50237469Ssklower if (ifra->ifra_snpaoffset) 50337469Ssklower ia->ia_snpaoffset = ifra->ifra_snpaoffset; 50437469Ssklower return (error); 50537469Ssklower 50637469Ssklower case SIOCDIFADDR_ISO: 50737469Ssklower iso_ifscrub(ifp, ia); 50837469Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 50937469Ssklower ifp->if_addrlist = ifa->ifa_next; 51037469Ssklower else { 51137469Ssklower while (ifa->ifa_next && 51237469Ssklower (ifa->ifa_next != (struct ifaddr *)ia)) 51337469Ssklower ifa = ifa->ifa_next; 51437469Ssklower if (ifa->ifa_next) 51537469Ssklower ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 51637469Ssklower else 51737469Ssklower printf("Couldn't unlink isoifaddr from ifp\n"); 51837469Ssklower } 51937469Ssklower oia = ia; 52037469Ssklower if (oia == (ia = iso_ifaddr)) { 52137469Ssklower iso_ifaddr = ia->ia_next; 52237469Ssklower } else { 52337469Ssklower while (ia->ia_next && (ia->ia_next != oia)) { 52437469Ssklower ia = ia->ia_next; 52536384Ssklower } 52637469Ssklower if (ia->ia_next) 52737469Ssklower ia->ia_next = oia->ia_next; 52837469Ssklower else 52937469Ssklower printf("Didn't unlink isoifadr from list\n"); 53036384Ssklower } 53152030Ssklower IFAFREE((&oia->ia_ifa)); 53237469Ssklower break; 53336384Ssklower 53436384Ssklower default: 53536384Ssklower if (ifp == 0 || ifp->if_ioctl == 0) 53636384Ssklower return (EOPNOTSUPP); 53736384Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data)); 53836384Ssklower } 53937469Ssklower return (0); 54036384Ssklower } 54136384Ssklower 54237469Ssklower /* 54337469Ssklower * Delete any existing route for an interface. 54437469Ssklower */ 54537469Ssklower iso_ifscrub(ifp, ia) 54637469Ssklower register struct ifnet *ifp; 54737469Ssklower register struct iso_ifaddr *ia; 54837469Ssklower { 54943333Ssklower int nsellength = ia->ia_addr.siso_tlen; 55037469Ssklower if ((ia->ia_flags & IFA_ROUTE) == 0) 55137469Ssklower return; 55243333Ssklower ia->ia_addr.siso_tlen = 0; 55337469Ssklower if (ifp->if_flags & IFF_LOOPBACK) 55437469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 55537469Ssklower else if (ifp->if_flags & IFF_POINTOPOINT) 55637469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 55737469Ssklower else { 55837469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 55937469Ssklower } 56043333Ssklower ia->ia_addr.siso_tlen = nsellength; 56137469Ssklower ia->ia_flags &= ~IFA_ROUTE; 56237469Ssklower } 56337469Ssklower 56437469Ssklower /* 56537469Ssklower * Initialize an interface's internet address 56637469Ssklower * and routing table entry. 56737469Ssklower */ 56837469Ssklower iso_ifinit(ifp, ia, siso, scrub) 56937469Ssklower register struct ifnet *ifp; 57037469Ssklower register struct iso_ifaddr *ia; 57137469Ssklower struct sockaddr_iso *siso; 57237469Ssklower { 57337469Ssklower struct sockaddr_iso oldaddr; 57443333Ssklower int s = splimp(), error, nsellength; 57537469Ssklower 57637469Ssklower oldaddr = ia->ia_addr; 57737469Ssklower ia->ia_addr = *siso; 57837469Ssklower /* 57937469Ssklower * Give the interface a chance to initialize 58037469Ssklower * if this is its first address, 58137469Ssklower * and to validate the address if necessary. 58237469Ssklower */ 583*54823Ssklower if (ifp->if_ioctl && 584*54823Ssklower (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) { 58537469Ssklower splx(s); 58637469Ssklower ia->ia_addr = oldaddr; 58737469Ssklower return (error); 58837469Ssklower } 58937469Ssklower if (scrub) { 59037469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 59137469Ssklower iso_ifscrub(ifp, ia); 59237469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 59337469Ssklower } 59443333Ssklower /* XXX -- The following is here temporarily out of laziness 59543333Ssklower in not changing every ethernet driver's if_ioctl routine */ 59643333Ssklower if (ifp->if_output == ether_output) { 59743333Ssklower ia->ia_ifa.ifa_rtrequest = llc_rtrequest; 59843333Ssklower ia->ia_ifa.ifa_flags |= RTF_CLONING; 59943333Ssklower } 60037469Ssklower /* 60137469Ssklower * Add route for the network. 60237469Ssklower */ 60343333Ssklower nsellength = ia->ia_addr.siso_tlen; 60443333Ssklower ia->ia_addr.siso_tlen = 0; 60537469Ssklower if (ifp->if_flags & IFF_LOOPBACK) { 60637469Ssklower ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 60740894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 60837469Ssklower } else if (ifp->if_flags & IFF_POINTOPOINT && 60937469Ssklower ia->ia_dstaddr.siso_family == AF_ISO) 61040894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 61137469Ssklower else { 61240894Ssklower rt_maskedcopy(ia->ia_ifa.ifa_addr, ia->ia_ifa.ifa_dstaddr, 61340894Ssklower ia->ia_ifa.ifa_netmask); 61449936Ssklower ia->ia_dstaddr.siso_nlen = 61549936Ssklower min(ia->ia_addr.siso_nlen, (ia->ia_sockmask.siso_len - 6)); 61640894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP); 61737469Ssklower } 61843333Ssklower ia->ia_addr.siso_tlen = nsellength; 61937469Ssklower ia->ia_flags |= IFA_ROUTE; 62037469Ssklower splx(s); 62140894Ssklower return (error); 62237469Ssklower } 62337469Ssklower #ifdef notdef 62437469Ssklower 62536384Ssklower struct ifaddr * 62636384Ssklower iso_ifwithidi(addr) 62736384Ssklower register struct sockaddr *addr; 62836384Ssklower { 62936384Ssklower register struct ifnet *ifp; 63036384Ssklower register struct ifaddr *ifa; 63136384Ssklower register u_int af = addr->sa_family; 63236384Ssklower 63336384Ssklower if (af != AF_ISO) 63436384Ssklower return (0); 63536384Ssklower IFDEBUG(D_ROUTE) 63636384Ssklower printf(">>> iso_ifwithidi addr\n"); 63736384Ssklower dump_isoaddr( (struct sockaddr_iso *)(addr)); 63836384Ssklower printf("\n"); 63936384Ssklower ENDDEBUG 64036384Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) { 64136384Ssklower IFDEBUG(D_ROUTE) 64236384Ssklower printf("iso_ifwithidi ifnet %s\n", ifp->if_name); 64336384Ssklower ENDDEBUG 64436384Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 64536384Ssklower IFDEBUG(D_ROUTE) 64636384Ssklower printf("iso_ifwithidi address "); 64737469Ssklower dump_isoaddr( (struct sockaddr_iso *)(ifa->ifa_addr)); 64836384Ssklower ENDDEBUG 64937469Ssklower if (ifa->ifa_addr->sa_family != addr->sa_family) 65036384Ssklower continue; 65136384Ssklower 65236384Ssklower #define IFA_SIS(ifa)\ 65337469Ssklower ((struct sockaddr_iso *)((ifa)->ifa_addr)) 65436384Ssklower 65536384Ssklower IFDEBUG(D_ROUTE) 65636384Ssklower printf(" af same, args to iso_eqtype:\n"); 65736384Ssklower printf("0x%x ", IFA_SIS(ifa)->siso_addr); 65836384Ssklower printf(" 0x%x\n", 65936384Ssklower &(((struct sockaddr_iso *)addr)->siso_addr)); 66036384Ssklower ENDDEBUG 66136384Ssklower 66236384Ssklower if (iso_eqtype(&(IFA_SIS(ifa)->siso_addr), 66336384Ssklower &(((struct sockaddr_iso *)addr)->siso_addr))) { 66436384Ssklower IFDEBUG(D_ROUTE) 66536384Ssklower printf("ifa_ifwithidi: ifa found\n"); 66636384Ssklower ENDDEBUG 66736384Ssklower return (ifa); 66836384Ssklower } 66936384Ssklower IFDEBUG(D_ROUTE) 67036384Ssklower printf(" iso_eqtype failed\n"); 67136384Ssklower ENDDEBUG 67236384Ssklower } 67336384Ssklower } 67436384Ssklower return ((struct ifaddr *)0); 67536384Ssklower } 67636384Ssklower 67737469Ssklower #endif notdef 67836384Ssklower /* 67936384Ssklower * FUNCTION: iso_ck_addr 68036384Ssklower * 68136384Ssklower * PURPOSE: return true if the iso_addr passed is 68236384Ssklower * within the legal size limit for an iso address. 68336384Ssklower * 68436384Ssklower * RETURNS: true or false 68536384Ssklower * 68636384Ssklower * SIDE EFFECTS: 68736384Ssklower * 68836384Ssklower */ 68936384Ssklower iso_ck_addr(isoa) 69036384Ssklower struct iso_addr *isoa; /* address to check */ 69136384Ssklower { 69236384Ssklower return (isoa->isoa_len <= 20); 69336384Ssklower 69436384Ssklower } 69536384Ssklower 69637469Ssklower #ifdef notdef 69736384Ssklower /* 69836384Ssklower * FUNCTION: iso_eqtype 69936384Ssklower * 70036384Ssklower * PURPOSE: Determine if two iso addresses are of the same type. 70136384Ssklower * This is flaky. Really we should consider all type 47 addrs to be the 70236384Ssklower * same - but there do exist different structures for 47 addrs. 70336384Ssklower * Gosip adds a 3rd. 70436384Ssklower * 70536384Ssklower * RETURNS: true if the addresses are the same type 70636384Ssklower * 70736384Ssklower * SIDE EFFECTS: 70836384Ssklower * 70936384Ssklower * NOTES: By type, I mean rfc986, t37, or osinet 71036384Ssklower * 71136384Ssklower * This will first compare afis. If they match, then 71236384Ssklower * if the addr is not t37, the idis must be compared. 71336384Ssklower */ 71436384Ssklower iso_eqtype(isoaa, isoab) 71536384Ssklower struct iso_addr *isoaa; /* first addr to check */ 71636384Ssklower struct iso_addr *isoab; /* other addr to check */ 71736384Ssklower { 71836384Ssklower if (isoaa->isoa_afi == isoab->isoa_afi) { 71936384Ssklower if (isoaa->isoa_afi == AFI_37) 72036384Ssklower return(1); 72136384Ssklower else 72236384Ssklower return (!bcmp(&isoaa->isoa_u, &isoab->isoa_u, 2)); 72336384Ssklower } 72436384Ssklower return(0); 72536384Ssklower } 72637469Ssklower #endif notdef 72736384Ssklower /* 72837469Ssklower * FUNCTION: iso_localifa() 72936384Ssklower * 73037469Ssklower * PURPOSE: Find an interface addresss having a given destination 73137469Ssklower * or at least matching the net. 73236384Ssklower * 73336384Ssklower * RETURNS: ptr to an interface address 73436384Ssklower * 73536384Ssklower * SIDE EFFECTS: 73636384Ssklower * 73736384Ssklower * NOTES: 73836384Ssklower */ 73936384Ssklower struct iso_ifaddr * 74037469Ssklower iso_localifa(siso) 74137469Ssklower register struct sockaddr_iso *siso; 74236384Ssklower { 74336384Ssklower register struct iso_ifaddr *ia; 74437469Ssklower register char *cp1, *cp2, *cp3; 74537469Ssklower register struct ifnet *ifp; 74637469Ssklower struct iso_ifaddr *ia_maybe = 0; 74737469Ssklower /* 74837469Ssklower * We make one pass looking for both net matches and an exact 74937469Ssklower * dst addr. 75037469Ssklower */ 75137469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 75237469Ssklower if ((ifp = ia->ia_ifp) == 0 || ((ifp->if_flags & IFF_UP) == 0)) 75337469Ssklower continue; 75437469Ssklower if (ifp->if_flags & IFF_POINTOPOINT) { 75537469Ssklower if ((ia->ia_dstaddr.siso_family == AF_ISO) && 75637469Ssklower SAME_ISOADDR(&ia->ia_dstaddr, siso)) 75737469Ssklower return (ia); 75837469Ssklower else 75937469Ssklower if (SAME_ISOADDR(&ia->ia_addr, siso)) 76037469Ssklower ia_maybe = ia; 76137469Ssklower continue; 76237469Ssklower } 76337469Ssklower if (ia->ia_sockmask.siso_len) { 76437469Ssklower char *cplim = ia->ia_sockmask.siso_len + (char *)&ia->ia_sockmask; 76537469Ssklower cp1 = ia->ia_sockmask.siso_data; 76637469Ssklower cp2 = siso->siso_data; 76737469Ssklower cp3 = ia->ia_addr.siso_data; 76839936Ssklower while (cp1 < cplim) 76937469Ssklower if (*cp1++ & (*cp2++ ^ *cp3++)) 77037469Ssklower goto next; 77137469Ssklower ia_maybe = ia; 77237469Ssklower } 77337469Ssklower if (SAME_ISOADDR(&ia->ia_addr, siso)) 77437469Ssklower return ia; 77537469Ssklower next:; 77637469Ssklower } 77737469Ssklower return ia_maybe; 77836384Ssklower } 77936384Ssklower 78047272Ssklower #ifdef TPCONS 78136384Ssklower #include "cons.h" 78247272Ssklower #endif TPCONS 78336384Ssklower /* 78436384Ssklower * FUNCTION: iso_nlctloutput 78536384Ssklower * 78636384Ssklower * PURPOSE: Set options at the network level 78736384Ssklower * 78836384Ssklower * RETURNS: E* 78936384Ssklower * 79036384Ssklower * SIDE EFFECTS: 79136384Ssklower * 79236384Ssklower * NOTES: This could embody some of the functions of 79336384Ssklower * rclnp_ctloutput and cons_ctloutput. 79436384Ssklower */ 79536384Ssklower iso_nlctloutput(cmd, optname, pcb, m) 79636384Ssklower int cmd; /* command:set or get */ 79736384Ssklower int optname; /* option of interest */ 79836384Ssklower caddr_t pcb; /* nl pcb */ 79936384Ssklower struct mbuf *m; /* data for set, buffer for get */ 80036384Ssklower { 80136384Ssklower struct isopcb *isop = (struct isopcb *)pcb; 80236384Ssklower int error = 0; /* return value */ 80336384Ssklower caddr_t data; /* data for option */ 80436384Ssklower int data_len; /* data's length */ 80536384Ssklower 80636384Ssklower IFDEBUG(D_ISO) 80736384Ssklower printf("iso_nlctloutput: cmd %x, opt %x, pcb %x, m %x\n", 80836384Ssklower cmd, optname, pcb, m); 80936384Ssklower ENDDEBUG 81036384Ssklower 81136384Ssklower if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT)) 81236384Ssklower return(EOPNOTSUPP); 81336384Ssklower 81436384Ssklower data = mtod(m, caddr_t); 81536384Ssklower data_len = (m)->m_len; 81636384Ssklower 81736384Ssklower IFDEBUG(D_ISO) 81836384Ssklower printf("iso_nlctloutput: data is:\n"); 81936384Ssklower dump_buf(data, data_len); 82036384Ssklower ENDDEBUG 82136384Ssklower 82236384Ssklower switch (optname) { 82336384Ssklower 82447272Ssklower #ifdef TPCONS 82536384Ssklower case CONSOPT_X25CRUD: 82636384Ssklower if (cmd == PRCO_GETOPT) { 82736384Ssklower error = EOPNOTSUPP; 82836384Ssklower break; 82936384Ssklower } 83036384Ssklower 83136384Ssklower if (data_len > MAXX25CRUDLEN) { 83236384Ssklower error = EINVAL; 83336384Ssklower break; 83436384Ssklower } 83536384Ssklower 83636384Ssklower IFDEBUG(D_ISO) 83736384Ssklower printf("iso_nlctloutput: setting x25 crud\n"); 83836384Ssklower ENDDEBUG 83936384Ssklower 84037469Ssklower bcopy(data, (caddr_t)isop->isop_x25crud, (unsigned)data_len); 84136384Ssklower isop->isop_x25crud_len = data_len; 84236384Ssklower break; 84347272Ssklower #endif TPCONS 84436384Ssklower 84536384Ssklower default: 84636384Ssklower error = EOPNOTSUPP; 84736384Ssklower } 84850972Ssklower if (cmd == PRCO_SETOPT) 84950972Ssklower m_freem(m); 85036384Ssklower return error; 85136384Ssklower } 85236384Ssklower #endif ISO 85336384Ssklower 85436384Ssklower #ifdef ARGO_DEBUG 85536384Ssklower 85636384Ssklower /* 85736384Ssklower * FUNCTION: dump_isoaddr 85836384Ssklower * 85936384Ssklower * PURPOSE: debugging 86036384Ssklower * 86136384Ssklower * RETURNS: nada 86236384Ssklower * 86336384Ssklower */ 86436384Ssklower dump_isoaddr(s) 86536384Ssklower struct sockaddr_iso *s; 86636384Ssklower { 86737469Ssklower char *clnp_saddr_isop(); 86836384Ssklower register int i; 86936384Ssklower 87036384Ssklower if( s->siso_family == AF_ISO) { 87137469Ssklower printf("ISO address: suffixlen %d, %s\n", 87238841Ssklower s->siso_tlen, clnp_saddr_isop(s)); 87336384Ssklower } else if( s->siso_family == AF_INET) { 87436384Ssklower /* hack */ 87536384Ssklower struct sockaddr_in *sin = (struct sockaddr_in *)s; 87636384Ssklower 87736384Ssklower printf("%d.%d.%d.%d: %d", 87836384Ssklower (sin->sin_addr.s_addr>>24)&0xff, 87936384Ssklower (sin->sin_addr.s_addr>>16)&0xff, 88036384Ssklower (sin->sin_addr.s_addr>>8)&0xff, 88136384Ssklower (sin->sin_addr.s_addr)&0xff, 88236384Ssklower sin->sin_port); 88336384Ssklower } 88436384Ssklower } 88536384Ssklower 88636384Ssklower #endif ARGO_DEBUG 887