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