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.16 (Berkeley) 09/03/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 iso_init() 84 { 85 if (rt_tables[AF_ISO] == 0) { 86 rn_inithead(rt_tables + AF_ISO, 48); 87 } 88 } 89 90 /* 91 * FUNCTION: iso_addrmatch1 92 * 93 * PURPOSE: decide if the two iso_addrs passed are equal 94 * 95 * RETURNS: true if the addrs match, false if they do not 96 * 97 * SIDE EFFECTS: 98 * 99 * NOTES: 100 */ 101 iso_addrmatch1(isoaa, isoab) 102 register struct iso_addr *isoaa, *isoab; /* addresses to check */ 103 { 104 u_int compare_len; 105 106 IFDEBUG(D_ROUTE) 107 printf("iso_addrmatch1: comparing lengths: %d to %d\n", isoaa->isoa_len, 108 isoab->isoa_len); 109 printf("a:\n"); 110 dump_buf(isoaa->isoa_genaddr, isoaa->isoa_len); 111 printf("b:\n"); 112 dump_buf(isoab->isoa_genaddr, isoab->isoa_len); 113 ENDDEBUG 114 115 if ((compare_len = isoaa->isoa_len) != isoab->isoa_len) { 116 IFDEBUG(D_ROUTE) 117 printf("iso_addrmatch1: returning false because of lengths\n"); 118 ENDDEBUG 119 return 0; 120 } 121 122 #ifdef notdef 123 /* TODO : generalize this to all afis with masks */ 124 if( isoaa->isoa_afi == AFI_37 ) { 125 /* must not compare 2 least significant digits, or for 126 * that matter, the DSP 127 */ 128 compare_len = ADDR37_IDI_LEN - 1; 129 } 130 #endif 131 132 IFDEBUG(D_ROUTE) 133 int i; 134 char *a, *b; 135 136 a = isoaa->isoa_genaddr; 137 b = isoab->isoa_genaddr; 138 139 for (i=0; i<compare_len; i++) { 140 printf("<%x=%x>", a[i]&0xff, b[i]&0xff); 141 if (a[i] != b[i]) { 142 printf("\naddrs are not equal at byte %d\n", i); 143 return(0); 144 } 145 } 146 printf("\n"); 147 printf("addrs are equal\n"); 148 return (1); 149 ENDDEBUG 150 return (!bcmp(isoaa->isoa_genaddr, isoab->isoa_genaddr, compare_len)); 151 } 152 153 /* 154 * FUNCTION: iso_addrmatch 155 * 156 * PURPOSE: decide if the two sockadrr_isos passed are equal 157 * 158 * RETURNS: true if the addrs match, false if they do not 159 * 160 * SIDE EFFECTS: 161 * 162 * NOTES: 163 */ 164 iso_addrmatch(sisoa, sisob) 165 struct sockaddr_iso *sisoa, *sisob; /* addresses to check */ 166 { 167 return(iso_addrmatch1(&sisoa->siso_addr, &sisob->siso_addr)); 168 } 169 #ifdef notdef 170 /* 171 * FUNCTION: iso_netmatch 172 * 173 * PURPOSE: similar to iso_addrmatch but takes sockaddr_iso 174 * as argument. 175 * 176 * RETURNS: true if same net, false if not 177 * 178 * SIDE EFFECTS: 179 * 180 * NOTES: 181 */ 182 iso_netmatch(sisoa, sisob) 183 struct sockaddr_iso *sisoa, *sisob; 184 { 185 u_char bufa[sizeof(struct sockaddr_iso)]; 186 u_char bufb[sizeof(struct sockaddr_iso)]; 187 register int lena, lenb; 188 189 lena = iso_netof(&sisoa->siso_addr, bufa); 190 lenb = iso_netof(&sisob->siso_addr, bufb); 191 192 IFDEBUG(D_ROUTE) 193 printf("iso_netmatch: comparing lengths: %d to %d\n", lena, lenb); 194 printf("a:\n"); 195 dump_buf(bufa, lena); 196 printf("b:\n"); 197 dump_buf(bufb, lenb); 198 ENDDEBUG 199 200 return ((lena == lenb) && (!bcmp(bufa, bufb, lena))); 201 } 202 #endif notdef 203 204 /* 205 * FUNCTION: iso_hashchar 206 * 207 * PURPOSE: Hash all character in the buffer specified into 208 * a long. Return the long. 209 * 210 * RETURNS: The hash value. 211 * 212 * SIDE EFFECTS: 213 * 214 * NOTES: The hash is achieved by exclusive ORing 4 byte 215 * quantities. 216 */ 217 u_long 218 iso_hashchar(buf, len) 219 register caddr_t buf; /* buffer to pack from */ 220 register int len; /* length of buffer */ 221 { 222 register u_long h = 0; 223 register int i; 224 225 for (i=0; i<len; i+=4) { 226 register u_long l = 0; 227 228 if ((len - i) < 4) { 229 /* buffer not multiple of 4 */ 230 switch (len - i) { 231 case 3: 232 l |= buf[i+2] << 8; 233 case 2: 234 l |= buf[i+1] << 16; 235 case 1: 236 l |= buf[i] << 24; 237 break; 238 default: 239 printf("iso_hashchar: unexpected value x%x\n", len - i); 240 break; 241 } 242 } else { 243 l |= buf[i] << 24; 244 l |= buf[i+1] << 16; 245 l |= buf[i+2] << 8; 246 l |= buf[i+3]; 247 } 248 249 h ^= l; 250 } 251 252 h ^= (u_long) (len % 4); 253 254 return(h); 255 } 256 #ifdef notdef 257 /* 258 * FUNCTION: iso_hash 259 * 260 * PURPOSE: Fill in fields of afhash structure based upon addr passed. 261 * 262 * RETURNS: none 263 * 264 * SIDE EFFECTS: 265 * 266 * NOTES: 267 */ 268 iso_hash(siso, hp) 269 struct sockaddr_iso *siso; /* address to perform hash on */ 270 struct afhash *hp; /* RETURN: hash info here */ 271 { 272 u_long buf[sizeof(struct sockaddr_iso)+1/4]; 273 register int bufsize; 274 275 276 bzero(buf, sizeof(buf)); 277 278 bufsize = iso_netof(&siso->siso_addr, buf); 279 hp->afh_nethash = iso_hashchar((caddr_t)buf, bufsize); 280 281 IFDEBUG(D_ROUTE) 282 printf("iso_hash: iso_netof: bufsize = %d\n", bufsize); 283 ENDDEBUG 284 285 hp->afh_hosthash = iso_hashchar((caddr_t)&siso->siso_addr, 286 siso->siso_addr.isoa_len); 287 288 IFDEBUG(D_ROUTE) 289 printf("iso_hash: %s: nethash = x%x, hosthash = x%x\n", 290 clnp_iso_addrp(&siso->siso_addr), hp->afh_nethash, 291 hp->afh_hosthash); 292 ENDDEBUG 293 } 294 /* 295 * FUNCTION: iso_netof 296 * 297 * PURPOSE: Extract the network portion of the iso address. 298 * The network portion of the iso address varies depending 299 * on the type of address. The network portion of the 300 * address will include the IDP. The network portion is: 301 * 302 * TYPE DESC 303 * t37 The AFI and x.121 (IDI) 304 * osinet The AFI, orgid, snetid 305 * rfc986 The AFI, vers and network part of 306 * internet address. 307 * 308 * RETURNS: number of bytes placed into buf. 309 * 310 * SIDE EFFECTS: 311 * 312 * NOTES: Buf is assumed to be big enough 313 */ 314 iso_netof(isoa, buf) 315 struct iso_addr *isoa; /* address */ 316 caddr_t buf; /* RESULT: network portion of address here */ 317 { 318 u_int len = 1; /* length of afi */ 319 320 switch (isoa->isoa_afi) { 321 case AFI_37: 322 /* 323 * Due to classic x.25 tunnel vision, there is no 324 * net portion of an x.121 address. For our purposes 325 * the AFI will do, so that all x.25 -type addresses 326 * map to the single x.25 SNPA. (Cannot have more than 327 * one, obviously). 328 */ 329 330 break; 331 332 /* case AFI_OSINET:*/ 333 case AFI_RFC986: { 334 u_short idi; /* value of idi */ 335 336 /* osinet and rfc986 have idi in the same place */ 337 CTOH(isoa->rfc986_idi[0], isoa->rfc986_idi[1], idi); 338 339 if (idi == IDI_OSINET) 340 /* 341 * Network portion of OSINET address can only be the IDI. Clearly, 342 * with one x25 interface, one could get to several orgids, and 343 * several snetids. 344 len += (ADDROSINET_IDI_LEN + OVLOSINET_ORGID_LEN + 345 OVLOSINET_SNETID_LEN); 346 */ 347 len += ADDROSINET_IDI_LEN; 348 else if (idi == IDI_RFC986) { 349 u_long inetaddr; 350 struct ovl_rfc986 *o986 = (struct ovl_rfc986 *)isoa; 351 352 /* bump len to include idi and version (1 byte) */ 353 len += ADDRRFC986_IDI_LEN + 1; 354 355 /* get inet addr long aligned */ 356 bcopy(o986->o986_inetaddr, &inetaddr, sizeof(inetaddr)); 357 inetaddr = ntohl(inetaddr); /* convert to host byte order */ 358 359 IFDEBUG(D_ROUTE) 360 printf("iso_netof: isoa "); 361 dump_buf(isoa, sizeof(*isoa)); 362 printf("iso_netof: inetaddr 0x%x ", inetaddr); 363 ENDDEBUG 364 365 /* bump len by size of network portion of inet address */ 366 if (IN_CLASSA(inetaddr)) { 367 len += 4-IN_CLASSA_NSHIFT/8; 368 IFDEBUG(D_ROUTE) 369 printf("iso_netof: class A net len is now %d\n", len); 370 ENDDEBUG 371 } else if (IN_CLASSB(inetaddr)) { 372 len += 4-IN_CLASSB_NSHIFT/8; 373 IFDEBUG(D_ROUTE) 374 printf("iso_netof: class B net len is now %d\n", len); 375 ENDDEBUG 376 } else { 377 len += 4-IN_CLASSC_NSHIFT/8; 378 IFDEBUG(D_ROUTE) 379 printf("iso_netof: class C net len is now %d\n", len); 380 ENDDEBUG 381 } 382 } else 383 len = 0; 384 } break; 385 386 default: 387 len = 0; 388 } 389 390 bcopy((caddr_t)isoa, buf, len); 391 IFDEBUG(D_ROUTE) 392 printf("in_netof: isoa "); 393 dump_buf(isoa, len); 394 printf("in_netof: net "); 395 dump_buf(buf, len); 396 ENDDEBUG 397 return len; 398 } 399 #endif notdef 400 /* 401 * Generic iso control operations (ioctl's). 402 * Ifp is 0 if not an interface-specific ioctl. 403 */ 404 /* ARGSUSED */ 405 iso_control(so, cmd, data, ifp) 406 struct socket *so; 407 int cmd; 408 caddr_t data; 409 register struct ifnet *ifp; 410 { 411 register struct iso_ifreq *ifr = (struct iso_ifreq *)data; 412 register struct iso_ifaddr *ia = 0; 413 register struct ifaddr *ifa; 414 struct iso_ifaddr *oia; 415 struct iso_aliasreq *ifra = (struct iso_aliasreq *)data; 416 int error, hostIsNew, maskIsNew; 417 418 /* 419 * Find address for this interface, if it exists. 420 */ 421 if (ifp) 422 for (ia = iso_ifaddr; ia; ia = ia->ia_next) 423 if (ia->ia_ifp == ifp) 424 break; 425 426 switch (cmd) { 427 428 case SIOCAIFADDR_ISO: 429 case SIOCDIFADDR_ISO: 430 if (ifra->ifra_addr.siso_family == AF_ISO) 431 for (oia = ia; ia; ia = ia->ia_next) { 432 if (ia->ia_ifp == ifp && 433 SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr)) 434 break; 435 } 436 if ((so->so_state & SS_PRIV) == 0) 437 return (EPERM); 438 if (ifp == 0) 439 panic("iso_control"); 440 if (ia == (struct iso_ifaddr *)0) { 441 struct iso_ifaddr *nia; 442 if (cmd == SIOCDIFADDR_ISO) 443 return (EADDRNOTAVAIL); 444 MALLOC(nia, struct iso_ifaddr *, sizeof(*nia), 445 M_IFADDR, M_WAITOK); 446 if (nia == (struct iso_ifaddr *)0) 447 return (ENOBUFS); 448 bzero((caddr_t)nia, sizeof(*nia)); 449 if (ia = iso_ifaddr) { 450 for ( ; ia->ia_next; ia = ia->ia_next) 451 ; 452 ia->ia_next = nia; 453 } else 454 iso_ifaddr = nia; 455 ia = nia; 456 if (ifa = ifp->if_addrlist) { 457 for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 458 ; 459 ifa->ifa_next = (struct ifaddr *) ia; 460 } else 461 ifp->if_addrlist = (struct ifaddr *) ia; 462 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 463 ia->ia_ifa.ifa_dstaddr 464 = (struct sockaddr *)&ia->ia_dstaddr; 465 ia->ia_ifa.ifa_netmask 466 = (struct sockaddr *)&ia->ia_sockmask; 467 ia->ia_ifp = ifp; 468 if (ifp != &loif) 469 iso_interfaces++; 470 } 471 break; 472 473 #define cmdbyte(x) (((x) >> 8) & 0xff) 474 default: 475 if (cmdbyte(cmd) == 'a') 476 return (snpac_ioctl(so, cmd, data)); 477 if (ia == (struct iso_ifaddr *)0) 478 return (EADDRNOTAVAIL); 479 break; 480 } 481 switch (cmd) { 482 483 case SIOCGIFADDR_ISO: 484 ifr->ifr_Addr = ia->ia_addr; 485 break; 486 487 case SIOCGIFDSTADDR_ISO: 488 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 489 return (EINVAL); 490 ifr->ifr_Addr = ia->ia_dstaddr; 491 break; 492 493 case SIOCGIFNETMASK_ISO: 494 ifr->ifr_Addr = ia->ia_sockmask; 495 break; 496 497 case SIOCAIFADDR_ISO: 498 maskIsNew = 0; hostIsNew = 1; error = 0; 499 if (ia->ia_addr.siso_family == AF_ISO) { 500 if (ifra->ifra_addr.siso_len == 0) { 501 ifra->ifra_addr = ia->ia_addr; 502 hostIsNew = 0; 503 } else if (SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr)) 504 hostIsNew = 0; 505 } 506 if (ifra->ifra_mask.siso_len) { 507 iso_ifscrub(ifp, ia); 508 ia->ia_sockmask = ifra->ifra_mask; 509 maskIsNew = 1; 510 } 511 if ((ifp->if_flags & IFF_POINTOPOINT) && 512 (ifra->ifra_dstaddr.siso_family == AF_ISO)) { 513 iso_ifscrub(ifp, ia); 514 ia->ia_dstaddr = ifra->ifra_dstaddr; 515 maskIsNew = 1; /* We lie; but the effect's the same */ 516 } 517 if (ifra->ifra_addr.siso_family == AF_ISO && 518 (hostIsNew || maskIsNew)) { 519 error = iso_ifinit(ifp, ia, &ifra->ifra_addr, 0); 520 } 521 if (ifra->ifra_snpaoffset) 522 ia->ia_snpaoffset = ifra->ifra_snpaoffset; 523 return (error); 524 525 case SIOCDIFADDR_ISO: 526 iso_ifscrub(ifp, ia); 527 if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 528 ifp->if_addrlist = ifa->ifa_next; 529 else { 530 while (ifa->ifa_next && 531 (ifa->ifa_next != (struct ifaddr *)ia)) 532 ifa = ifa->ifa_next; 533 if (ifa->ifa_next) 534 ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 535 else 536 printf("Couldn't unlink isoifaddr from ifp\n"); 537 } 538 oia = ia; 539 if (oia == (ia = iso_ifaddr)) { 540 iso_ifaddr = ia->ia_next; 541 } else { 542 while (ia->ia_next && (ia->ia_next != oia)) { 543 ia = ia->ia_next; 544 } 545 if (ia->ia_next) 546 ia->ia_next = oia->ia_next; 547 else 548 printf("Didn't unlink isoifadr from list\n"); 549 } 550 free((caddr_t)oia, M_IFADDR); 551 break; 552 553 default: 554 if (ifp == 0 || ifp->if_ioctl == 0) 555 return (EOPNOTSUPP); 556 return ((*ifp->if_ioctl)(ifp, cmd, data)); 557 } 558 return (0); 559 } 560 561 /* 562 * Delete any existing route for an interface. 563 */ 564 iso_ifscrub(ifp, ia) 565 register struct ifnet *ifp; 566 register struct iso_ifaddr *ia; 567 { 568 int nsellength = ia->ia_addr.siso_tlen; 569 if ((ia->ia_flags & IFA_ROUTE) == 0) 570 return; 571 ia->ia_addr.siso_tlen = 0; 572 if (ifp->if_flags & IFF_LOOPBACK) 573 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 574 else if (ifp->if_flags & IFF_POINTOPOINT) 575 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 576 else { 577 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 578 } 579 ia->ia_addr.siso_tlen = nsellength; 580 ia->ia_flags &= ~IFA_ROUTE; 581 } 582 583 /* 584 * Initialize an interface's internet address 585 * and routing table entry. 586 */ 587 iso_ifinit(ifp, ia, siso, scrub) 588 register struct ifnet *ifp; 589 register struct iso_ifaddr *ia; 590 struct sockaddr_iso *siso; 591 { 592 struct sockaddr_iso oldaddr; 593 int s = splimp(), error, nsellength; 594 595 oldaddr = ia->ia_addr; 596 ia->ia_addr = *siso; 597 /* 598 * Give the interface a chance to initialize 599 * if this is its first address, 600 * and to validate the address if necessary. 601 */ 602 if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 603 splx(s); 604 ia->ia_addr = oldaddr; 605 return (error); 606 } 607 if (scrub) { 608 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 609 iso_ifscrub(ifp, ia); 610 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 611 } 612 /* XXX -- The following is here temporarily out of laziness 613 in not changing every ethernet driver's if_ioctl routine */ 614 if (ifp->if_output == ether_output) { 615 ia->ia_ifa.ifa_rtrequest = llc_rtrequest; 616 ia->ia_ifa.ifa_flags |= RTF_CLONING; 617 ia->ia_ifa.ifa_llinfolen = sizeof(struct llinfo_llc); 618 } 619 /* 620 * Add route for the network. 621 */ 622 nsellength = ia->ia_addr.siso_tlen; 623 ia->ia_addr.siso_tlen = 0; 624 if (ifp->if_flags & IFF_LOOPBACK) { 625 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 626 error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 627 } else if (ifp->if_flags & IFF_POINTOPOINT && 628 ia->ia_dstaddr.siso_family == AF_ISO) 629 error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 630 else { 631 rt_maskedcopy(ia->ia_ifa.ifa_addr, ia->ia_ifa.ifa_dstaddr, 632 ia->ia_ifa.ifa_netmask); 633 ia->ia_dstaddr.siso_nlen = 634 min(ia->ia_addr.siso_nlen, (ia->ia_sockmask.siso_len - 6)); 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 if (cmd == PRCO_SETOPT) 868 m_freem(m); 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