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