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