149268Sbostic /*-
263222Sbostic * Copyright (c) 1991, 1993
363222Sbostic * The Regents of the University of California. All rights reserved.
449268Sbostic *
549268Sbostic * %sccs.include.redist.c%
649268Sbostic *
7*68165Scgd * @(#)iso.c 8.3 (Berkeley) 01/09/95
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
4356533Sbostic #include <sys/param.h>
4456533Sbostic #include <sys/systm.h>
4556533Sbostic #include <sys/ioctl.h>
4656533Sbostic #include <sys/mbuf.h>
4756533Sbostic #include <sys/domain.h>
4856533Sbostic #include <sys/protosw.h>
4956533Sbostic #include <sys/socket.h>
5056533Sbostic #include <sys/socketvar.h>
5156533Sbostic #include <sys/errno.h>
5236384Ssklower
5356533Sbostic #include <net/if.h>
5456533Sbostic #include <net/route.h>
5536384Ssklower
5656533Sbostic #include <netiso/iso.h>
5756533Sbostic #include <netiso/iso_var.h>
5856533Sbostic #include <netiso/iso_snpac.h>
5956533Sbostic #include <netiso/iso_pcb.h>
6056533Sbostic #include <netiso/clnp.h>
6156533Sbostic #include <netiso/argo_debug.h>
6256913Ssklower #ifdef TUBA
6356913Ssklower #include <netiso/tuba_table.h>
6456913Ssklower #endif
6536384Ssklower
6636384Ssklower #ifdef ISO
6736384Ssklower
6836384Ssklower int iso_interfaces = 0; /* number of external interfaces */
6936384Ssklower extern struct ifnet loif; /* loopback interface */
7054823Ssklower int ether_output();
7154823Ssklower void llc_rtrequest();
7236384Ssklower
7336384Ssklower /*
7436384Ssklower * FUNCTION: iso_addrmatch1
7536384Ssklower *
7636384Ssklower * PURPOSE: decide if the two iso_addrs passed are equal
7736384Ssklower *
7836384Ssklower * RETURNS: true if the addrs match, false if they do not
7936384Ssklower *
8036384Ssklower * SIDE EFFECTS:
8136384Ssklower *
8236384Ssklower * NOTES:
8336384Ssklower */
iso_addrmatch1(isoaa,isoab)8436384Ssklower iso_addrmatch1(isoaa, isoab)
8537469Ssklower register struct iso_addr *isoaa, *isoab; /* addresses to check */
8636384Ssklower {
8737469Ssklower u_int compare_len;
8836384Ssklower
8936384Ssklower IFDEBUG(D_ROUTE)
9036384Ssklower printf("iso_addrmatch1: comparing lengths: %d to %d\n", isoaa->isoa_len,
9136384Ssklower isoab->isoa_len);
9236384Ssklower printf("a:\n");
9337469Ssklower dump_buf(isoaa->isoa_genaddr, isoaa->isoa_len);
9436384Ssklower printf("b:\n");
9537469Ssklower dump_buf(isoab->isoa_genaddr, isoab->isoa_len);
9636384Ssklower ENDDEBUG
9736384Ssklower
9836384Ssklower if ((compare_len = isoaa->isoa_len) != isoab->isoa_len) {
9936384Ssklower IFDEBUG(D_ROUTE)
10036384Ssklower printf("iso_addrmatch1: returning false because of lengths\n");
10136384Ssklower ENDDEBUG
10236384Ssklower return 0;
10336384Ssklower }
10436384Ssklower
10537469Ssklower #ifdef notdef
10636384Ssklower /* TODO : generalize this to all afis with masks */
10736384Ssklower if( isoaa->isoa_afi == AFI_37 ) {
10836384Ssklower /* must not compare 2 least significant digits, or for
10936384Ssklower * that matter, the DSP
11036384Ssklower */
11136384Ssklower compare_len = ADDR37_IDI_LEN - 1;
11236384Ssklower }
11337469Ssklower #endif
11436384Ssklower
11536384Ssklower IFDEBUG(D_ROUTE)
11636384Ssklower int i;
11736384Ssklower char *a, *b;
11836384Ssklower
11937469Ssklower a = isoaa->isoa_genaddr;
12037469Ssklower b = isoab->isoa_genaddr;
12136384Ssklower
12236384Ssklower for (i=0; i<compare_len; i++) {
12336384Ssklower printf("<%x=%x>", a[i]&0xff, b[i]&0xff);
12436384Ssklower if (a[i] != b[i]) {
12536384Ssklower printf("\naddrs are not equal at byte %d\n", i);
12636384Ssklower return(0);
12736384Ssklower }
12836384Ssklower }
12936384Ssklower printf("\n");
13036384Ssklower printf("addrs are equal\n");
13136384Ssklower return (1);
13236384Ssklower ENDDEBUG
13337469Ssklower return (!bcmp(isoaa->isoa_genaddr, isoab->isoa_genaddr, compare_len));
13436384Ssklower }
13536384Ssklower
13636384Ssklower /*
13736384Ssklower * FUNCTION: iso_addrmatch
13836384Ssklower *
13936384Ssklower * PURPOSE: decide if the two sockadrr_isos passed are equal
14036384Ssklower *
14136384Ssklower * RETURNS: true if the addrs match, false if they do not
14236384Ssklower *
14336384Ssklower * SIDE EFFECTS:
14436384Ssklower *
14536384Ssklower * NOTES:
14636384Ssklower */
14736384Ssklower iso_addrmatch(sisoa, sisob)
14836384Ssklower struct sockaddr_iso *sisoa, *sisob; /* addresses to check */
14936384Ssklower {
15036384Ssklower return(iso_addrmatch1(&sisoa->siso_addr, &sisob->siso_addr));
15136384Ssklower }
15237469Ssklower #ifdef notdef
15336384Ssklower /*
15436384Ssklower * FUNCTION: iso_netmatch
15536384Ssklower *
15636384Ssklower * PURPOSE: similar to iso_addrmatch but takes sockaddr_iso
15736384Ssklower * as argument.
15836384Ssklower *
15936384Ssklower * RETURNS: true if same net, false if not
16036384Ssklower *
16136384Ssklower * SIDE EFFECTS:
16236384Ssklower *
16336384Ssklower * NOTES:
16436384Ssklower */
16536384Ssklower iso_netmatch(sisoa, sisob)
16636384Ssklower struct sockaddr_iso *sisoa, *sisob;
16736384Ssklower {
16836384Ssklower u_char bufa[sizeof(struct sockaddr_iso)];
16936384Ssklower u_char bufb[sizeof(struct sockaddr_iso)];
17036384Ssklower register int lena, lenb;
17136384Ssklower
17236384Ssklower lena = iso_netof(&sisoa->siso_addr, bufa);
17336384Ssklower lenb = iso_netof(&sisob->siso_addr, bufb);
17436384Ssklower
17536384Ssklower IFDEBUG(D_ROUTE)
17636384Ssklower printf("iso_netmatch: comparing lengths: %d to %d\n", lena, lenb);
17736384Ssklower printf("a:\n");
17836384Ssklower dump_buf(bufa, lena);
17936384Ssklower printf("b:\n");
18036384Ssklower dump_buf(bufb, lenb);
18136384Ssklower ENDDEBUG
18236384Ssklower
18336384Ssklower return ((lena == lenb) && (!bcmp(bufa, bufb, lena)));
18436384Ssklower }
18560359Sbostic #endif /* notdef */
18636384Ssklower
18736384Ssklower /*
18836384Ssklower * FUNCTION: iso_hashchar
18936384Ssklower *
19036384Ssklower * PURPOSE: Hash all character in the buffer specified into
19136384Ssklower * a long. Return the long.
19236384Ssklower *
19336384Ssklower * RETURNS: The hash value.
19436384Ssklower *
19536384Ssklower * SIDE EFFECTS:
19636384Ssklower *
19736384Ssklower * NOTES: The hash is achieved by exclusive ORing 4 byte
19836384Ssklower * quantities.
19936384Ssklower */
20036384Ssklower u_long
iso_hashchar(buf,len)20136384Ssklower iso_hashchar(buf, len)
20236384Ssklower register caddr_t buf; /* buffer to pack from */
20336384Ssklower register int len; /* length of buffer */
20436384Ssklower {
20536384Ssklower register u_long h = 0;
20636384Ssklower register int i;
20736384Ssklower
20836384Ssklower for (i=0; i<len; i+=4) {
20936384Ssklower register u_long l = 0;
21036384Ssklower
21136384Ssklower if ((len - i) < 4) {
21236384Ssklower /* buffer not multiple of 4 */
21336384Ssklower switch (len - i) {
21436384Ssklower case 3:
21536384Ssklower l |= buf[i+2] << 8;
21636384Ssklower case 2:
21736384Ssklower l |= buf[i+1] << 16;
21836384Ssklower case 1:
21936384Ssklower l |= buf[i] << 24;
22036384Ssklower break;
22136384Ssklower default:
22236384Ssklower printf("iso_hashchar: unexpected value x%x\n", len - i);
22336384Ssklower break;
22436384Ssklower }
22536384Ssklower } else {
22636384Ssklower l |= buf[i] << 24;
22736384Ssklower l |= buf[i+1] << 16;
22836384Ssklower l |= buf[i+2] << 8;
22936384Ssklower l |= buf[i+3];
23036384Ssklower }
23136384Ssklower
23236384Ssklower h ^= l;
23336384Ssklower }
23436384Ssklower
23536384Ssklower h ^= (u_long) (len % 4);
23636384Ssklower
23736384Ssklower return(h);
23836384Ssklower }
23937469Ssklower #ifdef notdef
24036384Ssklower /*
24136384Ssklower * FUNCTION: iso_hash
24236384Ssklower *
24336384Ssklower * PURPOSE: Fill in fields of afhash structure based upon addr passed.
24436384Ssklower *
24536384Ssklower * RETURNS: none
24636384Ssklower *
24736384Ssklower * SIDE EFFECTS:
24836384Ssklower *
24936384Ssklower * NOTES:
25036384Ssklower */
25136384Ssklower iso_hash(siso, hp)
25236384Ssklower struct sockaddr_iso *siso; /* address to perform hash on */
25336384Ssklower struct afhash *hp; /* RETURN: hash info here */
25436384Ssklower {
25536384Ssklower u_long buf[sizeof(struct sockaddr_iso)+1/4];
25636384Ssklower register int bufsize;
25736384Ssklower
25836384Ssklower
25936384Ssklower bzero(buf, sizeof(buf));
26036384Ssklower
26136384Ssklower bufsize = iso_netof(&siso->siso_addr, buf);
26236384Ssklower hp->afh_nethash = iso_hashchar((caddr_t)buf, bufsize);
26336384Ssklower
26436384Ssklower IFDEBUG(D_ROUTE)
26536384Ssklower printf("iso_hash: iso_netof: bufsize = %d\n", bufsize);
26636384Ssklower ENDDEBUG
26736384Ssklower
26836384Ssklower hp->afh_hosthash = iso_hashchar((caddr_t)&siso->siso_addr,
26936384Ssklower siso->siso_addr.isoa_len);
27036384Ssklower
27136384Ssklower IFDEBUG(D_ROUTE)
27236384Ssklower printf("iso_hash: %s: nethash = x%x, hosthash = x%x\n",
27336384Ssklower clnp_iso_addrp(&siso->siso_addr), hp->afh_nethash,
27436384Ssklower hp->afh_hosthash);
27536384Ssklower ENDDEBUG
27636384Ssklower }
27736384Ssklower /*
27836384Ssklower * FUNCTION: iso_netof
27936384Ssklower *
28036384Ssklower * PURPOSE: Extract the network portion of the iso address.
28136384Ssklower * The network portion of the iso address varies depending
28236384Ssklower * on the type of address. The network portion of the
28336384Ssklower * address will include the IDP. The network portion is:
28436384Ssklower *
28536384Ssklower * TYPE DESC
28636384Ssklower * t37 The AFI and x.121 (IDI)
28736384Ssklower * osinet The AFI, orgid, snetid
28836384Ssklower * rfc986 The AFI, vers and network part of
28936384Ssklower * internet address.
29036384Ssklower *
29136384Ssklower * RETURNS: number of bytes placed into buf.
29236384Ssklower *
29336384Ssklower * SIDE EFFECTS:
29436384Ssklower *
29536384Ssklower * NOTES: Buf is assumed to be big enough
29636384Ssklower */
29736384Ssklower iso_netof(isoa, buf)
29836384Ssklower struct iso_addr *isoa; /* address */
29936384Ssklower caddr_t buf; /* RESULT: network portion of address here */
30036384Ssklower {
30136384Ssklower u_int len = 1; /* length of afi */
30236384Ssklower
30336384Ssklower switch (isoa->isoa_afi) {
30436384Ssklower case AFI_37:
30536384Ssklower /*
30636384Ssklower * Due to classic x.25 tunnel vision, there is no
30736384Ssklower * net portion of an x.121 address. For our purposes
30836384Ssklower * the AFI will do, so that all x.25 -type addresses
30936384Ssklower * map to the single x.25 SNPA. (Cannot have more than
31036384Ssklower * one, obviously).
31136384Ssklower */
31236384Ssklower
31336384Ssklower break;
31436384Ssklower
31536384Ssklower /* case AFI_OSINET:*/
31636384Ssklower case AFI_RFC986: {
31736384Ssklower u_short idi; /* value of idi */
31836384Ssklower
31936384Ssklower /* osinet and rfc986 have idi in the same place */
32036384Ssklower CTOH(isoa->rfc986_idi[0], isoa->rfc986_idi[1], idi);
32136384Ssklower
32236384Ssklower if (idi == IDI_OSINET)
32336384Ssklower /*
32436384Ssklower * Network portion of OSINET address can only be the IDI. Clearly,
32536384Ssklower * with one x25 interface, one could get to several orgids, and
32636384Ssklower * several snetids.
32736384Ssklower len += (ADDROSINET_IDI_LEN + OVLOSINET_ORGID_LEN +
32836384Ssklower OVLOSINET_SNETID_LEN);
32936384Ssklower */
33036384Ssklower len += ADDROSINET_IDI_LEN;
33136384Ssklower else if (idi == IDI_RFC986) {
33236384Ssklower u_long inetaddr;
33336384Ssklower struct ovl_rfc986 *o986 = (struct ovl_rfc986 *)isoa;
33436384Ssklower
33536384Ssklower /* bump len to include idi and version (1 byte) */
33636384Ssklower len += ADDRRFC986_IDI_LEN + 1;
33736384Ssklower
33836384Ssklower /* get inet addr long aligned */
33936384Ssklower bcopy(o986->o986_inetaddr, &inetaddr, sizeof(inetaddr));
34036384Ssklower inetaddr = ntohl(inetaddr); /* convert to host byte order */
34136384Ssklower
34236384Ssklower IFDEBUG(D_ROUTE)
34336384Ssklower printf("iso_netof: isoa ");
34436384Ssklower dump_buf(isoa, sizeof(*isoa));
34536384Ssklower printf("iso_netof: inetaddr 0x%x ", inetaddr);
34636384Ssklower ENDDEBUG
34736384Ssklower
34836384Ssklower /* bump len by size of network portion of inet address */
34936384Ssklower if (IN_CLASSA(inetaddr)) {
35036384Ssklower len += 4-IN_CLASSA_NSHIFT/8;
35136384Ssklower IFDEBUG(D_ROUTE)
35236384Ssklower printf("iso_netof: class A net len is now %d\n", len);
35336384Ssklower ENDDEBUG
35436384Ssklower } else if (IN_CLASSB(inetaddr)) {
35536384Ssklower len += 4-IN_CLASSB_NSHIFT/8;
35636384Ssklower IFDEBUG(D_ROUTE)
35736384Ssklower printf("iso_netof: class B net len is now %d\n", len);
35836384Ssklower ENDDEBUG
35936384Ssklower } else {
36036384Ssklower len += 4-IN_CLASSC_NSHIFT/8;
36136384Ssklower IFDEBUG(D_ROUTE)
36236384Ssklower printf("iso_netof: class C net len is now %d\n", len);
36336384Ssklower ENDDEBUG
36436384Ssklower }
36536384Ssklower } else
36636384Ssklower len = 0;
36736384Ssklower } break;
36836384Ssklower
36936384Ssklower default:
37036384Ssklower len = 0;
37136384Ssklower }
37236384Ssklower
37336384Ssklower bcopy((caddr_t)isoa, buf, len);
37436384Ssklower IFDEBUG(D_ROUTE)
37558601Ssklower printf("iso_netof: isoa ");
37636384Ssklower dump_buf(isoa, len);
37758601Ssklower printf("iso_netof: net ");
37836384Ssklower dump_buf(buf, len);
37936384Ssklower ENDDEBUG
38036384Ssklower return len;
38136384Ssklower }
38260359Sbostic #endif /* notdef */
38336384Ssklower /*
38437469Ssklower * Generic iso control operations (ioctl's).
38537469Ssklower * Ifp is 0 if not an interface-specific ioctl.
38636384Ssklower */
38737469Ssklower /* ARGSUSED */
38836384Ssklower iso_control(so, cmd, data, ifp)
38937469Ssklower struct socket *so;
390*68165Scgd u_long cmd;
39137469Ssklower caddr_t data;
39237469Ssklower register struct ifnet *ifp;
39336384Ssklower {
39437469Ssklower register struct iso_ifreq *ifr = (struct iso_ifreq *)data;
39537469Ssklower register struct iso_ifaddr *ia = 0;
39637469Ssklower register struct ifaddr *ifa;
39737469Ssklower struct iso_ifaddr *oia;
39837469Ssklower struct iso_aliasreq *ifra = (struct iso_aliasreq *)data;
39937469Ssklower int error, hostIsNew, maskIsNew;
40036384Ssklower
40137469Ssklower /*
40237469Ssklower * Find address for this interface, if it exists.
40337469Ssklower */
40437469Ssklower if (ifp)
40537469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next)
40637469Ssklower if (ia->ia_ifp == ifp)
40737469Ssklower break;
40836384Ssklower
40936384Ssklower switch (cmd) {
41037469Ssklower
41137469Ssklower case SIOCAIFADDR_ISO:
41237469Ssklower case SIOCDIFADDR_ISO:
41337469Ssklower if (ifra->ifra_addr.siso_family == AF_ISO)
41437469Ssklower for (oia = ia; ia; ia = ia->ia_next) {
41537469Ssklower if (ia->ia_ifp == ifp &&
41637469Ssklower SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr))
41737469Ssklower break;
41837469Ssklower }
41950232Ssklower if ((so->so_state & SS_PRIV) == 0)
42050232Ssklower return (EPERM);
42136384Ssklower if (ifp == 0)
42237469Ssklower panic("iso_control");
42337469Ssklower if (ia == (struct iso_ifaddr *)0) {
42437469Ssklower struct iso_ifaddr *nia;
42537469Ssklower if (cmd == SIOCDIFADDR_ISO)
42637469Ssklower return (EADDRNOTAVAIL);
42756913Ssklower #ifdef TUBA
42856913Ssklower /* XXXXXX can't be done in the proto init routines */
42956913Ssklower if (tuba_tree == 0)
43056913Ssklower tuba_table_init();
43156913Ssklower #endif
43237469Ssklower MALLOC(nia, struct iso_ifaddr *, sizeof(*nia),
43337469Ssklower M_IFADDR, M_WAITOK);
43437469Ssklower if (nia == (struct iso_ifaddr *)0)
43537469Ssklower return (ENOBUFS);
43637469Ssklower bzero((caddr_t)nia, sizeof(*nia));
43737469Ssklower if (ia = iso_ifaddr) {
43837469Ssklower for ( ; ia->ia_next; ia = ia->ia_next)
43937469Ssklower ;
44037469Ssklower ia->ia_next = nia;
44137469Ssklower } else
44237469Ssklower iso_ifaddr = nia;
44337469Ssklower ia = nia;
44437469Ssklower if (ifa = ifp->if_addrlist) {
44537469Ssklower for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
44637469Ssklower ;
44737469Ssklower ifa->ifa_next = (struct ifaddr *) ia;
44837469Ssklower } else
44937469Ssklower ifp->if_addrlist = (struct ifaddr *) ia;
45037469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
45137469Ssklower ia->ia_ifa.ifa_dstaddr
45237469Ssklower = (struct sockaddr *)&ia->ia_dstaddr;
45337469Ssklower ia->ia_ifa.ifa_netmask
45437469Ssklower = (struct sockaddr *)&ia->ia_sockmask;
45537469Ssklower ia->ia_ifp = ifp;
45637469Ssklower if (ifp != &loif)
45737469Ssklower iso_interfaces++;
45837469Ssklower }
45937469Ssklower break;
46036384Ssklower
46137469Ssklower #define cmdbyte(x) (((x) >> 8) & 0xff)
46237469Ssklower default:
46337469Ssklower if (cmdbyte(cmd) == 'a')
46450232Ssklower return (snpac_ioctl(so, cmd, data));
46537469Ssklower if (ia == (struct iso_ifaddr *)0)
46637469Ssklower return (EADDRNOTAVAIL);
46737469Ssklower break;
46837469Ssklower }
46937469Ssklower switch (cmd) {
47036384Ssklower
47137469Ssklower case SIOCGIFADDR_ISO:
47237469Ssklower ifr->ifr_Addr = ia->ia_addr;
47337469Ssklower break;
47436384Ssklower
47537469Ssklower case SIOCGIFDSTADDR_ISO:
47637469Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
47737469Ssklower return (EINVAL);
47837469Ssklower ifr->ifr_Addr = ia->ia_dstaddr;
47937469Ssklower break;
48036384Ssklower
48137469Ssklower case SIOCGIFNETMASK_ISO:
48237469Ssklower ifr->ifr_Addr = ia->ia_sockmask;
48337469Ssklower break;
48436384Ssklower
48537469Ssklower case SIOCAIFADDR_ISO:
48643428Ssklower maskIsNew = 0; hostIsNew = 1; error = 0;
48737469Ssklower if (ia->ia_addr.siso_family == AF_ISO) {
48837469Ssklower if (ifra->ifra_addr.siso_len == 0) {
48937469Ssklower ifra->ifra_addr = ia->ia_addr;
49037469Ssklower hostIsNew = 0;
49137469Ssklower } else if (SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr))
49237469Ssklower hostIsNew = 0;
49337469Ssklower }
49437469Ssklower if (ifra->ifra_mask.siso_len) {
49537469Ssklower iso_ifscrub(ifp, ia);
49637469Ssklower ia->ia_sockmask = ifra->ifra_mask;
49737469Ssklower maskIsNew = 1;
49837469Ssklower }
49937469Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) &&
50037469Ssklower (ifra->ifra_dstaddr.siso_family == AF_ISO)) {
50137469Ssklower iso_ifscrub(ifp, ia);
50237469Ssklower ia->ia_dstaddr = ifra->ifra_dstaddr;
50337469Ssklower maskIsNew = 1; /* We lie; but the effect's the same */
50437469Ssklower }
50537469Ssklower if (ifra->ifra_addr.siso_family == AF_ISO &&
50637469Ssklower (hostIsNew || maskIsNew)) {
50737469Ssklower error = iso_ifinit(ifp, ia, &ifra->ifra_addr, 0);
50837469Ssklower }
50937469Ssklower if (ifra->ifra_snpaoffset)
51037469Ssklower ia->ia_snpaoffset = ifra->ifra_snpaoffset;
51137469Ssklower return (error);
51237469Ssklower
51337469Ssklower case SIOCDIFADDR_ISO:
51437469Ssklower iso_ifscrub(ifp, ia);
51537469Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
51637469Ssklower ifp->if_addrlist = ifa->ifa_next;
51737469Ssklower else {
51837469Ssklower while (ifa->ifa_next &&
51937469Ssklower (ifa->ifa_next != (struct ifaddr *)ia))
52037469Ssklower ifa = ifa->ifa_next;
52137469Ssklower if (ifa->ifa_next)
52237469Ssklower ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
52337469Ssklower else
52437469Ssklower printf("Couldn't unlink isoifaddr from ifp\n");
52537469Ssklower }
52637469Ssklower oia = ia;
52737469Ssklower if (oia == (ia = iso_ifaddr)) {
52837469Ssklower iso_ifaddr = ia->ia_next;
52937469Ssklower } else {
53037469Ssklower while (ia->ia_next && (ia->ia_next != oia)) {
53137469Ssklower ia = ia->ia_next;
53236384Ssklower }
53337469Ssklower if (ia->ia_next)
53437469Ssklower ia->ia_next = oia->ia_next;
53537469Ssklower else
53637469Ssklower printf("Didn't unlink isoifadr from list\n");
53736384Ssklower }
53852030Ssklower IFAFREE((&oia->ia_ifa));
53937469Ssklower break;
54036384Ssklower
54136384Ssklower default:
54236384Ssklower if (ifp == 0 || ifp->if_ioctl == 0)
54336384Ssklower return (EOPNOTSUPP);
54436384Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data));
54536384Ssklower }
54637469Ssklower return (0);
54736384Ssklower }
54836384Ssklower
54937469Ssklower /*
55037469Ssklower * Delete any existing route for an interface.
55137469Ssklower */
iso_ifscrub(ifp,ia)55237469Ssklower iso_ifscrub(ifp, ia)
55337469Ssklower register struct ifnet *ifp;
55437469Ssklower register struct iso_ifaddr *ia;
55537469Ssklower {
55643333Ssklower int nsellength = ia->ia_addr.siso_tlen;
55737469Ssklower if ((ia->ia_flags & IFA_ROUTE) == 0)
55837469Ssklower return;
55943333Ssklower ia->ia_addr.siso_tlen = 0;
56037469Ssklower if (ifp->if_flags & IFF_LOOPBACK)
56137469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
56237469Ssklower else if (ifp->if_flags & IFF_POINTOPOINT)
56337469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
56437469Ssklower else {
56537469Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
56637469Ssklower }
56743333Ssklower ia->ia_addr.siso_tlen = nsellength;
56837469Ssklower ia->ia_flags &= ~IFA_ROUTE;
56937469Ssklower }
57037469Ssklower
57137469Ssklower /*
57237469Ssklower * Initialize an interface's internet address
57337469Ssklower * and routing table entry.
57437469Ssklower */
iso_ifinit(ifp,ia,siso,scrub)57537469Ssklower iso_ifinit(ifp, ia, siso, scrub)
57637469Ssklower register struct ifnet *ifp;
57737469Ssklower register struct iso_ifaddr *ia;
57837469Ssklower struct sockaddr_iso *siso;
57937469Ssklower {
58037469Ssklower struct sockaddr_iso oldaddr;
58143333Ssklower int s = splimp(), error, nsellength;
58237469Ssklower
58337469Ssklower oldaddr = ia->ia_addr;
58437469Ssklower ia->ia_addr = *siso;
58537469Ssklower /*
58637469Ssklower * Give the interface a chance to initialize
58737469Ssklower * if this is its first address,
58837469Ssklower * and to validate the address if necessary.
58937469Ssklower */
59054823Ssklower if (ifp->if_ioctl &&
59154823Ssklower (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
59237469Ssklower splx(s);
59337469Ssklower ia->ia_addr = oldaddr;
59437469Ssklower return (error);
59537469Ssklower }
59637469Ssklower if (scrub) {
59737469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
59837469Ssklower iso_ifscrub(ifp, ia);
59937469Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
60037469Ssklower }
60143333Ssklower /* XXX -- The following is here temporarily out of laziness
60243333Ssklower in not changing every ethernet driver's if_ioctl routine */
60343333Ssklower if (ifp->if_output == ether_output) {
60443333Ssklower ia->ia_ifa.ifa_rtrequest = llc_rtrequest;
60543333Ssklower ia->ia_ifa.ifa_flags |= RTF_CLONING;
60643333Ssklower }
60737469Ssklower /*
60837469Ssklower * Add route for the network.
60937469Ssklower */
61043333Ssklower nsellength = ia->ia_addr.siso_tlen;
61143333Ssklower ia->ia_addr.siso_tlen = 0;
61237469Ssklower if (ifp->if_flags & IFF_LOOPBACK) {
61337469Ssklower ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
61440894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
61537469Ssklower } else if (ifp->if_flags & IFF_POINTOPOINT &&
61637469Ssklower ia->ia_dstaddr.siso_family == AF_ISO)
61740894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
61837469Ssklower else {
61940894Ssklower rt_maskedcopy(ia->ia_ifa.ifa_addr, ia->ia_ifa.ifa_dstaddr,
62040894Ssklower ia->ia_ifa.ifa_netmask);
62149936Ssklower ia->ia_dstaddr.siso_nlen =
62249936Ssklower min(ia->ia_addr.siso_nlen, (ia->ia_sockmask.siso_len - 6));
62340894Ssklower error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
62437469Ssklower }
62543333Ssklower ia->ia_addr.siso_tlen = nsellength;
62637469Ssklower ia->ia_flags |= IFA_ROUTE;
62737469Ssklower splx(s);
62840894Ssklower return (error);
62937469Ssklower }
63037469Ssklower #ifdef notdef
63137469Ssklower
63236384Ssklower struct ifaddr *
iso_ifwithidi(addr)63336384Ssklower iso_ifwithidi(addr)
63436384Ssklower register struct sockaddr *addr;
63536384Ssklower {
63636384Ssklower register struct ifnet *ifp;
63736384Ssklower register struct ifaddr *ifa;
63836384Ssklower register u_int af = addr->sa_family;
63936384Ssklower
64036384Ssklower if (af != AF_ISO)
64136384Ssklower return (0);
64236384Ssklower IFDEBUG(D_ROUTE)
64336384Ssklower printf(">>> iso_ifwithidi addr\n");
64436384Ssklower dump_isoaddr( (struct sockaddr_iso *)(addr));
64536384Ssklower printf("\n");
64636384Ssklower ENDDEBUG
64736384Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) {
64836384Ssklower IFDEBUG(D_ROUTE)
64936384Ssklower printf("iso_ifwithidi ifnet %s\n", ifp->if_name);
65036384Ssklower ENDDEBUG
65136384Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
65236384Ssklower IFDEBUG(D_ROUTE)
65336384Ssklower printf("iso_ifwithidi address ");
65437469Ssklower dump_isoaddr( (struct sockaddr_iso *)(ifa->ifa_addr));
65536384Ssklower ENDDEBUG
65637469Ssklower if (ifa->ifa_addr->sa_family != addr->sa_family)
65736384Ssklower continue;
65836384Ssklower
65936384Ssklower #define IFA_SIS(ifa)\
66037469Ssklower ((struct sockaddr_iso *)((ifa)->ifa_addr))
66136384Ssklower
66236384Ssklower IFDEBUG(D_ROUTE)
66336384Ssklower printf(" af same, args to iso_eqtype:\n");
66436384Ssklower printf("0x%x ", IFA_SIS(ifa)->siso_addr);
66536384Ssklower printf(" 0x%x\n",
66636384Ssklower &(((struct sockaddr_iso *)addr)->siso_addr));
66736384Ssklower ENDDEBUG
66836384Ssklower
66936384Ssklower if (iso_eqtype(&(IFA_SIS(ifa)->siso_addr),
67036384Ssklower &(((struct sockaddr_iso *)addr)->siso_addr))) {
67136384Ssklower IFDEBUG(D_ROUTE)
67236384Ssklower printf("ifa_ifwithidi: ifa found\n");
67336384Ssklower ENDDEBUG
67436384Ssklower return (ifa);
67536384Ssklower }
67636384Ssklower IFDEBUG(D_ROUTE)
67736384Ssklower printf(" iso_eqtype failed\n");
67836384Ssklower ENDDEBUG
67936384Ssklower }
68036384Ssklower }
68136384Ssklower return ((struct ifaddr *)0);
68236384Ssklower }
68336384Ssklower
68460359Sbostic #endif /* notdef */
68536384Ssklower /*
68636384Ssklower * FUNCTION: iso_ck_addr
68736384Ssklower *
68836384Ssklower * PURPOSE: return true if the iso_addr passed is
68936384Ssklower * within the legal size limit for an iso address.
69036384Ssklower *
69136384Ssklower * RETURNS: true or false
69236384Ssklower *
69336384Ssklower * SIDE EFFECTS:
69436384Ssklower *
69536384Ssklower */
69636384Ssklower iso_ck_addr(isoa)
69736384Ssklower struct iso_addr *isoa; /* address to check */
69836384Ssklower {
69936384Ssklower return (isoa->isoa_len <= 20);
70036384Ssklower
70136384Ssklower }
70236384Ssklower
70337469Ssklower #ifdef notdef
70436384Ssklower /*
70536384Ssklower * FUNCTION: iso_eqtype
70636384Ssklower *
70736384Ssklower * PURPOSE: Determine if two iso addresses are of the same type.
70836384Ssklower * This is flaky. Really we should consider all type 47 addrs to be the
70936384Ssklower * same - but there do exist different structures for 47 addrs.
71036384Ssklower * Gosip adds a 3rd.
71136384Ssklower *
71236384Ssklower * RETURNS: true if the addresses are the same type
71336384Ssklower *
71436384Ssklower * SIDE EFFECTS:
71536384Ssklower *
71636384Ssklower * NOTES: By type, I mean rfc986, t37, or osinet
71736384Ssklower *
71836384Ssklower * This will first compare afis. If they match, then
71936384Ssklower * if the addr is not t37, the idis must be compared.
72036384Ssklower */
72136384Ssklower iso_eqtype(isoaa, isoab)
72236384Ssklower struct iso_addr *isoaa; /* first addr to check */
72336384Ssklower struct iso_addr *isoab; /* other addr to check */
72436384Ssklower {
72536384Ssklower if (isoaa->isoa_afi == isoab->isoa_afi) {
72636384Ssklower if (isoaa->isoa_afi == AFI_37)
72736384Ssklower return(1);
72836384Ssklower else
72936384Ssklower return (!bcmp(&isoaa->isoa_u, &isoab->isoa_u, 2));
73036384Ssklower }
73136384Ssklower return(0);
73236384Ssklower }
73360359Sbostic #endif /* notdef */
73436384Ssklower /*
73537469Ssklower * FUNCTION: iso_localifa()
73636384Ssklower *
73737469Ssklower * PURPOSE: Find an interface addresss having a given destination
73837469Ssklower * or at least matching the net.
73936384Ssklower *
74036384Ssklower * RETURNS: ptr to an interface address
74136384Ssklower *
74236384Ssklower * SIDE EFFECTS:
74336384Ssklower *
74436384Ssklower * NOTES:
74536384Ssklower */
74636384Ssklower struct iso_ifaddr *
iso_localifa(siso)74737469Ssklower iso_localifa(siso)
74837469Ssklower register struct sockaddr_iso *siso;
74936384Ssklower {
75036384Ssklower register struct iso_ifaddr *ia;
75137469Ssklower register char *cp1, *cp2, *cp3;
75237469Ssklower register struct ifnet *ifp;
75337469Ssklower struct iso_ifaddr *ia_maybe = 0;
75437469Ssklower /*
75537469Ssklower * We make one pass looking for both net matches and an exact
75637469Ssklower * dst addr.
75737469Ssklower */
75837469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) {
75937469Ssklower if ((ifp = ia->ia_ifp) == 0 || ((ifp->if_flags & IFF_UP) == 0))
76037469Ssklower continue;
76137469Ssklower if (ifp->if_flags & IFF_POINTOPOINT) {
76237469Ssklower if ((ia->ia_dstaddr.siso_family == AF_ISO) &&
76337469Ssklower SAME_ISOADDR(&ia->ia_dstaddr, siso))
76437469Ssklower return (ia);
76537469Ssklower else
76637469Ssklower if (SAME_ISOADDR(&ia->ia_addr, siso))
76737469Ssklower ia_maybe = ia;
76837469Ssklower continue;
76937469Ssklower }
77037469Ssklower if (ia->ia_sockmask.siso_len) {
77137469Ssklower char *cplim = ia->ia_sockmask.siso_len + (char *)&ia->ia_sockmask;
77237469Ssklower cp1 = ia->ia_sockmask.siso_data;
77337469Ssklower cp2 = siso->siso_data;
77437469Ssklower cp3 = ia->ia_addr.siso_data;
77539936Ssklower while (cp1 < cplim)
77637469Ssklower if (*cp1++ & (*cp2++ ^ *cp3++))
77737469Ssklower goto next;
77837469Ssklower ia_maybe = ia;
77937469Ssklower }
78037469Ssklower if (SAME_ISOADDR(&ia->ia_addr, siso))
78137469Ssklower return ia;
78237469Ssklower next:;
78337469Ssklower }
78437469Ssklower return ia_maybe;
78536384Ssklower }
78636384Ssklower
78747272Ssklower #ifdef TPCONS
78856533Sbostic #include <netiso/cons.h>
78960359Sbostic #endif /* TPCONS */
79036384Ssklower /*
79136384Ssklower * FUNCTION: iso_nlctloutput
79236384Ssklower *
79336384Ssklower * PURPOSE: Set options at the network level
79436384Ssklower *
79536384Ssklower * RETURNS: E*
79636384Ssklower *
79736384Ssklower * SIDE EFFECTS:
79836384Ssklower *
79936384Ssklower * NOTES: This could embody some of the functions of
80036384Ssklower * rclnp_ctloutput and cons_ctloutput.
80136384Ssklower */
iso_nlctloutput(cmd,optname,pcb,m)80236384Ssklower iso_nlctloutput(cmd, optname, pcb, m)
80336384Ssklower int cmd; /* command:set or get */
80436384Ssklower int optname; /* option of interest */
80536384Ssklower caddr_t pcb; /* nl pcb */
80636384Ssklower struct mbuf *m; /* data for set, buffer for get */
80736384Ssklower {
80836384Ssklower struct isopcb *isop = (struct isopcb *)pcb;
80936384Ssklower int error = 0; /* return value */
81036384Ssklower caddr_t data; /* data for option */
81136384Ssklower int data_len; /* data's length */
81236384Ssklower
81336384Ssklower IFDEBUG(D_ISO)
81436384Ssklower printf("iso_nlctloutput: cmd %x, opt %x, pcb %x, m %x\n",
81536384Ssklower cmd, optname, pcb, m);
81636384Ssklower ENDDEBUG
81736384Ssklower
81836384Ssklower if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT))
81936384Ssklower return(EOPNOTSUPP);
82036384Ssklower
82136384Ssklower data = mtod(m, caddr_t);
82236384Ssklower data_len = (m)->m_len;
82336384Ssklower
82436384Ssklower IFDEBUG(D_ISO)
82536384Ssklower printf("iso_nlctloutput: data is:\n");
82636384Ssklower dump_buf(data, data_len);
82736384Ssklower ENDDEBUG
82836384Ssklower
82936384Ssklower switch (optname) {
83036384Ssklower
83147272Ssklower #ifdef TPCONS
83236384Ssklower case CONSOPT_X25CRUD:
83336384Ssklower if (cmd == PRCO_GETOPT) {
83436384Ssklower error = EOPNOTSUPP;
83536384Ssklower break;
83636384Ssklower }
83736384Ssklower
83836384Ssklower if (data_len > MAXX25CRUDLEN) {
83936384Ssklower error = EINVAL;
84036384Ssklower break;
84136384Ssklower }
84236384Ssklower
84336384Ssklower IFDEBUG(D_ISO)
84436384Ssklower printf("iso_nlctloutput: setting x25 crud\n");
84536384Ssklower ENDDEBUG
84636384Ssklower
84737469Ssklower bcopy(data, (caddr_t)isop->isop_x25crud, (unsigned)data_len);
84836384Ssklower isop->isop_x25crud_len = data_len;
84936384Ssklower break;
85060359Sbostic #endif /* TPCONS */
85136384Ssklower
85236384Ssklower default:
85336384Ssklower error = EOPNOTSUPP;
85436384Ssklower }
85550972Ssklower if (cmd == PRCO_SETOPT)
85650972Ssklower m_freem(m);
85736384Ssklower return error;
85836384Ssklower }
85960359Sbostic #endif /* ISO */
86036384Ssklower
86136384Ssklower #ifdef ARGO_DEBUG
86236384Ssklower
86336384Ssklower /*
86436384Ssklower * FUNCTION: dump_isoaddr
86536384Ssklower *
86636384Ssklower * PURPOSE: debugging
86736384Ssklower *
86836384Ssklower * RETURNS: nada
86936384Ssklower *
87036384Ssklower */
87136384Ssklower dump_isoaddr(s)
87236384Ssklower struct sockaddr_iso *s;
87336384Ssklower {
87437469Ssklower char *clnp_saddr_isop();
87536384Ssklower register int i;
87636384Ssklower
87736384Ssklower if( s->siso_family == AF_ISO) {
87837469Ssklower printf("ISO address: suffixlen %d, %s\n",
87938841Ssklower s->siso_tlen, clnp_saddr_isop(s));
88036384Ssklower } else if( s->siso_family == AF_INET) {
88136384Ssklower /* hack */
88236384Ssklower struct sockaddr_in *sin = (struct sockaddr_in *)s;
88336384Ssklower
88436384Ssklower printf("%d.%d.%d.%d: %d",
88536384Ssklower (sin->sin_addr.s_addr>>24)&0xff,
88636384Ssklower (sin->sin_addr.s_addr>>16)&0xff,
88736384Ssklower (sin->sin_addr.s_addr>>8)&0xff,
88836384Ssklower (sin->sin_addr.s_addr)&0xff,
88936384Ssklower sin->sin_port);
89036384Ssklower }
89136384Ssklower }
89236384Ssklower
89360359Sbostic #endif /* ARGO_DEBUG */
894