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