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