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