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