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