1/* $NetBSD: iso.c,v 1.57 2009/08/07 14:04:34 wiz 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 65Permission to use, copy, modify, and distribute this software and its 66documentation for any purpose and without fee is hereby granted, 67provided that the above copyright notice appear in all copies and that 68both that copyright notice and this permission notice appear in 69supporting documentation, and that the name of IBM not be 70used in advertising or publicity pertaining to distribution of the 71software without specific, written prior permission. 72 73IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 74ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 75IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 76ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 77WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 78ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 79SOFTWARE. 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.57 2009/08/07 14:04:34 wiz 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 119int 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 */ 132int 133iso_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 (!memcmp(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 */ 201int 202iso_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 */ 220int 221iso_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) && (!memcmp(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 */ 258u_long 259iso_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 */ 310void 311iso_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 memset(buf, 0, 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 */ 361u_int 362iso_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 memcpy(buf, (void *) isoa, 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 */ 470int 471iso_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 ia = malloc(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 return ENOTTY; 591 } 592 return (0); 593} 594 595void 596iso_purgeaddr(struct ifaddr *ifa) 597{ 598 struct ifnet *ifp = ifa->ifa_ifp; 599 struct iso_ifaddr *ia = (void *) ifa; 600 601 iso_ifscrub(ifp, ia); 602 ifa_remove(ifp, &ia->ia_ifa); 603 TAILQ_REMOVE(&iso_ifaddr, ia, ia_list); 604 IFAFREE(&ia->ia_ifa); 605} 606 607void 608iso_purgeif(struct ifnet *ifp) 609{ 610 if_purgeaddrs(ifp, AF_ISO, iso_purgeaddr); 611} 612 613/* 614 * Delete any existing route for an interface. 615 */ 616void 617iso_ifscrub(struct ifnet *ifp, struct iso_ifaddr *ia) 618{ 619 int nsellength = ia->ia_addr.siso_tlen; 620 if ((ia->ia_flags & IFA_ROUTE) == 0) 621 return; 622 ia->ia_addr.siso_tlen = 0; 623 if (ifp->if_flags & IFF_LOOPBACK) 624 rtinit(&(ia->ia_ifa), (int) RTM_DELETE, RTF_HOST); 625 else if (ifp->if_flags & IFF_POINTOPOINT) 626 rtinit(&(ia->ia_ifa), (int) RTM_DELETE, RTF_HOST); 627 else { 628 rtinit(&(ia->ia_ifa), (int) RTM_DELETE, 0); 629 } 630 ia->ia_addr.siso_tlen = nsellength; 631 ia->ia_flags &= ~IFA_ROUTE; 632} 633 634/* 635 * Initialize an interface's internet address 636 * and routing table entry. 637 */ 638int 639iso_ifinit(struct ifnet *ifp, struct iso_ifaddr *ia, struct sockaddr_iso *siso, 640 int scrub) 641{ 642 struct sockaddr_iso oldaddr; 643 int s = splnet(), error, nsellength; 644 645 oldaddr = ia->ia_addr; 646 ia->ia_addr = *siso; 647 /* 648 * Give the interface a chance to initialize 649 * if this is its first address, 650 * and to validate the address if necessary. 651 */ 652 if ((error = if_addr_init(ifp, &ia->ia_ifa, true)) != 0) { 653 splx(s); 654 ia->ia_addr = oldaddr; 655 return (error); 656 } 657 if (scrub) { 658 ia->ia_ifa.ifa_addr = sisotosa(&oldaddr); 659 iso_ifscrub(ifp, ia); 660 ia->ia_ifa.ifa_addr = sisotosa(&ia->ia_addr); 661 } 662 /* 663 * XXX -- The following is here temporarily out of laziness in not 664 * changing every ethernet driver's if_ioctl routine 665 * 666 * XXX extract llc_ifinit() and call from ether_ioctl(), 667 * XXX fddi_ioctl(). --dyoung 668 * 669 */ 670 if (ifp->if_type == IFT_ETHER || ifp->if_type == IFT_FDDI) { 671 ia->ia_ifa.ifa_rtrequest = llc_rtrequest; 672 ia->ia_ifa.ifa_flags |= RTF_CLONING; 673 } 674 /* 675 * Add route for the network. 676 */ 677 nsellength = ia->ia_addr.siso_tlen; 678 ia->ia_addr.siso_tlen = 0; 679 if (ifp->if_flags & IFF_LOOPBACK) { 680 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 681 error = rtinit(&(ia->ia_ifa), (int) RTM_ADD, RTF_HOST | RTF_UP); 682 } else if (ifp->if_flags & IFF_POINTOPOINT && 683 ia->ia_dstaddr.siso_family == AF_ISO) 684 error = rtinit(&(ia->ia_ifa), (int) RTM_ADD, RTF_HOST | RTF_UP); 685 else { 686 rt_maskedcopy(ia->ia_ifa.ifa_addr, ia->ia_ifa.ifa_dstaddr, 687 ia->ia_ifa.ifa_netmask); 688 ia->ia_dstaddr.siso_nlen = 689 min(ia->ia_addr.siso_nlen, (ia->ia_sockmask.siso_len - 6)); 690 error = rtinit(&(ia->ia_ifa), (int) RTM_ADD, RTF_UP); 691 } 692 ia->ia_addr.siso_tlen = nsellength; 693 ia->ia_flags |= IFA_ROUTE; 694 splx(s); 695 return (error); 696} 697#ifdef notdef 698 699struct ifaddr * 700iso_ifwithidi(struct sockaddr *addr) 701{ 702 struct ifnet *ifp; 703 struct ifaddr *ifa; 704 u_int af = addr->sa_family; 705 706 if (af != AF_ISO) 707 return (0); 708#ifdef ARGO_DEBUG 709 if (argo_debug[D_ROUTE]) { 710 printf(">>> iso_ifwithidi addr\n"); 711 dump_isoaddr(satosiso(addr)); 712 printf("\n"); 713 } 714#endif 715 TAILQ_FOREACH(ifp, &ifnet, if_list) { 716#ifdef ARGO_DEBUG 717 if (argo_debug[D_ROUTE]) { 718 printf("iso_ifwithidi ifnet %s\n", ifp->if_name); 719 } 720#endif 721 IFADDR_FOREACH(ifa, ifp) { 722#ifdef ARGO_DEBUG 723 if (argo_debug[D_ROUTE]) { 724 printf("iso_ifwithidi address "); 725 dump_isoaddr(satosiso(ifa->ifa_addr)); 726 } 727#endif 728 if (ifa->ifa_addr->sa_family != addr->sa_family) 729 continue; 730 731#ifdef ARGO_DEBUG 732 if (argo_debug[D_ROUTE]) { 733 printf(" af same, args to iso_eqtype:\n"); 734 printf("0x%x ", satosiso(ifa->ifa_addr)->siso_addr); 735 printf(" 0x%x\n", 736 &satosiso(addr)->siso_addr); 737 } 738#endif 739 740 if (iso_eqtype(&satosiso(ifa->ifa_addr)->siso_addr, 741 &satosiso(addr)->siso_addr)) { 742#ifdef ARGO_DEBUG 743 if (argo_debug[D_ROUTE]) { 744 printf("ifa_ifwithidi: ifa found\n"); 745 } 746#endif 747 return (ifa); 748 } 749#ifdef ARGO_DEBUG 750 if (argo_debug[D_ROUTE]) { 751 printf(" iso_eqtype failed\n"); 752 } 753#endif 754 } 755 } 756 return ((struct ifaddr *) 0); 757} 758 759#endif /* notdef */ 760/* 761 * FUNCTION: iso_ck_addr 762 * 763 * PURPOSE: return true if the iso_addr passed is 764 * within the legal size limit for an iso address. 765 * 766 * RETURNS: true or false 767 * 768 * SIDE EFFECTS: 769 * 770 */ 771int 772iso_ck_addr(struct iso_addr *isoa) 773{ 774 return (isoa->isoa_len <= 20); 775 776} 777 778#ifdef notdef 779/* 780 * FUNCTION: iso_eqtype 781 * 782 * PURPOSE: Determine if two iso addresses are of the same type. 783 * This is flaky. Really we should consider all type 784 * 47 addrs to be the same - but there do exist different 785 * structures for 47 addrs. Gosip adds a 3rd. 786 * 787 * RETURNS: true if the addresses are the same type 788 * 789 * SIDE EFFECTS: 790 * 791 * NOTES: By type, I mean rfc986, t37, or osinet 792 * 793 * This will first compare afis. If they match, then 794 * if the addr is not t37, the idis must be compared. 795 */ 796int 797iso_eqtype( 798 struct iso_addr *isoaa, /* first addr to check */ 799 struct iso_addr *isoab) /* other addr to check */ 800{ 801 if (isoaa->isoa_afi == isoab->isoa_afi) { 802 if (isoaa->isoa_afi == AFI_37) 803 return (1); 804 else 805 return (!memcmp(&isoaa->isoa_u, &isoab->isoa_u, 2)); 806 } 807 return (0); 808} 809#endif /* notdef */ 810/* 811 * FUNCTION: iso_localifa() 812 * 813 * PURPOSE: Find an interface addresss having a given destination 814 * or at least matching the net. 815 * 816 * RETURNS: ptr to an interface address 817 * 818 * SIDE EFFECTS: 819 * 820 * NOTES: 821 */ 822struct iso_ifaddr * 823iso_localifa(const struct sockaddr_iso *siso) 824{ 825 struct iso_ifaddr *ia; 826 const char *cp1, *cp2, *cp3; 827 struct ifnet *ifp; 828 struct iso_ifaddr *ia_maybe = 0; 829 /* 830 * We make one pass looking for both net matches and an exact 831 * dst addr. 832 */ 833 TAILQ_FOREACH(ia, &iso_ifaddr, ia_list) { 834 if ((ifp = ia->ia_ifp) == 0 || ((ifp->if_flags & IFF_UP) == 0)) 835 continue; 836 if (ifp->if_flags & IFF_POINTOPOINT) { 837 if ((ia->ia_dstaddr.siso_family == AF_ISO) && 838 SAME_ISOADDR(&ia->ia_dstaddr, siso)) 839 return (ia); 840 else if (SAME_ISOADDR(&ia->ia_addr, siso)) 841 ia_maybe = ia; 842 continue; 843 } 844 if (ia->ia_sockmask.siso_len) { 845 char *cplim = ia->ia_sockmask.siso_len + 846 (char *) &ia->ia_sockmask; 847 cp1 = ia->ia_sockmask.siso_data; 848 cp2 = siso->siso_data; 849 cp3 = ia->ia_addr.siso_data; 850 while (cp1 < cplim) 851 if (*cp1++ & (*cp2++ ^ *cp3++)) 852 goto next; 853 ia_maybe = ia; 854 } 855 if (SAME_ISOADDR(&ia->ia_addr, siso)) 856 return ia; 857next: ; 858 } 859 return ia_maybe; 860} 861 862/* 863 * FUNCTION: iso_nlctloutput 864 * 865 * PURPOSE: Set options at the network level 866 * 867 * RETURNS: E* 868 * 869 * SIDE EFFECTS: 870 * 871 * NOTES: This could embody some of the functions of 872 * rclnp_ctloutput and cons_ctloutput. 873 */ 874int 875iso_nlctloutput( 876 int cmd, /* command:set or get */ 877 int optname, /* option of interest */ 878 void * pcb, /* nl pcb */ 879 struct mbuf *m) /* data for set, buffer for get */ 880{ 881 int error = 0; /* return value */ 882 void * data; /* data for option */ 883 int data_len; /* data's length */ 884 885#ifdef ARGO_DEBUG 886 if (argo_debug[D_ISO]) { 887 printf("iso_nlctloutput: cmd %x, opt %x, pcb %p, m %p\n", 888 cmd, optname, pcb, m); 889 } 890#endif 891 892 if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT)) 893 return (EOPNOTSUPP); 894 895 data = mtod(m, void *); 896 data_len = (m)->m_len; 897 898#ifdef ARGO_DEBUG 899 if (argo_debug[D_ISO]) { 900 printf("iso_nlctloutput: data is:\n"); 901 dump_buf(data, data_len); 902 } 903#endif 904 905 switch (optname) { 906 default: 907 error = EOPNOTSUPP; 908 } 909 if (cmd == PRCO_SETOPT) 910 m_freem(m); 911 return error; 912} 913#endif /* ISO */ 914 915#ifdef ARGO_DEBUG 916 917/* 918 * FUNCTION: dump_isoaddr 919 * 920 * PURPOSE: debugging 921 * 922 * RETURNS: nada 923 * 924 */ 925void 926dump_isoaddr(const struct sockaddr_iso *s) 927{ 928 if (s->siso_family == AF_ISO) { 929 printf("ISO address: suffixlen %d, %s\n", 930 s->siso_tlen, clnp_saddr_isop(s)); 931 } else if (s->siso_family == AF_INET) { 932 /* hack */ 933 const struct sockaddr_in *sin = satocsin(s); 934 935 printf("%d.%d.%d.%d: %d", 936 (sin->sin_addr.s_addr >> 24) & 0xff, 937 (sin->sin_addr.s_addr >> 16) & 0xff, 938 (sin->sin_addr.s_addr >> 8) & 0xff, 939 (sin->sin_addr.s_addr) & 0xff, 940 sin->sin_port); 941 } 942} 943 944#endif /* ARGO_DEBUG */ 945 946struct queue { 947 struct queue *q_next, *q_prev; 948}; 949 950/* 951 * FUNCTION: iso_insque 952 * 953 * PURPOSE: insert an element into a queue 954 * 955 * RETURNS: 956 */ 957void 958iso_insque(void *v1, void *v2) 959{ 960 struct queue *elem = v1, *head = v2; 961 struct queue *next; 962 963 next = head->q_next; 964 elem->q_next = next; 965 head->q_next = elem; 966 elem->q_prev = head; 967 next->q_prev = elem; 968} 969 970/* 971 * FUNCTION: iso_remque 972 * 973 * PURPOSE: remove an element from a queue 974 * 975 * RETURNS: 976 */ 977void 978iso_remque(void *v) 979{ 980 struct queue *elem = v; 981 struct queue *next, *prev; 982 983 next = elem->q_next; 984 prev = elem->q_prev; 985 next->q_prev = prev; 986 prev->q_next = next; 987 elem->q_prev = NULL; 988} 989