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.17 (Berkeley) 12/19/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 IFAFREE((&oia->ia_ifa)); 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 } 618 /* 619 * Add route for the network. 620 */ 621 nsellength = ia->ia_addr.siso_tlen; 622 ia->ia_addr.siso_tlen = 0; 623 if (ifp->if_flags & IFF_LOOPBACK) { 624 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 625 error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 626 } else if (ifp->if_flags & IFF_POINTOPOINT && 627 ia->ia_dstaddr.siso_family == AF_ISO) 628 error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 629 else { 630 rt_maskedcopy(ia->ia_ifa.ifa_addr, ia->ia_ifa.ifa_dstaddr, 631 ia->ia_ifa.ifa_netmask); 632 ia->ia_dstaddr.siso_nlen = 633 min(ia->ia_addr.siso_nlen, (ia->ia_sockmask.siso_len - 6)); 634 error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP); 635 } 636 ia->ia_addr.siso_tlen = nsellength; 637 ia->ia_flags |= IFA_ROUTE; 638 splx(s); 639 return (error); 640 } 641 #ifdef notdef 642 643 struct ifaddr * 644 iso_ifwithidi(addr) 645 register struct sockaddr *addr; 646 { 647 register struct ifnet *ifp; 648 register struct ifaddr *ifa; 649 register u_int af = addr->sa_family; 650 651 if (af != AF_ISO) 652 return (0); 653 IFDEBUG(D_ROUTE) 654 printf(">>> iso_ifwithidi addr\n"); 655 dump_isoaddr( (struct sockaddr_iso *)(addr)); 656 printf("\n"); 657 ENDDEBUG 658 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 659 IFDEBUG(D_ROUTE) 660 printf("iso_ifwithidi ifnet %s\n", ifp->if_name); 661 ENDDEBUG 662 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 663 IFDEBUG(D_ROUTE) 664 printf("iso_ifwithidi address "); 665 dump_isoaddr( (struct sockaddr_iso *)(ifa->ifa_addr)); 666 ENDDEBUG 667 if (ifa->ifa_addr->sa_family != addr->sa_family) 668 continue; 669 670 #define IFA_SIS(ifa)\ 671 ((struct sockaddr_iso *)((ifa)->ifa_addr)) 672 673 IFDEBUG(D_ROUTE) 674 printf(" af same, args to iso_eqtype:\n"); 675 printf("0x%x ", IFA_SIS(ifa)->siso_addr); 676 printf(" 0x%x\n", 677 &(((struct sockaddr_iso *)addr)->siso_addr)); 678 ENDDEBUG 679 680 if (iso_eqtype(&(IFA_SIS(ifa)->siso_addr), 681 &(((struct sockaddr_iso *)addr)->siso_addr))) { 682 IFDEBUG(D_ROUTE) 683 printf("ifa_ifwithidi: ifa found\n"); 684 ENDDEBUG 685 return (ifa); 686 } 687 IFDEBUG(D_ROUTE) 688 printf(" iso_eqtype failed\n"); 689 ENDDEBUG 690 } 691 } 692 return ((struct ifaddr *)0); 693 } 694 695 #endif notdef 696 /* 697 * FUNCTION: iso_ck_addr 698 * 699 * PURPOSE: return true if the iso_addr passed is 700 * within the legal size limit for an iso address. 701 * 702 * RETURNS: true or false 703 * 704 * SIDE EFFECTS: 705 * 706 */ 707 iso_ck_addr(isoa) 708 struct iso_addr *isoa; /* address to check */ 709 { 710 return (isoa->isoa_len <= 20); 711 712 } 713 714 #ifdef notdef 715 /* 716 * FUNCTION: iso_eqtype 717 * 718 * PURPOSE: Determine if two iso addresses are of the same type. 719 * This is flaky. Really we should consider all type 47 addrs to be the 720 * same - but there do exist different structures for 47 addrs. 721 * Gosip adds a 3rd. 722 * 723 * RETURNS: true if the addresses are the same type 724 * 725 * SIDE EFFECTS: 726 * 727 * NOTES: By type, I mean rfc986, t37, or osinet 728 * 729 * This will first compare afis. If they match, then 730 * if the addr is not t37, the idis must be compared. 731 */ 732 iso_eqtype(isoaa, isoab) 733 struct iso_addr *isoaa; /* first addr to check */ 734 struct iso_addr *isoab; /* other addr to check */ 735 { 736 if (isoaa->isoa_afi == isoab->isoa_afi) { 737 if (isoaa->isoa_afi == AFI_37) 738 return(1); 739 else 740 return (!bcmp(&isoaa->isoa_u, &isoab->isoa_u, 2)); 741 } 742 return(0); 743 } 744 #endif notdef 745 /* 746 * FUNCTION: iso_localifa() 747 * 748 * PURPOSE: Find an interface addresss having a given destination 749 * or at least matching the net. 750 * 751 * RETURNS: ptr to an interface address 752 * 753 * SIDE EFFECTS: 754 * 755 * NOTES: 756 */ 757 struct iso_ifaddr * 758 iso_localifa(siso) 759 register struct sockaddr_iso *siso; 760 { 761 register struct iso_ifaddr *ia; 762 register char *cp1, *cp2, *cp3; 763 register struct ifnet *ifp; 764 struct iso_ifaddr *ia_maybe = 0; 765 /* 766 * We make one pass looking for both net matches and an exact 767 * dst addr. 768 */ 769 for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 770 if ((ifp = ia->ia_ifp) == 0 || ((ifp->if_flags & IFF_UP) == 0)) 771 continue; 772 if (ifp->if_flags & IFF_POINTOPOINT) { 773 if ((ia->ia_dstaddr.siso_family == AF_ISO) && 774 SAME_ISOADDR(&ia->ia_dstaddr, siso)) 775 return (ia); 776 else 777 if (SAME_ISOADDR(&ia->ia_addr, siso)) 778 ia_maybe = ia; 779 continue; 780 } 781 if (ia->ia_sockmask.siso_len) { 782 char *cplim = ia->ia_sockmask.siso_len + (char *)&ia->ia_sockmask; 783 cp1 = ia->ia_sockmask.siso_data; 784 cp2 = siso->siso_data; 785 cp3 = ia->ia_addr.siso_data; 786 while (cp1 < cplim) 787 if (*cp1++ & (*cp2++ ^ *cp3++)) 788 goto next; 789 ia_maybe = ia; 790 } 791 if (SAME_ISOADDR(&ia->ia_addr, siso)) 792 return ia; 793 next:; 794 } 795 return ia_maybe; 796 } 797 798 #ifdef TPCONS 799 #include "cons.h" 800 #endif TPCONS 801 /* 802 * FUNCTION: iso_nlctloutput 803 * 804 * PURPOSE: Set options at the network level 805 * 806 * RETURNS: E* 807 * 808 * SIDE EFFECTS: 809 * 810 * NOTES: This could embody some of the functions of 811 * rclnp_ctloutput and cons_ctloutput. 812 */ 813 iso_nlctloutput(cmd, optname, pcb, m) 814 int cmd; /* command:set or get */ 815 int optname; /* option of interest */ 816 caddr_t pcb; /* nl pcb */ 817 struct mbuf *m; /* data for set, buffer for get */ 818 { 819 struct isopcb *isop = (struct isopcb *)pcb; 820 int error = 0; /* return value */ 821 caddr_t data; /* data for option */ 822 int data_len; /* data's length */ 823 824 IFDEBUG(D_ISO) 825 printf("iso_nlctloutput: cmd %x, opt %x, pcb %x, m %x\n", 826 cmd, optname, pcb, m); 827 ENDDEBUG 828 829 if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT)) 830 return(EOPNOTSUPP); 831 832 data = mtod(m, caddr_t); 833 data_len = (m)->m_len; 834 835 IFDEBUG(D_ISO) 836 printf("iso_nlctloutput: data is:\n"); 837 dump_buf(data, data_len); 838 ENDDEBUG 839 840 switch (optname) { 841 842 #ifdef TPCONS 843 case CONSOPT_X25CRUD: 844 if (cmd == PRCO_GETOPT) { 845 error = EOPNOTSUPP; 846 break; 847 } 848 849 if (data_len > MAXX25CRUDLEN) { 850 error = EINVAL; 851 break; 852 } 853 854 IFDEBUG(D_ISO) 855 printf("iso_nlctloutput: setting x25 crud\n"); 856 ENDDEBUG 857 858 bcopy(data, (caddr_t)isop->isop_x25crud, (unsigned)data_len); 859 isop->isop_x25crud_len = data_len; 860 break; 861 #endif TPCONS 862 863 default: 864 error = EOPNOTSUPP; 865 } 866 if (cmd == PRCO_SETOPT) 867 m_freem(m); 868 return error; 869 } 870 #endif ISO 871 872 #ifdef ARGO_DEBUG 873 874 /* 875 * FUNCTION: dump_isoaddr 876 * 877 * PURPOSE: debugging 878 * 879 * RETURNS: nada 880 * 881 */ 882 dump_isoaddr(s) 883 struct sockaddr_iso *s; 884 { 885 char *clnp_saddr_isop(); 886 register int i; 887 888 if( s->siso_family == AF_ISO) { 889 printf("ISO address: suffixlen %d, %s\n", 890 s->siso_tlen, clnp_saddr_isop(s)); 891 } else if( s->siso_family == AF_INET) { 892 /* hack */ 893 struct sockaddr_in *sin = (struct sockaddr_in *)s; 894 895 printf("%d.%d.%d.%d: %d", 896 (sin->sin_addr.s_addr>>24)&0xff, 897 (sin->sin_addr.s_addr>>16)&0xff, 898 (sin->sin_addr.s_addr>>8)&0xff, 899 (sin->sin_addr.s_addr)&0xff, 900 sin->sin_port); 901 } 902 } 903 904 #endif ARGO_DEBUG 905