xref: /original-bsd/sys/netiso/iso.c (revision b9cffa27)
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.16 (Berkeley) 09/03/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 		free((caddr_t)oia, M_IFADDR);
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 		ia->ia_ifa.ifa_llinfolen = sizeof(struct llinfo_llc);
618 	}
619 	/*
620 	 * Add route for the network.
621 	 */
622 	nsellength = ia->ia_addr.siso_tlen;
623 	ia->ia_addr.siso_tlen = 0;
624 	if (ifp->if_flags & IFF_LOOPBACK) {
625 		ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
626 		error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
627 	} else if (ifp->if_flags & IFF_POINTOPOINT &&
628 		 ia->ia_dstaddr.siso_family == AF_ISO)
629 		error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
630 	else {
631 		rt_maskedcopy(ia->ia_ifa.ifa_addr, ia->ia_ifa.ifa_dstaddr,
632 			ia->ia_ifa.ifa_netmask);
633 		ia->ia_dstaddr.siso_nlen =
634 			min(ia->ia_addr.siso_nlen, (ia->ia_sockmask.siso_len - 6));
635 		error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
636 	}
637 	ia->ia_addr.siso_tlen = nsellength;
638 	ia->ia_flags |= IFA_ROUTE;
639 	splx(s);
640 	return (error);
641 }
642 #ifdef notdef
643 
644 struct ifaddr *
645 iso_ifwithidi(addr)
646 	register struct sockaddr *addr;
647 {
648 	register struct ifnet *ifp;
649 	register struct ifaddr *ifa;
650 	register u_int af = addr->sa_family;
651 
652 	if (af != AF_ISO)
653 		return (0);
654 	IFDEBUG(D_ROUTE)
655 		printf(">>> iso_ifwithidi addr\n");
656 		dump_isoaddr( (struct sockaddr_iso *)(addr));
657 		printf("\n");
658 	ENDDEBUG
659 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
660 		IFDEBUG(D_ROUTE)
661 			printf("iso_ifwithidi ifnet %s\n", ifp->if_name);
662 		ENDDEBUG
663 		for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
664 			IFDEBUG(D_ROUTE)
665 				printf("iso_ifwithidi address ");
666 				dump_isoaddr( (struct sockaddr_iso *)(ifa->ifa_addr));
667 			ENDDEBUG
668 			if (ifa->ifa_addr->sa_family != addr->sa_family)
669 				continue;
670 
671 #define	IFA_SIS(ifa)\
672 	((struct sockaddr_iso *)((ifa)->ifa_addr))
673 
674 			IFDEBUG(D_ROUTE)
675 				printf(" af same, args to iso_eqtype:\n");
676 				printf("0x%x ", IFA_SIS(ifa)->siso_addr);
677 				printf(" 0x%x\n",
678 				&(((struct sockaddr_iso *)addr)->siso_addr));
679 			ENDDEBUG
680 
681 			if (iso_eqtype(&(IFA_SIS(ifa)->siso_addr),
682 				&(((struct sockaddr_iso *)addr)->siso_addr))) {
683 				IFDEBUG(D_ROUTE)
684 					printf("ifa_ifwithidi: ifa found\n");
685 				ENDDEBUG
686 				return (ifa);
687 			}
688 			IFDEBUG(D_ROUTE)
689 				printf(" iso_eqtype failed\n");
690 			ENDDEBUG
691 		}
692 	}
693 	return ((struct ifaddr *)0);
694 }
695 
696 #endif notdef
697 /*
698  * FUNCTION:		iso_ck_addr
699  *
700  * PURPOSE:			return true if the iso_addr passed is
701  *					within the legal size limit for an iso address.
702  *
703  * RETURNS:			true or false
704  *
705  * SIDE EFFECTS:
706  *
707  */
708 iso_ck_addr(isoa)
709 struct iso_addr	*isoa;	/* address to check */
710 {
711 	return (isoa->isoa_len <= 20);
712 
713 }
714 
715 #ifdef notdef
716 /*
717  * FUNCTION:		iso_eqtype
718  *
719  * PURPOSE:			Determine if two iso addresses are of the same type.
720  *  This is flaky.  Really we should consider all type 47 addrs to be the
721  *  same - but there do exist different structures for 47 addrs.
722  *  Gosip adds a 3rd.
723  *
724  * RETURNS:			true if the addresses are the same type
725  *
726  * SIDE EFFECTS:
727  *
728  * NOTES:			By type, I mean rfc986, t37, or osinet
729  *
730  *					This will first compare afis. If they match, then
731  *					if the addr is not t37, the idis must be compared.
732  */
733 iso_eqtype(isoaa, isoab)
734 struct iso_addr	*isoaa;		/* first addr to check */
735 struct iso_addr	*isoab;		/* other addr to check */
736 {
737 	if (isoaa->isoa_afi == isoab->isoa_afi) {
738 		if (isoaa->isoa_afi == AFI_37)
739 			return(1);
740 		else
741 			return (!bcmp(&isoaa->isoa_u, &isoab->isoa_u, 2));
742 	}
743 	return(0);
744 }
745 #endif notdef
746 /*
747  * FUNCTION:		iso_localifa()
748  *
749  * PURPOSE:			Find an interface addresss having a given destination
750  *					or at least matching the net.
751  *
752  * RETURNS:			ptr to an interface address
753  *
754  * SIDE EFFECTS:
755  *
756  * NOTES:
757  */
758 struct iso_ifaddr *
759 iso_localifa(siso)
760 	register struct sockaddr_iso *siso;
761 {
762 	register struct iso_ifaddr *ia;
763 	register char *cp1, *cp2, *cp3;
764 	register struct ifnet *ifp;
765 	struct iso_ifaddr *ia_maybe = 0;
766 	/*
767 	 * We make one pass looking for both net matches and an exact
768 	 * dst addr.
769 	 */
770 	for (ia = iso_ifaddr; ia; ia = ia->ia_next) {
771 		if ((ifp = ia->ia_ifp) == 0 || ((ifp->if_flags & IFF_UP) == 0))
772 			continue;
773 		if (ifp->if_flags & IFF_POINTOPOINT) {
774 			if ((ia->ia_dstaddr.siso_family == AF_ISO) &&
775 				SAME_ISOADDR(&ia->ia_dstaddr, siso))
776 				return (ia);
777 			else
778 				if (SAME_ISOADDR(&ia->ia_addr, siso))
779 					ia_maybe = ia;
780 			continue;
781 		}
782 		if (ia->ia_sockmask.siso_len) {
783 			char *cplim = ia->ia_sockmask.siso_len + (char *)&ia->ia_sockmask;
784 			cp1 = ia->ia_sockmask.siso_data;
785 			cp2 = siso->siso_data;
786 			cp3 = ia->ia_addr.siso_data;
787 			while (cp1 < cplim)
788 				if (*cp1++ & (*cp2++ ^ *cp3++))
789 					goto next;
790 			ia_maybe = ia;
791 		}
792 		if (SAME_ISOADDR(&ia->ia_addr, siso))
793 			return ia;
794 	next:;
795 	}
796 	return ia_maybe;
797 }
798 
799 #ifdef	TPCONS
800 #include "cons.h"
801 #endif	TPCONS
802 /*
803  * FUNCTION:		iso_nlctloutput
804  *
805  * PURPOSE:			Set options at the network level
806  *
807  * RETURNS:			E*
808  *
809  * SIDE EFFECTS:
810  *
811  * NOTES:			This could embody some of the functions of
812  *					rclnp_ctloutput and cons_ctloutput.
813  */
814 iso_nlctloutput(cmd, optname, pcb, m)
815 int			cmd;		/* command:set or get */
816 int			optname;	/* option of interest */
817 caddr_t		pcb;		/* nl pcb */
818 struct mbuf	*m;			/* data for set, buffer for get */
819 {
820 	struct isopcb	*isop = (struct isopcb *)pcb;
821 	int				error = 0;	/* return value */
822 	caddr_t			data;		/* data for option */
823 	int				data_len;	/* data's length */
824 
825 	IFDEBUG(D_ISO)
826 		printf("iso_nlctloutput: cmd %x, opt %x, pcb %x, m %x\n",
827 			cmd, optname, pcb, m);
828 	ENDDEBUG
829 
830 	if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT))
831 		return(EOPNOTSUPP);
832 
833 	data = mtod(m, caddr_t);
834 	data_len = (m)->m_len;
835 
836 	IFDEBUG(D_ISO)
837 		printf("iso_nlctloutput: data is:\n");
838 		dump_buf(data, data_len);
839 	ENDDEBUG
840 
841 	switch (optname) {
842 
843 #ifdef	TPCONS
844 		case CONSOPT_X25CRUD:
845 			if (cmd == PRCO_GETOPT) {
846 				error = EOPNOTSUPP;
847 				break;
848 			}
849 
850 			if (data_len > MAXX25CRUDLEN) {
851 				error = EINVAL;
852 				break;
853 			}
854 
855 			IFDEBUG(D_ISO)
856 				printf("iso_nlctloutput: setting x25 crud\n");
857 			ENDDEBUG
858 
859 			bcopy(data, (caddr_t)isop->isop_x25crud, (unsigned)data_len);
860 			isop->isop_x25crud_len = data_len;
861 			break;
862 #endif	TPCONS
863 
864 		default:
865 			error = EOPNOTSUPP;
866 	}
867 	if (cmd == PRCO_SETOPT)
868 		m_freem(m);
869 	return error;
870 }
871 #endif ISO
872 
873 #ifdef ARGO_DEBUG
874 
875 /*
876  * FUNCTION:		dump_isoaddr
877  *
878  * PURPOSE:			debugging
879  *
880  * RETURNS:			nada
881  *
882  */
883 dump_isoaddr(s)
884 	struct sockaddr_iso *s;
885 {
886 	char *clnp_saddr_isop();
887 	register int i;
888 
889 	if( s->siso_family == AF_ISO) {
890 		printf("ISO address: suffixlen %d, %s\n",
891 			s->siso_tlen, clnp_saddr_isop(s));
892 	} else if( s->siso_family == AF_INET) {
893 		/* hack */
894 		struct sockaddr_in *sin = (struct sockaddr_in *)s;
895 
896 		printf("%d.%d.%d.%d: %d",
897 			(sin->sin_addr.s_addr>>24)&0xff,
898 			(sin->sin_addr.s_addr>>16)&0xff,
899 			(sin->sin_addr.s_addr>>8)&0xff,
900 			(sin->sin_addr.s_addr)&0xff,
901 			sin->sin_port);
902 	}
903 }
904 
905 #endif ARGO_DEBUG
906