149268Sbostic /*- 249268Sbostic * Copyright (c) 1991 The Regents of the University of California. 349268Sbostic * All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*52030Ssklower * @(#)iso.c 7.17 (Berkeley) 12/19/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 */ 8336384Ssklower iso_init() 8436384Ssklower { 8550692Ssklower if (rt_tables[AF_ISO] == 0) { 8650692Ssklower rn_inithead(rt_tables + AF_ISO, 48); 8737469Ssklower } 8836384Ssklower } 8936384Ssklower 9036384Ssklower /* 9136384Ssklower * FUNCTION: iso_addrmatch1 9236384Ssklower * 9336384Ssklower * PURPOSE: decide if the two iso_addrs passed are equal 9436384Ssklower * 9536384Ssklower * RETURNS: true if the addrs match, false if they do not 9636384Ssklower * 9736384Ssklower * SIDE EFFECTS: 9836384Ssklower * 9936384Ssklower * NOTES: 10036384Ssklower */ 10136384Ssklower iso_addrmatch1(isoaa, isoab) 10237469Ssklower register struct iso_addr *isoaa, *isoab; /* addresses to check */ 10336384Ssklower { 10437469Ssklower u_int compare_len; 10536384Ssklower 10636384Ssklower IFDEBUG(D_ROUTE) 10736384Ssklower printf("iso_addrmatch1: comparing lengths: %d to %d\n", isoaa->isoa_len, 10836384Ssklower isoab->isoa_len); 10936384Ssklower printf("a:\n"); 11037469Ssklower dump_buf(isoaa->isoa_genaddr, isoaa->isoa_len); 11136384Ssklower printf("b:\n"); 11237469Ssklower dump_buf(isoab->isoa_genaddr, isoab->isoa_len); 11336384Ssklower ENDDEBUG 11436384Ssklower 11536384Ssklower if ((compare_len = isoaa->isoa_len) != isoab->isoa_len) { 11636384Ssklower IFDEBUG(D_ROUTE) 11736384Ssklower printf("iso_addrmatch1: returning false because of lengths\n"); 11836384Ssklower ENDDEBUG 11936384Ssklower return 0; 12036384Ssklower } 12136384Ssklower 12237469Ssklower #ifdef notdef 12336384Ssklower /* TODO : generalize this to all afis with masks */ 12436384Ssklower if( isoaa->isoa_afi == AFI_37 ) { 12536384Ssklower /* must not compare 2 least significant digits, or for 12636384Ssklower * that matter, the DSP 12736384Ssklower */ 12836384Ssklower compare_len = ADDR37_IDI_LEN - 1; 12936384Ssklower } 13037469Ssklower #endif 13136384Ssklower 13236384Ssklower IFDEBUG(D_ROUTE) 13336384Ssklower int i; 13436384Ssklower char *a, *b; 13536384Ssklower 13637469Ssklower a = isoaa->isoa_genaddr; 13737469Ssklower b = isoab->isoa_genaddr; 13836384Ssklower 13936384Ssklower for (i=0; i<compare_len; i++) { 14036384Ssklower printf("<%x=%x>", a[i]&0xff, b[i]&0xff); 14136384Ssklower if (a[i] != b[i]) { 14236384Ssklower printf("\naddrs are not equal at byte %d\n", i); 14336384Ssklower return(0); 14436384Ssklower } 14536384Ssklower } 14636384Ssklower printf("\n"); 14736384Ssklower printf("addrs are equal\n"); 14836384Ssklower return (1); 14936384Ssklower ENDDEBUG 15037469Ssklower return (!bcmp(isoaa->isoa_genaddr, isoab->isoa_genaddr, compare_len)); 15136384Ssklower } 15236384Ssklower 15336384Ssklower /* 15436384Ssklower * FUNCTION: iso_addrmatch 15536384Ssklower * 15636384Ssklower * PURPOSE: decide if the two sockadrr_isos passed are equal 15736384Ssklower * 15836384Ssklower * RETURNS: true if the addrs match, false if they do not 15936384Ssklower * 16036384Ssklower * SIDE EFFECTS: 16136384Ssklower * 16236384Ssklower * NOTES: 16336384Ssklower */ 16436384Ssklower iso_addrmatch(sisoa, sisob) 16536384Ssklower struct sockaddr_iso *sisoa, *sisob; /* addresses to check */ 16636384Ssklower { 16736384Ssklower return(iso_addrmatch1(&sisoa->siso_addr, &sisob->siso_addr)); 16836384Ssklower } 16937469Ssklower #ifdef notdef 17036384Ssklower /* 17136384Ssklower * FUNCTION: iso_netmatch 17236384Ssklower * 17336384Ssklower * PURPOSE: similar to iso_addrmatch but takes sockaddr_iso 17436384Ssklower * as argument. 17536384Ssklower * 17636384Ssklower * RETURNS: true if same net, false if not 17736384Ssklower * 17836384Ssklower * SIDE EFFECTS: 17936384Ssklower * 18036384Ssklower * NOTES: 18136384Ssklower */ 18236384Ssklower iso_netmatch(sisoa, sisob) 18336384Ssklower struct sockaddr_iso *sisoa, *sisob; 18436384Ssklower { 18536384Ssklower u_char bufa[sizeof(struct sockaddr_iso)]; 18636384Ssklower u_char bufb[sizeof(struct sockaddr_iso)]; 18736384Ssklower register int lena, lenb; 18836384Ssklower 18936384Ssklower lena = iso_netof(&sisoa->siso_addr, bufa); 19036384Ssklower lenb = iso_netof(&sisob->siso_addr, bufb); 19136384Ssklower 19236384Ssklower IFDEBUG(D_ROUTE) 19336384Ssklower printf("iso_netmatch: comparing lengths: %d to %d\n", lena, lenb); 19436384Ssklower printf("a:\n"); 19536384Ssklower dump_buf(bufa, lena); 19636384Ssklower printf("b:\n"); 19736384Ssklower dump_buf(bufb, lenb); 19836384Ssklower ENDDEBUG 19936384Ssklower 20036384Ssklower return ((lena == lenb) && (!bcmp(bufa, bufb, lena))); 20136384Ssklower } 20237469Ssklower #endif notdef 20336384Ssklower 20436384Ssklower /* 20536384Ssklower * FUNCTION: iso_hashchar 20636384Ssklower * 20736384Ssklower * PURPOSE: Hash all character in the buffer specified into 20836384Ssklower * a long. Return the long. 20936384Ssklower * 21036384Ssklower * RETURNS: The hash value. 21136384Ssklower * 21236384Ssklower * SIDE EFFECTS: 21336384Ssklower * 21436384Ssklower * NOTES: The hash is achieved by exclusive ORing 4 byte 21536384Ssklower * quantities. 21636384Ssklower */ 21736384Ssklower u_long 21836384Ssklower iso_hashchar(buf, len) 21936384Ssklower register caddr_t buf; /* buffer to pack from */ 22036384Ssklower register int len; /* length of buffer */ 22136384Ssklower { 22236384Ssklower register u_long h = 0; 22336384Ssklower register int i; 22436384Ssklower 22536384Ssklower for (i=0; i<len; i+=4) { 22636384Ssklower register u_long l = 0; 22736384Ssklower 22836384Ssklower if ((len - i) < 4) { 22936384Ssklower /* buffer not multiple of 4 */ 23036384Ssklower switch (len - i) { 23136384Ssklower case 3: 23236384Ssklower l |= buf[i+2] << 8; 23336384Ssklower case 2: 23436384Ssklower l |= buf[i+1] << 16; 23536384Ssklower case 1: 23636384Ssklower l |= buf[i] << 24; 23736384Ssklower break; 23836384Ssklower default: 23936384Ssklower printf("iso_hashchar: unexpected value x%x\n", len - i); 24036384Ssklower break; 24136384Ssklower } 24236384Ssklower } else { 24336384Ssklower l |= buf[i] << 24; 24436384Ssklower l |= buf[i+1] << 16; 24536384Ssklower l |= buf[i+2] << 8; 24636384Ssklower l |= buf[i+3]; 24736384Ssklower } 24836384Ssklower 24936384Ssklower h ^= l; 25036384Ssklower } 25136384Ssklower 25236384Ssklower h ^= (u_long) (len % 4); 25336384Ssklower 25436384Ssklower return(h); 25536384Ssklower } 25637469Ssklower #ifdef notdef 25736384Ssklower /* 25836384Ssklower * FUNCTION: iso_hash 25936384Ssklower * 26036384Ssklower * PURPOSE: Fill in fields of afhash structure based upon addr passed. 26136384Ssklower * 26236384Ssklower * RETURNS: none 26336384Ssklower * 26436384Ssklower * SIDE EFFECTS: 26536384Ssklower * 26636384Ssklower * NOTES: 26736384Ssklower */ 26836384Ssklower iso_hash(siso, hp) 26936384Ssklower struct sockaddr_iso *siso; /* address to perform hash on */ 27036384Ssklower struct afhash *hp; /* RETURN: hash info here */ 27136384Ssklower { 27236384Ssklower u_long buf[sizeof(struct sockaddr_iso)+1/4]; 27336384Ssklower register int bufsize; 27436384Ssklower 27536384Ssklower 27636384Ssklower bzero(buf, sizeof(buf)); 27736384Ssklower 27836384Ssklower bufsize = iso_netof(&siso->siso_addr, buf); 27936384Ssklower hp->afh_nethash = iso_hashchar((caddr_t)buf, bufsize); 28036384Ssklower 28136384Ssklower IFDEBUG(D_ROUTE) 28236384Ssklower printf("iso_hash: iso_netof: bufsize = %d\n", bufsize); 28336384Ssklower ENDDEBUG 28436384Ssklower 28536384Ssklower hp->afh_hosthash = iso_hashchar((caddr_t)&siso->siso_addr, 28636384Ssklower siso->siso_addr.isoa_len); 28736384Ssklower 28836384Ssklower IFDEBUG(D_ROUTE) 28936384Ssklower printf("iso_hash: %s: nethash = x%x, hosthash = x%x\n", 29036384Ssklower clnp_iso_addrp(&siso->siso_addr), hp->afh_nethash, 29136384Ssklower hp->afh_hosthash); 29236384Ssklower ENDDEBUG 29336384Ssklower } 29436384Ssklower /* 29536384Ssklower * FUNCTION: iso_netof 29636384Ssklower * 29736384Ssklower * PURPOSE: Extract the network portion of the iso address. 29836384Ssklower * The network portion of the iso address varies depending 29936384Ssklower * on the type of address. The network portion of the 30036384Ssklower * address will include the IDP. The network portion is: 30136384Ssklower * 30236384Ssklower * TYPE DESC 30336384Ssklower * t37 The AFI and x.121 (IDI) 30436384Ssklower * osinet The AFI, orgid, snetid 30536384Ssklower * rfc986 The AFI, vers and network part of 30636384Ssklower * internet address. 30736384Ssklower * 30836384Ssklower * RETURNS: number of bytes placed into buf. 30936384Ssklower * 31036384Ssklower * SIDE EFFECTS: 31136384Ssklower * 31236384Ssklower * NOTES: Buf is assumed to be big enough 31336384Ssklower */ 31436384Ssklower iso_netof(isoa, buf) 31536384Ssklower struct iso_addr *isoa; /* address */ 31636384Ssklower caddr_t buf; /* RESULT: network portion of address here */ 31736384Ssklower { 31836384Ssklower u_int len = 1; /* length of afi */ 31936384Ssklower 32036384Ssklower switch (isoa->isoa_afi) { 32136384Ssklower case AFI_37: 32236384Ssklower /* 32336384Ssklower * Due to classic x.25 tunnel vision, there is no 32436384Ssklower * net portion of an x.121 address. For our purposes 32536384Ssklower * the AFI will do, so that all x.25 -type addresses 32636384Ssklower * map to the single x.25 SNPA. (Cannot have more than 32736384Ssklower * one, obviously). 32836384Ssklower */ 32936384Ssklower 33036384Ssklower break; 33136384Ssklower 33236384Ssklower /* case AFI_OSINET:*/ 33336384Ssklower case AFI_RFC986: { 33436384Ssklower u_short idi; /* value of idi */ 33536384Ssklower 33636384Ssklower /* osinet and rfc986 have idi in the same place */ 33736384Ssklower CTOH(isoa->rfc986_idi[0], isoa->rfc986_idi[1], idi); 33836384Ssklower 33936384Ssklower if (idi == IDI_OSINET) 34036384Ssklower /* 34136384Ssklower * Network portion of OSINET address can only be the IDI. Clearly, 34236384Ssklower * with one x25 interface, one could get to several orgids, and 34336384Ssklower * several snetids. 34436384Ssklower len += (ADDROSINET_IDI_LEN + OVLOSINET_ORGID_LEN + 34536384Ssklower OVLOSINET_SNETID_LEN); 34636384Ssklower */ 34736384Ssklower len += ADDROSINET_IDI_LEN; 34836384Ssklower else if (idi == IDI_RFC986) { 34936384Ssklower u_long inetaddr; 35036384Ssklower struct ovl_rfc986 *o986 = (struct ovl_rfc986 *)isoa; 35136384Ssklower 35236384Ssklower /* bump len to include idi and version (1 byte) */ 35336384Ssklower len += ADDRRFC986_IDI_LEN + 1; 35436384Ssklower 35536384Ssklower /* get inet addr long aligned */ 35636384Ssklower bcopy(o986->o986_inetaddr, &inetaddr, sizeof(inetaddr)); 35736384Ssklower inetaddr = ntohl(inetaddr); /* convert to host byte order */ 35836384Ssklower 35936384Ssklower IFDEBUG(D_ROUTE) 36036384Ssklower printf("iso_netof: isoa "); 36136384Ssklower dump_buf(isoa, sizeof(*isoa)); 36236384Ssklower printf("iso_netof: inetaddr 0x%x ", inetaddr); 36336384Ssklower ENDDEBUG 36436384Ssklower 36536384Ssklower /* bump len by size of network portion of inet address */ 36636384Ssklower if (IN_CLASSA(inetaddr)) { 36736384Ssklower len += 4-IN_CLASSA_NSHIFT/8; 36836384Ssklower IFDEBUG(D_ROUTE) 36936384Ssklower printf("iso_netof: class A net len is now %d\n", len); 37036384Ssklower ENDDEBUG 37136384Ssklower } else if (IN_CLASSB(inetaddr)) { 37236384Ssklower len += 4-IN_CLASSB_NSHIFT/8; 37336384Ssklower IFDEBUG(D_ROUTE) 37436384Ssklower printf("iso_netof: class B net len is now %d\n", len); 37536384Ssklower ENDDEBUG 37636384Ssklower } else { 37736384Ssklower len += 4-IN_CLASSC_NSHIFT/8; 37836384Ssklower IFDEBUG(D_ROUTE) 37936384Ssklower printf("iso_netof: class C net len is now %d\n", len); 38036384Ssklower ENDDEBUG 38136384Ssklower } 38236384Ssklower } else 38336384Ssklower len = 0; 38436384Ssklower } break; 38536384Ssklower 38636384Ssklower default: 38736384Ssklower len = 0; 38836384Ssklower } 38936384Ssklower 39036384Ssklower bcopy((caddr_t)isoa, buf, len); 39136384Ssklower IFDEBUG(D_ROUTE) 39236384Ssklower printf("in_netof: isoa "); 39336384Ssklower dump_buf(isoa, len); 39436384Ssklower printf("in_netof: net "); 39536384Ssklower dump_buf(buf, len); 39636384Ssklower ENDDEBUG 39736384Ssklower return len; 39836384Ssklower } 39937469Ssklower #endif notdef 40036384Ssklower /* 40137469Ssklower * Generic iso control operations (ioctl's). 40237469Ssklower * Ifp is 0 if not an interface-specific ioctl. 40336384Ssklower */ 40437469Ssklower /* ARGSUSED */ 40536384Ssklower iso_control(so, cmd, data, ifp) 40637469Ssklower struct socket *so; 40737469Ssklower int cmd; 40837469Ssklower caddr_t data; 40937469Ssklower register struct ifnet *ifp; 41036384Ssklower { 41137469Ssklower register struct iso_ifreq *ifr = (struct iso_ifreq *)data; 41237469Ssklower register struct iso_ifaddr *ia = 0; 41337469Ssklower register struct ifaddr *ifa; 41437469Ssklower struct iso_ifaddr *oia; 41537469Ssklower struct iso_aliasreq *ifra = (struct iso_aliasreq *)data; 41637469Ssklower int error, hostIsNew, maskIsNew; 41736384Ssklower 41837469Ssklower /* 41937469Ssklower * Find address for this interface, if it exists. 42037469Ssklower */ 42137469Ssklower if (ifp) 42237469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) 42337469Ssklower if (ia->ia_ifp == ifp) 42437469Ssklower break; 42536384Ssklower 42636384Ssklower switch (cmd) { 42737469Ssklower 42837469Ssklower case SIOCAIFADDR_ISO: 42937469Ssklower case SIOCDIFADDR_ISO: 43037469Ssklower if (ifra->ifra_addr.siso_family == AF_ISO) 43137469Ssklower for (oia = ia; ia; ia = ia->ia_next) { 43237469Ssklower if (ia->ia_ifp == ifp && 43337469Ssklower SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr)) 43437469Ssklower break; 43537469Ssklower } 43650232Ssklower if ((so->so_state & SS_PRIV) == 0) 43750232Ssklower return (EPERM); 43836384Ssklower if (ifp == 0) 43937469Ssklower panic("iso_control"); 44037469Ssklower if (ia == (struct iso_ifaddr *)0) { 44137469Ssklower struct iso_ifaddr *nia; 44237469Ssklower if (cmd == SIOCDIFADDR_ISO) 44337469Ssklower return (EADDRNOTAVAIL); 44437469Ssklower MALLOC(nia, struct iso_ifaddr *, sizeof(*nia), 44537469Ssklower M_IFADDR, M_WAITOK); 44637469Ssklower if (nia == (struct iso_ifaddr *)0) 44737469Ssklower return (ENOBUFS); 44837469Ssklower bzero((caddr_t)nia, sizeof(*nia)); 44937469Ssklower if (ia = iso_ifaddr) { 45037469Ssklower for ( ; ia->ia_next; ia = ia->ia_next) 45137469Ssklower ; 45237469Ssklower ia->ia_next = nia; 45337469Ssklower } else 45437469Ssklower iso_ifaddr = nia; 45537469Ssklower ia = nia; 45637469Ssklower if (ifa = ifp->if_addrlist) { 45737469Ssklower for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 45837469Ssklower ; 45937469Ssklower ifa->ifa_next = (struct ifaddr *) ia; 46037469Ssklower } else 46137469Ssklower ifp->if_addrlist = (struct ifaddr *) ia; 46237469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 46337469Ssklower ia->ia_ifa.ifa_dstaddr 46437469Ssklower = (struct sockaddr *)&ia->ia_dstaddr; 46537469Ssklower ia->ia_ifa.ifa_netmask 46637469Ssklower = (struct sockaddr *)&ia->ia_sockmask; 46737469Ssklower ia->ia_ifp = ifp; 46837469Ssklower if (ifp != &loif) 46937469Ssklower iso_interfaces++; 47037469Ssklower } 47137469Ssklower break; 47236384Ssklower 47337469Ssklower #define cmdbyte(x) (((x) >> 8) & 0xff) 47437469Ssklower default: 47537469Ssklower if (cmdbyte(cmd) == 'a') 47650232Ssklower return (snpac_ioctl(so, cmd, data)); 47737469Ssklower if (ia == (struct iso_ifaddr *)0) 47837469Ssklower return (EADDRNOTAVAIL); 47937469Ssklower break; 48037469Ssklower } 48137469Ssklower switch (cmd) { 48236384Ssklower 48337469Ssklower case SIOCGIFADDR_ISO: 48437469Ssklower ifr->ifr_Addr = ia->ia_addr; 48537469Ssklower break; 48636384Ssklower 48737469Ssklower case SIOCGIFDSTADDR_ISO: 48837469Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 48937469Ssklower return (EINVAL); 49037469Ssklower ifr->ifr_Addr = ia->ia_dstaddr; 49137469Ssklower break; 49236384Ssklower 49337469Ssklower case SIOCGIFNETMASK_ISO: 49437469Ssklower ifr->ifr_Addr = ia->ia_sockmask; 49537469Ssklower break; 49636384Ssklower 49737469Ssklower case SIOCAIFADDR_ISO: 49843428Ssklower maskIsNew = 0; hostIsNew = 1; error = 0; 49937469Ssklower if (ia->ia_addr.siso_family == AF_ISO) { 50037469Ssklower if (ifra->ifra_addr.siso_len == 0) { 50137469Ssklower ifra->ifra_addr = ia->ia_addr; 50237469Ssklower hostIsNew = 0; 50337469Ssklower } else if (SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr)) 50437469Ssklower hostIsNew = 0; 50537469Ssklower } 50637469Ssklower if (ifra->ifra_mask.siso_len) { 50737469Ssklower iso_ifscrub(ifp, ia); 50837469Ssklower ia->ia_sockmask = ifra->ifra_mask; 50937469Ssklower maskIsNew = 1; 51037469Ssklower } 51137469Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) && 51237469Ssklower (ifra->ifra_dstaddr.siso_family == AF_ISO)) { 51337469Ssklower iso_ifscrub(ifp, ia); 51437469Ssklower ia->ia_dstaddr = ifra->ifra_dstaddr; 51537469Ssklower maskIsNew = 1; /* We lie; but the effect's the same */ 51637469Ssklower } 51737469Ssklower if (ifra->ifra_addr.siso_family == AF_ISO && 51837469Ssklower (hostIsNew || maskIsNew)) { 51937469Ssklower error = iso_ifinit(ifp, ia, &ifra->ifra_addr, 0); 52037469Ssklower } 52137469Ssklower if (ifra->ifra_snpaoffset) 52237469Ssklower ia->ia_snpaoffset = ifra->ifra_snpaoffset; 52337469Ssklower return (error); 52437469Ssklower 52537469Ssklower case SIOCDIFADDR_ISO: 52637469Ssklower iso_ifscrub(ifp, ia); 52737469Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 52837469Ssklower ifp->if_addrlist = ifa->ifa_next; 52937469Ssklower else { 53037469Ssklower while (ifa->ifa_next && 53137469Ssklower (ifa->ifa_next != (struct ifaddr *)ia)) 53237469Ssklower ifa = ifa->ifa_next; 53337469Ssklower if (ifa->ifa_next) 53437469Ssklower ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 53537469Ssklower else 53637469Ssklower printf("Couldn't unlink isoifaddr from ifp\n"); 53737469Ssklower } 53837469Ssklower oia = ia; 53937469Ssklower if (oia == (ia = iso_ifaddr)) { 54037469Ssklower iso_ifaddr = ia->ia_next; 54137469Ssklower } else { 54237469Ssklower while (ia->ia_next && (ia->ia_next != oia)) { 54337469Ssklower ia = ia->ia_next; 54436384Ssklower } 54537469Ssklower if (ia->ia_next) 54637469Ssklower ia->ia_next = oia->ia_next; 54737469Ssklower else 54837469Ssklower printf("Didn't unlink isoifadr from list\n"); 54936384Ssklower } 550*52030Ssklower IFAFREE((&oia->ia_ifa)); 55137469Ssklower break; 55236384Ssklower 55336384Ssklower default: 55436384Ssklower if (ifp == 0 || ifp->if_ioctl == 0) 55536384Ssklower return (EOPNOTSUPP); 55636384Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data)); 55736384Ssklower } 55837469Ssklower return (0); 55936384Ssklower } 56036384Ssklower 56137469Ssklower /* 56237469Ssklower * Delete any existing route for an interface. 56337469Ssklower */ 56437469Ssklower iso_ifscrub(ifp, ia) 56537469Ssklower register struct ifnet *ifp; 56637469Ssklower register struct iso_ifaddr *ia; 56737469Ssklower { 56843333Ssklower int nsellength = ia->ia_addr.siso_tlen; 56937469Ssklower if ((ia->ia_flags & IFA_ROUTE) == 0) 57037469Ssklower return; 57143333Ssklower ia->ia_addr.siso_tlen = 0; 57237469Ssklower if (ifp->if_flags & IFF_LOOPBACK) 57337469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 57437469Ssklower else if (ifp->if_flags & IFF_POINTOPOINT) 57537469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 57637469Ssklower else { 57737469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 57837469Ssklower } 57943333Ssklower ia->ia_addr.siso_tlen = nsellength; 58037469Ssklower ia->ia_flags &= ~IFA_ROUTE; 58137469Ssklower } 58237469Ssklower 58337469Ssklower /* 58437469Ssklower * Initialize an interface's internet address 58537469Ssklower * and routing table entry. 58637469Ssklower */ 58737469Ssklower iso_ifinit(ifp, ia, siso, scrub) 58837469Ssklower register struct ifnet *ifp; 58937469Ssklower register struct iso_ifaddr *ia; 59037469Ssklower struct sockaddr_iso *siso; 59137469Ssklower { 59237469Ssklower struct sockaddr_iso oldaddr; 59343333Ssklower int s = splimp(), error, nsellength; 59437469Ssklower 59537469Ssklower oldaddr = ia->ia_addr; 59637469Ssklower ia->ia_addr = *siso; 59737469Ssklower /* 59837469Ssklower * Give the interface a chance to initialize 59937469Ssklower * if this is its first address, 60037469Ssklower * and to validate the address if necessary. 60137469Ssklower */ 60237469Ssklower if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 60337469Ssklower splx(s); 60437469Ssklower ia->ia_addr = oldaddr; 60537469Ssklower return (error); 60637469Ssklower } 60737469Ssklower if (scrub) { 60837469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 60937469Ssklower iso_ifscrub(ifp, ia); 61037469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 61137469Ssklower } 61243333Ssklower /* XXX -- The following is here temporarily out of laziness 61343333Ssklower in not changing every ethernet driver's if_ioctl routine */ 61443333Ssklower if (ifp->if_output == ether_output) { 61543333Ssklower ia->ia_ifa.ifa_rtrequest = llc_rtrequest; 61643333Ssklower ia->ia_ifa.ifa_flags |= RTF_CLONING; 61743333Ssklower } 61837469Ssklower /* 61937469Ssklower * Add route for the network. 62037469Ssklower */ 62143333Ssklower nsellength = ia->ia_addr.siso_tlen; 62243333Ssklower ia->ia_addr.siso_tlen = 0; 62337469Ssklower if (ifp->if_flags & IFF_LOOPBACK) { 62437469Ssklower ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 62540894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 62637469Ssklower } else if (ifp->if_flags & IFF_POINTOPOINT && 62737469Ssklower ia->ia_dstaddr.siso_family == AF_ISO) 62840894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 62937469Ssklower else { 63040894Ssklower rt_maskedcopy(ia->ia_ifa.ifa_addr, ia->ia_ifa.ifa_dstaddr, 63140894Ssklower ia->ia_ifa.ifa_netmask); 63249936Ssklower ia->ia_dstaddr.siso_nlen = 63349936Ssklower min(ia->ia_addr.siso_nlen, (ia->ia_sockmask.siso_len - 6)); 63440894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP); 63537469Ssklower } 63643333Ssklower ia->ia_addr.siso_tlen = nsellength; 63737469Ssklower ia->ia_flags |= IFA_ROUTE; 63837469Ssklower splx(s); 63940894Ssklower return (error); 64037469Ssklower } 64137469Ssklower #ifdef notdef 64237469Ssklower 64336384Ssklower struct ifaddr * 64436384Ssklower iso_ifwithidi(addr) 64536384Ssklower register struct sockaddr *addr; 64636384Ssklower { 64736384Ssklower register struct ifnet *ifp; 64836384Ssklower register struct ifaddr *ifa; 64936384Ssklower register u_int af = addr->sa_family; 65036384Ssklower 65136384Ssklower if (af != AF_ISO) 65236384Ssklower return (0); 65336384Ssklower IFDEBUG(D_ROUTE) 65436384Ssklower printf(">>> iso_ifwithidi addr\n"); 65536384Ssklower dump_isoaddr( (struct sockaddr_iso *)(addr)); 65636384Ssklower printf("\n"); 65736384Ssklower ENDDEBUG 65836384Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) { 65936384Ssklower IFDEBUG(D_ROUTE) 66036384Ssklower printf("iso_ifwithidi ifnet %s\n", ifp->if_name); 66136384Ssklower ENDDEBUG 66236384Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 66336384Ssklower IFDEBUG(D_ROUTE) 66436384Ssklower printf("iso_ifwithidi address "); 66537469Ssklower dump_isoaddr( (struct sockaddr_iso *)(ifa->ifa_addr)); 66636384Ssklower ENDDEBUG 66737469Ssklower if (ifa->ifa_addr->sa_family != addr->sa_family) 66836384Ssklower continue; 66936384Ssklower 67036384Ssklower #define IFA_SIS(ifa)\ 67137469Ssklower ((struct sockaddr_iso *)((ifa)->ifa_addr)) 67236384Ssklower 67336384Ssklower IFDEBUG(D_ROUTE) 67436384Ssklower printf(" af same, args to iso_eqtype:\n"); 67536384Ssklower printf("0x%x ", IFA_SIS(ifa)->siso_addr); 67636384Ssklower printf(" 0x%x\n", 67736384Ssklower &(((struct sockaddr_iso *)addr)->siso_addr)); 67836384Ssklower ENDDEBUG 67936384Ssklower 68036384Ssklower if (iso_eqtype(&(IFA_SIS(ifa)->siso_addr), 68136384Ssklower &(((struct sockaddr_iso *)addr)->siso_addr))) { 68236384Ssklower IFDEBUG(D_ROUTE) 68336384Ssklower printf("ifa_ifwithidi: ifa found\n"); 68436384Ssklower ENDDEBUG 68536384Ssklower return (ifa); 68636384Ssklower } 68736384Ssklower IFDEBUG(D_ROUTE) 68836384Ssklower printf(" iso_eqtype failed\n"); 68936384Ssklower ENDDEBUG 69036384Ssklower } 69136384Ssklower } 69236384Ssklower return ((struct ifaddr *)0); 69336384Ssklower } 69436384Ssklower 69537469Ssklower #endif notdef 69636384Ssklower /* 69736384Ssklower * FUNCTION: iso_ck_addr 69836384Ssklower * 69936384Ssklower * PURPOSE: return true if the iso_addr passed is 70036384Ssklower * within the legal size limit for an iso address. 70136384Ssklower * 70236384Ssklower * RETURNS: true or false 70336384Ssklower * 70436384Ssklower * SIDE EFFECTS: 70536384Ssklower * 70636384Ssklower */ 70736384Ssklower iso_ck_addr(isoa) 70836384Ssklower struct iso_addr *isoa; /* address to check */ 70936384Ssklower { 71036384Ssklower return (isoa->isoa_len <= 20); 71136384Ssklower 71236384Ssklower } 71336384Ssklower 71437469Ssklower #ifdef notdef 71536384Ssklower /* 71636384Ssklower * FUNCTION: iso_eqtype 71736384Ssklower * 71836384Ssklower * PURPOSE: Determine if two iso addresses are of the same type. 71936384Ssklower * This is flaky. Really we should consider all type 47 addrs to be the 72036384Ssklower * same - but there do exist different structures for 47 addrs. 72136384Ssklower * Gosip adds a 3rd. 72236384Ssklower * 72336384Ssklower * RETURNS: true if the addresses are the same type 72436384Ssklower * 72536384Ssklower * SIDE EFFECTS: 72636384Ssklower * 72736384Ssklower * NOTES: By type, I mean rfc986, t37, or osinet 72836384Ssklower * 72936384Ssklower * This will first compare afis. If they match, then 73036384Ssklower * if the addr is not t37, the idis must be compared. 73136384Ssklower */ 73236384Ssklower iso_eqtype(isoaa, isoab) 73336384Ssklower struct iso_addr *isoaa; /* first addr to check */ 73436384Ssklower struct iso_addr *isoab; /* other addr to check */ 73536384Ssklower { 73636384Ssklower if (isoaa->isoa_afi == isoab->isoa_afi) { 73736384Ssklower if (isoaa->isoa_afi == AFI_37) 73836384Ssklower return(1); 73936384Ssklower else 74036384Ssklower return (!bcmp(&isoaa->isoa_u, &isoab->isoa_u, 2)); 74136384Ssklower } 74236384Ssklower return(0); 74336384Ssklower } 74437469Ssklower #endif notdef 74536384Ssklower /* 74637469Ssklower * FUNCTION: iso_localifa() 74736384Ssklower * 74837469Ssklower * PURPOSE: Find an interface addresss having a given destination 74937469Ssklower * or at least matching the net. 75036384Ssklower * 75136384Ssklower * RETURNS: ptr to an interface address 75236384Ssklower * 75336384Ssklower * SIDE EFFECTS: 75436384Ssklower * 75536384Ssklower * NOTES: 75636384Ssklower */ 75736384Ssklower struct iso_ifaddr * 75837469Ssklower iso_localifa(siso) 75937469Ssklower register struct sockaddr_iso *siso; 76036384Ssklower { 76136384Ssklower register struct iso_ifaddr *ia; 76237469Ssklower register char *cp1, *cp2, *cp3; 76337469Ssklower register struct ifnet *ifp; 76437469Ssklower struct iso_ifaddr *ia_maybe = 0; 76537469Ssklower /* 76637469Ssklower * We make one pass looking for both net matches and an exact 76737469Ssklower * dst addr. 76837469Ssklower */ 76937469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 77037469Ssklower if ((ifp = ia->ia_ifp) == 0 || ((ifp->if_flags & IFF_UP) == 0)) 77137469Ssklower continue; 77237469Ssklower if (ifp->if_flags & IFF_POINTOPOINT) { 77337469Ssklower if ((ia->ia_dstaddr.siso_family == AF_ISO) && 77437469Ssklower SAME_ISOADDR(&ia->ia_dstaddr, siso)) 77537469Ssklower return (ia); 77637469Ssklower else 77737469Ssklower if (SAME_ISOADDR(&ia->ia_addr, siso)) 77837469Ssklower ia_maybe = ia; 77937469Ssklower continue; 78037469Ssklower } 78137469Ssklower if (ia->ia_sockmask.siso_len) { 78237469Ssklower char *cplim = ia->ia_sockmask.siso_len + (char *)&ia->ia_sockmask; 78337469Ssklower cp1 = ia->ia_sockmask.siso_data; 78437469Ssklower cp2 = siso->siso_data; 78537469Ssklower cp3 = ia->ia_addr.siso_data; 78639936Ssklower while (cp1 < cplim) 78737469Ssklower if (*cp1++ & (*cp2++ ^ *cp3++)) 78837469Ssklower goto next; 78937469Ssklower ia_maybe = ia; 79037469Ssklower } 79137469Ssklower if (SAME_ISOADDR(&ia->ia_addr, siso)) 79237469Ssklower return ia; 79337469Ssklower next:; 79437469Ssklower } 79537469Ssklower return ia_maybe; 79636384Ssklower } 79736384Ssklower 79847272Ssklower #ifdef TPCONS 79936384Ssklower #include "cons.h" 80047272Ssklower #endif TPCONS 80136384Ssklower /* 80236384Ssklower * FUNCTION: iso_nlctloutput 80336384Ssklower * 80436384Ssklower * PURPOSE: Set options at the network level 80536384Ssklower * 80636384Ssklower * RETURNS: E* 80736384Ssklower * 80836384Ssklower * SIDE EFFECTS: 80936384Ssklower * 81036384Ssklower * NOTES: This could embody some of the functions of 81136384Ssklower * rclnp_ctloutput and cons_ctloutput. 81236384Ssklower */ 81336384Ssklower iso_nlctloutput(cmd, optname, pcb, m) 81436384Ssklower int cmd; /* command:set or get */ 81536384Ssklower int optname; /* option of interest */ 81636384Ssklower caddr_t pcb; /* nl pcb */ 81736384Ssklower struct mbuf *m; /* data for set, buffer for get */ 81836384Ssklower { 81936384Ssklower struct isopcb *isop = (struct isopcb *)pcb; 82036384Ssklower int error = 0; /* return value */ 82136384Ssklower caddr_t data; /* data for option */ 82236384Ssklower int data_len; /* data's length */ 82336384Ssklower 82436384Ssklower IFDEBUG(D_ISO) 82536384Ssklower printf("iso_nlctloutput: cmd %x, opt %x, pcb %x, m %x\n", 82636384Ssklower cmd, optname, pcb, m); 82736384Ssklower ENDDEBUG 82836384Ssklower 82936384Ssklower if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT)) 83036384Ssklower return(EOPNOTSUPP); 83136384Ssklower 83236384Ssklower data = mtod(m, caddr_t); 83336384Ssklower data_len = (m)->m_len; 83436384Ssklower 83536384Ssklower IFDEBUG(D_ISO) 83636384Ssklower printf("iso_nlctloutput: data is:\n"); 83736384Ssklower dump_buf(data, data_len); 83836384Ssklower ENDDEBUG 83936384Ssklower 84036384Ssklower switch (optname) { 84136384Ssklower 84247272Ssklower #ifdef TPCONS 84336384Ssklower case CONSOPT_X25CRUD: 84436384Ssklower if (cmd == PRCO_GETOPT) { 84536384Ssklower error = EOPNOTSUPP; 84636384Ssklower break; 84736384Ssklower } 84836384Ssklower 84936384Ssklower if (data_len > MAXX25CRUDLEN) { 85036384Ssklower error = EINVAL; 85136384Ssklower break; 85236384Ssklower } 85336384Ssklower 85436384Ssklower IFDEBUG(D_ISO) 85536384Ssklower printf("iso_nlctloutput: setting x25 crud\n"); 85636384Ssklower ENDDEBUG 85736384Ssklower 85837469Ssklower bcopy(data, (caddr_t)isop->isop_x25crud, (unsigned)data_len); 85936384Ssklower isop->isop_x25crud_len = data_len; 86036384Ssklower break; 86147272Ssklower #endif TPCONS 86236384Ssklower 86336384Ssklower default: 86436384Ssklower error = EOPNOTSUPP; 86536384Ssklower } 86650972Ssklower if (cmd == PRCO_SETOPT) 86750972Ssklower m_freem(m); 86836384Ssklower return error; 86936384Ssklower } 87036384Ssklower #endif ISO 87136384Ssklower 87236384Ssklower #ifdef ARGO_DEBUG 87336384Ssklower 87436384Ssklower /* 87536384Ssklower * FUNCTION: dump_isoaddr 87636384Ssklower * 87736384Ssklower * PURPOSE: debugging 87836384Ssklower * 87936384Ssklower * RETURNS: nada 88036384Ssklower * 88136384Ssklower */ 88236384Ssklower dump_isoaddr(s) 88336384Ssklower struct sockaddr_iso *s; 88436384Ssklower { 88537469Ssklower char *clnp_saddr_isop(); 88636384Ssklower register int i; 88736384Ssklower 88836384Ssklower if( s->siso_family == AF_ISO) { 88937469Ssklower printf("ISO address: suffixlen %d, %s\n", 89038841Ssklower s->siso_tlen, clnp_saddr_isop(s)); 89136384Ssklower } else if( s->siso_family == AF_INET) { 89236384Ssklower /* hack */ 89336384Ssklower struct sockaddr_in *sin = (struct sockaddr_in *)s; 89436384Ssklower 89536384Ssklower printf("%d.%d.%d.%d: %d", 89636384Ssklower (sin->sin_addr.s_addr>>24)&0xff, 89736384Ssklower (sin->sin_addr.s_addr>>16)&0xff, 89836384Ssklower (sin->sin_addr.s_addr>>8)&0xff, 89936384Ssklower (sin->sin_addr.s_addr)&0xff, 90036384Ssklower sin->sin_port); 90136384Ssklower } 90236384Ssklower } 90336384Ssklower 90436384Ssklower #endif ARGO_DEBUG 905