FreeBSD/Linux Kernel Cross Reference
sys/netiso/iso.c
1 /* $NetBSD: iso.c,v 1.39 2006/10/25 23:40:57 elad 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.39 2006/10/25 23:40:57 elad 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 #include <sys/kauth.h>
78
79 #include <net/if.h>
80 #include <net/if_types.h>
81 #include <net/route.h>
82
83 #include <netiso/iso.h>
84 #include <netiso/iso_var.h>
85 #include <netiso/iso_snpac.h>
86 #include <netiso/iso_pcb.h>
87 #include <netiso/clnp.h>
88 #include <netiso/argo_debug.h>
89
90 #include "opt_iso.h"
91 #ifdef ISO
92
93 int iso_interfaces = 0; /* number of external interfaces */
94
95 /*
96 * FUNCTION: iso_addrmatch1
97 *
98 * PURPOSE: decide if the two iso_addrs passed are equal
99 *
100 * RETURNS: true if the addrs match, false if they do not
101 *
102 * SIDE EFFECTS:
103 *
104 * NOTES:
105 */
106 int
107 iso_addrmatch1(const struct iso_addr *isoaa, const struct iso_addr *isoab)
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 const 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(const struct sockaddr_iso *sisoa,
177 const struct sockaddr_iso *sisob)
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(const struct sockaddr_iso *sisoa,
196 const struct sockaddr_iso *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(caddr_t buf, int len)
234 {
235 u_long h = 0;
236 int i;
237
238 for (i = 0; i < len; i += 4) {
239 u_long l = 0;
240
241 if ((len - i) < 4) {
242 /* buffer not multiple of 4 */
243 switch (len - i) {
244 case 3:
245 l |= buf[i + 2] << 8;
246 case 2:
247 l |= buf[i + 1] << 16;
248 case 1:
249 l |= buf[i] << 24;
250 break;
251 default:
252 printf("iso_hashchar: unexpected value x%x\n", len - i);
253 break;
254 }
255 } else {
256 l |= buf[i] << 24;
257 l |= buf[i + 1] << 16;
258 l |= buf[i + 2] << 8;
259 l |= buf[i + 3];
260 }
261
262 h ^= l;
263 }
264
265 h ^= (u_long) (len % 4);
266
267 return (h);
268 }
269
270 #ifdef notdef
271 /*
272 * FUNCTION: iso_hash
273 *
274 * PURPOSE: Fill in fields of afhash structure based upon addr
275 * passed.
276 *
277 * RETURNS: none
278 *
279 * SIDE EFFECTS:
280 *
281 * NOTES:
282 */
283 void
284 iso_hash(
285 struct sockaddr_iso *siso, /* address to perform hash on */
286 struct afhash *hp) /* RETURN: hash info here */
287 {
288 u_long buf[sizeof(struct sockaddr_iso) / 4 + 1];
289 int bufsize;
290
291
292 bzero(buf, sizeof(buf));
293
294 bufsize = iso_netof(&siso->siso_addr, buf);
295 hp->afh_nethash = iso_hashchar((caddr_t) buf, bufsize);
296
297 #ifdef ARGO_DEBUG
298 if (argo_debug[D_ROUTE]) {
299 printf("iso_hash: iso_netof: bufsize = %d\n", bufsize);
300 }
301 #endif
302
303 hp->afh_hosthash = iso_hashchar((caddr_t) & siso->siso_addr,
304 siso->siso_addr.isoa_len);
305
306 #ifdef ARGO_DEBUG
307 if (argo_debug[D_ROUTE]) {
308 printf("iso_hash: %s: nethash = x%x, hosthash = x%x\n",
309 clnp_iso_addrp(&siso->siso_addr), hp->afh_nethash,
310 hp->afh_hosthash);
311 }
312 #endif
313 }
314 /*
315 * FUNCTION: iso_netof
316 *
317 * PURPOSE: Extract the network portion of the iso address.
318 * The network portion of the iso address varies depending
319 * on the type of address. The network portion of the
320 * address will include the IDP. The network portion is:
321 *
322 * TYPE DESC
323 * t37 The AFI and x.121 (IDI)
324 * osinet The AFI, orgid, snetid
325 * rfc986 The AFI, vers and network part
326 * of internet address.
327 *
328 * RETURNS: number of bytes placed into buf.
329 *
330 * SIDE EFFECTS:
331 *
332 * NOTES: Buf is assumed to be big enough
333 */
334 u_int
335 iso_netof(
336 struct iso_addr *isoa, /* address */
337 caddr_t buf) /* RESULT: network portion of address here */
338 {
339 u_int len = 1;/* length of afi */
340
341 switch (isoa->isoa_afi) {
342 case AFI_37:
343 /*
344 * Due to classic x.25 tunnel vision, there is no
345 * net portion of an x.121 address. For our purposes
346 * the AFI will do, so that all x.25 -type addresses
347 * map to the single x.25 SNPA. (Cannot have more than
348 * one, obviously).
349 */
350
351 break;
352
353 /* case AFI_OSINET: */
354 case AFI_RFC986:{
355 u_short idi; /* value of idi */
356
357 /* osinet and rfc986 have idi in the same place */
358 CTOH(isoa->rfc986_idi[0], isoa->rfc986_idi[1], idi);
359
360 if (idi == IDI_OSINET)
361 /*
362 * Network portion of OSINET address can only
363 * be the IDI. Clearly, with one x25 interface,
364 * one could get to several orgids, and
365 * several snetids.
366 */
367 #if 0
368 len += (ADDROSINET_IDI_LEN +
369 OVLOSINET_ORGID_LEN +
370 OVLOSINET_SNETID_LEN);
371 #endif
372 len += ADDROSINET_IDI_LEN;
373 else if (idi == IDI_RFC986) {
374 struct ovl_rfc986 *o986 =
375 (struct ovl_rfc986 *) isoa;
376
377 /*
378 * bump len to include idi and version (1
379 * byte)
380 */
381 len += ADDRRFC986_IDI_LEN + 1;
382
383 #ifdef ARGO_DEBUG
384 if (argo_debug[D_ROUTE]) {
385 printf("iso_netof: isoa ");
386 dump_buf(isoa, sizeof(*isoa));
387 printf("iso_netof: inetaddr 0x%x ",
388 inetaddr);
389 }
390 #endif
391
392 /*
393 * bump len by size of network portion of
394 * inet address
395 */
396 if (IN_CLASSA(o986->o986_inetaddr)) {
397 len += 4 - IN_CLASSA_NSHIFT / 8;
398 #ifdef ARGO_DEBUG
399 if (argo_debug[D_ROUTE]) {
400 printf("iso_netof: class A net len is now %d\n", len);
401 }
402 #endif
403 } else if (IN_CLASSB(o986->o986_inetaddr)) {
404 len += 4 - IN_CLASSB_NSHIFT / 8;
405 #ifdef ARGO_DEBUG
406 if (argo_debug[D_ROUTE]) {
407 printf("iso_netof: class B net len is now %d\n", len);
408 }
409 #endif
410 } else {
411 len += 4 - IN_CLASSC_NSHIFT / 8;
412 #ifdef ARGO_DEBUG
413 if (argo_debug[D_ROUTE]) {
414 printf("iso_netof: class C net len is now %d\n", len);
415 }
416 #endif
417 }
418 } else
419 len = 0;
420 } break;
421
422 default:
423 len = 0;
424 }
425
426 bcopy((caddr_t) isoa, buf, len);
427 #ifdef ARGO_DEBUG
428 if (argo_debug[D_ROUTE]) {
429 printf("iso_netof: isoa ");
430 dump_buf(isoa, len);
431 printf("iso_netof: net ");
432 dump_buf(buf, len);
433 }
434 #endif
435 return len;
436 }
437 #endif /* notdef */
438 /*
439 * Generic iso control operations (ioctl's).
440 * Ifp is 0 if not an interface-specific ioctl.
441 */
442 /* ARGSUSED */
443 int
444 iso_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
445 struct lwp *l)
446 {
447 struct iso_ifreq *ifr = (struct iso_ifreq *) data;
448 struct iso_ifaddr *ia = 0;
449 struct iso_aliasreq *ifra = (struct iso_aliasreq *) data;
450 int error, hostIsNew, maskIsNew;
451
452 /*
453 * Find address for this interface, if it exists.
454 */
455 if (ifp)
456 for (ia = iso_ifaddr.tqh_first; ia != 0; ia = ia->ia_list.tqe_next)
457 if (ia->ia_ifp == ifp)
458 break;
459
460 switch (cmd) {
461
462 case SIOCAIFADDR_ISO:
463 case SIOCDIFADDR_ISO:
464 if (ifra->ifra_addr.siso_family == AF_ISO)
465 for (; ia != 0; ia = ia->ia_list.tqe_next) {
466 if (ia->ia_ifp == ifp &&
467 SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr))
468 break;
469 }
470 if (cmd == SIOCDIFADDR_ISO && ia == 0)
471 return (EADDRNOTAVAIL);
472 /* FALLTHROUGH */
473 #if 0
474 case SIOCSIFADDR:
475 case SIOCSIFNETMASK:
476 case SIOCSIFDSTADDR:
477 #endif
478 if (l == 0 || kauth_authorize_network(l->l_cred,
479 KAUTH_NETWORK_INTERFACE,
480 KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd,
481 NULL))
482 return (EPERM);
483
484 if (ifp == 0)
485 panic("iso_control");
486 if (ia == 0) {
487 MALLOC(ia, struct iso_ifaddr *, sizeof(*ia),
488 M_IFADDR, M_WAITOK|M_ZERO);
489 if (ia == 0)
490 return (ENOBUFS);
491 TAILQ_INSERT_TAIL(&iso_ifaddr, ia, ia_list);
492 IFAREF((struct ifaddr *)ia);
493 TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia,
494 ifa_list);
495 IFAREF((struct ifaddr *)ia);
496 ia->ia_ifa.ifa_addr = sisotosa(&ia->ia_addr);
497 ia->ia_ifa.ifa_dstaddr = sisotosa(&ia->ia_dstaddr);
498 ia->ia_ifa.ifa_netmask = sisotosa(&ia->ia_sockmask);
499 ia->ia_ifp = ifp;
500 if ((ifp->if_flags & IFF_LOOPBACK) == 0)
501 iso_interfaces++;
502 }
503 break;
504
505 case SIOCGIFADDR_ISO:
506 case SIOCGIFNETMASK_ISO:
507 case SIOCGIFDSTADDR_ISO:
508 if (ia == 0)
509 return (EADDRNOTAVAIL);
510 break;
511 }
512 switch (cmd) {
513
514 case SIOCGIFADDR_ISO:
515 ifr->ifr_Addr = ia->ia_addr;
516 break;
517
518 case SIOCGIFDSTADDR_ISO:
519 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
520 return (EINVAL);
521 ifr->ifr_Addr = ia->ia_dstaddr;
522 break;
523
524 case SIOCGIFNETMASK_ISO:
525 ifr->ifr_Addr = ia->ia_sockmask;
526 break;
527
528 case SIOCAIFADDR_ISO:
529 maskIsNew = 0;
530 hostIsNew = 1;
531 error = 0;
532 if (ia->ia_addr.siso_family == AF_ISO) {
533 if (ifra->ifra_addr.siso_len == 0) {
534 ifra->ifra_addr = ia->ia_addr;
535 hostIsNew = 0;
536 } else if (SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr))
537 hostIsNew = 0;
538 }
539 if (ifra->ifra_mask.siso_len) {
540 iso_ifscrub(ifp, ia);
541 ia->ia_sockmask = ifra->ifra_mask;
542 maskIsNew = 1;
543 }
544 if ((ifp->if_flags & IFF_POINTOPOINT) &&
545 (ifra->ifra_dstaddr.siso_family == AF_ISO)) {
546 iso_ifscrub(ifp, ia);
547 ia->ia_dstaddr = ifra->ifra_dstaddr;
548 maskIsNew = 1; /* We lie; but the effect's the same */
549 }
550 if (ifra->ifra_addr.siso_family == AF_ISO &&
551 (hostIsNew || maskIsNew))
552 error = iso_ifinit(ifp, ia, &ifra->ifra_addr, 0);
553 if (ifra->ifra_snpaoffset)
554 ia->ia_snpaoffset = ifra->ifra_snpaoffset;
555 return (error);
556
557 case SIOCDIFADDR_ISO:
558 iso_purgeaddr(&ia->ia_ifa, ifp);
559 break;
560
561 #define cmdbyte(x) (((x) >> 8) & 0xff)
562 default:
563 if (cmdbyte(cmd) == 'a')
564 return (snpac_ioctl(so, cmd, data, l));
565 if (ifp == 0 || ifp->if_ioctl == 0)
566 return (EOPNOTSUPP);
567 return ((*ifp->if_ioctl)(ifp, cmd, data));
568 }
569 return (0);
570 }
571
572 void
573 iso_purgeaddr(struct ifaddr *ifa, struct ifnet *ifp)
574 {
575 struct iso_ifaddr *ia = (void *) ifa;
576
577 iso_ifscrub(ifp, ia);
578 TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
579 IFAFREE(&ia->ia_ifa);
580 TAILQ_REMOVE(&iso_ifaddr, ia, ia_list);
581 IFAFREE((&ia->ia_ifa));
582 }
583
584 void
585 iso_purgeif(struct ifnet *ifp)
586 {
587 struct ifaddr *ifa, *nifa;
588
589 for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; ifa = nifa) {
590 nifa = TAILQ_NEXT(ifa, ifa_list);
591 if (ifa->ifa_addr->sa_family != AF_ISO)
592 continue;
593 iso_purgeaddr(ifa, ifp);
594 }
595 }
596
597 /*
598 * Delete any existing route for an interface.
599 */
600 void
601 iso_ifscrub(struct ifnet *ifp, struct iso_ifaddr *ia)
602 {
603 int nsellength = ia->ia_addr.siso_tlen;
604 if ((ia->ia_flags & IFA_ROUTE) == 0)
605 return;
606 ia->ia_addr.siso_tlen = 0;
607 if (ifp->if_flags & IFF_LOOPBACK)
608 rtinit(&(ia->ia_ifa), (int) RTM_DELETE, RTF_HOST);
609 else if (ifp->if_flags & IFF_POINTOPOINT)
610 rtinit(&(ia->ia_ifa), (int) RTM_DELETE, RTF_HOST);
611 else {
612 rtinit(&(ia->ia_ifa), (int) RTM_DELETE, 0);
613 }
614 ia->ia_addr.siso_tlen = nsellength;
615 ia->ia_flags &= ~IFA_ROUTE;
616 }
617
618 /*
619 * Initialize an interface's internet address
620 * and routing table entry.
621 */
622 int
623 iso_ifinit(struct ifnet *ifp, struct iso_ifaddr *ia, struct sockaddr_iso *siso,
624 int scrub)
625 {
626 struct sockaddr_iso oldaddr;
627 int s = splnet(), error, nsellength;
628
629 oldaddr = ia->ia_addr;
630 ia->ia_addr = *siso;
631 /*
632 * Give the interface a chance to initialize
633 * if this is its first address,
634 * and to validate the address if necessary.
635 */
636 if (ifp->if_ioctl &&
637 (error = (*ifp->if_ioctl) (ifp, SIOCSIFADDR, (caddr_t) ia))) {
638 splx(s);
639 ia->ia_addr = oldaddr;
640 return (error);
641 }
642 if (scrub) {
643 ia->ia_ifa.ifa_addr = sisotosa(&oldaddr);
644 iso_ifscrub(ifp, ia);
645 ia->ia_ifa.ifa_addr = sisotosa(&ia->ia_addr);
646 }
647 /*
648 * XXX -- The following is here temporarily out of laziness in not
649 * changing every ethernet driver's if_ioctl routine
650 */
651 if (ifp->if_type == IFT_ETHER || ifp->if_type == IFT_FDDI) {
652 ia->ia_ifa.ifa_rtrequest = llc_rtrequest;
653 ia->ia_ifa.ifa_flags |= RTF_CLONING;
654 }
655 /*
656 * Add route for the network.
657 */
658 nsellength = ia->ia_addr.siso_tlen;
659 ia->ia_addr.siso_tlen = 0;
660 if (ifp->if_flags & IFF_LOOPBACK) {
661 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
662 error = rtinit(&(ia->ia_ifa), (int) RTM_ADD, RTF_HOST | RTF_UP);
663 } else if (ifp->if_flags & IFF_POINTOPOINT &&
664 ia->ia_dstaddr.siso_family == AF_ISO)
665 error = rtinit(&(ia->ia_ifa), (int) RTM_ADD, RTF_HOST | RTF_UP);
666 else {
667 rt_maskedcopy(ia->ia_ifa.ifa_addr, ia->ia_ifa.ifa_dstaddr,
668 ia->ia_ifa.ifa_netmask);
669 ia->ia_dstaddr.siso_nlen =
670 min(ia->ia_addr.siso_nlen, (ia->ia_sockmask.siso_len - 6));
671 error = rtinit(&(ia->ia_ifa), (int) RTM_ADD, RTF_UP);
672 }
673 ia->ia_addr.siso_tlen = nsellength;
674 ia->ia_flags |= IFA_ROUTE;
675 splx(s);
676 return (error);
677 }
678 #ifdef notdef
679
680 struct ifaddr *
681 iso_ifwithidi(struct sockaddr *addr)
682 {
683 struct ifnet *ifp;
684 struct ifaddr *ifa;
685 u_int af = addr->sa_family;
686
687 if (af != AF_ISO)
688 return (0);
689 #ifdef ARGO_DEBUG
690 if (argo_debug[D_ROUTE]) {
691 printf(">>> iso_ifwithidi addr\n");
692 dump_isoaddr(satosiso(addr));
693 printf("\n");
694 }
695 #endif
696 for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) {
697 #ifdef ARGO_DEBUG
698 if (argo_debug[D_ROUTE]) {
699 printf("iso_ifwithidi ifnet %s\n", ifp->if_name);
700 }
701 #endif
702 for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;
703 ifa = ifa->ifa_list.tqe_next) {
704 #ifdef ARGO_DEBUG
705 if (argo_debug[D_ROUTE]) {
706 printf("iso_ifwithidi address ");
707 dump_isoaddr(satosiso(ifa->ifa_addr));
708 }
709 #endif
710 if (ifa->ifa_addr->sa_family != addr->sa_family)
711 continue;
712
713 #ifdef ARGO_DEBUG
714 if (argo_debug[D_ROUTE]) {
715 printf(" af same, args to iso_eqtype:\n");
716 printf("0x%x ", satosiso(ifa->ifa_addr)->siso_addr);
717 printf(" 0x%x\n",
718 &satosiso(addr)->siso_addr));
719 }
720 #endif
721
722 if (iso_eqtype(&satosiso(ifa->ifa_addr)->siso_addr,
723 &satosiso(addr)->siso_addr)) {
724 #ifdef ARGO_DEBUG
725 if (argo_debug[D_ROUTE]) {
726 printf("ifa_ifwithidi: ifa found\n");
727 }
728 #endif
729 return (ifa);
730 }
731 #ifdef ARGO_DEBUG
732 if (argo_debug[D_ROUTE]) {
733 printf(" iso_eqtype failed\n");
734 }
735 #endif
736 }
737 }
738 return ((struct ifaddr *) 0);
739 }
740
741 #endif /* notdef */
742 /*
743 * FUNCTION: iso_ck_addr
744 *
745 * PURPOSE: return true if the iso_addr passed is
746 * within the legal size limit for an iso address.
747 *
748 * RETURNS: true or false
749 *
750 * SIDE EFFECTS:
751 *
752 */
753 int
754 iso_ck_addr(struct iso_addr *isoa)
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
766 * 47 addrs to be the same - but there do exist different
767 * structures for 47 addrs. 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 */
778 int
779 iso_eqtype(
780 struct iso_addr *isoaa, /* first addr to check */
781 struct iso_addr *isoab) /* other addr to check */
782 {
783 if (isoaa->isoa_afi == isoab->isoa_afi) {
784 if (isoaa->isoa_afi == AFI_37)
785 return (1);
786 else
787 return (!bcmp(&isoaa->isoa_u, &isoab->isoa_u, 2));
788 }
789 return (0);
790 }
791 #endif /* notdef */
792 /*
793 * FUNCTION: iso_localifa()
794 *
795 * PURPOSE: Find an interface addresss having a given destination
796 * or at least matching the net.
797 *
798 * RETURNS: ptr to an interface address
799 *
800 * SIDE EFFECTS:
801 *
802 * NOTES:
803 */
804 struct iso_ifaddr *
805 iso_localifa(struct sockaddr_iso *siso)
806 {
807 struct iso_ifaddr *ia;
808 char *cp1, *cp2, *cp3;
809 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.tqh_first; ia != 0; ia = ia->ia_list.tqe_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 if (SAME_ISOADDR(&ia->ia_addr, siso))
823 ia_maybe = ia;
824 continue;
825 }
826 if (ia->ia_sockmask.siso_len) {
827 char *cplim = ia->ia_sockmask.siso_len +
828 (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 <netiso/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 */
859 int
860 iso_nlctloutput(
861 int cmd, /* command:set or get */
862 int optname, /* option of interest */
863 caddr_t pcb, /* nl pcb */
864 struct mbuf *m) /* data for set, buffer for get */
865 {
866 #ifdef TPCONS
867 struct isopcb *isop = (struct isopcb *) pcb;
868 #endif
869 int error = 0; /* return value */
870 caddr_t data; /* data for option */
871 int data_len; /* data's length */
872
873 #ifdef ARGO_DEBUG
874 if (argo_debug[D_ISO]) {
875 printf("iso_nlctloutput: cmd %x, opt %x, pcb %p, m %p\n",
876 cmd, optname, pcb, m);
877 }
878 #endif
879
880 if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT))
881 return (EOPNOTSUPP);
882
883 data = mtod(m, caddr_t);
884 data_len = (m)->m_len;
885
886 #ifdef ARGO_DEBUG
887 if (argo_debug[D_ISO]) {
888 printf("iso_nlctloutput: data is:\n");
889 dump_buf(data, data_len);
890 }
891 #endif
892
893 switch (optname) {
894
895 #ifdef TPCONS
896 case CONSOPT_X25CRUD:
897 if (cmd == PRCO_GETOPT) {
898 error = EOPNOTSUPP;
899 break;
900 }
901 if (data_len > MAXX25CRUDLEN) {
902 error = EINVAL;
903 break;
904 }
905 #ifdef ARGO_DEBUG
906 if (argo_debug[D_ISO]) {
907 printf("iso_nlctloutput: setting x25 crud\n");
908 }
909 #endif
910
911 bcopy(data, (caddr_t) isop->isop_x25crud, (unsigned) data_len);
912 isop->isop_x25crud_len = data_len;
913 break;
914 #endif /* TPCONS */
915
916 default:
917 error = EOPNOTSUPP;
918 }
919 if (cmd == PRCO_SETOPT)
920 m_freem(m);
921 return error;
922 }
923 #endif /* ISO */
924
925 #ifdef ARGO_DEBUG
926
927 /*
928 * FUNCTION: dump_isoaddr
929 *
930 * PURPOSE: debugging
931 *
932 * RETURNS: nada
933 *
934 */
935 void
936 dump_isoaddr(struct sockaddr_iso *s)
937 {
938 if (s->siso_family == AF_ISO) {
939 printf("ISO address: suffixlen %d, %s\n",
940 s->siso_tlen, clnp_saddr_isop(s));
941 } else if (s->siso_family == AF_INET) {
942 /* hack */
943 struct sockaddr_in *sin = satosin(s);
944
945 printf("%d.%d.%d.%d: %d",
946 (sin->sin_addr.s_addr >> 24) & 0xff,
947 (sin->sin_addr.s_addr >> 16) & 0xff,
948 (sin->sin_addr.s_addr >> 8) & 0xff,
949 (sin->sin_addr.s_addr) & 0xff,
950 sin->sin_port);
951 }
952 }
953
954 #endif /* ARGO_DEBUG */
Cache object: 6d8b50947c961607824e71b34856ce45
|