xref: /csrg-svn/sys/netiso/iso.c (revision 37469)
1 /***********************************************************
2 		Copyright IBM Corporation 1987
3 
4                       All Rights Reserved
5 
6 Permission to use, copy, modify, and distribute this software and its
7 documentation for any purpose and without fee is hereby granted,
8 provided that the above copyright notice appear in all copies and that
9 both that copyright notice and this permission notice appear in
10 supporting documentation, and that the name of IBM not be
11 used in advertising or publicity pertaining to distribution of the
12 software without specific, written prior permission.
13 
14 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20 SOFTWARE.
21 
22 ******************************************************************/
23 
24 /*
25  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
26  */
27 /*
28  * $Header: iso.c,v 4.11 88/09/19 14:58:35 root Exp $
29  * $Source: /usr/argo/sys/netiso/RCS/iso.c,v $
30  *	@(#)iso.c	7.2 (Berkeley) 04/22/89
31  *
32  * iso.c: miscellaneous routines to support the iso address family
33  */
34 
35 #ifndef lint
36 static char *rcsid = "$Header: iso.c,v 4.11 88/09/19 14:58:35 root Exp $";
37 #endif
38 
39 
40 #include "types.h"
41 #include "param.h"
42 #include "ioctl.h"
43 #include "mbuf.h"
44 #include "domain.h"
45 #include "protosw.h"
46 #include "socket.h"
47 #include "socketvar.h"
48 #include "uio.h"
49 #include "dir.h"
50 #include "user.h"
51 #include "errno.h"
52 
53 #include "../net/if.h"
54 #include "../net/route.h"
55 #include "../net/af.h"
56 
57 #include "iso.h"
58 #include "iso_var.h"
59 #include "iso_snpac.h"
60 #include "iso_pcb.h"
61 #include "clnp.h"
62 #include "argo_debug.h"
63 
64 #ifdef ISO
65 #include "argoxtwentyfive.h"
66 
67 int	iso_interfaces = 0;		/* number of external interfaces */
68 extern	struct ifnet loif;	/* loopback interface */
69 
70 
71 /*
72  * FUNCTION:		iso_init
73  *
74  * PURPOSE:			initialize the iso address family
75  *
76  * RETURNS:			nothing
77  *
78  * SIDE EFFECTS:	1) zeros the maptab table.
79  *					2) initializes the routing table.
80  *
81  * NOTES:
82  */
83 struct radix_node_head *iso_rnhead;
84 iso_init()
85 {
86 	extern struct spna_cache	iso_snpac[];
87 	extern u_int 				iso_snpac_size;
88 	static iso_init_done;
89 
90 	if (iso_init_done == 0) {
91 		iso_init_done++;
92 		bzero((caddr_t)iso_snpac, iso_snpac_size * sizeof(struct snpa_cache));
93 		rn_inithead(&iso_rnhead, 40, AF_ISO);
94 	}
95 }
96 
97 /*
98  * FUNCTION:		iso_addrmatch1
99  *
100  * PURPOSE:			decide if the two iso_addrs passed are equal
101  *
102  * RETURNS:			true if the addrs match, false if they do not
103  *
104  * SIDE EFFECTS:
105  *
106  * NOTES:
107  */
108 iso_addrmatch1(isoaa, isoab)
109 register struct iso_addr *isoaa, *isoab;		/* addresses to check */
110 {
111 	u_int	compare_len;
112 
113 	IFDEBUG(D_ROUTE)
114 		printf("iso_addrmatch1: comparing lengths: %d to %d\n", isoaa->isoa_len,
115 			isoab->isoa_len);
116 		printf("a:\n");
117 		dump_buf(isoaa->isoa_genaddr, isoaa->isoa_len);
118 		printf("b:\n");
119 		dump_buf(isoab->isoa_genaddr, isoab->isoa_len);
120 	ENDDEBUG
121 
122 	if ((compare_len = isoaa->isoa_len) != isoab->isoa_len) {
123 		IFDEBUG(D_ROUTE)
124 			printf("iso_addrmatch1: returning false because of lengths\n");
125 		ENDDEBUG
126 		return 0;
127 	}
128 
129 #ifdef notdef
130 	/* TODO : generalize this to all afis with masks */
131 	if(	isoaa->isoa_afi == AFI_37 ) {
132 		/* must not compare 2 least significant digits, or for
133 		 * that matter, the DSP
134 		 */
135 		compare_len = ADDR37_IDI_LEN - 1;
136 	}
137 #endif
138 
139 	IFDEBUG(D_ROUTE)
140 		int i;
141 		char *a, *b;
142 
143 		a = isoaa->isoa_genaddr;
144 		b = isoab->isoa_genaddr;
145 
146 		for (i=0; i<compare_len; i++) {
147 			printf("<%x=%x>", a[i]&0xff, b[i]&0xff);
148 			if (a[i] != b[i]) {
149 				printf("\naddrs are not equal at byte %d\n", i);
150 				return(0);
151 			}
152 		}
153 		printf("\n");
154 		printf("addrs are equal\n");
155 		return (1);
156 	ENDDEBUG
157 	return (!bcmp(isoaa->isoa_genaddr, isoab->isoa_genaddr, compare_len));
158 }
159 
160 /*
161  * FUNCTION:		iso_addrmatch
162  *
163  * PURPOSE:			decide if the two sockadrr_isos passed are equal
164  *
165  * RETURNS:			true if the addrs match, false if they do not
166  *
167  * SIDE EFFECTS:
168  *
169  * NOTES:
170  */
171 iso_addrmatch(sisoa, sisob)
172 struct sockaddr_iso	*sisoa, *sisob;		/* addresses to check */
173 {
174 	return(iso_addrmatch1(&sisoa->siso_addr, &sisob->siso_addr));
175 }
176 #ifdef notdef
177 /*
178  * FUNCTION:		iso_netmatch
179  *
180  * PURPOSE:			similar to iso_addrmatch but takes sockaddr_iso
181  *					as argument.
182  *
183  * RETURNS:			true if same net, false if not
184  *
185  * SIDE EFFECTS:
186  *
187  * NOTES:
188  */
189 iso_netmatch(sisoa, sisob)
190 struct sockaddr_iso *sisoa, *sisob;
191 {
192 	u_char			bufa[sizeof(struct sockaddr_iso)];
193 	u_char			bufb[sizeof(struct sockaddr_iso)];
194 	register int	lena, lenb;
195 
196 	lena = iso_netof(&sisoa->siso_addr, bufa);
197 	lenb = iso_netof(&sisob->siso_addr, bufb);
198 
199 	IFDEBUG(D_ROUTE)
200 		printf("iso_netmatch: comparing lengths: %d to %d\n", lena, lenb);
201 		printf("a:\n");
202 		dump_buf(bufa, lena);
203 		printf("b:\n");
204 		dump_buf(bufb, lenb);
205 	ENDDEBUG
206 
207 	return ((lena == lenb) && (!bcmp(bufa, bufb, lena)));
208 }
209 #endif notdef
210 
211 /*
212  * FUNCTION:		iso_hashchar
213  *
214  * PURPOSE:			Hash all character in the buffer specified into
215  *					a long. Return the long.
216  *
217  * RETURNS:			The hash value.
218  *
219  * SIDE EFFECTS:
220  *
221  * NOTES:			The hash is achieved by exclusive ORing 4 byte
222  *					quantities.
223  */
224 u_long
225 iso_hashchar(buf, len)
226 register caddr_t	buf;		/* buffer to pack from */
227 register int		len;		/* length of buffer */
228 {
229 	register u_long	h = 0;
230 	register int	i;
231 
232 	for (i=0; i<len; i+=4) {
233 		register u_long	l = 0;
234 
235 		if ((len - i) < 4) {
236 			/* buffer not multiple of 4 */
237 			switch (len - i) {
238 				case 3:
239 					l |= buf[i+2] << 8;
240 				case 2:
241 					l |= buf[i+1] << 16;
242 				case 1:
243 					l |= buf[i] << 24;
244 					break;
245 				default:
246 					printf("iso_hashchar: unexpected value x%x\n", len - i);
247 					break;
248 			}
249 		} else {
250 			l |= buf[i] << 24;
251 			l |= buf[i+1] << 16;
252 			l |= buf[i+2] << 8;
253 			l |= buf[i+3];
254 		}
255 
256 		h ^= l;
257 	}
258 
259 	h ^= (u_long) (len % 4);
260 
261 	return(h);
262 }
263 #ifdef notdef
264 /*
265  * FUNCTION:		iso_hash
266  *
267  * PURPOSE:			Fill in fields of afhash structure based upon addr passed.
268  *
269  * RETURNS:			none
270  *
271  * SIDE EFFECTS:
272  *
273  * NOTES:
274  */
275 iso_hash(siso, hp)
276 struct sockaddr_iso	*siso;		/* address to perform hash on */
277 struct afhash		*hp;		/* RETURN: hash info here */
278 {
279 	u_long			buf[sizeof(struct sockaddr_iso)+1/4];
280 	register int	bufsize;
281 
282 
283 	bzero(buf, sizeof(buf));
284 
285 	bufsize = iso_netof(&siso->siso_addr, buf);
286 	hp->afh_nethash = iso_hashchar((caddr_t)buf, bufsize);
287 
288 	IFDEBUG(D_ROUTE)
289 		printf("iso_hash: iso_netof: bufsize = %d\n", bufsize);
290 	ENDDEBUG
291 
292 	hp->afh_hosthash = iso_hashchar((caddr_t)&siso->siso_addr,
293 		siso->siso_addr.isoa_len);
294 
295 	IFDEBUG(D_ROUTE)
296 		printf("iso_hash: %s: nethash = x%x, hosthash = x%x\n",
297 			clnp_iso_addrp(&siso->siso_addr), hp->afh_nethash,
298 			hp->afh_hosthash);
299 	ENDDEBUG
300 }
301 /*
302  * FUNCTION:		iso_netof
303  *
304  * PURPOSE:			Extract the network portion of the iso address.
305  *					The network portion of the iso address varies depending
306  *					on the type of address. The network portion of the
307  *					address will include the IDP. The network portion is:
308  *
309  *						TYPE			DESC
310  *					t37					The AFI and x.121 (IDI)
311  *					osinet				The AFI, orgid, snetid
312  *					rfc986				The AFI, vers and network part of
313  *										internet address.
314  *
315  * RETURNS:			number of bytes placed into buf.
316  *
317  * SIDE EFFECTS:
318  *
319  * NOTES:			Buf is assumed to be big enough
320  */
321 iso_netof(isoa, buf)
322 struct iso_addr	*isoa;		/* address */
323 caddr_t			buf;		/* RESULT: network portion of address here */
324 {
325 	u_int		len = 1;	/* length of afi */
326 
327 	switch (isoa->isoa_afi) {
328 		case AFI_37:
329 			/*
330 			 * Due to classic x.25 tunnel vision, there is no
331 			 * net portion of an x.121 address.  For our purposes
332 			 * the AFI will do, so that all x.25 -type addresses
333 			 * map to the single x.25 SNPA. (Cannot have more than
334 			 * one, obviously).
335 			 */
336 
337 			break;
338 
339 /* 		case AFI_OSINET:*/
340 		case AFI_RFC986: {
341 			u_short	idi;	/* value of idi */
342 
343 			/* osinet and rfc986 have idi in the same place */
344 			CTOH(isoa->rfc986_idi[0], isoa->rfc986_idi[1], idi);
345 
346 			if (idi == IDI_OSINET)
347 /*
348  *	Network portion of OSINET address can only be the IDI. Clearly,
349  *	with one x25 interface, one could get to several orgids, and
350  *	several snetids.
351 				len += (ADDROSINET_IDI_LEN + OVLOSINET_ORGID_LEN +
352 						OVLOSINET_SNETID_LEN);
353  */
354 				len += ADDROSINET_IDI_LEN;
355 			else if (idi == IDI_RFC986) {
356 				u_long				inetaddr;
357 				struct ovl_rfc986	*o986 = (struct ovl_rfc986 *)isoa;
358 
359 				/* bump len to include idi and version (1 byte) */
360 				len += ADDRRFC986_IDI_LEN + 1;
361 
362 				/* get inet addr long aligned */
363 				bcopy(o986->o986_inetaddr, &inetaddr, sizeof(inetaddr));
364 				inetaddr = ntohl(inetaddr);	/* convert to host byte order */
365 
366 				IFDEBUG(D_ROUTE)
367 					printf("iso_netof: isoa ");
368 					dump_buf(isoa, sizeof(*isoa));
369 					printf("iso_netof: inetaddr 0x%x ", inetaddr);
370 				ENDDEBUG
371 
372 				/* bump len by size of network portion of inet address */
373 				if (IN_CLASSA(inetaddr)) {
374 					len += 4-IN_CLASSA_NSHIFT/8;
375 					IFDEBUG(D_ROUTE)
376 						printf("iso_netof: class A net len is now %d\n", len);
377 					ENDDEBUG
378 				} else if (IN_CLASSB(inetaddr)) {
379 					len += 4-IN_CLASSB_NSHIFT/8;
380 					IFDEBUG(D_ROUTE)
381 						printf("iso_netof: class B net len is now %d\n", len);
382 					ENDDEBUG
383 				} else {
384 					len += 4-IN_CLASSC_NSHIFT/8;
385 					IFDEBUG(D_ROUTE)
386 						printf("iso_netof: class C net len is now %d\n", len);
387 					ENDDEBUG
388 				}
389 			} else
390 				len = 0;
391 		} break;
392 
393 		default:
394 			len = 0;
395 	}
396 
397 	bcopy((caddr_t)isoa, buf, len);
398 	IFDEBUG(D_ROUTE)
399 		printf("in_netof: isoa ");
400 		dump_buf(isoa, len);
401 		printf("in_netof: net ");
402 		dump_buf(buf, len);
403 	ENDDEBUG
404 	return len;
405 }
406 #endif notdef
407 /*
408  * Generic iso control operations (ioctl's).
409  * Ifp is 0 if not an interface-specific ioctl.
410  */
411 /* ARGSUSED */
412 iso_control(so, cmd, data, ifp)
413 	struct socket *so;
414 	int cmd;
415 	caddr_t data;
416 	register struct ifnet *ifp;
417 {
418 	register struct iso_ifreq *ifr = (struct iso_ifreq *)data;
419 	register struct iso_ifaddr *ia = 0;
420 	register struct ifaddr *ifa;
421 	struct iso_ifaddr *oia;
422 	struct iso_aliasreq *ifra = (struct iso_aliasreq *)data;
423 	int error, hostIsNew, maskIsNew;
424 
425 	/*
426 	 * Find address for this interface, if it exists.
427 	 */
428 	if (ifp)
429 		for (ia = iso_ifaddr; ia; ia = ia->ia_next)
430 			if (ia->ia_ifp == ifp)
431 				break;
432 
433 	switch (cmd) {
434 
435 	case SIOCAIFADDR_ISO:
436 	case SIOCDIFADDR_ISO:
437 		if (ifra->ifra_addr.siso_family == AF_ISO)
438 		    for (oia = ia; ia; ia = ia->ia_next) {
439 			if (ia->ia_ifp == ifp  &&
440 			    SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr))
441 				break;
442 		}
443 		if (!suser())
444 			return (u.u_error);
445 		if (ifp == 0)
446 			panic("iso_control");
447 		if (ia == (struct iso_ifaddr *)0) {
448 			struct iso_ifaddr *nia;
449 			if (cmd == SIOCDIFADDR_ISO)
450 				return (EADDRNOTAVAIL);
451 			MALLOC(nia, struct iso_ifaddr *, sizeof(*nia),
452 				       M_IFADDR, M_WAITOK);
453 			if (nia == (struct iso_ifaddr *)0)
454 				return (ENOBUFS);
455 			bzero((caddr_t)nia, sizeof(*nia));
456 			if (ia = iso_ifaddr) {
457 				for ( ; ia->ia_next; ia = ia->ia_next)
458 					;
459 				ia->ia_next = nia;
460 			} else
461 				iso_ifaddr = nia;
462 			ia = nia;
463 			if (ifa = ifp->if_addrlist) {
464 				for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
465 					;
466 				ifa->ifa_next = (struct ifaddr *) ia;
467 			} else
468 				ifp->if_addrlist = (struct ifaddr *) ia;
469 			ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
470 			ia->ia_ifa.ifa_dstaddr
471 					= (struct sockaddr *)&ia->ia_dstaddr;
472 			ia->ia_ifa.ifa_netmask
473 					= (struct sockaddr *)&ia->ia_sockmask;
474 			ia->ia_ifp = ifp;
475 			if (ifp != &loif)
476 				iso_interfaces++;
477 		}
478 		break;
479 
480 #define cmdbyte(x)	(((x) >> 8) & 0xff)
481 	default:
482 		if (cmdbyte(cmd) == 'a')
483 			return (snpac_ioctl(cmd, data));
484 		if (ia == (struct iso_ifaddr *)0)
485 			return (EADDRNOTAVAIL);
486 		break;
487 	}
488 	switch (cmd) {
489 
490 	case SIOCGIFADDR_ISO:
491 		ifr->ifr_Addr = ia->ia_addr;
492 		break;
493 
494 	case SIOCGIFDSTADDR_ISO:
495 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
496 			return (EINVAL);
497 		ifr->ifr_Addr = ia->ia_dstaddr;
498 		break;
499 
500 	case SIOCGIFNETMASK_ISO:
501 		ifr->ifr_Addr = ia->ia_sockmask;
502 		break;
503 
504 	case SIOCAIFADDR_ISO:
505 		maskIsNew = 0; hostIsNew = 1; error = u.u_error;
506 		if (ia->ia_addr.siso_family == AF_ISO) {
507 			if (ifra->ifra_addr.siso_len == 0) {
508 				ifra->ifra_addr = ia->ia_addr;
509 				hostIsNew = 0;
510 			} else if (SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr))
511 				hostIsNew = 0;
512 		}
513 		if (ifra->ifra_mask.siso_len) {
514 			iso_ifscrub(ifp, ia);
515 			ia->ia_sockmask = ifra->ifra_mask;
516 			maskIsNew = 1;
517 		}
518 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
519 		    (ifra->ifra_dstaddr.siso_family == AF_ISO)) {
520 			iso_ifscrub(ifp, ia);
521 			ia->ia_dstaddr = ifra->ifra_dstaddr;
522 			maskIsNew  = 1; /* We lie; but the effect's the same */
523 		}
524 		if (ifra->ifra_addr.siso_family == AF_ISO &&
525 					    (hostIsNew || maskIsNew)) {
526 			error = iso_ifinit(ifp, ia, &ifra->ifra_addr, 0);
527 		}
528 		if (ifra->ifra_snpaoffset)
529 			ia->ia_snpaoffset = ifra->ifra_snpaoffset;
530 		return (error);
531 
532 	case SIOCDIFADDR_ISO:
533 		iso_ifscrub(ifp, ia);
534 		if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
535 			ifp->if_addrlist = ifa->ifa_next;
536 		else {
537 			while (ifa->ifa_next &&
538 			       (ifa->ifa_next != (struct ifaddr *)ia))
539 				    ifa = ifa->ifa_next;
540 			if (ifa->ifa_next)
541 			    ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
542 			else
543 				printf("Couldn't unlink isoifaddr from ifp\n");
544 		}
545 		oia = ia;
546 		if (oia == (ia = iso_ifaddr)) {
547 			iso_ifaddr = ia->ia_next;
548 		} else {
549 			while (ia->ia_next && (ia->ia_next != oia)) {
550 				ia = ia->ia_next;
551 			}
552 			if (ia->ia_next)
553 			    ia->ia_next = oia->ia_next;
554 			else
555 				printf("Didn't unlink isoifadr from list\n");
556 		}
557 		free((caddr_t)oia, M_IFADDR);
558 		break;
559 
560 	default:
561 		if (ifp == 0 || ifp->if_ioctl == 0)
562 			return (EOPNOTSUPP);
563 		return ((*ifp->if_ioctl)(ifp, cmd, data));
564 	}
565 	return (0);
566 }
567 
568 /*
569  * Delete any existing route for an interface.
570  */
571 iso_ifscrub(ifp, ia)
572 	register struct ifnet *ifp;
573 	register struct iso_ifaddr *ia;
574 {
575 	if ((ia->ia_flags & IFA_ROUTE) == 0)
576 		return;
577 	if (ifp->if_flags & IFF_LOOPBACK)
578 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
579 	else if (ifp->if_flags & IFF_POINTOPOINT)
580 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
581 	else {
582 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
583 	}
584 	ia->ia_flags &= ~IFA_ROUTE;
585 }
586 
587 /*
588  * Initialize an interface's internet address
589  * and routing table entry.
590  */
591 iso_ifinit(ifp, ia, siso, scrub)
592 	register struct ifnet *ifp;
593 	register struct iso_ifaddr *ia;
594 	struct sockaddr_iso *siso;
595 {
596 	struct sockaddr_iso oldaddr;
597 	int s = splimp(), error;
598 
599 	oldaddr = ia->ia_addr;
600 	ia->ia_addr = *siso;
601 	/*
602 	 * Give the interface a chance to initialize
603 	 * if this is its first address,
604 	 * and to validate the address if necessary.
605 	 */
606 	if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
607 		splx(s);
608 		ia->ia_addr = oldaddr;
609 		return (error);
610 	}
611 	if (scrub) {
612 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
613 		iso_ifscrub(ifp, ia);
614 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
615 	}
616 	/*
617 	 * Add route for the network.
618 	 */
619 	if (ifp->if_flags & IFF_LOOPBACK) {
620 		ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
621 		rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
622 	} else if (ifp->if_flags & IFF_POINTOPOINT &&
623 		 ia->ia_dstaddr.siso_family == AF_ISO)
624 		rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
625 	else {
626 		rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
627 	}
628 	ia->ia_flags |= IFA_ROUTE;
629 	splx(s);
630 	return (0);
631 }
632 #ifdef notdef
633 
634 struct ifaddr *
635 iso_ifwithidi(addr)
636 	register struct sockaddr *addr;
637 {
638 	register struct ifnet *ifp;
639 	register struct ifaddr *ifa;
640 	register u_int af = addr->sa_family;
641 
642 	if (af != AF_ISO)
643 		return (0);
644 	IFDEBUG(D_ROUTE)
645 		printf(">>> iso_ifwithidi addr\n");
646 		dump_isoaddr( (struct sockaddr_iso *)(addr));
647 		printf("\n");
648 	ENDDEBUG
649 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
650 		IFDEBUG(D_ROUTE)
651 			printf("iso_ifwithidi ifnet %s\n", ifp->if_name);
652 		ENDDEBUG
653 		for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
654 			IFDEBUG(D_ROUTE)
655 				printf("iso_ifwithidi address ");
656 				dump_isoaddr( (struct sockaddr_iso *)(ifa->ifa_addr));
657 			ENDDEBUG
658 			if (ifa->ifa_addr->sa_family != addr->sa_family)
659 				continue;
660 
661 #define	IFA_SIS(ifa)\
662 	((struct sockaddr_iso *)((ifa)->ifa_addr))
663 
664 			IFDEBUG(D_ROUTE)
665 				printf(" af same, args to iso_eqtype:\n");
666 				printf("0x%x ", IFA_SIS(ifa)->siso_addr);
667 				printf(" 0x%x\n",
668 				&(((struct sockaddr_iso *)addr)->siso_addr));
669 			ENDDEBUG
670 
671 			if (iso_eqtype(&(IFA_SIS(ifa)->siso_addr),
672 				&(((struct sockaddr_iso *)addr)->siso_addr))) {
673 				IFDEBUG(D_ROUTE)
674 					printf("ifa_ifwithidi: ifa found\n");
675 				ENDDEBUG
676 				return (ifa);
677 			}
678 			IFDEBUG(D_ROUTE)
679 				printf(" iso_eqtype failed\n");
680 			ENDDEBUG
681 		}
682 	}
683 	return ((struct ifaddr *)0);
684 }
685 
686 #endif notdef
687 /*
688  * FUNCTION:		iso_ck_addr
689  *
690  * PURPOSE:			return true if the iso_addr passed is
691  *					within the legal size limit for an iso address.
692  *
693  * RETURNS:			true or false
694  *
695  * SIDE EFFECTS:
696  *
697  */
698 iso_ck_addr(isoa)
699 struct iso_addr	*isoa;	/* address to check */
700 {
701 	return (isoa->isoa_len <= 20);
702 
703 }
704 
705 #ifdef notdef
706 /*
707  * FUNCTION:		iso_eqtype
708  *
709  * PURPOSE:			Determine if two iso addresses are of the same type.
710  *  This is flaky.  Really we should consider all type 47 addrs to be the
711  *  same - but there do exist different structures for 47 addrs.
712  *  Gosip adds a 3rd.
713  *
714  * RETURNS:			true if the addresses are the same type
715  *
716  * SIDE EFFECTS:
717  *
718  * NOTES:			By type, I mean rfc986, t37, or osinet
719  *
720  *					This will first compare afis. If they match, then
721  *					if the addr is not t37, the idis must be compared.
722  */
723 iso_eqtype(isoaa, isoab)
724 struct iso_addr	*isoaa;		/* first addr to check */
725 struct iso_addr	*isoab;		/* other addr to check */
726 {
727 	if (isoaa->isoa_afi == isoab->isoa_afi) {
728 		if (isoaa->isoa_afi == AFI_37)
729 			return(1);
730 		else
731 			return (!bcmp(&isoaa->isoa_u, &isoab->isoa_u, 2));
732 	}
733 	return(0);
734 }
735 #endif notdef
736 /*
737  * FUNCTION:		iso_localifa()
738  *
739  * PURPOSE:			Find an interface addresss having a given destination
740  *					or at least matching the net.
741  *
742  * RETURNS:			ptr to an interface address
743  *
744  * SIDE EFFECTS:
745  *
746  * NOTES:
747  */
748 struct iso_ifaddr *
749 iso_localifa(siso)
750 	register struct sockaddr_iso *siso;
751 {
752 	register struct iso_ifaddr *ia;
753 	register char *cp1, *cp2, *cp3;
754 	register struct ifnet *ifp;
755 	struct iso_ifaddr *ia_maybe = 0;
756 	/*
757 	 * We make one pass looking for both net matches and an exact
758 	 * dst addr.
759 	 */
760 	for (ia = iso_ifaddr; ia; ia = ia->ia_next) {
761 		if ((ifp = ia->ia_ifp) == 0 || ((ifp->if_flags & IFF_UP) == 0))
762 			continue;
763 		if (ifp->if_flags & IFF_POINTOPOINT) {
764 			if ((ia->ia_dstaddr.siso_family == AF_ISO) &&
765 				SAME_ISOADDR(&ia->ia_dstaddr, siso))
766 				return (ia);
767 			else
768 				if (SAME_ISOADDR(&ia->ia_addr, siso))
769 					ia_maybe = ia;
770 			continue;
771 		}
772 		if (ia->ia_sockmask.siso_len) {
773 			char *cplim = ia->ia_sockmask.siso_len + (char *)&ia->ia_sockmask;
774 			cp1 = ia->ia_sockmask.siso_data;
775 			cp2 = siso->siso_data;
776 			cp3 = ia->ia_addr.siso_data;
777 			while (cp2 < cplim)
778 				if (*cp1++ & (*cp2++ ^ *cp3++))
779 					goto next;
780 			ia_maybe = ia;
781 		}
782 		if (SAME_ISOADDR(&ia->ia_addr, siso))
783 			return ia;
784 	next:;
785 	}
786 	return ia_maybe;
787 }
788 
789 #ifdef	NARGOXTWENTYFIVE > 0
790 #include "cons.h"
791 #endif	NARGOXTWENTYFIVE > 0
792 /*
793  * FUNCTION:		iso_nlctloutput
794  *
795  * PURPOSE:			Set options at the network level
796  *
797  * RETURNS:			E*
798  *
799  * SIDE EFFECTS:
800  *
801  * NOTES:			This could embody some of the functions of
802  *					rclnp_ctloutput and cons_ctloutput.
803  */
804 iso_nlctloutput(cmd, optname, pcb, m)
805 int			cmd;		/* command:set or get */
806 int			optname;	/* option of interest */
807 caddr_t		pcb;		/* nl pcb */
808 struct mbuf	*m;			/* data for set, buffer for get */
809 {
810 	struct isopcb	*isop = (struct isopcb *)pcb;
811 	int				error = 0;	/* return value */
812 	caddr_t			data;		/* data for option */
813 	int				data_len;	/* data's length */
814 
815 	IFDEBUG(D_ISO)
816 		printf("iso_nlctloutput: cmd %x, opt %x, pcb %x, m %x\n",
817 			cmd, optname, pcb, m);
818 	ENDDEBUG
819 
820 	if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT))
821 		return(EOPNOTSUPP);
822 
823 	data = mtod(m, caddr_t);
824 	data_len = (m)->m_len;
825 
826 	IFDEBUG(D_ISO)
827 		printf("iso_nlctloutput: data is:\n");
828 		dump_buf(data, data_len);
829 	ENDDEBUG
830 
831 	switch (optname) {
832 
833 #ifdef	NARGOXTWENTYFIVE > 0
834 		case CONSOPT_X25CRUD:
835 			if (cmd == PRCO_GETOPT) {
836 				error = EOPNOTSUPP;
837 				break;
838 			}
839 
840 			if (data_len > MAXX25CRUDLEN) {
841 				error = EINVAL;
842 				break;
843 			}
844 
845 			IFDEBUG(D_ISO)
846 				printf("iso_nlctloutput: setting x25 crud\n");
847 			ENDDEBUG
848 
849 			bcopy(data, (caddr_t)isop->isop_x25crud, (unsigned)data_len);
850 			isop->isop_x25crud_len = data_len;
851 			break;
852 #endif	NARGOXTWENTYFIVE > 0
853 
854 		default:
855 			error = EOPNOTSUPP;
856 	}
857 
858 	return error;
859 }
860 
861 /*
862  * FUNCTION:		iso_routeifp
863  *
864  * PURPOSE:			Route on a sockaddr and return ifp
865  *
866  * RETURNS:			ifp of outgoing interface, or null
867  *
868  * SIDE EFFECTS:
869  *
870  * NOTES:
871  */
872 struct iso_ifaddr *
873 iso_routeifa(dst)
874 struct sockaddr	*dst;		/* destination to route to */
875 {
876 	struct rtentry	*rt;
877 	struct ifaddr *ifa = 0;
878 	struct ifnet *ifp = 0;
879 
880 
881 	IFDEBUG(D_ROUTE)
882 		printf("iso_routeifp: dst:");
883 		dump_isoaddr((struct sockaddr_iso *)dst);
884 	ENDDEBUG
885 
886 	rt = rtalloc1(dst, 0);
887 
888 	if (rt) {
889 		ifa = rt->rt_ifa;
890 		ifp = rt->rt_ifp;
891 		RTFREE(rt);
892 	}
893 
894 	IFDEBUG(D_ROUTE)
895 		printf("iso_routeifp: ifa x%x", ifa);
896 		if (ifp)
897 			printf(" (%s%d)\n", ifp->if_name, ifp->if_unit);
898 		else
899 			printf("\n");
900 	ENDDEBUG
901 
902 	return((struct iso_ifaddr *)ifa);
903 }
904 #endif ISO
905 
906 #ifdef ARGO_DEBUG
907 
908 /*
909  * FUNCTION:		dump_isoaddr
910  *
911  * PURPOSE:			debugging
912  *
913  * RETURNS:			nada
914  *
915  */
916 dump_isoaddr(s)
917 	struct sockaddr_iso *s;
918 {
919 	char *clnp_saddr_isop();
920 	register int i;
921 
922 	if( s->siso_family == AF_ISO) {
923 		printf("ISO address: suffixlen %d, %s\n",
924 			s->siso_tsuffixlen, clnp_saddr_isop(s));
925 	} else if( s->siso_family == AF_INET) {
926 		/* hack */
927 		struct sockaddr_in *sin = (struct sockaddr_in *)s;
928 
929 		printf("%d.%d.%d.%d: %d",
930 			(sin->sin_addr.s_addr>>24)&0xff,
931 			(sin->sin_addr.s_addr>>16)&0xff,
932 			(sin->sin_addr.s_addr>>8)&0xff,
933 			(sin->sin_addr.s_addr)&0xff,
934 			sin->sin_port);
935 	}
936 }
937 
938 #endif ARGO_DEBUG
939