add to KSRCS, rather than replacing, so that we can have
[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 *
b965365f 7 * @(#)iso.c 7.17 (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 }
b965365f 550 IFAFREE((&oia->ia_ifa));
a50e2bc0 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;
c2bb180a 617 }
a50e2bc0
KS
618 /*
619 * Add route for the network.
620 */
c2bb180a
KS
621 nsellength = ia->ia_addr.siso_tlen;
622 ia->ia_addr.siso_tlen = 0;
a50e2bc0
KS
623 if (ifp->if_flags & IFF_LOOPBACK) {
624 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
7b1cab50 625 error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
a50e2bc0
KS
626 } else if (ifp->if_flags & IFF_POINTOPOINT &&
627 ia->ia_dstaddr.siso_family == AF_ISO)
7b1cab50 628 error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
a50e2bc0 629 else {
7b1cab50
KS
630 rt_maskedcopy(ia->ia_ifa.ifa_addr, ia->ia_ifa.ifa_dstaddr,
631 ia->ia_ifa.ifa_netmask);
e6e05018
KS
632 ia->ia_dstaddr.siso_nlen =
633 min(ia->ia_addr.siso_nlen, (ia->ia_sockmask.siso_len - 6));
7b1cab50 634 error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
a50e2bc0 635 }
c2bb180a 636 ia->ia_addr.siso_tlen = nsellength;
a50e2bc0
KS
637 ia->ia_flags |= IFA_ROUTE;
638 splx(s);
7b1cab50 639 return (error);
56d0087e 640}
a50e2bc0 641#ifdef notdef
56d0087e
KS
642
643struct ifaddr *
644iso_ifwithidi(addr)
645 register struct sockaddr *addr;
646{
647 register struct ifnet *ifp;
648 register struct ifaddr *ifa;
649 register u_int af = addr->sa_family;
650
651 if (af != AF_ISO)
652 return (0);
653 IFDEBUG(D_ROUTE)
654 printf(">>> iso_ifwithidi addr\n");
655 dump_isoaddr( (struct sockaddr_iso *)(addr));
656 printf("\n");
657 ENDDEBUG
658 for (ifp = ifnet; ifp; ifp = ifp->if_next) {
659 IFDEBUG(D_ROUTE)
660 printf("iso_ifwithidi ifnet %s\n", ifp->if_name);
661 ENDDEBUG
662 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
663 IFDEBUG(D_ROUTE)
664 printf("iso_ifwithidi address ");
a50e2bc0 665 dump_isoaddr( (struct sockaddr_iso *)(ifa->ifa_addr));
56d0087e 666 ENDDEBUG
a50e2bc0 667 if (ifa->ifa_addr->sa_family != addr->sa_family)
56d0087e
KS
668 continue;
669
670#define IFA_SIS(ifa)\
a50e2bc0 671 ((struct sockaddr_iso *)((ifa)->ifa_addr))
56d0087e
KS
672
673 IFDEBUG(D_ROUTE)
674 printf(" af same, args to iso_eqtype:\n");
675 printf("0x%x ", IFA_SIS(ifa)->siso_addr);
676 printf(" 0x%x\n",
677 &(((struct sockaddr_iso *)addr)->siso_addr));
678 ENDDEBUG
679
680 if (iso_eqtype(&(IFA_SIS(ifa)->siso_addr),
681 &(((struct sockaddr_iso *)addr)->siso_addr))) {
682 IFDEBUG(D_ROUTE)
683 printf("ifa_ifwithidi: ifa found\n");
684 ENDDEBUG
685 return (ifa);
686 }
687 IFDEBUG(D_ROUTE)
688 printf(" iso_eqtype failed\n");
689 ENDDEBUG
690 }
691 }
692 return ((struct ifaddr *)0);
693}
694
a50e2bc0 695#endif notdef
56d0087e
KS
696/*
697 * FUNCTION: iso_ck_addr
698 *
699 * PURPOSE: return true if the iso_addr passed is
700 * within the legal size limit for an iso address.
701 *
702 * RETURNS: true or false
703 *
704 * SIDE EFFECTS:
705 *
706 */
707iso_ck_addr(isoa)
708struct iso_addr *isoa; /* address to check */
709{
710 return (isoa->isoa_len <= 20);
711
712}
713
a50e2bc0 714#ifdef notdef
56d0087e
KS
715/*
716 * FUNCTION: iso_eqtype
717 *
718 * PURPOSE: Determine if two iso addresses are of the same type.
719 * This is flaky. Really we should consider all type 47 addrs to be the
720 * same - but there do exist different structures for 47 addrs.
721 * Gosip adds a 3rd.
722 *
723 * RETURNS: true if the addresses are the same type
724 *
725 * SIDE EFFECTS:
726 *
727 * NOTES: By type, I mean rfc986, t37, or osinet
728 *
729 * This will first compare afis. If they match, then
730 * if the addr is not t37, the idis must be compared.
731 */
732iso_eqtype(isoaa, isoab)
733struct iso_addr *isoaa; /* first addr to check */
734struct iso_addr *isoab; /* other addr to check */
735{
736 if (isoaa->isoa_afi == isoab->isoa_afi) {
737 if (isoaa->isoa_afi == AFI_37)
738 return(1);
739 else
740 return (!bcmp(&isoaa->isoa_u, &isoab->isoa_u, 2));
741 }
742 return(0);
743}
a50e2bc0 744#endif notdef
56d0087e 745/*
a50e2bc0 746 * FUNCTION: iso_localifa()
56d0087e 747 *
a50e2bc0
KS
748 * PURPOSE: Find an interface addresss having a given destination
749 * or at least matching the net.
56d0087e
KS
750 *
751 * RETURNS: ptr to an interface address
752 *
753 * SIDE EFFECTS:
754 *
755 * NOTES:
756 */
757struct iso_ifaddr *
a50e2bc0
KS
758iso_localifa(siso)
759 register struct sockaddr_iso *siso;
56d0087e
KS
760{
761 register struct iso_ifaddr *ia;
a50e2bc0
KS
762 register char *cp1, *cp2, *cp3;
763 register struct ifnet *ifp;
764 struct iso_ifaddr *ia_maybe = 0;
765 /*
766 * We make one pass looking for both net matches and an exact
767 * dst addr.
768 */
769 for (ia = iso_ifaddr; ia; ia = ia->ia_next) {
770 if ((ifp = ia->ia_ifp) == 0 || ((ifp->if_flags & IFF_UP) == 0))
771 continue;
772 if (ifp->if_flags & IFF_POINTOPOINT) {
773 if ((ia->ia_dstaddr.siso_family == AF_ISO) &&
774 SAME_ISOADDR(&ia->ia_dstaddr, siso))
775 return (ia);
776 else
777 if (SAME_ISOADDR(&ia->ia_addr, siso))
778 ia_maybe = ia;
779 continue;
780 }
781 if (ia->ia_sockmask.siso_len) {
782 char *cplim = ia->ia_sockmask.siso_len + (char *)&ia->ia_sockmask;
783 cp1 = ia->ia_sockmask.siso_data;
784 cp2 = siso->siso_data;
785 cp3 = ia->ia_addr.siso_data;
0d552c85 786 while (cp1 < cplim)
a50e2bc0
KS
787 if (*cp1++ & (*cp2++ ^ *cp3++))
788 goto next;
789 ia_maybe = ia;
790 }
791 if (SAME_ISOADDR(&ia->ia_addr, siso))
792 return ia;
793 next:;
794 }
795 return ia_maybe;
56d0087e
KS
796}
797
7abea69b 798#ifdef TPCONS
56d0087e 799#include "cons.h"
7abea69b 800#endif TPCONS
56d0087e
KS
801/*
802 * FUNCTION: iso_nlctloutput
803 *
804 * PURPOSE: Set options at the network level
805 *
806 * RETURNS: E*
807 *
808 * SIDE EFFECTS:
809 *
810 * NOTES: This could embody some of the functions of
811 * rclnp_ctloutput and cons_ctloutput.
812 */
813iso_nlctloutput(cmd, optname, pcb, m)
814int cmd; /* command:set or get */
815int optname; /* option of interest */
816caddr_t pcb; /* nl pcb */
817struct mbuf *m; /* data for set, buffer for get */
818{
819 struct isopcb *isop = (struct isopcb *)pcb;
820 int error = 0; /* return value */
821 caddr_t data; /* data for option */
822 int data_len; /* data's length */
823
824 IFDEBUG(D_ISO)
825 printf("iso_nlctloutput: cmd %x, opt %x, pcb %x, m %x\n",
826 cmd, optname, pcb, m);
827 ENDDEBUG
828
829 if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT))
830 return(EOPNOTSUPP);
831
832 data = mtod(m, caddr_t);
833 data_len = (m)->m_len;
834
835 IFDEBUG(D_ISO)
836 printf("iso_nlctloutput: data is:\n");
837 dump_buf(data, data_len);
838 ENDDEBUG
839
840 switch (optname) {
841
7abea69b 842#ifdef TPCONS
56d0087e
KS
843 case CONSOPT_X25CRUD:
844 if (cmd == PRCO_GETOPT) {
845 error = EOPNOTSUPP;
846 break;
847 }
848
849 if (data_len > MAXX25CRUDLEN) {
850 error = EINVAL;
851 break;
852 }
853
854 IFDEBUG(D_ISO)
855 printf("iso_nlctloutput: setting x25 crud\n");
856 ENDDEBUG
857
a50e2bc0 858 bcopy(data, (caddr_t)isop->isop_x25crud, (unsigned)data_len);
56d0087e
KS
859 isop->isop_x25crud_len = data_len;
860 break;
7abea69b 861#endif TPCONS
56d0087e
KS
862
863 default:
864 error = EOPNOTSUPP;
865 }
d169a5dd
KS
866 if (cmd == PRCO_SETOPT)
867 m_freem(m);
56d0087e
KS
868 return error;
869}
56d0087e
KS
870#endif ISO
871
872#ifdef ARGO_DEBUG
873
874/*
875 * FUNCTION: dump_isoaddr
876 *
877 * PURPOSE: debugging
878 *
879 * RETURNS: nada
880 *
881 */
882dump_isoaddr(s)
883 struct sockaddr_iso *s;
884{
a50e2bc0 885 char *clnp_saddr_isop();
56d0087e
KS
886 register int i;
887
888 if( s->siso_family == AF_ISO) {
a50e2bc0 889 printf("ISO address: suffixlen %d, %s\n",
44f52ea5 890 s->siso_tlen, clnp_saddr_isop(s));
56d0087e
KS
891 } else if( s->siso_family == AF_INET) {
892 /* hack */
893 struct sockaddr_in *sin = (struct sockaddr_in *)s;
894
895 printf("%d.%d.%d.%d: %d",
896 (sin->sin_addr.s_addr>>24)&0xff,
897 (sin->sin_addr.s_addr>>16)&0xff,
898 (sin->sin_addr.s_addr>>8)&0xff,
899 (sin->sin_addr.s_addr)&0xff,
900 sin->sin_port);
901 }
902}
903
904#endif ARGO_DEBUG