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