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