1 /* $NetBSD: iso.c,v 1.56 2009/04/18 14:58:06 tsutsui Exp $ */
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
30 * Copyright (c) 1991, 1993
31 * The Regents of the University of California. All rights reserved.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * @(#)iso.c 8.3 (Berkeley) 1/9/95
60 /***********************************************************
61 Copyright IBM Corporation 1987
65 Permission to use, copy, modify, and distribute this software and its
66 documentation for any purpose and without fee is hereby granted,
67 provided that the above copyright notice appear in all copies and that
68 both that copyright notice and this permission notice appear in
69 supporting documentation, and that the name of IBM not be
70 used in advertising or publicity pertaining to distribution of the
71 software without specific, written prior permission.
73 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
74 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
75 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
76 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
77 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
78 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
81 ******************************************************************/
84 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
87 * iso.c: miscellaneous routines to support the iso address family
90 #include <sys/cdefs.h>
91 __KERNEL_RCSID(0, "$NetBSD: iso.c,v 1.56 2009/04/18 14:58:06 tsutsui Exp $");
93 #include <sys/param.h>
94 #include <sys/systm.h>
95 #include <sys/ioctl.h>
97 #include <sys/domain.h>
98 #include <sys/protosw.h>
99 #include <sys/socket.h>
100 #include <sys/socketvar.h>
101 #include <sys/errno.h>
102 #include <sys/proc.h>
103 #include <sys/kauth.h>
106 #include <net/if_types.h>
107 #include <net/route.h>
109 #include <netiso/iso.h>
110 #include <netiso/iso_var.h>
111 #include <netiso/iso_snpac.h>
112 #include <netiso/iso_pcb.h>
113 #include <netiso/clnp.h>
114 #include <netiso/argo_debug.h>
119 int iso_interfaces
= 0; /* number of external interfaces */
122 * FUNCTION: iso_addrmatch1
124 * PURPOSE: decide if the two iso_addrs passed are equal
126 * RETURNS: true if the addrs match, false if they do not
133 iso_addrmatch1(const struct iso_addr
*isoaa
, const struct iso_addr
*isoab
)
138 if (argo_debug
[D_ROUTE
]) {
139 printf("iso_addrmatch1: comparing lengths: %d to %d\n", isoaa
->isoa_len
,
142 dump_buf(isoaa
->isoa_genaddr
, isoaa
->isoa_len
);
144 dump_buf(isoab
->isoa_genaddr
, isoab
->isoa_len
);
148 if ((compare_len
= isoaa
->isoa_len
) != isoab
->isoa_len
) {
150 if (argo_debug
[D_ROUTE
]) {
151 printf("iso_addrmatch1: returning false because of lengths\n");
157 /* TODO : generalize this to all afis with masks */
158 if (isoaa
->isoa_afi
== AFI_37
) {
160 * must not compare 2 least significant digits, or for that
163 compare_len
= ADDR37_IDI_LEN
- 1;
168 if (argo_debug
[D_ROUTE
]) {
172 a
= isoaa
->isoa_genaddr
;
173 b
= isoab
->isoa_genaddr
;
175 for (i
= 0; i
< compare_len
; i
++) {
176 printf("<%x=%x>", a
[i
] & 0xff, b
[i
] & 0xff);
178 printf("\naddrs are not equal at byte %d\n", i
);
183 printf("addrs are equal\n");
187 return (!memcmp(isoaa
->isoa_genaddr
, isoab
->isoa_genaddr
, compare_len
));
191 * FUNCTION: iso_addrmatch
193 * PURPOSE: decide if the two sockadrr_isos passed are equal
195 * RETURNS: true if the addrs match, false if they do not
202 iso_addrmatch(const struct sockaddr_iso
*sisoa
,
203 const struct sockaddr_iso
*sisob
)
205 return (iso_addrmatch1(&sisoa
->siso_addr
, &sisob
->siso_addr
));
209 * FUNCTION: iso_netmatch
211 * PURPOSE: similar to iso_addrmatch but takes sockaddr_iso
214 * RETURNS: true if same net, false if not
221 iso_netmatch(const struct sockaddr_iso
*sisoa
,
222 const struct sockaddr_iso
*sisob
)
224 u_char bufa
[sizeof(struct sockaddr_iso
)];
225 u_char bufb
[sizeof(struct sockaddr_iso
)];
228 lena
= iso_netof(&sisoa
->siso_addr
, bufa
);
229 lenb
= iso_netof(&sisob
->siso_addr
, bufb
);
232 if (argo_debug
[D_ROUTE
]) {
233 printf("iso_netmatch: comparing lengths: %d to %d\n", lena
, lenb
);
235 dump_buf(bufa
, lena
);
237 dump_buf(bufb
, lenb
);
241 return ((lena
== lenb
) && (!memcmp(bufa
, bufb
, lena
)));
246 * FUNCTION: iso_hashchar
248 * PURPOSE: Hash all character in the buffer specified into
249 * a long. Return the long.
251 * RETURNS: The hash value.
255 * NOTES: The hash is achieved by exclusive ORing 4 byte
259 iso_hashchar(void *bufv
, int len
)
265 for (i
= 0; i
< len
; i
+= 4) {
269 /* buffer not multiple of 4 */
272 l
|= buf
[i
+ 2] << 8;
274 l
|= buf
[i
+ 1] << 16;
279 printf("iso_hashchar: unexpected value x%x\n", len
- i
);
284 l
|= buf
[i
+ 1] << 16;
285 l
|= buf
[i
+ 2] << 8;
292 h
^= (u_long
) (len
% 4);
301 * PURPOSE: Fill in fields of afhash structure based upon addr
312 struct sockaddr_iso
*siso
, /* address to perform hash on */
313 struct afhash
*hp
) /* RETURN: hash info here */
315 u_long buf
[sizeof(struct sockaddr_iso
) / 4 + 1];
319 memset(buf
, 0, sizeof(buf
));
321 bufsize
= iso_netof(&siso
->siso_addr
, buf
);
322 hp
->afh_nethash
= iso_hashchar((void *) buf
, bufsize
);
325 if (argo_debug
[D_ROUTE
]) {
326 printf("iso_hash: iso_netof: bufsize = %d\n", bufsize
);
330 hp
->afh_hosthash
= iso_hashchar((void *) & siso
->siso_addr
,
331 siso
->siso_addr
.isoa_len
);
334 if (argo_debug
[D_ROUTE
]) {
335 printf("iso_hash: %s: nethash = x%x, hosthash = x%x\n",
336 clnp_iso_addrp(&siso
->siso_addr
), hp
->afh_nethash
,
342 * FUNCTION: iso_netof
344 * PURPOSE: Extract the network portion of the iso address.
345 * The network portion of the iso address varies depending
346 * on the type of address. The network portion of the
347 * address will include the IDP. The network portion is:
350 * t37 The AFI and x.121 (IDI)
351 * osinet The AFI, orgid, snetid
352 * rfc986 The AFI, vers and network part
353 * of internet address.
355 * RETURNS: number of bytes placed into buf.
359 * NOTES: Buf is assumed to be big enough
363 struct iso_addr
*isoa
, /* address */
364 void * buf
) /* RESULT: network portion of address here */
366 u_int len
= 1;/* length of afi */
368 switch (isoa
->isoa_afi
) {
371 * Due to classic x.25 tunnel vision, there is no
372 * net portion of an x.121 address. For our purposes
373 * the AFI will do, so that all x.25 -type addresses
374 * map to the single x.25 SNPA. (Cannot have more than
380 /* case AFI_OSINET: */
382 u_short idi
; /* value of idi */
384 /* osinet and rfc986 have idi in the same place */
385 CTOH(isoa
->rfc986_idi
[0], isoa
->rfc986_idi
[1], idi
);
387 if (idi
== IDI_OSINET
)
389 * Network portion of OSINET address can only
390 * be the IDI. Clearly, with one x25 interface,
391 * one could get to several orgids, and
395 len
+= (ADDROSINET_IDI_LEN
+
396 OVLOSINET_ORGID_LEN
+
397 OVLOSINET_SNETID_LEN
);
399 len
+= ADDROSINET_IDI_LEN
;
400 else if (idi
== IDI_RFC986
) {
401 struct ovl_rfc986
*o986
=
402 (struct ovl_rfc986
*) isoa
;
405 * bump len to include idi and version (1
408 len
+= ADDRRFC986_IDI_LEN
+ 1;
411 if (argo_debug
[D_ROUTE
]) {
412 printf("iso_netof: isoa ");
413 dump_buf(isoa
, sizeof(*isoa
));
414 printf("iso_netof: inetaddr 0x%x ",
420 * bump len by size of network portion of
423 if (IN_CLASSA(o986
->o986_inetaddr
)) {
424 len
+= 4 - IN_CLASSA_NSHIFT
/ 8;
426 if (argo_debug
[D_ROUTE
]) {
427 printf("iso_netof: class A net len is now %d\n", len
);
430 } else if (IN_CLASSB(o986
->o986_inetaddr
)) {
431 len
+= 4 - IN_CLASSB_NSHIFT
/ 8;
433 if (argo_debug
[D_ROUTE
]) {
434 printf("iso_netof: class B net len is now %d\n", len
);
438 len
+= 4 - IN_CLASSC_NSHIFT
/ 8;
440 if (argo_debug
[D_ROUTE
]) {
441 printf("iso_netof: class C net len is now %d\n", len
);
453 memcpy(buf
, (void *) isoa
, len
);
455 if (argo_debug
[D_ROUTE
]) {
456 printf("iso_netof: isoa ");
458 printf("iso_netof: net ");
466 * Generic iso control operations (ioctl's).
467 * Ifp is 0 if not an interface-specific ioctl.
471 iso_control(struct socket
*so
, u_long cmd
, void *data
, struct ifnet
*ifp
,
474 struct iso_ifreq
*ifr
= (struct iso_ifreq
*) data
;
475 struct iso_ifaddr
*ia
= 0;
476 struct iso_aliasreq
*ifra
= (struct iso_aliasreq
*) data
;
477 int error
, hostIsNew
, maskIsNew
;
480 * Find address for this interface, if it exists.
483 TAILQ_FOREACH(ia
, &iso_ifaddr
, ia_list
)
484 if (ia
->ia_ifp
== ifp
)
489 case SIOCAIFADDR_ISO
:
490 case SIOCDIFADDR_ISO
:
491 if (ifra
->ifra_addr
.siso_family
== AF_ISO
)
492 for (; ia
!= 0; ia
= ia
->ia_list
.tqe_next
) {
493 if (ia
->ia_ifp
== ifp
&&
494 SAME_ISOADDR(&ia
->ia_addr
, &ifra
->ifra_addr
))
497 if (cmd
== SIOCDIFADDR_ISO
&& ia
== 0)
498 return (EADDRNOTAVAIL
);
505 if (l
== 0 || kauth_authorize_network(l
->l_cred
,
506 KAUTH_NETWORK_INTERFACE
,
507 KAUTH_REQ_NETWORK_INTERFACE_SETPRIV
, ifp
, (void *)cmd
,
512 panic("iso_control");
514 ia
= malloc(sizeof(*ia
),
515 M_IFADDR
, M_WAITOK
|M_ZERO
);
518 TAILQ_INSERT_TAIL(&iso_ifaddr
, ia
, ia_list
);
520 ifa_insert(ifp
, &ia
->ia_ifa
);
521 ia
->ia_ifa
.ifa_addr
= sisotosa(&ia
->ia_addr
);
522 ia
->ia_ifa
.ifa_dstaddr
= sisotosa(&ia
->ia_dstaddr
);
523 ia
->ia_ifa
.ifa_netmask
= sisotosa(&ia
->ia_sockmask
);
525 if ((ifp
->if_flags
& IFF_LOOPBACK
) == 0)
530 case SIOCGIFADDR_ISO
:
531 case SIOCGIFNETMASK_ISO
:
532 case SIOCGIFDSTADDR_ISO
:
534 return (EADDRNOTAVAIL
);
539 case SIOCGIFADDR_ISO
:
540 ifr
->ifr_Addr
= ia
->ia_addr
;
543 case SIOCGIFDSTADDR_ISO
:
544 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
546 ifr
->ifr_Addr
= ia
->ia_dstaddr
;
549 case SIOCGIFNETMASK_ISO
:
550 ifr
->ifr_Addr
= ia
->ia_sockmask
;
553 case SIOCAIFADDR_ISO
:
557 if (ia
->ia_addr
.siso_family
== AF_ISO
) {
558 if (ifra
->ifra_addr
.siso_len
== 0) {
559 ifra
->ifra_addr
= ia
->ia_addr
;
561 } else if (SAME_ISOADDR(&ia
->ia_addr
, &ifra
->ifra_addr
))
564 if (ifra
->ifra_mask
.siso_len
) {
565 iso_ifscrub(ifp
, ia
);
566 ia
->ia_sockmask
= ifra
->ifra_mask
;
569 if ((ifp
->if_flags
& IFF_POINTOPOINT
) &&
570 (ifra
->ifra_dstaddr
.siso_family
== AF_ISO
)) {
571 iso_ifscrub(ifp
, ia
);
572 ia
->ia_dstaddr
= ifra
->ifra_dstaddr
;
573 maskIsNew
= 1; /* We lie; but the effect's the same */
575 if (ifra
->ifra_addr
.siso_family
== AF_ISO
&&
576 (hostIsNew
|| maskIsNew
))
577 error
= iso_ifinit(ifp
, ia
, &ifra
->ifra_addr
, 0);
578 if (ifra
->ifra_snpaoffset
)
579 ia
->ia_snpaoffset
= ifra
->ifra_snpaoffset
;
582 case SIOCDIFADDR_ISO
:
583 iso_purgeaddr(&ia
->ia_ifa
);
586 #define cmdbyte(x) (((x) >> 8) & 0xff)
588 if (cmdbyte(cmd
) == 'a')
589 return (snpac_ioctl(so
, cmd
, data
, l
));
596 iso_purgeaddr(struct ifaddr
*ifa
)
598 struct ifnet
*ifp
= ifa
->ifa_ifp
;
599 struct iso_ifaddr
*ia
= (void *) ifa
;
601 iso_ifscrub(ifp
, ia
);
602 ifa_remove(ifp
, &ia
->ia_ifa
);
603 TAILQ_REMOVE(&iso_ifaddr
, ia
, ia_list
);
604 IFAFREE(&ia
->ia_ifa
);
608 iso_purgeif(struct ifnet
*ifp
)
610 if_purgeaddrs(ifp
, AF_ISO
, iso_purgeaddr
);
614 * Delete any existing route for an interface.
617 iso_ifscrub(struct ifnet
*ifp
, struct iso_ifaddr
*ia
)
619 int nsellength
= ia
->ia_addr
.siso_tlen
;
620 if ((ia
->ia_flags
& IFA_ROUTE
) == 0)
622 ia
->ia_addr
.siso_tlen
= 0;
623 if (ifp
->if_flags
& IFF_LOOPBACK
)
624 rtinit(&(ia
->ia_ifa
), (int) RTM_DELETE
, RTF_HOST
);
625 else if (ifp
->if_flags
& IFF_POINTOPOINT
)
626 rtinit(&(ia
->ia_ifa
), (int) RTM_DELETE
, RTF_HOST
);
628 rtinit(&(ia
->ia_ifa
), (int) RTM_DELETE
, 0);
630 ia
->ia_addr
.siso_tlen
= nsellength
;
631 ia
->ia_flags
&= ~IFA_ROUTE
;
635 * Initialize an interface's internet address
636 * and routing table entry.
639 iso_ifinit(struct ifnet
*ifp
, struct iso_ifaddr
*ia
, struct sockaddr_iso
*siso
,
642 struct sockaddr_iso oldaddr
;
643 int s
= splnet(), error
, nsellength
;
645 oldaddr
= ia
->ia_addr
;
648 * Give the interface a chance to initialize
649 * if this is its first address,
650 * and to validate the address if necessary.
652 if ((error
= (*ifp
->if_ioctl
)(ifp
, SIOCINITIFADDR
, ia
)) != 0) {
654 ia
->ia_addr
= oldaddr
;
658 ia
->ia_ifa
.ifa_addr
= sisotosa(&oldaddr
);
659 iso_ifscrub(ifp
, ia
);
660 ia
->ia_ifa
.ifa_addr
= sisotosa(&ia
->ia_addr
);
663 * XXX -- The following is here temporarily out of laziness in not
664 * changing every ethernet driver's if_ioctl routine
666 * XXX extract llc_ifinit() and call from ether_ioctl(),
667 * XXX fddi_ioctl(). --dyoung
670 if (ifp
->if_type
== IFT_ETHER
|| ifp
->if_type
== IFT_FDDI
) {
671 ia
->ia_ifa
.ifa_rtrequest
= llc_rtrequest
;
672 ia
->ia_ifa
.ifa_flags
|= RTF_CLONING
;
675 * Add route for the network.
677 nsellength
= ia
->ia_addr
.siso_tlen
;
678 ia
->ia_addr
.siso_tlen
= 0;
679 if (ifp
->if_flags
& IFF_LOOPBACK
) {
680 ia
->ia_ifa
.ifa_dstaddr
= ia
->ia_ifa
.ifa_addr
;
681 error
= rtinit(&(ia
->ia_ifa
), (int) RTM_ADD
, RTF_HOST
| RTF_UP
);
682 } else if (ifp
->if_flags
& IFF_POINTOPOINT
&&
683 ia
->ia_dstaddr
.siso_family
== AF_ISO
)
684 error
= rtinit(&(ia
->ia_ifa
), (int) RTM_ADD
, RTF_HOST
| RTF_UP
);
686 rt_maskedcopy(ia
->ia_ifa
.ifa_addr
, ia
->ia_ifa
.ifa_dstaddr
,
687 ia
->ia_ifa
.ifa_netmask
);
688 ia
->ia_dstaddr
.siso_nlen
=
689 min(ia
->ia_addr
.siso_nlen
, (ia
->ia_sockmask
.siso_len
- 6));
690 error
= rtinit(&(ia
->ia_ifa
), (int) RTM_ADD
, RTF_UP
);
692 ia
->ia_addr
.siso_tlen
= nsellength
;
693 ia
->ia_flags
|= IFA_ROUTE
;
700 iso_ifwithidi(struct sockaddr
*addr
)
704 u_int af
= addr
->sa_family
;
709 if (argo_debug
[D_ROUTE
]) {
710 printf(">>> iso_ifwithidi addr\n");
711 dump_isoaddr(satosiso(addr
));
715 TAILQ_FOREACH(ifp
, &ifnet
, if_list
) {
717 if (argo_debug
[D_ROUTE
]) {
718 printf("iso_ifwithidi ifnet %s\n", ifp
->if_name
);
721 IFADDR_FOREACH(ifa
, ifp
) {
723 if (argo_debug
[D_ROUTE
]) {
724 printf("iso_ifwithidi address ");
725 dump_isoaddr(satosiso(ifa
->ifa_addr
));
728 if (ifa
->ifa_addr
->sa_family
!= addr
->sa_family
)
732 if (argo_debug
[D_ROUTE
]) {
733 printf(" af same, args to iso_eqtype:\n");
734 printf("0x%x ", satosiso(ifa
->ifa_addr
)->siso_addr
);
736 &satosiso(addr
)->siso_addr
);
740 if (iso_eqtype(&satosiso(ifa
->ifa_addr
)->siso_addr
,
741 &satosiso(addr
)->siso_addr
)) {
743 if (argo_debug
[D_ROUTE
]) {
744 printf("ifa_ifwithidi: ifa found\n");
750 if (argo_debug
[D_ROUTE
]) {
751 printf(" iso_eqtype failed\n");
756 return ((struct ifaddr
*) 0);
761 * FUNCTION: iso_ck_addr
763 * PURPOSE: return true if the iso_addr passed is
764 * within the legal size limit for an iso address.
766 * RETURNS: true or false
772 iso_ck_addr(struct iso_addr
*isoa
)
774 return (isoa
->isoa_len
<= 20);
780 * FUNCTION: iso_eqtype
782 * PURPOSE: Determine if two iso addresses are of the same type.
783 * This is flaky. Really we should consider all type
784 * 47 addrs to be the same - but there do exist different
785 * structures for 47 addrs. Gosip adds a 3rd.
787 * RETURNS: true if the addresses are the same type
791 * NOTES: By type, I mean rfc986, t37, or osinet
793 * This will first compare afis. If they match, then
794 * if the addr is not t37, the idis must be compared.
798 struct iso_addr
*isoaa
, /* first addr to check */
799 struct iso_addr
*isoab
) /* other addr to check */
801 if (isoaa
->isoa_afi
== isoab
->isoa_afi
) {
802 if (isoaa
->isoa_afi
== AFI_37
)
805 return (!memcmp(&isoaa
->isoa_u
, &isoab
->isoa_u
, 2));
811 * FUNCTION: iso_localifa()
813 * PURPOSE: Find an interface addresss having a given destination
814 * or at least matching the net.
816 * RETURNS: ptr to an interface address
823 iso_localifa(const struct sockaddr_iso
*siso
)
825 struct iso_ifaddr
*ia
;
826 const char *cp1
, *cp2
, *cp3
;
828 struct iso_ifaddr
*ia_maybe
= 0;
830 * We make one pass looking for both net matches and an exact
833 TAILQ_FOREACH(ia
, &iso_ifaddr
, ia_list
) {
834 if ((ifp
= ia
->ia_ifp
) == 0 || ((ifp
->if_flags
& IFF_UP
) == 0))
836 if (ifp
->if_flags
& IFF_POINTOPOINT
) {
837 if ((ia
->ia_dstaddr
.siso_family
== AF_ISO
) &&
838 SAME_ISOADDR(&ia
->ia_dstaddr
, siso
))
840 else if (SAME_ISOADDR(&ia
->ia_addr
, siso
))
844 if (ia
->ia_sockmask
.siso_len
) {
845 char *cplim
= ia
->ia_sockmask
.siso_len
+
846 (char *) &ia
->ia_sockmask
;
847 cp1
= ia
->ia_sockmask
.siso_data
;
848 cp2
= siso
->siso_data
;
849 cp3
= ia
->ia_addr
.siso_data
;
851 if (*cp1
++ & (*cp2
++ ^ *cp3
++))
855 if (SAME_ISOADDR(&ia
->ia_addr
, siso
))
863 * FUNCTION: iso_nlctloutput
865 * PURPOSE: Set options at the network level
871 * NOTES: This could embody some of the functions of
872 * rclnp_ctloutput and cons_ctloutput.
876 int cmd
, /* command:set or get */
877 int optname
, /* option of interest */
878 void * pcb
, /* nl pcb */
879 struct mbuf
*m
) /* data for set, buffer for get */
881 int error
= 0; /* return value */
882 void * data
; /* data for option */
883 int data_len
; /* data's length */
886 if (argo_debug
[D_ISO
]) {
887 printf("iso_nlctloutput: cmd %x, opt %x, pcb %p, m %p\n",
888 cmd
, optname
, pcb
, m
);
892 if ((cmd
!= PRCO_GETOPT
) && (cmd
!= PRCO_SETOPT
))
895 data
= mtod(m
, void *);
896 data_len
= (m
)->m_len
;
899 if (argo_debug
[D_ISO
]) {
900 printf("iso_nlctloutput: data is:\n");
901 dump_buf(data
, data_len
);
909 if (cmd
== PRCO_SETOPT
)
918 * FUNCTION: dump_isoaddr
926 dump_isoaddr(const struct sockaddr_iso
*s
)
928 if (s
->siso_family
== AF_ISO
) {
929 printf("ISO address: suffixlen %d, %s\n",
930 s
->siso_tlen
, clnp_saddr_isop(s
));
931 } else if (s
->siso_family
== AF_INET
) {
933 const struct sockaddr_in
*sin
= satocsin(s
);
935 printf("%d.%d.%d.%d: %d",
936 (sin
->sin_addr
.s_addr
>> 24) & 0xff,
937 (sin
->sin_addr
.s_addr
>> 16) & 0xff,
938 (sin
->sin_addr
.s_addr
>> 8) & 0xff,
939 (sin
->sin_addr
.s_addr
) & 0xff,
944 #endif /* ARGO_DEBUG */
947 struct queue
*q_next
, *q_prev
;
951 * FUNCTION: iso_insque
953 * PURPOSE: insert an element into a queue
958 iso_insque(void *v1
, void *v2
)
960 struct queue
*elem
= v1
, *head
= v2
;
971 * FUNCTION: iso_remque
973 * PURPOSE: remove an element from a queue
980 struct queue
*elem
= v
;
981 struct queue
*next
, *prev
;