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