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