149268Sbostic /*- 249268Sbostic * Copyright (c) 1991 The Regents of the University of California. 349268Sbostic * All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*49936Ssklower * @(#)iso.c 7.13 (Berkeley) 05/29/91 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 "user.h" 5237469Ssklower #include "errno.h" 5336384Ssklower 5436384Ssklower #include "../net/if.h" 5536384Ssklower #include "../net/route.h" 5636384Ssklower #include "../net/af.h" 5736384Ssklower 5837469Ssklower #include "iso.h" 5937469Ssklower #include "iso_var.h" 6037469Ssklower #include "iso_snpac.h" 6137469Ssklower #include "iso_pcb.h" 6237469Ssklower #include "clnp.h" 6337469Ssklower #include "argo_debug.h" 6436384Ssklower 6536384Ssklower #ifdef ISO 6636384Ssklower 6736384Ssklower int iso_interfaces = 0; /* number of external interfaces */ 6836384Ssklower extern struct ifnet loif; /* loopback interface */ 6943333Ssklower int ether_output(), llc_rtrequest(); 7036384Ssklower 7136384Ssklower 7236384Ssklower /* 7336384Ssklower * FUNCTION: iso_init 7436384Ssklower * 7536384Ssklower * PURPOSE: initialize the iso address family 7636384Ssklower * 7736384Ssklower * RETURNS: nothing 7836384Ssklower * 79*49936Ssklower * SIDE EFFECTS: 1) initializes the routing table. 8036384Ssklower * 81*49936Ssklower * 8236384Ssklower * NOTES: 8336384Ssklower */ 8437469Ssklower struct radix_node_head *iso_rnhead; 8536384Ssklower iso_init() 8636384Ssklower { 8737469Ssklower static iso_init_done; 8836384Ssklower 8937469Ssklower if (iso_init_done == 0) { 9037469Ssklower iso_init_done++; 91*49936Ssklower rn_inithead(&iso_rnhead, 48, AF_ISO); 9237469Ssklower } 9336384Ssklower } 9436384Ssklower 9536384Ssklower /* 9636384Ssklower * FUNCTION: iso_addrmatch1 9736384Ssklower * 9836384Ssklower * PURPOSE: decide if the two iso_addrs passed are equal 9936384Ssklower * 10036384Ssklower * RETURNS: true if the addrs match, false if they do not 10136384Ssklower * 10236384Ssklower * SIDE EFFECTS: 10336384Ssklower * 10436384Ssklower * NOTES: 10536384Ssklower */ 10636384Ssklower iso_addrmatch1(isoaa, isoab) 10737469Ssklower register struct iso_addr *isoaa, *isoab; /* addresses to check */ 10836384Ssklower { 10937469Ssklower u_int compare_len; 11036384Ssklower 11136384Ssklower IFDEBUG(D_ROUTE) 11236384Ssklower printf("iso_addrmatch1: comparing lengths: %d to %d\n", isoaa->isoa_len, 11336384Ssklower isoab->isoa_len); 11436384Ssklower printf("a:\n"); 11537469Ssklower dump_buf(isoaa->isoa_genaddr, isoaa->isoa_len); 11636384Ssklower printf("b:\n"); 11737469Ssklower dump_buf(isoab->isoa_genaddr, isoab->isoa_len); 11836384Ssklower ENDDEBUG 11936384Ssklower 12036384Ssklower if ((compare_len = isoaa->isoa_len) != isoab->isoa_len) { 12136384Ssklower IFDEBUG(D_ROUTE) 12236384Ssklower printf("iso_addrmatch1: returning false because of lengths\n"); 12336384Ssklower ENDDEBUG 12436384Ssklower return 0; 12536384Ssklower } 12636384Ssklower 12737469Ssklower #ifdef notdef 12836384Ssklower /* TODO : generalize this to all afis with masks */ 12936384Ssklower if( isoaa->isoa_afi == AFI_37 ) { 13036384Ssklower /* must not compare 2 least significant digits, or for 13136384Ssklower * that matter, the DSP 13236384Ssklower */ 13336384Ssklower compare_len = ADDR37_IDI_LEN - 1; 13436384Ssklower } 13537469Ssklower #endif 13636384Ssklower 13736384Ssklower IFDEBUG(D_ROUTE) 13836384Ssklower int i; 13936384Ssklower char *a, *b; 14036384Ssklower 14137469Ssklower a = isoaa->isoa_genaddr; 14237469Ssklower b = isoab->isoa_genaddr; 14336384Ssklower 14436384Ssklower for (i=0; i<compare_len; i++) { 14536384Ssklower printf("<%x=%x>", a[i]&0xff, b[i]&0xff); 14636384Ssklower if (a[i] != b[i]) { 14736384Ssklower printf("\naddrs are not equal at byte %d\n", i); 14836384Ssklower return(0); 14936384Ssklower } 15036384Ssklower } 15136384Ssklower printf("\n"); 15236384Ssklower printf("addrs are equal\n"); 15336384Ssklower return (1); 15436384Ssklower ENDDEBUG 15537469Ssklower return (!bcmp(isoaa->isoa_genaddr, isoab->isoa_genaddr, compare_len)); 15636384Ssklower } 15736384Ssklower 15836384Ssklower /* 15936384Ssklower * FUNCTION: iso_addrmatch 16036384Ssklower * 16136384Ssklower * PURPOSE: decide if the two sockadrr_isos passed are equal 16236384Ssklower * 16336384Ssklower * RETURNS: true if the addrs match, false if they do not 16436384Ssklower * 16536384Ssklower * SIDE EFFECTS: 16636384Ssklower * 16736384Ssklower * NOTES: 16836384Ssklower */ 16936384Ssklower iso_addrmatch(sisoa, sisob) 17036384Ssklower struct sockaddr_iso *sisoa, *sisob; /* addresses to check */ 17136384Ssklower { 17236384Ssklower return(iso_addrmatch1(&sisoa->siso_addr, &sisob->siso_addr)); 17336384Ssklower } 17437469Ssklower #ifdef notdef 17536384Ssklower /* 17636384Ssklower * FUNCTION: iso_netmatch 17736384Ssklower * 17836384Ssklower * PURPOSE: similar to iso_addrmatch but takes sockaddr_iso 17936384Ssklower * as argument. 18036384Ssklower * 18136384Ssklower * RETURNS: true if same net, false if not 18236384Ssklower * 18336384Ssklower * SIDE EFFECTS: 18436384Ssklower * 18536384Ssklower * NOTES: 18636384Ssklower */ 18736384Ssklower iso_netmatch(sisoa, sisob) 18836384Ssklower struct sockaddr_iso *sisoa, *sisob; 18936384Ssklower { 19036384Ssklower u_char bufa[sizeof(struct sockaddr_iso)]; 19136384Ssklower u_char bufb[sizeof(struct sockaddr_iso)]; 19236384Ssklower register int lena, lenb; 19336384Ssklower 19436384Ssklower lena = iso_netof(&sisoa->siso_addr, bufa); 19536384Ssklower lenb = iso_netof(&sisob->siso_addr, bufb); 19636384Ssklower 19736384Ssklower IFDEBUG(D_ROUTE) 19836384Ssklower printf("iso_netmatch: comparing lengths: %d to %d\n", lena, lenb); 19936384Ssklower printf("a:\n"); 20036384Ssklower dump_buf(bufa, lena); 20136384Ssklower printf("b:\n"); 20236384Ssklower dump_buf(bufb, lenb); 20336384Ssklower ENDDEBUG 20436384Ssklower 20536384Ssklower return ((lena == lenb) && (!bcmp(bufa, bufb, lena))); 20636384Ssklower } 20737469Ssklower #endif notdef 20836384Ssklower 20936384Ssklower /* 21036384Ssklower * FUNCTION: iso_hashchar 21136384Ssklower * 21236384Ssklower * PURPOSE: Hash all character in the buffer specified into 21336384Ssklower * a long. Return the long. 21436384Ssklower * 21536384Ssklower * RETURNS: The hash value. 21636384Ssklower * 21736384Ssklower * SIDE EFFECTS: 21836384Ssklower * 21936384Ssklower * NOTES: The hash is achieved by exclusive ORing 4 byte 22036384Ssklower * quantities. 22136384Ssklower */ 22236384Ssklower u_long 22336384Ssklower iso_hashchar(buf, len) 22436384Ssklower register caddr_t buf; /* buffer to pack from */ 22536384Ssklower register int len; /* length of buffer */ 22636384Ssklower { 22736384Ssklower register u_long h = 0; 22836384Ssklower register int i; 22936384Ssklower 23036384Ssklower for (i=0; i<len; i+=4) { 23136384Ssklower register u_long l = 0; 23236384Ssklower 23336384Ssklower if ((len - i) < 4) { 23436384Ssklower /* buffer not multiple of 4 */ 23536384Ssklower switch (len - i) { 23636384Ssklower case 3: 23736384Ssklower l |= buf[i+2] << 8; 23836384Ssklower case 2: 23936384Ssklower l |= buf[i+1] << 16; 24036384Ssklower case 1: 24136384Ssklower l |= buf[i] << 24; 24236384Ssklower break; 24336384Ssklower default: 24436384Ssklower printf("iso_hashchar: unexpected value x%x\n", len - i); 24536384Ssklower break; 24636384Ssklower } 24736384Ssklower } else { 24836384Ssklower l |= buf[i] << 24; 24936384Ssklower l |= buf[i+1] << 16; 25036384Ssklower l |= buf[i+2] << 8; 25136384Ssklower l |= buf[i+3]; 25236384Ssklower } 25336384Ssklower 25436384Ssklower h ^= l; 25536384Ssklower } 25636384Ssklower 25736384Ssklower h ^= (u_long) (len % 4); 25836384Ssklower 25936384Ssklower return(h); 26036384Ssklower } 26137469Ssklower #ifdef notdef 26236384Ssklower /* 26336384Ssklower * FUNCTION: iso_hash 26436384Ssklower * 26536384Ssklower * PURPOSE: Fill in fields of afhash structure based upon addr passed. 26636384Ssklower * 26736384Ssklower * RETURNS: none 26836384Ssklower * 26936384Ssklower * SIDE EFFECTS: 27036384Ssklower * 27136384Ssklower * NOTES: 27236384Ssklower */ 27336384Ssklower iso_hash(siso, hp) 27436384Ssklower struct sockaddr_iso *siso; /* address to perform hash on */ 27536384Ssklower struct afhash *hp; /* RETURN: hash info here */ 27636384Ssklower { 27736384Ssklower u_long buf[sizeof(struct sockaddr_iso)+1/4]; 27836384Ssklower register int bufsize; 27936384Ssklower 28036384Ssklower 28136384Ssklower bzero(buf, sizeof(buf)); 28236384Ssklower 28336384Ssklower bufsize = iso_netof(&siso->siso_addr, buf); 28436384Ssklower hp->afh_nethash = iso_hashchar((caddr_t)buf, bufsize); 28536384Ssklower 28636384Ssklower IFDEBUG(D_ROUTE) 28736384Ssklower printf("iso_hash: iso_netof: bufsize = %d\n", bufsize); 28836384Ssklower ENDDEBUG 28936384Ssklower 29036384Ssklower hp->afh_hosthash = iso_hashchar((caddr_t)&siso->siso_addr, 29136384Ssklower siso->siso_addr.isoa_len); 29236384Ssklower 29336384Ssklower IFDEBUG(D_ROUTE) 29436384Ssklower printf("iso_hash: %s: nethash = x%x, hosthash = x%x\n", 29536384Ssklower clnp_iso_addrp(&siso->siso_addr), hp->afh_nethash, 29636384Ssklower hp->afh_hosthash); 29736384Ssklower ENDDEBUG 29836384Ssklower } 29936384Ssklower /* 30036384Ssklower * FUNCTION: iso_netof 30136384Ssklower * 30236384Ssklower * PURPOSE: Extract the network portion of the iso address. 30336384Ssklower * The network portion of the iso address varies depending 30436384Ssklower * on the type of address. The network portion of the 30536384Ssklower * address will include the IDP. The network portion is: 30636384Ssklower * 30736384Ssklower * TYPE DESC 30836384Ssklower * t37 The AFI and x.121 (IDI) 30936384Ssklower * osinet The AFI, orgid, snetid 31036384Ssklower * rfc986 The AFI, vers and network part of 31136384Ssklower * internet address. 31236384Ssklower * 31336384Ssklower * RETURNS: number of bytes placed into buf. 31436384Ssklower * 31536384Ssklower * SIDE EFFECTS: 31636384Ssklower * 31736384Ssklower * NOTES: Buf is assumed to be big enough 31836384Ssklower */ 31936384Ssklower iso_netof(isoa, buf) 32036384Ssklower struct iso_addr *isoa; /* address */ 32136384Ssklower caddr_t buf; /* RESULT: network portion of address here */ 32236384Ssklower { 32336384Ssklower u_int len = 1; /* length of afi */ 32436384Ssklower 32536384Ssklower switch (isoa->isoa_afi) { 32636384Ssklower case AFI_37: 32736384Ssklower /* 32836384Ssklower * Due to classic x.25 tunnel vision, there is no 32936384Ssklower * net portion of an x.121 address. For our purposes 33036384Ssklower * the AFI will do, so that all x.25 -type addresses 33136384Ssklower * map to the single x.25 SNPA. (Cannot have more than 33236384Ssklower * one, obviously). 33336384Ssklower */ 33436384Ssklower 33536384Ssklower break; 33636384Ssklower 33736384Ssklower /* case AFI_OSINET:*/ 33836384Ssklower case AFI_RFC986: { 33936384Ssklower u_short idi; /* value of idi */ 34036384Ssklower 34136384Ssklower /* osinet and rfc986 have idi in the same place */ 34236384Ssklower CTOH(isoa->rfc986_idi[0], isoa->rfc986_idi[1], idi); 34336384Ssklower 34436384Ssklower if (idi == IDI_OSINET) 34536384Ssklower /* 34636384Ssklower * Network portion of OSINET address can only be the IDI. Clearly, 34736384Ssklower * with one x25 interface, one could get to several orgids, and 34836384Ssklower * several snetids. 34936384Ssklower len += (ADDROSINET_IDI_LEN + OVLOSINET_ORGID_LEN + 35036384Ssklower OVLOSINET_SNETID_LEN); 35136384Ssklower */ 35236384Ssklower len += ADDROSINET_IDI_LEN; 35336384Ssklower else if (idi == IDI_RFC986) { 35436384Ssklower u_long inetaddr; 35536384Ssklower struct ovl_rfc986 *o986 = (struct ovl_rfc986 *)isoa; 35636384Ssklower 35736384Ssklower /* bump len to include idi and version (1 byte) */ 35836384Ssklower len += ADDRRFC986_IDI_LEN + 1; 35936384Ssklower 36036384Ssklower /* get inet addr long aligned */ 36136384Ssklower bcopy(o986->o986_inetaddr, &inetaddr, sizeof(inetaddr)); 36236384Ssklower inetaddr = ntohl(inetaddr); /* convert to host byte order */ 36336384Ssklower 36436384Ssklower IFDEBUG(D_ROUTE) 36536384Ssklower printf("iso_netof: isoa "); 36636384Ssklower dump_buf(isoa, sizeof(*isoa)); 36736384Ssklower printf("iso_netof: inetaddr 0x%x ", inetaddr); 36836384Ssklower ENDDEBUG 36936384Ssklower 37036384Ssklower /* bump len by size of network portion of inet address */ 37136384Ssklower if (IN_CLASSA(inetaddr)) { 37236384Ssklower len += 4-IN_CLASSA_NSHIFT/8; 37336384Ssklower IFDEBUG(D_ROUTE) 37436384Ssklower printf("iso_netof: class A net len is now %d\n", len); 37536384Ssklower ENDDEBUG 37636384Ssklower } else if (IN_CLASSB(inetaddr)) { 37736384Ssklower len += 4-IN_CLASSB_NSHIFT/8; 37836384Ssklower IFDEBUG(D_ROUTE) 37936384Ssklower printf("iso_netof: class B net len is now %d\n", len); 38036384Ssklower ENDDEBUG 38136384Ssklower } else { 38236384Ssklower len += 4-IN_CLASSC_NSHIFT/8; 38336384Ssklower IFDEBUG(D_ROUTE) 38436384Ssklower printf("iso_netof: class C net len is now %d\n", len); 38536384Ssklower ENDDEBUG 38636384Ssklower } 38736384Ssklower } else 38836384Ssklower len = 0; 38936384Ssklower } break; 39036384Ssklower 39136384Ssklower default: 39236384Ssklower len = 0; 39336384Ssklower } 39436384Ssklower 39536384Ssklower bcopy((caddr_t)isoa, buf, len); 39636384Ssklower IFDEBUG(D_ROUTE) 39736384Ssklower printf("in_netof: isoa "); 39836384Ssklower dump_buf(isoa, len); 39936384Ssklower printf("in_netof: net "); 40036384Ssklower dump_buf(buf, len); 40136384Ssklower ENDDEBUG 40236384Ssklower return len; 40336384Ssklower } 40437469Ssklower #endif notdef 40536384Ssklower /* 40637469Ssklower * Generic iso control operations (ioctl's). 40737469Ssklower * Ifp is 0 if not an interface-specific ioctl. 40836384Ssklower */ 40937469Ssklower /* ARGSUSED */ 41036384Ssklower iso_control(so, cmd, data, ifp) 41137469Ssklower struct socket *so; 41237469Ssklower int cmd; 41337469Ssklower caddr_t data; 41437469Ssklower register struct ifnet *ifp; 41536384Ssklower { 41637469Ssklower register struct iso_ifreq *ifr = (struct iso_ifreq *)data; 41737469Ssklower register struct iso_ifaddr *ia = 0; 41837469Ssklower register struct ifaddr *ifa; 41937469Ssklower struct iso_ifaddr *oia; 42037469Ssklower struct iso_aliasreq *ifra = (struct iso_aliasreq *)data; 42137469Ssklower int error, hostIsNew, maskIsNew; 42236384Ssklower 42337469Ssklower /* 42437469Ssklower * Find address for this interface, if it exists. 42537469Ssklower */ 42637469Ssklower if (ifp) 42737469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) 42837469Ssklower if (ia->ia_ifp == ifp) 42937469Ssklower break; 43036384Ssklower 43136384Ssklower switch (cmd) { 43237469Ssklower 43337469Ssklower case SIOCAIFADDR_ISO: 43437469Ssklower case SIOCDIFADDR_ISO: 43537469Ssklower if (ifra->ifra_addr.siso_family == AF_ISO) 43637469Ssklower for (oia = ia; ia; ia = ia->ia_next) { 43737469Ssklower if (ia->ia_ifp == ifp && 43837469Ssklower SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr)) 43937469Ssklower break; 44037469Ssklower } 44137547Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 44237547Smckusick return (error); 44336384Ssklower if (ifp == 0) 44437469Ssklower panic("iso_control"); 44537469Ssklower if (ia == (struct iso_ifaddr *)0) { 44637469Ssklower struct iso_ifaddr *nia; 44737469Ssklower if (cmd == SIOCDIFADDR_ISO) 44837469Ssklower return (EADDRNOTAVAIL); 44937469Ssklower MALLOC(nia, struct iso_ifaddr *, sizeof(*nia), 45037469Ssklower M_IFADDR, M_WAITOK); 45137469Ssklower if (nia == (struct iso_ifaddr *)0) 45237469Ssklower return (ENOBUFS); 45337469Ssklower bzero((caddr_t)nia, sizeof(*nia)); 45437469Ssklower if (ia = iso_ifaddr) { 45537469Ssklower for ( ; ia->ia_next; ia = ia->ia_next) 45637469Ssklower ; 45737469Ssklower ia->ia_next = nia; 45837469Ssklower } else 45937469Ssklower iso_ifaddr = nia; 46037469Ssklower ia = nia; 46137469Ssklower if (ifa = ifp->if_addrlist) { 46237469Ssklower for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 46337469Ssklower ; 46437469Ssklower ifa->ifa_next = (struct ifaddr *) ia; 46537469Ssklower } else 46637469Ssklower ifp->if_addrlist = (struct ifaddr *) ia; 46737469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 46837469Ssklower ia->ia_ifa.ifa_dstaddr 46937469Ssklower = (struct sockaddr *)&ia->ia_dstaddr; 47037469Ssklower ia->ia_ifa.ifa_netmask 47137469Ssklower = (struct sockaddr *)&ia->ia_sockmask; 47237469Ssklower ia->ia_ifp = ifp; 47337469Ssklower if (ifp != &loif) 47437469Ssklower iso_interfaces++; 47537469Ssklower } 47637469Ssklower break; 47736384Ssklower 47837469Ssklower #define cmdbyte(x) (((x) >> 8) & 0xff) 47937469Ssklower default: 48037469Ssklower if (cmdbyte(cmd) == 'a') 48137469Ssklower return (snpac_ioctl(cmd, data)); 48237469Ssklower if (ia == (struct iso_ifaddr *)0) 48337469Ssklower return (EADDRNOTAVAIL); 48437469Ssklower break; 48537469Ssklower } 48637469Ssklower switch (cmd) { 48736384Ssklower 48837469Ssklower case SIOCGIFADDR_ISO: 48937469Ssklower ifr->ifr_Addr = ia->ia_addr; 49037469Ssklower break; 49136384Ssklower 49237469Ssklower case SIOCGIFDSTADDR_ISO: 49337469Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 49437469Ssklower return (EINVAL); 49537469Ssklower ifr->ifr_Addr = ia->ia_dstaddr; 49637469Ssklower break; 49736384Ssklower 49837469Ssklower case SIOCGIFNETMASK_ISO: 49937469Ssklower ifr->ifr_Addr = ia->ia_sockmask; 50037469Ssklower break; 50136384Ssklower 50237469Ssklower case SIOCAIFADDR_ISO: 50343428Ssklower maskIsNew = 0; hostIsNew = 1; error = 0; 50437469Ssklower if (ia->ia_addr.siso_family == AF_ISO) { 50537469Ssklower if (ifra->ifra_addr.siso_len == 0) { 50637469Ssklower ifra->ifra_addr = ia->ia_addr; 50737469Ssklower hostIsNew = 0; 50837469Ssklower } else if (SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr)) 50937469Ssklower hostIsNew = 0; 51037469Ssklower } 51137469Ssklower if (ifra->ifra_mask.siso_len) { 51237469Ssklower iso_ifscrub(ifp, ia); 51337469Ssklower ia->ia_sockmask = ifra->ifra_mask; 51437469Ssklower maskIsNew = 1; 51537469Ssklower } 51637469Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) && 51737469Ssklower (ifra->ifra_dstaddr.siso_family == AF_ISO)) { 51837469Ssklower iso_ifscrub(ifp, ia); 51937469Ssklower ia->ia_dstaddr = ifra->ifra_dstaddr; 52037469Ssklower maskIsNew = 1; /* We lie; but the effect's the same */ 52137469Ssklower } 52237469Ssklower if (ifra->ifra_addr.siso_family == AF_ISO && 52337469Ssklower (hostIsNew || maskIsNew)) { 52437469Ssklower error = iso_ifinit(ifp, ia, &ifra->ifra_addr, 0); 52537469Ssklower } 52637469Ssklower if (ifra->ifra_snpaoffset) 52737469Ssklower ia->ia_snpaoffset = ifra->ifra_snpaoffset; 52837469Ssklower return (error); 52937469Ssklower 53037469Ssklower case SIOCDIFADDR_ISO: 53137469Ssklower iso_ifscrub(ifp, ia); 53237469Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 53337469Ssklower ifp->if_addrlist = ifa->ifa_next; 53437469Ssklower else { 53537469Ssklower while (ifa->ifa_next && 53637469Ssklower (ifa->ifa_next != (struct ifaddr *)ia)) 53737469Ssklower ifa = ifa->ifa_next; 53837469Ssklower if (ifa->ifa_next) 53937469Ssklower ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 54037469Ssklower else 54137469Ssklower printf("Couldn't unlink isoifaddr from ifp\n"); 54237469Ssklower } 54337469Ssklower oia = ia; 54437469Ssklower if (oia == (ia = iso_ifaddr)) { 54537469Ssklower iso_ifaddr = ia->ia_next; 54637469Ssklower } else { 54737469Ssklower while (ia->ia_next && (ia->ia_next != oia)) { 54837469Ssklower ia = ia->ia_next; 54936384Ssklower } 55037469Ssklower if (ia->ia_next) 55137469Ssklower ia->ia_next = oia->ia_next; 55237469Ssklower else 55337469Ssklower printf("Didn't unlink isoifadr from list\n"); 55436384Ssklower } 55537469Ssklower free((caddr_t)oia, M_IFADDR); 55637469Ssklower break; 55736384Ssklower 55836384Ssklower default: 55936384Ssklower if (ifp == 0 || ifp->if_ioctl == 0) 56036384Ssklower return (EOPNOTSUPP); 56136384Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data)); 56236384Ssklower } 56337469Ssklower return (0); 56436384Ssklower } 56536384Ssklower 56637469Ssklower /* 56737469Ssklower * Delete any existing route for an interface. 56837469Ssklower */ 56937469Ssklower iso_ifscrub(ifp, ia) 57037469Ssklower register struct ifnet *ifp; 57137469Ssklower register struct iso_ifaddr *ia; 57237469Ssklower { 57343333Ssklower int nsellength = ia->ia_addr.siso_tlen; 57437469Ssklower if ((ia->ia_flags & IFA_ROUTE) == 0) 57537469Ssklower return; 57643333Ssklower ia->ia_addr.siso_tlen = 0; 57737469Ssklower if (ifp->if_flags & IFF_LOOPBACK) 57837469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 57937469Ssklower else if (ifp->if_flags & IFF_POINTOPOINT) 58037469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 58137469Ssklower else { 58237469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 58337469Ssklower } 58443333Ssklower ia->ia_addr.siso_tlen = nsellength; 58537469Ssklower ia->ia_flags &= ~IFA_ROUTE; 58637469Ssklower } 58737469Ssklower 58837469Ssklower /* 58937469Ssklower * Initialize an interface's internet address 59037469Ssklower * and routing table entry. 59137469Ssklower */ 59237469Ssklower iso_ifinit(ifp, ia, siso, scrub) 59337469Ssklower register struct ifnet *ifp; 59437469Ssklower register struct iso_ifaddr *ia; 59537469Ssklower struct sockaddr_iso *siso; 59637469Ssklower { 59737469Ssklower struct sockaddr_iso oldaddr; 59843333Ssklower int s = splimp(), error, nsellength; 59937469Ssklower 60037469Ssklower oldaddr = ia->ia_addr; 60137469Ssklower ia->ia_addr = *siso; 60237469Ssklower /* 60337469Ssklower * Give the interface a chance to initialize 60437469Ssklower * if this is its first address, 60537469Ssklower * and to validate the address if necessary. 60637469Ssklower */ 60737469Ssklower if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 60837469Ssklower splx(s); 60937469Ssklower ia->ia_addr = oldaddr; 61037469Ssklower return (error); 61137469Ssklower } 61237469Ssklower if (scrub) { 61337469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 61437469Ssklower iso_ifscrub(ifp, ia); 61537469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 61637469Ssklower } 61743333Ssklower /* XXX -- The following is here temporarily out of laziness 61843333Ssklower in not changing every ethernet driver's if_ioctl routine */ 61943333Ssklower if (ifp->if_output == ether_output) { 62043333Ssklower ia->ia_ifa.ifa_rtrequest = llc_rtrequest; 62143333Ssklower ia->ia_ifa.ifa_flags |= RTF_CLONING; 62243333Ssklower ia->ia_ifa.ifa_llinfolen = sizeof(struct llinfo_llc); 62343333Ssklower } 62437469Ssklower /* 62537469Ssklower * Add route for the network. 62637469Ssklower */ 62743333Ssklower nsellength = ia->ia_addr.siso_tlen; 62843333Ssklower ia->ia_addr.siso_tlen = 0; 62937469Ssklower if (ifp->if_flags & IFF_LOOPBACK) { 63037469Ssklower ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 63140894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 63237469Ssklower } else if (ifp->if_flags & IFF_POINTOPOINT && 63337469Ssklower ia->ia_dstaddr.siso_family == AF_ISO) 63440894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 63537469Ssklower else { 63640894Ssklower rt_maskedcopy(ia->ia_ifa.ifa_addr, ia->ia_ifa.ifa_dstaddr, 63740894Ssklower ia->ia_ifa.ifa_netmask); 638*49936Ssklower ia->ia_dstaddr.siso_nlen = 639*49936Ssklower min(ia->ia_addr.siso_nlen, (ia->ia_sockmask.siso_len - 6)); 64040894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP); 64137469Ssklower } 64243333Ssklower ia->ia_addr.siso_tlen = nsellength; 64337469Ssklower ia->ia_flags |= IFA_ROUTE; 64437469Ssklower splx(s); 64540894Ssklower return (error); 64637469Ssklower } 64737469Ssklower #ifdef notdef 64837469Ssklower 64936384Ssklower struct ifaddr * 65036384Ssklower iso_ifwithidi(addr) 65136384Ssklower register struct sockaddr *addr; 65236384Ssklower { 65336384Ssklower register struct ifnet *ifp; 65436384Ssklower register struct ifaddr *ifa; 65536384Ssklower register u_int af = addr->sa_family; 65636384Ssklower 65736384Ssklower if (af != AF_ISO) 65836384Ssklower return (0); 65936384Ssklower IFDEBUG(D_ROUTE) 66036384Ssklower printf(">>> iso_ifwithidi addr\n"); 66136384Ssklower dump_isoaddr( (struct sockaddr_iso *)(addr)); 66236384Ssklower printf("\n"); 66336384Ssklower ENDDEBUG 66436384Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) { 66536384Ssklower IFDEBUG(D_ROUTE) 66636384Ssklower printf("iso_ifwithidi ifnet %s\n", ifp->if_name); 66736384Ssklower ENDDEBUG 66836384Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 66936384Ssklower IFDEBUG(D_ROUTE) 67036384Ssklower printf("iso_ifwithidi address "); 67137469Ssklower dump_isoaddr( (struct sockaddr_iso *)(ifa->ifa_addr)); 67236384Ssklower ENDDEBUG 67337469Ssklower if (ifa->ifa_addr->sa_family != addr->sa_family) 67436384Ssklower continue; 67536384Ssklower 67636384Ssklower #define IFA_SIS(ifa)\ 67737469Ssklower ((struct sockaddr_iso *)((ifa)->ifa_addr)) 67836384Ssklower 67936384Ssklower IFDEBUG(D_ROUTE) 68036384Ssklower printf(" af same, args to iso_eqtype:\n"); 68136384Ssklower printf("0x%x ", IFA_SIS(ifa)->siso_addr); 68236384Ssklower printf(" 0x%x\n", 68336384Ssklower &(((struct sockaddr_iso *)addr)->siso_addr)); 68436384Ssklower ENDDEBUG 68536384Ssklower 68636384Ssklower if (iso_eqtype(&(IFA_SIS(ifa)->siso_addr), 68736384Ssklower &(((struct sockaddr_iso *)addr)->siso_addr))) { 68836384Ssklower IFDEBUG(D_ROUTE) 68936384Ssklower printf("ifa_ifwithidi: ifa found\n"); 69036384Ssklower ENDDEBUG 69136384Ssklower return (ifa); 69236384Ssklower } 69336384Ssklower IFDEBUG(D_ROUTE) 69436384Ssklower printf(" iso_eqtype failed\n"); 69536384Ssklower ENDDEBUG 69636384Ssklower } 69736384Ssklower } 69836384Ssklower return ((struct ifaddr *)0); 69936384Ssklower } 70036384Ssklower 70137469Ssklower #endif notdef 70236384Ssklower /* 70336384Ssklower * FUNCTION: iso_ck_addr 70436384Ssklower * 70536384Ssklower * PURPOSE: return true if the iso_addr passed is 70636384Ssklower * within the legal size limit for an iso address. 70736384Ssklower * 70836384Ssklower * RETURNS: true or false 70936384Ssklower * 71036384Ssklower * SIDE EFFECTS: 71136384Ssklower * 71236384Ssklower */ 71336384Ssklower iso_ck_addr(isoa) 71436384Ssklower struct iso_addr *isoa; /* address to check */ 71536384Ssklower { 71636384Ssklower return (isoa->isoa_len <= 20); 71736384Ssklower 71836384Ssklower } 71936384Ssklower 72037469Ssklower #ifdef notdef 72136384Ssklower /* 72236384Ssklower * FUNCTION: iso_eqtype 72336384Ssklower * 72436384Ssklower * PURPOSE: Determine if two iso addresses are of the same type. 72536384Ssklower * This is flaky. Really we should consider all type 47 addrs to be the 72636384Ssklower * same - but there do exist different structures for 47 addrs. 72736384Ssklower * Gosip adds a 3rd. 72836384Ssklower * 72936384Ssklower * RETURNS: true if the addresses are the same type 73036384Ssklower * 73136384Ssklower * SIDE EFFECTS: 73236384Ssklower * 73336384Ssklower * NOTES: By type, I mean rfc986, t37, or osinet 73436384Ssklower * 73536384Ssklower * This will first compare afis. If they match, then 73636384Ssklower * if the addr is not t37, the idis must be compared. 73736384Ssklower */ 73836384Ssklower iso_eqtype(isoaa, isoab) 73936384Ssklower struct iso_addr *isoaa; /* first addr to check */ 74036384Ssklower struct iso_addr *isoab; /* other addr to check */ 74136384Ssklower { 74236384Ssklower if (isoaa->isoa_afi == isoab->isoa_afi) { 74336384Ssklower if (isoaa->isoa_afi == AFI_37) 74436384Ssklower return(1); 74536384Ssklower else 74636384Ssklower return (!bcmp(&isoaa->isoa_u, &isoab->isoa_u, 2)); 74736384Ssklower } 74836384Ssklower return(0); 74936384Ssklower } 75037469Ssklower #endif notdef 75136384Ssklower /* 75237469Ssklower * FUNCTION: iso_localifa() 75336384Ssklower * 75437469Ssklower * PURPOSE: Find an interface addresss having a given destination 75537469Ssklower * or at least matching the net. 75636384Ssklower * 75736384Ssklower * RETURNS: ptr to an interface address 75836384Ssklower * 75936384Ssklower * SIDE EFFECTS: 76036384Ssklower * 76136384Ssklower * NOTES: 76236384Ssklower */ 76336384Ssklower struct iso_ifaddr * 76437469Ssklower iso_localifa(siso) 76537469Ssklower register struct sockaddr_iso *siso; 76636384Ssklower { 76736384Ssklower register struct iso_ifaddr *ia; 76837469Ssklower register char *cp1, *cp2, *cp3; 76937469Ssklower register struct ifnet *ifp; 77037469Ssklower struct iso_ifaddr *ia_maybe = 0; 77137469Ssklower /* 77237469Ssklower * We make one pass looking for both net matches and an exact 77337469Ssklower * dst addr. 77437469Ssklower */ 77537469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 77637469Ssklower if ((ifp = ia->ia_ifp) == 0 || ((ifp->if_flags & IFF_UP) == 0)) 77737469Ssklower continue; 77837469Ssklower if (ifp->if_flags & IFF_POINTOPOINT) { 77937469Ssklower if ((ia->ia_dstaddr.siso_family == AF_ISO) && 78037469Ssklower SAME_ISOADDR(&ia->ia_dstaddr, siso)) 78137469Ssklower return (ia); 78237469Ssklower else 78337469Ssklower if (SAME_ISOADDR(&ia->ia_addr, siso)) 78437469Ssklower ia_maybe = ia; 78537469Ssklower continue; 78637469Ssklower } 78737469Ssklower if (ia->ia_sockmask.siso_len) { 78837469Ssklower char *cplim = ia->ia_sockmask.siso_len + (char *)&ia->ia_sockmask; 78937469Ssklower cp1 = ia->ia_sockmask.siso_data; 79037469Ssklower cp2 = siso->siso_data; 79137469Ssklower cp3 = ia->ia_addr.siso_data; 79239936Ssklower while (cp1 < cplim) 79337469Ssklower if (*cp1++ & (*cp2++ ^ *cp3++)) 79437469Ssklower goto next; 79537469Ssklower ia_maybe = ia; 79637469Ssklower } 79737469Ssklower if (SAME_ISOADDR(&ia->ia_addr, siso)) 79837469Ssklower return ia; 79937469Ssklower next:; 80037469Ssklower } 80137469Ssklower return ia_maybe; 80236384Ssklower } 80336384Ssklower 80447272Ssklower #ifdef TPCONS 80536384Ssklower #include "cons.h" 80647272Ssklower #endif TPCONS 80736384Ssklower /* 80836384Ssklower * FUNCTION: iso_nlctloutput 80936384Ssklower * 81036384Ssklower * PURPOSE: Set options at the network level 81136384Ssklower * 81236384Ssklower * RETURNS: E* 81336384Ssklower * 81436384Ssklower * SIDE EFFECTS: 81536384Ssklower * 81636384Ssklower * NOTES: This could embody some of the functions of 81736384Ssklower * rclnp_ctloutput and cons_ctloutput. 81836384Ssklower */ 81936384Ssklower iso_nlctloutput(cmd, optname, pcb, m) 82036384Ssklower int cmd; /* command:set or get */ 82136384Ssklower int optname; /* option of interest */ 82236384Ssklower caddr_t pcb; /* nl pcb */ 82336384Ssklower struct mbuf *m; /* data for set, buffer for get */ 82436384Ssklower { 82536384Ssklower struct isopcb *isop = (struct isopcb *)pcb; 82636384Ssklower int error = 0; /* return value */ 82736384Ssklower caddr_t data; /* data for option */ 82836384Ssklower int data_len; /* data's length */ 82936384Ssklower 83036384Ssklower IFDEBUG(D_ISO) 83136384Ssklower printf("iso_nlctloutput: cmd %x, opt %x, pcb %x, m %x\n", 83236384Ssklower cmd, optname, pcb, m); 83336384Ssklower ENDDEBUG 83436384Ssklower 83536384Ssklower if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT)) 83636384Ssklower return(EOPNOTSUPP); 83736384Ssklower 83836384Ssklower data = mtod(m, caddr_t); 83936384Ssklower data_len = (m)->m_len; 84036384Ssklower 84136384Ssklower IFDEBUG(D_ISO) 84236384Ssklower printf("iso_nlctloutput: data is:\n"); 84336384Ssklower dump_buf(data, data_len); 84436384Ssklower ENDDEBUG 84536384Ssklower 84636384Ssklower switch (optname) { 84736384Ssklower 84847272Ssklower #ifdef TPCONS 84936384Ssklower case CONSOPT_X25CRUD: 85036384Ssklower if (cmd == PRCO_GETOPT) { 85136384Ssklower error = EOPNOTSUPP; 85236384Ssklower break; 85336384Ssklower } 85436384Ssklower 85536384Ssklower if (data_len > MAXX25CRUDLEN) { 85636384Ssklower error = EINVAL; 85736384Ssklower break; 85836384Ssklower } 85936384Ssklower 86036384Ssklower IFDEBUG(D_ISO) 86136384Ssklower printf("iso_nlctloutput: setting x25 crud\n"); 86236384Ssklower ENDDEBUG 86336384Ssklower 86437469Ssklower bcopy(data, (caddr_t)isop->isop_x25crud, (unsigned)data_len); 86536384Ssklower isop->isop_x25crud_len = data_len; 86636384Ssklower break; 86747272Ssklower #endif TPCONS 86836384Ssklower 86936384Ssklower default: 87036384Ssklower error = EOPNOTSUPP; 87136384Ssklower } 87236384Ssklower 87336384Ssklower return error; 87436384Ssklower } 87536384Ssklower #endif ISO 87636384Ssklower 87736384Ssklower #ifdef ARGO_DEBUG 87836384Ssklower 87936384Ssklower /* 88036384Ssklower * FUNCTION: dump_isoaddr 88136384Ssklower * 88236384Ssklower * PURPOSE: debugging 88336384Ssklower * 88436384Ssklower * RETURNS: nada 88536384Ssklower * 88636384Ssklower */ 88736384Ssklower dump_isoaddr(s) 88836384Ssklower struct sockaddr_iso *s; 88936384Ssklower { 89037469Ssklower char *clnp_saddr_isop(); 89136384Ssklower register int i; 89236384Ssklower 89336384Ssklower if( s->siso_family == AF_ISO) { 89437469Ssklower printf("ISO address: suffixlen %d, %s\n", 89538841Ssklower s->siso_tlen, clnp_saddr_isop(s)); 89636384Ssklower } else if( s->siso_family == AF_INET) { 89736384Ssklower /* hack */ 89836384Ssklower struct sockaddr_in *sin = (struct sockaddr_in *)s; 89936384Ssklower 90036384Ssklower printf("%d.%d.%d.%d: %d", 90136384Ssklower (sin->sin_addr.s_addr>>24)&0xff, 90236384Ssklower (sin->sin_addr.s_addr>>16)&0xff, 90336384Ssklower (sin->sin_addr.s_addr>>8)&0xff, 90436384Ssklower (sin->sin_addr.s_addr)&0xff, 90536384Ssklower sin->sin_port); 90636384Ssklower } 90736384Ssklower } 90836384Ssklower 90936384Ssklower #endif ARGO_DEBUG 910