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 /* @(#)esis.c 7.7 (Berkeley) 06/09/90 */ 28 #ifndef lint 29 static char *rcsid = "$Header: esis.c,v 4.10 88/09/15 18:57:03 hagens Exp $"; 30 #endif 31 32 #ifdef ISO 33 34 #include "types.h" 35 #include "param.h" 36 #include "mbuf.h" 37 #include "domain.h" 38 #include "protosw.h" 39 #include "user.h" 40 #include "socket.h" 41 #include "socketvar.h" 42 #include "errno.h" 43 #include "kernel.h" 44 45 #include "../net/if.h" 46 #include "../net/route.h" 47 48 #include "iso.h" 49 #include "iso_pcb.h" 50 #include "iso_var.h" 51 #include "iso_snpac.h" 52 #include "clnl.h" 53 #include "clnp.h" 54 #include "clnp_stat.h" 55 #include "esis.h" 56 #include "argo_debug.h" 57 58 /* 59 * Global variables to esis implementation 60 * 61 * esis_holding_time - the holding time (sec) parameter for outgoing pdus 62 * esis_config_time - the frequency (sec) that hellos are generated 63 * 64 */ 65 struct isopcb esis_pcb; 66 int esis_sendspace = 2048; 67 int esis_recvspace = 2048; 68 short esis_holding_time = ESIS_HT; 69 short esis_config_time = ESIS_CONFIG; 70 extern int iso_systype; 71 extern struct snpa_cache all_es, all_is; 72 73 #define EXTEND_PACKET(m, mhdr, cp)\ 74 if (((m)->m_next = m_getclr(M_DONTWAIT, MT_HEADER)) == NULL) {\ 75 esis_stat.es_nomem++;\ 76 m_freem(mhdr);\ 77 return;\ 78 } else {\ 79 (m) = (m)->m_next;\ 80 (cp) = mtod((m), caddr_t);\ 81 } 82 /* 83 * FUNCTION: esis_init 84 * 85 * PURPOSE: Initialize the kernel portion of esis protocol 86 * 87 * RETURNS: nothing 88 * 89 * SIDE EFFECTS: 90 * 91 * NOTES: 92 */ 93 esis_init() 94 { 95 extern struct clnl_protosw clnl_protox[256]; 96 int esis_input(); 97 int snpac_age(); 98 int esis_config(); 99 #ifdef ISO_X25ESIS 100 x25esis_input(); 101 #endif ISO_X25ESIS 102 103 esis_pcb.isop_next = esis_pcb.isop_prev = &esis_pcb; 104 105 clnl_protox[ISO9542_ESIS].clnl_input = esis_input; 106 timeout(snpac_age, (caddr_t)0, hz); 107 timeout(esis_config, (caddr_t)0, hz); 108 109 #ifdef ISO_X25ESIS 110 clnl_protox[ISO9542X25_ESIS].clnl_input = x25esis_input; 111 #endif ISO_X25ESIS 112 } 113 114 /* 115 * FUNCTION: esis_usrreq 116 * 117 * PURPOSE: Handle user level esis requests 118 * 119 * RETURNS: 0 or appropriate errno 120 * 121 * SIDE EFFECTS: 122 * 123 * NOTES: This is here only so esis gets initialized. 124 */ 125 /*ARGSUSED*/ 126 esis_usrreq(so, req, m, nam, control) 127 struct socket *so; /* socket: used only to get to this code */ 128 int req; /* request */ 129 struct mbuf *m; /* data for request */ 130 struct mbuf *nam; /* optional name */ 131 struct mbuf *control; /* optional control */ 132 { 133 if (m != NULL) 134 m_freem(m); 135 136 return(EOPNOTSUPP); 137 } 138 139 /* 140 * FUNCTION: esis_input 141 * 142 * PURPOSE: Process an incoming esis packet 143 * 144 * RETURNS: nothing 145 * 146 * SIDE EFFECTS: 147 * 148 * NOTES: 149 */ 150 esis_input(m0, shp) 151 struct mbuf *m0; /* ptr to first mbuf of pkt */ 152 struct snpa_hdr *shp; /* subnetwork header */ 153 { 154 struct esis_fixed *pdu = mtod(m0, struct esis_fixed *); 155 register int type; 156 157 IFDEBUG(D_ESISINPUT) 158 int i; 159 160 printf("esis_input: pdu on ifp x%x (%s%d): from:", shp->snh_ifp, 161 shp->snh_ifp->if_name, shp->snh_ifp->if_unit); 162 for (i=0; i<6; i++) 163 printf("%x%c", shp->snh_shost[i]&0xff, (i<5) ? ':' : ' '); 164 printf(" to:"); 165 for (i=0; i<6; i++) 166 printf("%x%c", shp->snh_dhost[i]&0xff, (i<5) ? ':' : ' '); 167 printf("\n"); 168 ENDDEBUG 169 170 /* 171 * check checksum if necessary 172 */ 173 if (ESIS_CKSUM_REQUIRED(pdu) && iso_check_csum(m0, (int)pdu->esis_hdr_len)) { 174 esis_stat.es_badcsum++; 175 goto bad; 176 } 177 178 /* check version */ 179 if (pdu->esis_vers != ESIS_VERSION) { 180 esis_stat.es_badvers++; 181 goto bad; 182 } 183 184 type = pdu->esis_type & 0x1f; 185 switch (type) { 186 case ESIS_ESH: 187 esis_eshinput(m0, shp); 188 return; 189 190 case ESIS_ISH: 191 esis_ishinput(m0, shp); 192 return; 193 194 case ESIS_RD: 195 esis_rdinput(m0, shp); 196 return; 197 198 default: { 199 esis_stat.es_badtype++; 200 goto bad; 201 } 202 } 203 204 bad: 205 m_freem(m0); 206 } 207 208 /* 209 * FUNCTION: esis_rdoutput 210 * 211 * PURPOSE: Transmit a redirect pdu 212 * 213 * RETURNS: nothing 214 * 215 * SIDE EFFECTS: 216 * 217 * NOTES: Assumes there is enough space for fixed part of header, 218 * DA, BSNPA and NET in first mbuf. 219 */ 220 esis_rdoutput(inbound_shp, inbound_m, inbound_oidx, rd_dstnsap, nhop_sc) 221 struct snpa_hdr *inbound_shp; /* snpa hdr from incoming packet */ 222 struct mbuf *inbound_m; /* incoming pkt itself */ 223 struct clnp_optidx *inbound_oidx; /* clnp options assoc with incoming pkt */ 224 struct iso_addr *rd_dstnsap; /* ultimate destination of pkt */ 225 struct snpa_cache *nhop_sc; /* snpa cache info regarding next hop of 226 pkt */ 227 { 228 struct mbuf *m, *m0; 229 caddr_t cp; 230 struct esis_fixed *pdu; 231 int len, total_len = 0; 232 struct sockaddr_iso siso; 233 struct ifnet *ifp = inbound_shp->snh_ifp; 234 235 esis_stat.es_rdsent++; 236 237 IFDEBUG(D_ESISOUTPUT) 238 printf("esis_rdoutput: ifp x%x (%s%d), ht %d, m x%x, oidx x%x\n", 239 ifp, ifp->if_name, ifp->if_unit, esis_holding_time, inbound_m, 240 inbound_oidx); 241 printf("\tdestination: %s\n", clnp_iso_addrp(rd_dstnsap)); 242 printf("\tredirected toward:%s\n", clnp_iso_addrp(&nhop_sc->sc_nsap)); 243 ENDDEBUG 244 245 if ((m0 = m = m_gethdr(M_DONTWAIT, MT_HEADER)) == NULL) { 246 esis_stat.es_nomem++; 247 return; 248 } 249 bzero(mtod(m, caddr_t), MHLEN); 250 251 pdu = mtod(m, struct esis_fixed *); 252 cp = (caddr_t)(pdu + 1); /*pointer arith.; 1st byte after header */ 253 len = sizeof(struct esis_fixed); 254 255 /* 256 * Build fixed part of header 257 */ 258 pdu->esis_proto_id = ISO9542_ESIS; 259 pdu->esis_vers = ESIS_VERSION; 260 pdu->esis_type = ESIS_RD; 261 HTOC(pdu->esis_ht_msb, pdu->esis_ht_lsb, esis_holding_time); 262 263 /* Insert destination address */ 264 (void) esis_insert_addr(&cp, &len, rd_dstnsap, m, 0); 265 266 /* Insert the snpa of better next hop */ 267 *cp++ = nhop_sc->sc_len; 268 bcopy((caddr_t)nhop_sc->sc_snpa, cp, nhop_sc->sc_len); 269 len += (nhop_sc->sc_len + 1); 270 271 /* 272 * If the next hop is not the destination, then it ought to be 273 * an IS and it should be inserted next. Else, set the 274 * NETL to 0 275 */ 276 /* PHASE2 use mask from ifp of outgoing interface */ 277 if (!iso_addrmatch1(rd_dstnsap, &nhop_sc->sc_nsap)) { 278 if ((nhop_sc->sc_flags & SNPA_IS) == 0) { 279 /* this should not happen */ 280 printf("esis_rdoutput: next hop is not dst and not an IS\n"); 281 m_freem(m0); 282 return; 283 } 284 (void) esis_insert_addr(&cp, &len, &nhop_sc->sc_nsap, m, 0); 285 } else { 286 *cp++ = 0; /* NETL */ 287 len++; 288 } 289 m->m_len = len; 290 291 /* 292 * PHASE2 293 * If redirect is to an IS, add an address mask. The mask to be 294 * used should be the mask present in the routing entry used to 295 * forward the original data packet. 296 */ 297 298 /* 299 * Copy Qos, priority, or security options present in original npdu 300 */ 301 if (inbound_oidx) { 302 /* THIS CODE IS CURRENTLY UNTESTED */ 303 int optlen = 0; 304 if (inbound_oidx->cni_qos_formatp) 305 optlen += (inbound_oidx->cni_qos_len + 2); 306 if (inbound_oidx->cni_priorp) /* priority option is 1 byte long */ 307 optlen += 3; 308 if (inbound_oidx->cni_securep) 309 optlen += (inbound_oidx->cni_secure_len + 2); 310 if (M_TRAILINGSPACE(m) < optlen) { 311 EXTEND_PACKET(m, m0, cp); 312 m->m_len = 0; 313 /* assumes MLEN > optlen */ 314 } 315 /* assume MLEN-len > optlen */ 316 /* 317 * When copying options, copy from ptr - 2 in order to grab 318 * the option code and length 319 */ 320 if (inbound_oidx->cni_qos_formatp) { 321 bcopy((caddr_t)(inbound_m + inbound_oidx->cni_qos_formatp - 2), cp, 322 (unsigned)(inbound_oidx->cni_qos_len + 2)); 323 len += inbound_oidx->cni_qos_len + 2; 324 } 325 if (inbound_oidx->cni_priorp) { 326 bcopy((caddr_t)(inbound_m + inbound_oidx->cni_priorp - 2), cp, 3); 327 len += 3; 328 } 329 if (inbound_oidx->cni_securep) { 330 bcopy((caddr_t)(inbound_m + inbound_oidx->cni_securep - 2), cp, 331 (unsigned)(inbound_oidx->cni_secure_len + 2)); 332 len += inbound_oidx->cni_secure_len + 2; 333 } 334 m->m_len += optlen; 335 } 336 337 pdu->esis_hdr_len = m0->m_pkthdr.len = len; 338 iso_gen_csum(m0, ESIS_CKSUM_OFF, (int)pdu->esis_hdr_len); 339 340 bzero((caddr_t)&siso, sizeof(siso)); 341 siso.siso_len = 12; 342 siso.siso_family = AF_ISO; 343 siso.siso_data[0] = AFI_SNA; 344 siso.siso_nlen = 6 + 1; /* should be taken from snpa_hdr */ 345 /* +1 is for AFI */ 346 bcopy(inbound_shp->snh_shost, siso.siso_data + 1, 6); 347 (ifp->if_output)(ifp, m0, &siso, 0); 348 } 349 350 /* 351 * FUNCTION: esis_insert_addr 352 * 353 * PURPOSE: Insert an iso_addr into a buffer 354 * 355 * RETURNS: true if buffer was big enough, else false 356 * 357 * SIDE EFFECTS: Increment buf & len according to size of iso_addr 358 * 359 * NOTES: Plus 1 here is for length byte 360 */ 361 esis_insert_addr(buf, len, isoa, m, nsellen) 362 register caddr_t *buf; /* ptr to buffer to put address into */ 363 int *len; /* ptr to length of buffer so far */ 364 struct iso_addr *isoa; /* ptr to address */ 365 register struct mbuf *m; /* determine if there remains space */ 366 int nsellen; 367 { 368 register int newlen = isoa->isoa_len + 1 + nsellen; 369 370 if (newlen > M_TRAILINGSPACE(m)) 371 return(0); 372 bcopy((caddr_t)isoa, *buf, newlen); 373 if (nsellen) 374 *(u_char *)*buf += nsellen; 375 *len += newlen; 376 *buf += newlen; 377 m->m_len += newlen; 378 return(1); 379 } 380 381 #define ESIS_EXTRACT_ADDR(d, b) { d = (struct iso_addr *)(b); b += (1 + *b); \ 382 if (b > buflim) {esis_stat.es_toosmall++; goto bad;}} 383 #define ESIS_NEXT_OPTION(b) { b += (2 + b[1]); \ 384 if (b > buflim) {esis_stat.es_toosmall++; goto bad;}} 385 int ESHonly = 1; 386 /* 387 388 /* 389 * FUNCTION: esis_eshinput 390 * 391 * PURPOSE: Process an incoming ESH pdu 392 * 393 * RETURNS: nothing 394 * 395 * SIDE EFFECTS: 396 * 397 * NOTES: 398 */ 399 esis_eshinput(m, shp) 400 struct mbuf *m; /* esh pdu */ 401 struct snpa_hdr *shp; /* subnetwork header */ 402 { 403 struct esis_fixed *pdu = mtod(m, struct esis_fixed *); 404 u_short ht; /* holding time */ 405 struct iso_addr *nsap; 406 int naddr; 407 u_char *buf = (u_char *)(pdu + 1); 408 u_char *buflim = pdu->esis_hdr_len + (u_char *)pdu; 409 struct rtentry *rt; 410 int new_entry; 411 412 esis_stat.es_eshrcvd++; 413 414 CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 415 416 naddr = *buf++; 417 if (buf >= buflim) 418 goto bad; 419 420 IFDEBUG(D_ESISINPUT) 421 printf("esis_eshinput: esh: ht %d, naddr %d\n", ht, naddr); 422 ENDDEBUG 423 424 while (naddr-- > 0) { 425 ESIS_EXTRACT_ADDR(nsap, buf); 426 new_entry = snpac_add(shp->snh_ifp, nsap, shp->snh_shost, SNPA_ES, ht); 427 IFDEBUG(D_ESISINPUT) 428 printf("esis_eshinput: nsap %s is %s\n", 429 clnp_iso_addrp(nsap), new_entry ? "new" : "old"); 430 ENDDEBUG 431 if (new_entry) 432 esis_shoutput(shp->snh_ifp, 433 iso_systype & SNPA_ES ? ESIS_ESH : ESIS_ISH, 434 esis_holding_time, shp->snh_shost, 6); 435 } 436 bad: 437 m_freem(m); 438 return; 439 } 440 441 /* 442 * FUNCTION: esis_ishinput 443 * 444 * PURPOSE: process an incoming ISH pdu 445 * 446 * RETURNS: 447 * 448 * SIDE EFFECTS: 449 * 450 * NOTES: 451 */ 452 esis_ishinput(m, shp) 453 struct mbuf *m; /* esh pdu */ 454 struct snpa_hdr *shp; /* subnetwork header */ 455 { 456 struct esis_fixed *pdu = mtod(m, struct esis_fixed *); 457 u_short ht; /* holding time */ 458 struct iso_addr *nsap; /* Network Entity Title */ 459 register u_char *buf = (u_char *) (pdu + 1); 460 register u_char *buflim = pdu->esis_hdr_len + (u_char *)pdu; 461 int new_entry; 462 463 esis_stat.es_ishrcvd++; 464 CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 465 466 IFDEBUG(D_ESISINPUT) 467 printf("esis_ishinput: ish: ht %d\n", ht); 468 ENDDEBUG 469 if (ESHonly) 470 goto bad; 471 472 ESIS_EXTRACT_ADDR(nsap, buf); 473 474 while (buf < buflim) { 475 switch (*buf) { 476 case ESISOVAL_ESCT: 477 if (buf[1] != 2) 478 goto bad; 479 CTOH(buf[2], buf[3], esis_config_time); 480 break; 481 482 default: 483 printf("Unknown ISH option: %x\n", *buf); 484 } 485 ESIS_NEXT_OPTION(buf); 486 } 487 new_entry = snpac_add(shp->snh_ifp, nsap, shp->snh_shost, SNPA_IS, ht); 488 IFDEBUG(D_ESISINPUT) 489 printf("esis_ishinput: nsap %s is %s\n", 490 clnp_iso_addrp(nsap), new_entry ? "new" : "old"); 491 ENDDEBUG 492 493 if (new_entry) 494 esis_shoutput(shp->snh_ifp, 495 iso_systype & SNPA_ES ? ESIS_ESH : ESIS_ISH, 496 esis_holding_time, shp->snh_shost, 6); 497 bad: 498 m_freem(m); 499 return; 500 } 501 502 /* 503 * FUNCTION: esis_rdinput 504 * 505 * PURPOSE: Process an incoming RD pdu 506 * 507 * RETURNS: 508 * 509 * SIDE EFFECTS: 510 * 511 * NOTES: 512 */ 513 esis_rdinput(m0, shp) 514 struct mbuf *m0; /* esh pdu */ 515 struct snpa_hdr *shp; /* subnetwork header */ 516 { 517 struct esis_fixed *pdu = mtod(m0, struct esis_fixed *); 518 u_short ht; /* holding time */ 519 struct iso_addr *da, *net = 0, *netmask = 0, *snpamask = 0; 520 register struct iso_addr *bsnpa; 521 register u_char *buf = (u_char *)(pdu + 1); 522 register u_char *buflim = pdu->esis_hdr_len + (u_char *)pdu; 523 524 esis_stat.es_rdrcvd++; 525 526 /* intermediate systems ignore redirects */ 527 if (iso_systype & SNPA_IS) 528 goto bad; 529 if (ESHonly) 530 goto bad; 531 532 CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 533 if (buf >= buflim) 534 goto bad; 535 536 /* Extract DA */ 537 ESIS_EXTRACT_ADDR(da, buf); 538 539 /* Extract better snpa */ 540 ESIS_EXTRACT_ADDR(bsnpa, buf); 541 542 /* Extract NET if present */ 543 if (buf < buflim) { 544 ESIS_EXTRACT_ADDR(net, buf); 545 } 546 547 /* process options */ 548 while (buf < buflim) { 549 switch (*buf) { 550 case ESISOVAL_SNPAMASK: 551 if (snpamask) /* duplicate */ 552 goto bad; 553 snpamask = (struct iso_addr *)(buf + 1); 554 break; 555 556 case ESISOVAL_NETMASK: 557 if (netmask) /* duplicate */ 558 goto bad; 559 netmask = (struct iso_addr *)(buf + 1); 560 break; 561 562 default: 563 printf("Unknown option in ESIS RD (0x%x)\n", buf[-1]); 564 } 565 ESIS_NEXT_OPTION(buf); 566 } 567 568 IFDEBUG(D_ESISINPUT) 569 printf("esis_rdinput: rd: ht %d, da %s\n", ht, clnp_iso_addrp(da)); 570 if (net) 571 printf("\t: net %s\n", clnp_iso_addrp(net)); 572 ENDDEBUG 573 /* 574 * If netl is zero, then redirect is to an ES. We need to add an entry 575 * to the snpa cache for (destination, better snpa). 576 * If netl is not zero, then the redirect is to an IS. In this 577 * case, add an snpa cache entry for (net, better snpa). 578 * 579 * If the redirect is to an IS, add a route entry towards that 580 * IS. 581 */ 582 if (net == 0 || net->isoa_len == 0 || snpamask) { 583 /* redirect to an ES */ 584 snpac_add(shp->snh_ifp, da, 585 bsnpa->isoa_genaddr, SNPA_ES, ht); 586 } else { 587 snpac_add(shp->snh_ifp, net, 588 bsnpa->isoa_genaddr, SNPA_IS, ht); 589 snpac_addrt(shp->snh_ifp, da, net, netmask); 590 } 591 bad: 592 m_freem(m0); 593 } 594 595 /* 596 * FUNCTION: esis_config 597 * 598 * PURPOSE: Report configuration 599 * 600 * RETURNS: 601 * 602 * SIDE EFFECTS: 603 * 604 * NOTES: Called every esis_config_time seconds 605 */ 606 esis_config() 607 { 608 register struct ifnet *ifp; 609 610 timeout(esis_config, (caddr_t)0, hz * esis_config_time); 611 612 /* 613 * Report configuration for each interface that 614 * - is UP 615 * - is not loopback 616 * - has broadcast capabilities 617 * - has an ISO address 618 */ 619 620 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 621 if ((ifp->if_flags & IFF_UP) && 622 (ifp->if_flags & IFF_BROADCAST) && 623 ((ifp->if_flags & IFF_LOOPBACK) == 0)) { 624 /* search for an ISO address family */ 625 struct ifaddr *ia; 626 627 for (ia = ifp->if_addrlist; ia; ia = ia->ifa_next) { 628 if (ia->ifa_addr->sa_family == AF_ISO) { 629 esis_shoutput(ifp, 630 iso_systype & SNPA_ES ? ESIS_ESH : ESIS_ISH, 631 esis_holding_time, 632 (caddr_t)(iso_systype & SNPA_ES ? all_is.sc_snpa : 633 all_es.sc_snpa), 6); 634 break; 635 } 636 } 637 } 638 } 639 } 640 641 /* 642 * FUNCTION: esis_shoutput 643 * 644 * PURPOSE: Transmit an esh or ish pdu 645 * 646 * RETURNS: nothing 647 * 648 * SIDE EFFECTS: 649 * 650 * NOTES: 651 */ 652 esis_shoutput(ifp, type, ht, sn_addr, sn_len) 653 struct ifnet *ifp; 654 int type; 655 short ht; 656 caddr_t sn_addr; 657 int sn_len; 658 { 659 struct mbuf *m, *m0; 660 caddr_t cp, naddrp; 661 int naddr = 0; 662 struct esis_fixed *pdu; 663 struct ifaddr *ifa; 664 int len; 665 struct sockaddr_iso siso; 666 667 if (type == ESIS_ESH) 668 esis_stat.es_eshsent++; 669 else if (type == ESIS_ISH) 670 esis_stat.es_ishsent++; 671 else { 672 printf("esis_shoutput: bad pdu type\n"); 673 return; 674 } 675 676 IFDEBUG(D_ESISOUTPUT) 677 int i; 678 printf("esis_shoutput: ifp x%x (%s%d), %s, ht %d, to: [%d] ", 679 ifp, ifp->if_name, ifp->if_unit, type == ESIS_ESH ? "esh" : "ish", 680 ht, sn_len); 681 for (i=0; i<sn_len; i++) 682 printf("%x%c", *(sn_addr+i), i < (sn_len-1) ? ':' : ' '); 683 printf("\n"); 684 ENDDEBUG 685 686 if ((m0 = m = m_gethdr(M_DONTWAIT, MT_HEADER)) == NULL) { 687 esis_stat.es_nomem++; 688 return; 689 } 690 bzero(mtod(m, caddr_t), MHLEN); 691 692 pdu = mtod(m, struct esis_fixed *); 693 naddrp = cp = (caddr_t)(pdu + 1); 694 len = sizeof(struct esis_fixed); 695 696 /* 697 * Build fixed part of header 698 */ 699 pdu->esis_proto_id = ISO9542_ESIS; 700 pdu->esis_vers = ESIS_VERSION; 701 pdu->esis_type = type; 702 HTOC(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 703 704 if (type == ESIS_ESH) { 705 cp++; 706 len++; 707 } 708 709 m->m_len = len; 710 for (ifa = ifp->if_addrlist; ifa; ifa=ifa->ifa_next) { 711 if (ifa->ifa_addr->sa_family == AF_ISO) { 712 register struct iso_ifaddr *ia = (struct iso_ifaddr *)ifa; 713 int nsellen = (type == ESIS_ESH ? ia->ia_addr.siso_tlen : 0); 714 IFDEBUG(D_ESISOUTPUT) 715 printf("esis_shoutput: adding NET %s\n", 716 clnp_iso_addrp(&ia->ia_addr.siso_addr)); 717 ENDDEBUG 718 if (!esis_insert_addr(&cp, &len, 719 &ia->ia_addr.siso_addr, m, nsellen)) { 720 EXTEND_PACKET(m, m0, cp); 721 (void) esis_insert_addr(&cp, &len, &ia->ia_addr.siso_addr, m, 722 nsellen); 723 } 724 naddr++; 725 if (type == ESIS_ISH) 726 break; 727 } 728 } 729 730 if (type == ESIS_ESH) 731 *naddrp = naddr; 732 733 m0->m_pkthdr.len = len; 734 pdu->esis_hdr_len = len; 735 iso_gen_csum(m0, ESIS_CKSUM_OFF, (int)pdu->esis_hdr_len); 736 737 bzero((caddr_t)&siso, sizeof(siso)); 738 siso.siso_family = AF_ISO; 739 siso.siso_data[0] = AFI_SNA; 740 siso.siso_nlen = sn_len + 1; 741 siso.siso_len = sn_len + 6; 742 bcopy(sn_addr, siso.siso_data + 1, (unsigned)sn_len); 743 (ifp->if_output)(ifp, m0, &siso, 0); 744 } 745 746 /* 747 * FUNCTION: esis_ctlinput 748 * 749 * PURPOSE: Handle the PRC_IFDOWN transition 750 * 751 * RETURNS: nothing 752 * 753 * SIDE EFFECTS: 754 * 755 * NOTES: Calls snpac_flush for interface specified. 756 * The loop through iso_ifaddr is stupid because 757 * back in if_down, we knew the ifp... 758 */ 759 esis_ctlinput(req, siso) 760 int req; /* request: we handle only PRC_IFDOWN */ 761 struct sockaddr_iso *siso; /* address of ifp */ 762 { 763 register struct iso_ifaddr *ia; /* scan through interface addresses */ 764 765 if (req == PRC_IFDOWN) 766 for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 767 if (iso_addrmatch(IA_SIS(ia), siso)) 768 snpac_flushifp(ia->ia_ifp); 769 } 770 } 771 772 #endif ISO 773