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