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