xref: /original-bsd/sys/netiso/iso.c (revision 04218a6a)
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.8 (Berkeley) 04/12/90
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 		error = 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 		error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
623 	else {
624 		rt_maskedcopy(ia->ia_ifa.ifa_addr, ia->ia_ifa.ifa_dstaddr,
625 			ia->ia_ifa.ifa_netmask);
626 		error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
627 	}
628 	ia->ia_flags |= IFA_ROUTE;
629 	splx(s);
630 	return (error);
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 (cp1 < 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 #endif ISO
861 
862 #ifdef ARGO_DEBUG
863 
864 /*
865  * FUNCTION:		dump_isoaddr
866  *
867  * PURPOSE:			debugging
868  *
869  * RETURNS:			nada
870  *
871  */
872 dump_isoaddr(s)
873 	struct sockaddr_iso *s;
874 {
875 	char *clnp_saddr_isop();
876 	register int i;
877 
878 	if( s->siso_family == AF_ISO) {
879 		printf("ISO address: suffixlen %d, %s\n",
880 			s->siso_tlen, clnp_saddr_isop(s));
881 	} else if( s->siso_family == AF_INET) {
882 		/* hack */
883 		struct sockaddr_in *sin = (struct sockaddr_in *)s;
884 
885 		printf("%d.%d.%d.%d: %d",
886 			(sin->sin_addr.s_addr>>24)&0xff,
887 			(sin->sin_addr.s_addr>>16)&0xff,
888 			(sin->sin_addr.s_addr>>8)&0xff,
889 			(sin->sin_addr.s_addr)&0xff,
890 			sin->sin_port);
891 	}
892 }
893 
894 #endif ARGO_DEBUG
895