149268Sbostic /*- 249268Sbostic * Copyright (c) 1991 The Regents of the University of California. 349268Sbostic * All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*50972Ssklower * @(#)iso.c 7.16 (Berkeley) 09/03/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 } 55037469Ssklower free((caddr_t)oia, M_IFADDR); 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 ia->ia_ifa.ifa_llinfolen = sizeof(struct llinfo_llc); 61843333Ssklower } 61937469Ssklower /* 62037469Ssklower * Add route for the network. 62137469Ssklower */ 62243333Ssklower nsellength = ia->ia_addr.siso_tlen; 62343333Ssklower ia->ia_addr.siso_tlen = 0; 62437469Ssklower if (ifp->if_flags & IFF_LOOPBACK) { 62537469Ssklower ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 62640894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 62737469Ssklower } else if (ifp->if_flags & IFF_POINTOPOINT && 62837469Ssklower ia->ia_dstaddr.siso_family == AF_ISO) 62940894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 63037469Ssklower else { 63140894Ssklower rt_maskedcopy(ia->ia_ifa.ifa_addr, ia->ia_ifa.ifa_dstaddr, 63240894Ssklower ia->ia_ifa.ifa_netmask); 63349936Ssklower ia->ia_dstaddr.siso_nlen = 63449936Ssklower min(ia->ia_addr.siso_nlen, (ia->ia_sockmask.siso_len - 6)); 63540894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP); 63637469Ssklower } 63743333Ssklower ia->ia_addr.siso_tlen = nsellength; 63837469Ssklower ia->ia_flags |= IFA_ROUTE; 63937469Ssklower splx(s); 64040894Ssklower return (error); 64137469Ssklower } 64237469Ssklower #ifdef notdef 64337469Ssklower 64436384Ssklower struct ifaddr * 64536384Ssklower iso_ifwithidi(addr) 64636384Ssklower register struct sockaddr *addr; 64736384Ssklower { 64836384Ssklower register struct ifnet *ifp; 64936384Ssklower register struct ifaddr *ifa; 65036384Ssklower register u_int af = addr->sa_family; 65136384Ssklower 65236384Ssklower if (af != AF_ISO) 65336384Ssklower return (0); 65436384Ssklower IFDEBUG(D_ROUTE) 65536384Ssklower printf(">>> iso_ifwithidi addr\n"); 65636384Ssklower dump_isoaddr( (struct sockaddr_iso *)(addr)); 65736384Ssklower printf("\n"); 65836384Ssklower ENDDEBUG 65936384Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) { 66036384Ssklower IFDEBUG(D_ROUTE) 66136384Ssklower printf("iso_ifwithidi ifnet %s\n", ifp->if_name); 66236384Ssklower ENDDEBUG 66336384Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 66436384Ssklower IFDEBUG(D_ROUTE) 66536384Ssklower printf("iso_ifwithidi address "); 66637469Ssklower dump_isoaddr( (struct sockaddr_iso *)(ifa->ifa_addr)); 66736384Ssklower ENDDEBUG 66837469Ssklower if (ifa->ifa_addr->sa_family != addr->sa_family) 66936384Ssklower continue; 67036384Ssklower 67136384Ssklower #define IFA_SIS(ifa)\ 67237469Ssklower ((struct sockaddr_iso *)((ifa)->ifa_addr)) 67336384Ssklower 67436384Ssklower IFDEBUG(D_ROUTE) 67536384Ssklower printf(" af same, args to iso_eqtype:\n"); 67636384Ssklower printf("0x%x ", IFA_SIS(ifa)->siso_addr); 67736384Ssklower printf(" 0x%x\n", 67836384Ssklower &(((struct sockaddr_iso *)addr)->siso_addr)); 67936384Ssklower ENDDEBUG 68036384Ssklower 68136384Ssklower if (iso_eqtype(&(IFA_SIS(ifa)->siso_addr), 68236384Ssklower &(((struct sockaddr_iso *)addr)->siso_addr))) { 68336384Ssklower IFDEBUG(D_ROUTE) 68436384Ssklower printf("ifa_ifwithidi: ifa found\n"); 68536384Ssklower ENDDEBUG 68636384Ssklower return (ifa); 68736384Ssklower } 68836384Ssklower IFDEBUG(D_ROUTE) 68936384Ssklower printf(" iso_eqtype failed\n"); 69036384Ssklower ENDDEBUG 69136384Ssklower } 69236384Ssklower } 69336384Ssklower return ((struct ifaddr *)0); 69436384Ssklower } 69536384Ssklower 69637469Ssklower #endif notdef 69736384Ssklower /* 69836384Ssklower * FUNCTION: iso_ck_addr 69936384Ssklower * 70036384Ssklower * PURPOSE: return true if the iso_addr passed is 70136384Ssklower * within the legal size limit for an iso address. 70236384Ssklower * 70336384Ssklower * RETURNS: true or false 70436384Ssklower * 70536384Ssklower * SIDE EFFECTS: 70636384Ssklower * 70736384Ssklower */ 70836384Ssklower iso_ck_addr(isoa) 70936384Ssklower struct iso_addr *isoa; /* address to check */ 71036384Ssklower { 71136384Ssklower return (isoa->isoa_len <= 20); 71236384Ssklower 71336384Ssklower } 71436384Ssklower 71537469Ssklower #ifdef notdef 71636384Ssklower /* 71736384Ssklower * FUNCTION: iso_eqtype 71836384Ssklower * 71936384Ssklower * PURPOSE: Determine if two iso addresses are of the same type. 72036384Ssklower * This is flaky. Really we should consider all type 47 addrs to be the 72136384Ssklower * same - but there do exist different structures for 47 addrs. 72236384Ssklower * Gosip adds a 3rd. 72336384Ssklower * 72436384Ssklower * RETURNS: true if the addresses are the same type 72536384Ssklower * 72636384Ssklower * SIDE EFFECTS: 72736384Ssklower * 72836384Ssklower * NOTES: By type, I mean rfc986, t37, or osinet 72936384Ssklower * 73036384Ssklower * This will first compare afis. If they match, then 73136384Ssklower * if the addr is not t37, the idis must be compared. 73236384Ssklower */ 73336384Ssklower iso_eqtype(isoaa, isoab) 73436384Ssklower struct iso_addr *isoaa; /* first addr to check */ 73536384Ssklower struct iso_addr *isoab; /* other addr to check */ 73636384Ssklower { 73736384Ssklower if (isoaa->isoa_afi == isoab->isoa_afi) { 73836384Ssklower if (isoaa->isoa_afi == AFI_37) 73936384Ssklower return(1); 74036384Ssklower else 74136384Ssklower return (!bcmp(&isoaa->isoa_u, &isoab->isoa_u, 2)); 74236384Ssklower } 74336384Ssklower return(0); 74436384Ssklower } 74537469Ssklower #endif notdef 74636384Ssklower /* 74737469Ssklower * FUNCTION: iso_localifa() 74836384Ssklower * 74937469Ssklower * PURPOSE: Find an interface addresss having a given destination 75037469Ssklower * or at least matching the net. 75136384Ssklower * 75236384Ssklower * RETURNS: ptr to an interface address 75336384Ssklower * 75436384Ssklower * SIDE EFFECTS: 75536384Ssklower * 75636384Ssklower * NOTES: 75736384Ssklower */ 75836384Ssklower struct iso_ifaddr * 75937469Ssklower iso_localifa(siso) 76037469Ssklower register struct sockaddr_iso *siso; 76136384Ssklower { 76236384Ssklower register struct iso_ifaddr *ia; 76337469Ssklower register char *cp1, *cp2, *cp3; 76437469Ssklower register struct ifnet *ifp; 76537469Ssklower struct iso_ifaddr *ia_maybe = 0; 76637469Ssklower /* 76737469Ssklower * We make one pass looking for both net matches and an exact 76837469Ssklower * dst addr. 76937469Ssklower */ 77037469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 77137469Ssklower if ((ifp = ia->ia_ifp) == 0 || ((ifp->if_flags & IFF_UP) == 0)) 77237469Ssklower continue; 77337469Ssklower if (ifp->if_flags & IFF_POINTOPOINT) { 77437469Ssklower if ((ia->ia_dstaddr.siso_family == AF_ISO) && 77537469Ssklower SAME_ISOADDR(&ia->ia_dstaddr, siso)) 77637469Ssklower return (ia); 77737469Ssklower else 77837469Ssklower if (SAME_ISOADDR(&ia->ia_addr, siso)) 77937469Ssklower ia_maybe = ia; 78037469Ssklower continue; 78137469Ssklower } 78237469Ssklower if (ia->ia_sockmask.siso_len) { 78337469Ssklower char *cplim = ia->ia_sockmask.siso_len + (char *)&ia->ia_sockmask; 78437469Ssklower cp1 = ia->ia_sockmask.siso_data; 78537469Ssklower cp2 = siso->siso_data; 78637469Ssklower cp3 = ia->ia_addr.siso_data; 78739936Ssklower while (cp1 < cplim) 78837469Ssklower if (*cp1++ & (*cp2++ ^ *cp3++)) 78937469Ssklower goto next; 79037469Ssklower ia_maybe = ia; 79137469Ssklower } 79237469Ssklower if (SAME_ISOADDR(&ia->ia_addr, siso)) 79337469Ssklower return ia; 79437469Ssklower next:; 79537469Ssklower } 79637469Ssklower return ia_maybe; 79736384Ssklower } 79836384Ssklower 79947272Ssklower #ifdef TPCONS 80036384Ssklower #include "cons.h" 80147272Ssklower #endif TPCONS 80236384Ssklower /* 80336384Ssklower * FUNCTION: iso_nlctloutput 80436384Ssklower * 80536384Ssklower * PURPOSE: Set options at the network level 80636384Ssklower * 80736384Ssklower * RETURNS: E* 80836384Ssklower * 80936384Ssklower * SIDE EFFECTS: 81036384Ssklower * 81136384Ssklower * NOTES: This could embody some of the functions of 81236384Ssklower * rclnp_ctloutput and cons_ctloutput. 81336384Ssklower */ 81436384Ssklower iso_nlctloutput(cmd, optname, pcb, m) 81536384Ssklower int cmd; /* command:set or get */ 81636384Ssklower int optname; /* option of interest */ 81736384Ssklower caddr_t pcb; /* nl pcb */ 81836384Ssklower struct mbuf *m; /* data for set, buffer for get */ 81936384Ssklower { 82036384Ssklower struct isopcb *isop = (struct isopcb *)pcb; 82136384Ssklower int error = 0; /* return value */ 82236384Ssklower caddr_t data; /* data for option */ 82336384Ssklower int data_len; /* data's length */ 82436384Ssklower 82536384Ssklower IFDEBUG(D_ISO) 82636384Ssklower printf("iso_nlctloutput: cmd %x, opt %x, pcb %x, m %x\n", 82736384Ssklower cmd, optname, pcb, m); 82836384Ssklower ENDDEBUG 82936384Ssklower 83036384Ssklower if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT)) 83136384Ssklower return(EOPNOTSUPP); 83236384Ssklower 83336384Ssklower data = mtod(m, caddr_t); 83436384Ssklower data_len = (m)->m_len; 83536384Ssklower 83636384Ssklower IFDEBUG(D_ISO) 83736384Ssklower printf("iso_nlctloutput: data is:\n"); 83836384Ssklower dump_buf(data, data_len); 83936384Ssklower ENDDEBUG 84036384Ssklower 84136384Ssklower switch (optname) { 84236384Ssklower 84347272Ssklower #ifdef TPCONS 84436384Ssklower case CONSOPT_X25CRUD: 84536384Ssklower if (cmd == PRCO_GETOPT) { 84636384Ssklower error = EOPNOTSUPP; 84736384Ssklower break; 84836384Ssklower } 84936384Ssklower 85036384Ssklower if (data_len > MAXX25CRUDLEN) { 85136384Ssklower error = EINVAL; 85236384Ssklower break; 85336384Ssklower } 85436384Ssklower 85536384Ssklower IFDEBUG(D_ISO) 85636384Ssklower printf("iso_nlctloutput: setting x25 crud\n"); 85736384Ssklower ENDDEBUG 85836384Ssklower 85937469Ssklower bcopy(data, (caddr_t)isop->isop_x25crud, (unsigned)data_len); 86036384Ssklower isop->isop_x25crud_len = data_len; 86136384Ssklower break; 86247272Ssklower #endif TPCONS 86336384Ssklower 86436384Ssklower default: 86536384Ssklower error = EOPNOTSUPP; 86636384Ssklower } 867*50972Ssklower if (cmd == PRCO_SETOPT) 868*50972Ssklower m_freem(m); 86936384Ssklower return error; 87036384Ssklower } 87136384Ssklower #endif ISO 87236384Ssklower 87336384Ssklower #ifdef ARGO_DEBUG 87436384Ssklower 87536384Ssklower /* 87636384Ssklower * FUNCTION: dump_isoaddr 87736384Ssklower * 87836384Ssklower * PURPOSE: debugging 87936384Ssklower * 88036384Ssklower * RETURNS: nada 88136384Ssklower * 88236384Ssklower */ 88336384Ssklower dump_isoaddr(s) 88436384Ssklower struct sockaddr_iso *s; 88536384Ssklower { 88637469Ssklower char *clnp_saddr_isop(); 88736384Ssklower register int i; 88836384Ssklower 88936384Ssklower if( s->siso_family == AF_ISO) { 89037469Ssklower printf("ISO address: suffixlen %d, %s\n", 89138841Ssklower s->siso_tlen, clnp_saddr_isop(s)); 89236384Ssklower } else if( s->siso_family == AF_INET) { 89336384Ssklower /* hack */ 89436384Ssklower struct sockaddr_in *sin = (struct sockaddr_in *)s; 89536384Ssklower 89636384Ssklower printf("%d.%d.%d.%d: %d", 89736384Ssklower (sin->sin_addr.s_addr>>24)&0xff, 89836384Ssklower (sin->sin_addr.s_addr>>16)&0xff, 89936384Ssklower (sin->sin_addr.s_addr>>8)&0xff, 90036384Ssklower (sin->sin_addr.s_addr)&0xff, 90136384Ssklower sin->sin_port); 90236384Ssklower } 90336384Ssklower } 90436384Ssklower 90536384Ssklower #endif ARGO_DEBUG 906