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