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