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