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