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