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