No empty .Rs/.Re
[netbsd-mini2440.git] / sys / netiso / iso.c
blob6a218a4352c7cba865bb8520ec354e82c6ad3e40
1 /* $NetBSD: iso.c,v 1.56 2009/04/18 14:58:06 tsutsui Exp $ */
3 /*-
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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.
29 /*-
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
35 * are met:
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
55 * SUCH DAMAGE.
57 * @(#)iso.c 8.3 (Berkeley) 1/9/95
60 /***********************************************************
61 Copyright IBM Corporation 1987
63 All Rights Reserved
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
79 SOFTWARE.
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>
96 #include <sys/mbuf.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>
105 #include <net/if.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>
116 #include "opt_iso.h"
117 #ifdef ISO
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
128 * SIDE EFFECTS:
130 * NOTES:
133 iso_addrmatch1(const struct iso_addr *isoaa, const struct iso_addr *isoab)
135 u_int compare_len;
137 #ifdef ARGO_DEBUG
138 if (argo_debug[D_ROUTE]) {
139 printf("iso_addrmatch1: comparing lengths: %d to %d\n", isoaa->isoa_len,
140 isoab->isoa_len);
141 printf("a:\n");
142 dump_buf(isoaa->isoa_genaddr, isoaa->isoa_len);
143 printf("b:\n");
144 dump_buf(isoab->isoa_genaddr, isoab->isoa_len);
146 #endif
148 if ((compare_len = isoaa->isoa_len) != isoab->isoa_len) {
149 #ifdef ARGO_DEBUG
150 if (argo_debug[D_ROUTE]) {
151 printf("iso_addrmatch1: returning false because of lengths\n");
153 #endif
154 return 0;
156 #ifdef notdef
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
161 * matter, the DSP
163 compare_len = ADDR37_IDI_LEN - 1;
165 #endif
167 #ifdef ARGO_DEBUG
168 if (argo_debug[D_ROUTE]) {
169 int i;
170 const char *a, *b;
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);
177 if (a[i] != b[i]) {
178 printf("\naddrs are not equal at byte %d\n", i);
179 return (0);
182 printf("\n");
183 printf("addrs are equal\n");
184 return (1);
186 #endif
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
197 * SIDE EFFECTS:
199 * NOTES:
202 iso_addrmatch(const struct sockaddr_iso *sisoa,
203 const struct sockaddr_iso *sisob)
205 return (iso_addrmatch1(&sisoa->siso_addr, &sisob->siso_addr));
207 #ifdef notdef
209 * FUNCTION: iso_netmatch
211 * PURPOSE: similar to iso_addrmatch but takes sockaddr_iso
212 * as argument.
214 * RETURNS: true if same net, false if not
216 * SIDE EFFECTS:
218 * NOTES:
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)];
226 int lena, lenb;
228 lena = iso_netof(&sisoa->siso_addr, bufa);
229 lenb = iso_netof(&sisob->siso_addr, bufb);
231 #ifdef ARGO_DEBUG
232 if (argo_debug[D_ROUTE]) {
233 printf("iso_netmatch: comparing lengths: %d to %d\n", lena, lenb);
234 printf("a:\n");
235 dump_buf(bufa, lena);
236 printf("b:\n");
237 dump_buf(bufb, lenb);
239 #endif
241 return ((lena == lenb) && (!memcmp(bufa, bufb, lena)));
243 #endif /* notdef */
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.
253 * SIDE EFFECTS:
255 * NOTES: The hash is achieved by exclusive ORing 4 byte
256 * quantities.
258 u_long
259 iso_hashchar(void *bufv, int len)
261 char *buf = bufv;
262 u_long h = 0;
263 int i;
265 for (i = 0; i < len; i += 4) {
266 u_long l = 0;
268 if ((len - i) < 4) {
269 /* buffer not multiple of 4 */
270 switch (len - i) {
271 case 3:
272 l |= buf[i + 2] << 8;
273 case 2:
274 l |= buf[i + 1] << 16;
275 case 1:
276 l |= buf[i] << 24;
277 break;
278 default:
279 printf("iso_hashchar: unexpected value x%x\n", len - i);
280 break;
282 } else {
283 l |= buf[i] << 24;
284 l |= buf[i + 1] << 16;
285 l |= buf[i + 2] << 8;
286 l |= buf[i + 3];
289 h ^= l;
292 h ^= (u_long) (len % 4);
294 return (h);
297 #ifdef notdef
299 * FUNCTION: iso_hash
301 * PURPOSE: Fill in fields of afhash structure based upon addr
302 * passed.
304 * RETURNS: none
306 * SIDE EFFECTS:
308 * NOTES:
310 void
311 iso_hash(
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];
316 int bufsize;
319 memset(buf, 0, sizeof(buf));
321 bufsize = iso_netof(&siso->siso_addr, buf);
322 hp->afh_nethash = iso_hashchar((void *) buf, bufsize);
324 #ifdef ARGO_DEBUG
325 if (argo_debug[D_ROUTE]) {
326 printf("iso_hash: iso_netof: bufsize = %d\n", bufsize);
328 #endif
330 hp->afh_hosthash = iso_hashchar((void *) & siso->siso_addr,
331 siso->siso_addr.isoa_len);
333 #ifdef ARGO_DEBUG
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,
337 hp->afh_hosthash);
339 #endif
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:
349 * TYPE DESC
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.
357 * SIDE EFFECTS:
359 * NOTES: Buf is assumed to be big enough
361 u_int
362 iso_netof(
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) {
369 case AFI_37:
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
375 * one, obviously).
378 break;
380 /* case AFI_OSINET: */
381 case AFI_RFC986:{
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
392 * several snetids.
394 #if 0
395 len += (ADDROSINET_IDI_LEN +
396 OVLOSINET_ORGID_LEN +
397 OVLOSINET_SNETID_LEN);
398 #endif
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
406 * byte)
408 len += ADDRRFC986_IDI_LEN + 1;
410 #ifdef ARGO_DEBUG
411 if (argo_debug[D_ROUTE]) {
412 printf("iso_netof: isoa ");
413 dump_buf(isoa, sizeof(*isoa));
414 printf("iso_netof: inetaddr 0x%x ",
415 inetaddr);
417 #endif
420 * bump len by size of network portion of
421 * inet address
423 if (IN_CLASSA(o986->o986_inetaddr)) {
424 len += 4 - IN_CLASSA_NSHIFT / 8;
425 #ifdef ARGO_DEBUG
426 if (argo_debug[D_ROUTE]) {
427 printf("iso_netof: class A net len is now %d\n", len);
429 #endif
430 } else if (IN_CLASSB(o986->o986_inetaddr)) {
431 len += 4 - IN_CLASSB_NSHIFT / 8;
432 #ifdef ARGO_DEBUG
433 if (argo_debug[D_ROUTE]) {
434 printf("iso_netof: class B net len is now %d\n", len);
436 #endif
437 } else {
438 len += 4 - IN_CLASSC_NSHIFT / 8;
439 #ifdef ARGO_DEBUG
440 if (argo_debug[D_ROUTE]) {
441 printf("iso_netof: class C net len is now %d\n", len);
443 #endif
445 } else
446 len = 0;
447 } break;
449 default:
450 len = 0;
453 memcpy(buf, (void *) isoa, len);
454 #ifdef ARGO_DEBUG
455 if (argo_debug[D_ROUTE]) {
456 printf("iso_netof: isoa ");
457 dump_buf(isoa, len);
458 printf("iso_netof: net ");
459 dump_buf(buf, len);
461 #endif
462 return len;
464 #endif /* notdef */
466 * Generic iso control operations (ioctl's).
467 * Ifp is 0 if not an interface-specific ioctl.
469 /* ARGSUSED */
471 iso_control(struct socket *so, u_long cmd, void *data, struct ifnet *ifp,
472 struct lwp *l)
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.
482 if (ifp)
483 TAILQ_FOREACH(ia, &iso_ifaddr, ia_list)
484 if (ia->ia_ifp == ifp)
485 break;
487 switch (cmd) {
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))
495 break;
497 if (cmd == SIOCDIFADDR_ISO && ia == 0)
498 return (EADDRNOTAVAIL);
499 /* FALLTHROUGH */
500 #if 0
501 case SIOCSIFADDR:
502 case SIOCSIFNETMASK:
503 case SIOCSIFDSTADDR:
504 #endif
505 if (l == 0 || kauth_authorize_network(l->l_cred,
506 KAUTH_NETWORK_INTERFACE,
507 KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd,
508 NULL))
509 return (EPERM);
511 if (ifp == 0)
512 panic("iso_control");
513 if (ia == 0) {
514 ia = malloc(sizeof(*ia),
515 M_IFADDR, M_WAITOK|M_ZERO);
516 if (ia == 0)
517 return (ENOBUFS);
518 TAILQ_INSERT_TAIL(&iso_ifaddr, ia, ia_list);
519 IFAREF(&ia->ia_ifa);
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);
524 ia->ia_ifp = ifp;
525 if ((ifp->if_flags & IFF_LOOPBACK) == 0)
526 iso_interfaces++;
528 break;
530 case SIOCGIFADDR_ISO:
531 case SIOCGIFNETMASK_ISO:
532 case SIOCGIFDSTADDR_ISO:
533 if (ia == 0)
534 return (EADDRNOTAVAIL);
535 break;
537 switch (cmd) {
539 case SIOCGIFADDR_ISO:
540 ifr->ifr_Addr = ia->ia_addr;
541 break;
543 case SIOCGIFDSTADDR_ISO:
544 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
545 return (EINVAL);
546 ifr->ifr_Addr = ia->ia_dstaddr;
547 break;
549 case SIOCGIFNETMASK_ISO:
550 ifr->ifr_Addr = ia->ia_sockmask;
551 break;
553 case SIOCAIFADDR_ISO:
554 maskIsNew = 0;
555 hostIsNew = 1;
556 error = 0;
557 if (ia->ia_addr.siso_family == AF_ISO) {
558 if (ifra->ifra_addr.siso_len == 0) {
559 ifra->ifra_addr = ia->ia_addr;
560 hostIsNew = 0;
561 } else if (SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr))
562 hostIsNew = 0;
564 if (ifra->ifra_mask.siso_len) {
565 iso_ifscrub(ifp, ia);
566 ia->ia_sockmask = ifra->ifra_mask;
567 maskIsNew = 1;
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;
580 return (error);
582 case SIOCDIFADDR_ISO:
583 iso_purgeaddr(&ia->ia_ifa);
584 break;
586 #define cmdbyte(x) (((x) >> 8) & 0xff)
587 default:
588 if (cmdbyte(cmd) == 'a')
589 return (snpac_ioctl(so, cmd, data, l));
590 return ENOTTY;
592 return (0);
595 void
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);
607 void
608 iso_purgeif(struct ifnet *ifp)
610 if_purgeaddrs(ifp, AF_ISO, iso_purgeaddr);
614 * Delete any existing route for an interface.
616 void
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)
621 return;
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);
627 else {
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,
640 int scrub)
642 struct sockaddr_iso oldaddr;
643 int s = splnet(), error, nsellength;
645 oldaddr = ia->ia_addr;
646 ia->ia_addr = *siso;
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) {
653 splx(s);
654 ia->ia_addr = oldaddr;
655 return (error);
657 if (scrub) {
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);
685 else {
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;
694 splx(s);
695 return (error);
697 #ifdef notdef
699 struct ifaddr *
700 iso_ifwithidi(struct sockaddr *addr)
702 struct ifnet *ifp;
703 struct ifaddr *ifa;
704 u_int af = addr->sa_family;
706 if (af != AF_ISO)
707 return (0);
708 #ifdef ARGO_DEBUG
709 if (argo_debug[D_ROUTE]) {
710 printf(">>> iso_ifwithidi addr\n");
711 dump_isoaddr(satosiso(addr));
712 printf("\n");
714 #endif
715 TAILQ_FOREACH(ifp, &ifnet, if_list) {
716 #ifdef ARGO_DEBUG
717 if (argo_debug[D_ROUTE]) {
718 printf("iso_ifwithidi ifnet %s\n", ifp->if_name);
720 #endif
721 IFADDR_FOREACH(ifa, ifp) {
722 #ifdef ARGO_DEBUG
723 if (argo_debug[D_ROUTE]) {
724 printf("iso_ifwithidi address ");
725 dump_isoaddr(satosiso(ifa->ifa_addr));
727 #endif
728 if (ifa->ifa_addr->sa_family != addr->sa_family)
729 continue;
731 #ifdef ARGO_DEBUG
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);
735 printf(" 0x%x\n",
736 &satosiso(addr)->siso_addr);
738 #endif
740 if (iso_eqtype(&satosiso(ifa->ifa_addr)->siso_addr,
741 &satosiso(addr)->siso_addr)) {
742 #ifdef ARGO_DEBUG
743 if (argo_debug[D_ROUTE]) {
744 printf("ifa_ifwithidi: ifa found\n");
746 #endif
747 return (ifa);
749 #ifdef ARGO_DEBUG
750 if (argo_debug[D_ROUTE]) {
751 printf(" iso_eqtype failed\n");
753 #endif
756 return ((struct ifaddr *) 0);
759 #endif /* notdef */
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
768 * SIDE EFFECTS:
772 iso_ck_addr(struct iso_addr *isoa)
774 return (isoa->isoa_len <= 20);
778 #ifdef notdef
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
789 * SIDE EFFECTS:
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.
797 iso_eqtype(
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)
803 return (1);
804 else
805 return (!memcmp(&isoaa->isoa_u, &isoab->isoa_u, 2));
807 return (0);
809 #endif /* notdef */
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
818 * SIDE EFFECTS:
820 * NOTES:
822 struct iso_ifaddr *
823 iso_localifa(const struct sockaddr_iso *siso)
825 struct iso_ifaddr *ia;
826 const char *cp1, *cp2, *cp3;
827 struct ifnet *ifp;
828 struct iso_ifaddr *ia_maybe = 0;
830 * We make one pass looking for both net matches and an exact
831 * dst addr.
833 TAILQ_FOREACH(ia, &iso_ifaddr, ia_list) {
834 if ((ifp = ia->ia_ifp) == 0 || ((ifp->if_flags & IFF_UP) == 0))
835 continue;
836 if (ifp->if_flags & IFF_POINTOPOINT) {
837 if ((ia->ia_dstaddr.siso_family == AF_ISO) &&
838 SAME_ISOADDR(&ia->ia_dstaddr, siso))
839 return (ia);
840 else if (SAME_ISOADDR(&ia->ia_addr, siso))
841 ia_maybe = ia;
842 continue;
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;
850 while (cp1 < cplim)
851 if (*cp1++ & (*cp2++ ^ *cp3++))
852 goto next;
853 ia_maybe = ia;
855 if (SAME_ISOADDR(&ia->ia_addr, siso))
856 return ia;
857 next: ;
859 return ia_maybe;
863 * FUNCTION: iso_nlctloutput
865 * PURPOSE: Set options at the network level
867 * RETURNS: E*
869 * SIDE EFFECTS:
871 * NOTES: This could embody some of the functions of
872 * rclnp_ctloutput and cons_ctloutput.
875 iso_nlctloutput(
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 */
885 #ifdef ARGO_DEBUG
886 if (argo_debug[D_ISO]) {
887 printf("iso_nlctloutput: cmd %x, opt %x, pcb %p, m %p\n",
888 cmd, optname, pcb, m);
890 #endif
892 if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT))
893 return (EOPNOTSUPP);
895 data = mtod(m, void *);
896 data_len = (m)->m_len;
898 #ifdef ARGO_DEBUG
899 if (argo_debug[D_ISO]) {
900 printf("iso_nlctloutput: data is:\n");
901 dump_buf(data, data_len);
903 #endif
905 switch (optname) {
906 default:
907 error = EOPNOTSUPP;
909 if (cmd == PRCO_SETOPT)
910 m_freem(m);
911 return error;
913 #endif /* ISO */
915 #ifdef ARGO_DEBUG
918 * FUNCTION: dump_isoaddr
920 * PURPOSE: debugging
922 * RETURNS: nada
925 void
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) {
932 /* hack */
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,
940 sin->sin_port);
944 #endif /* ARGO_DEBUG */
946 struct queue {
947 struct queue *q_next, *q_prev;
951 * FUNCTION: iso_insque
953 * PURPOSE: insert an element into a queue
955 * RETURNS:
957 void
958 iso_insque(void *v1, void *v2)
960 struct queue *elem = v1, *head = v2;
961 struct queue *next;
963 next = head->q_next;
964 elem->q_next = next;
965 head->q_next = elem;
966 elem->q_prev = head;
967 next->q_prev = elem;
971 * FUNCTION: iso_remque
973 * PURPOSE: remove an element from a queue
975 * RETURNS:
977 void
978 iso_remque(void *v)
980 struct queue *elem = v;
981 struct queue *next, *prev;
983 next = elem->q_next;
984 prev = elem->q_prev;
985 next->q_prev = prev;
986 prev->q_next = next;
987 elem->q_prev = NULL;