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