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