split out descend and inherit attributes; add signal tracing
[unix-history] / usr / src / sys / netiso / iso.c
CommitLineData
56d0087e
KS
1/***********************************************************
2 Copyright IBM Corporation 1987
3
4 All Rights Reserved
5
6Permission to use, copy, modify, and distribute this software and its
7documentation for any purpose and without fee is hereby granted,
8provided that the above copyright notice appear in all copies and that
9both that copyright notice and this permission notice appear in
10supporting documentation, and that the name of IBM not be
11used in advertising or publicity pertaining to distribution of the
12software without specific, written prior permission.
13
14IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20SOFTWARE.
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 $
a966c50c 30 * @(#)iso.c 7.10 (Berkeley) %G%
56d0087e
KS
31 *
32 * iso.c: miscellaneous routines to support the iso address family
33 */
34
35#ifndef lint
36static char *rcsid = "$Header: iso.c,v 4.11 88/09/19 14:58:35 root Exp $";
37#endif
38
39
a50e2bc0
KS
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"
a50e2bc0
KS
48#include "user.h"
49#include "errno.h"
56d0087e
KS
50
51#include "../net/if.h"
52#include "../net/route.h"
53#include "../net/af.h"
54
a50e2bc0
KS
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"
56d0087e
KS
61
62#ifdef ISO
a50e2bc0 63#include "argoxtwentyfive.h"
56d0087e
KS
64
65int iso_interfaces = 0; /* number of external interfaces */
66extern struct ifnet loif; /* loopback interface */
c2bb180a 67int ether_output(), llc_rtrequest();
56d0087e
KS
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.
a50e2bc0 78 * 2) initializes the routing table.
56d0087e
KS
79 *
80 * NOTES:
81 */
a50e2bc0 82struct radix_node_head *iso_rnhead;
56d0087e
KS
83iso_init()
84{
a50e2bc0
KS
85 static iso_init_done;
86
87 if (iso_init_done == 0) {
88 iso_init_done++;
a50e2bc0
KS
89 rn_inithead(&iso_rnhead, 40, AF_ISO);
90 }
56d0087e
KS
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 */
104iso_addrmatch1(isoaa, isoab)
a50e2bc0 105register struct iso_addr *isoaa, *isoab; /* addresses to check */
56d0087e 106{
a50e2bc0 107 u_int compare_len;
56d0087e
KS
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");
a50e2bc0 113 dump_buf(isoaa->isoa_genaddr, isoaa->isoa_len);
56d0087e 114 printf("b:\n");
a50e2bc0 115 dump_buf(isoab->isoa_genaddr, isoab->isoa_len);
56d0087e
KS
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
a50e2bc0 125#ifdef notdef
56d0087e
KS
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 }
a50e2bc0 133#endif
56d0087e
KS
134
135 IFDEBUG(D_ROUTE)
136 int i;
137 char *a, *b;
138
a50e2bc0
KS
139 a = isoaa->isoa_genaddr;
140 b = isoab->isoa_genaddr;
56d0087e
KS
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
a50e2bc0 153 return (!bcmp(isoaa->isoa_genaddr, isoab->isoa_genaddr, compare_len));
56d0087e
KS
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 */
167iso_addrmatch(sisoa, sisob)
168struct sockaddr_iso *sisoa, *sisob; /* addresses to check */
169{
170 return(iso_addrmatch1(&sisoa->siso_addr, &sisob->siso_addr));
171}
a50e2bc0 172#ifdef notdef
56d0087e
KS
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 */
185iso_netmatch(sisoa, sisob)
186struct 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}
a50e2bc0 205#endif notdef
56d0087e
KS
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 */
220u_long
221iso_hashchar(buf, len)
222register caddr_t buf; /* buffer to pack from */
223register 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}
a50e2bc0 259#ifdef notdef
56d0087e
KS
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 */
271iso_hash(siso, hp)
272struct sockaddr_iso *siso; /* address to perform hash on */
273struct 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}
56d0087e
KS
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 */
317iso_netof(isoa, buf)
318struct iso_addr *isoa; /* address */
319caddr_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}
a50e2bc0 402#endif notdef
56d0087e 403/*
a50e2bc0
KS
404 * Generic iso control operations (ioctl's).
405 * Ifp is 0 if not an interface-specific ioctl.
56d0087e 406 */
a50e2bc0 407/* ARGSUSED */
56d0087e 408iso_control(so, cmd, data, ifp)
a50e2bc0
KS
409 struct socket *so;
410 int cmd;
411 caddr_t data;
412 register struct ifnet *ifp;
56d0087e 413{
a50e2bc0
KS
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;
56d0087e 420
a50e2bc0
KS
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;
56d0087e
KS
428
429 switch (cmd) {
a50e2bc0
KS
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 }
06c16dfa
KM
439 if (error = suser(u.u_cred, &u.u_acflag))
440 return (error);
56d0087e 441 if (ifp == 0)
a50e2bc0
KS
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;
56d0087e 475
a50e2bc0
KS
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) {
56d0087e 485
a50e2bc0
KS
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:
a966c50c 501 maskIsNew = 0; hostIsNew = 1; error = 0;
a50e2bc0
KS
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 */
56d0087e 519 }
a50e2bc0
KS
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);
56d0087e 527
a50e2bc0
KS
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;
56d0087e 547 }
a50e2bc0
KS
548 if (ia->ia_next)
549 ia->ia_next = oia->ia_next;
550 else
551 printf("Didn't unlink isoifadr from list\n");
56d0087e 552 }
a50e2bc0
KS
553 free((caddr_t)oia, M_IFADDR);
554 break;
56d0087e
KS
555
556 default:
557 if (ifp == 0 || ifp->if_ioctl == 0)
558 return (EOPNOTSUPP);
559 return ((*ifp->if_ioctl)(ifp, cmd, data));
560 }
a50e2bc0
KS
561 return (0);
562}
563
564/*
565 * Delete any existing route for an interface.
566 */
567iso_ifscrub(ifp, ia)
568 register struct ifnet *ifp;
569 register struct iso_ifaddr *ia;
570{
c2bb180a 571 int nsellength = ia->ia_addr.siso_tlen;
a50e2bc0
KS
572 if ((ia->ia_flags & IFA_ROUTE) == 0)
573 return;
c2bb180a 574 ia->ia_addr.siso_tlen = 0;
a50e2bc0
KS
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 }
c2bb180a 582 ia->ia_addr.siso_tlen = nsellength;
a50e2bc0
KS
583 ia->ia_flags &= ~IFA_ROUTE;
584}
585
586/*
587 * Initialize an interface's internet address
588 * and routing table entry.
589 */
590iso_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;
c2bb180a 596 int s = splimp(), error, nsellength;
a50e2bc0
KS
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 }
c2bb180a
KS
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 }
a50e2bc0
KS
622 /*
623 * Add route for the network.
624 */
c2bb180a
KS
625 nsellength = ia->ia_addr.siso_tlen;
626 ia->ia_addr.siso_tlen = 0;
a50e2bc0
KS
627 if (ifp->if_flags & IFF_LOOPBACK) {
628 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
7b1cab50 629 error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
a50e2bc0
KS
630 } else if (ifp->if_flags & IFF_POINTOPOINT &&
631 ia->ia_dstaddr.siso_family == AF_ISO)
7b1cab50 632 error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
a50e2bc0 633 else {
7b1cab50
KS
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);
a50e2bc0 637 }
c2bb180a 638 ia->ia_addr.siso_tlen = nsellength;
a50e2bc0
KS
639 ia->ia_flags |= IFA_ROUTE;
640 splx(s);
7b1cab50 641 return (error);
56d0087e 642}
a50e2bc0 643#ifdef notdef
56d0087e
KS
644
645struct ifaddr *
646iso_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 ");
a50e2bc0 667 dump_isoaddr( (struct sockaddr_iso *)(ifa->ifa_addr));
56d0087e 668 ENDDEBUG
a50e2bc0 669 if (ifa->ifa_addr->sa_family != addr->sa_family)
56d0087e
KS
670 continue;
671
672#define IFA_SIS(ifa)\
a50e2bc0 673 ((struct sockaddr_iso *)((ifa)->ifa_addr))
56d0087e
KS
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
a50e2bc0 697#endif notdef
56d0087e
KS
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 */
709iso_ck_addr(isoa)
710struct iso_addr *isoa; /* address to check */
711{
712 return (isoa->isoa_len <= 20);
713
714}
715
a50e2bc0 716#ifdef notdef
56d0087e
KS
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 */
734iso_eqtype(isoaa, isoab)
735struct iso_addr *isoaa; /* first addr to check */
736struct 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}
a50e2bc0 746#endif notdef
56d0087e 747/*
a50e2bc0 748 * FUNCTION: iso_localifa()
56d0087e 749 *
a50e2bc0
KS
750 * PURPOSE: Find an interface addresss having a given destination
751 * or at least matching the net.
56d0087e
KS
752 *
753 * RETURNS: ptr to an interface address
754 *
755 * SIDE EFFECTS:
756 *
757 * NOTES:
758 */
759struct iso_ifaddr *
a50e2bc0
KS
760iso_localifa(siso)
761 register struct sockaddr_iso *siso;
56d0087e
KS
762{
763 register struct iso_ifaddr *ia;
a50e2bc0
KS
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;
0d552c85 788 while (cp1 < cplim)
a50e2bc0
KS
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;
56d0087e
KS
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 */
815iso_nlctloutput(cmd, optname, pcb, m)
816int cmd; /* command:set or get */
817int optname; /* option of interest */
818caddr_t pcb; /* nl pcb */
819struct 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
a50e2bc0 860 bcopy(data, (caddr_t)isop->isop_x25crud, (unsigned)data_len);
56d0087e
KS
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}
56d0087e
KS
871#endif ISO
872
873#ifdef ARGO_DEBUG
874
875/*
876 * FUNCTION: dump_isoaddr
877 *
878 * PURPOSE: debugging
879 *
880 * RETURNS: nada
881 *
882 */
883dump_isoaddr(s)
884 struct sockaddr_iso *s;
885{
a50e2bc0 886 char *clnp_saddr_isop();
56d0087e
KS
887 register int i;
888
889 if( s->siso_family == AF_ISO) {
a50e2bc0 890 printf("ISO address: suffixlen %d, %s\n",
44f52ea5 891 s->siso_tlen, clnp_saddr_isop(s));
56d0087e
KS
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