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