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: if_eon.c,v 1.4 88/07/19 15:53:59 hagens Exp $ 29 * $Source: /usr/argo/sys/netiso/RCS/if_eon.c,v $ 30 * @(#)if_eon.c 7.4 (Berkeley) 08/29/89 * 31 * 32 * EON rfc 33 * Layer between IP and CLNL 34 * 35 * TODO: 36 * Put together a current rfc986 address format and get the right offset 37 * for the nsel 38 */ 39 40 #ifndef lint 41 static char *rcsid = "$Header: if_eon.c,v 1.4 88/07/19 15:53:59 hagens Exp $"; 42 #endif lint 43 44 #ifdef EON 45 #define NEON 1 46 47 48 #include "param.h" 49 #include "systm.h" 50 #include "types.h" 51 #include "mbuf.h" 52 #include "buf.h" 53 #include "protosw.h" 54 #include "socket.h" 55 #include "ioctl.h" 56 #include "errno.h" 57 #include "types.h" 58 59 #include "../net/if.h" 60 #include "../net/iftypes.h" 61 #include "../net/netisr.h" 62 #include "../net/route.h" 63 #include "machine/mtpr.h" 64 65 #include "../netinet/in.h" 66 #include "../netinet/in_systm.h" 67 #include "../netinet/ip.h" 68 #include "../netinet/ip_var.h" 69 #include "../netinet/if_ether.h" 70 71 #include "iso.h" 72 #include "iso_var.h" 73 #include "iso_snpac.h" 74 extern struct snpa_cache all_es, all_is; 75 #include "argo_debug.h" 76 #include "iso_errno.h" 77 #include "eonvar.h" 78 79 #define EOK 0 80 81 int eoninput(); 82 int eonint(); 83 int eonoutput(); 84 int eonioctl(); 85 int eonprobe(); 86 int eonattach(); 87 int eoninit(); 88 extern int ip_output(); 89 struct ifnet eonif[NEON]; 90 91 #ifdef FAKEIOCCDEV 92 #include "machine/io.h" 93 #include "../machineio/ioccvar.h" 94 95 #define EON_FAKE_CSR 0 96 int eon_fakeautoconf[2]; /* need at least 2 ints */ 97 98 caddr_t eonstd[] = { (caddr_t) eon_fakeautoconf, 0 }; 99 struct iocc_device *eoninfo[NEON]; 100 101 struct iocc_driver eondriver = { 102 eonprobe, /* idr_probe */ 103 0, /* idr_slave */ 104 eonattach, /* idr_attach */ 105 0, /* idr_dgo */ 106 eonstd, /* idr_addr - list of standard addresses for device */ 107 "eon", /* idr_dname */ 108 eoninfo, /* idr_dinfo - backptrs to iodinit structs */ 109 0, /* idr_mname - controller name */ 110 0, /* idr_minfo -- backptrs to iominit structs */ 111 eonint, /* idr_intr - interrupt rtn */ 112 0, /* idr_csr - offset to read/write csr */ 113 EON_FAKE_CSR, /* idr_chanrelse */ 114 0, /* idr_flags */ 115 }; 116 #else 117 struct iocc_device { 118 int iod_unit; 119 } bsd_iocc_fakeout; 120 121 eonprotoinit() { 122 (void) eonprobe(); 123 (void) eonattach(&bsd_iocc_fakeout); 124 } 125 #define PROBE_OK 0; 126 #endif 127 128 129 /* 130 * entry in the EON address cache (list) 131 * (or pt-pt links list, however you view it) 132 */ 133 134 struct eon_centry { 135 struct qhdr eonc_q_LINK; 136 #define eonc_nextLINK eonc_q_LINK.link 137 #define eonc_prevLINK eonc_q_LINK.flink 138 139 struct qhdr eonc_q_IS; 140 #define eonc_nextIS eonc_q_IS.link 141 #define eonc_prevIS eonc_q_IS.flink 142 143 struct qhdr eonc_q_ES; 144 #define eonc_nextES eonc_q_ES.link 145 #define eonc_prevES eonc_q_ES.flink 146 147 struct in_addr eonc_addr; 148 u_short eonc_status; 149 }; 150 151 /* kinda like mtod() but for eon_centries */ 152 #define qtocentry(q, off) ((struct eon_centry *) (((caddr_t)(q)) - off)) 153 #define centrytoq(c, off) ((struct qhdr *) (((caddr_t)(c)) + off)) 154 155 struct qhdr eon_LINK_hdr = { 156 (struct qhdr *)0, 157 (struct qhdr *)0, 158 }; 159 static struct qhdr eon_IS_hdr = { 160 (struct qhdr *)0, 161 (struct qhdr *)0, 162 }; 163 static struct qhdr eon_ES_hdr = { 164 (struct qhdr *)0, 165 (struct qhdr *)0, 166 }; 167 static struct qhdr eon_FREE_hdr = { 168 (struct qhdr *)0, 169 (struct qhdr *)0, 170 }; 171 172 #define INITQ(q) (q)->rlink = (q)->link = (q) 173 174 /* 175 * FUNCTION: eon_dumpcache 176 * 177 * PURPOSE: dump the cache beginning with the argument given 178 * 179 * RETURNS: 0 180 */ 181 182 eon_dumpcache(which) 183 int which; 184 { 185 register int off; 186 register struct eon_centry *ent; 187 struct qhdr *hdr; 188 189 switch (which) { 190 case E_FREE: 191 printf("FREE LIST\n"); 192 off = _offsetof( struct eon_centry, eonc_q_LINK); 193 hdr = &eon_FREE_hdr; 194 ent = qtocentry( hdr->link, 195 _offsetof( struct eon_centry, eonc_q_LINK)); 196 break; 197 case E_ES: 198 printf("ES LIST\n"); 199 off = _offsetof( struct eon_centry, eonc_q_ES); 200 hdr = &eon_ES_hdr; 201 ent = qtocentry( hdr->link, 202 _offsetof( struct eon_centry, eonc_q_ES)); 203 break; 204 case E_IS: 205 printf("IS LIST\n"); 206 off = _offsetof( struct eon_centry, eonc_q_IS); 207 hdr = &eon_IS_hdr; 208 ent = qtocentry( hdr->link, 209 _offsetof( struct eon_centry, eonc_q_IS)); 210 break; 211 case E_LINK: 212 printf("LINK LIST\n"); 213 off = _offsetof( struct eon_centry, eonc_q_LINK); 214 hdr = &eon_LINK_hdr; 215 ent = qtocentry( hdr->link, 216 _offsetof( struct eon_centry, eonc_q_LINK)); 217 break; 218 } 219 if(hdr == centrytoq(ent, off)->link ) 220 printf("EMPTY\n"); 221 else while(1) { 222 printf("0x%x: %d.%d.%d.%d, %s %s\n", ent, 223 (ent->eonc_addr.s_addr>>24)&0xff, 224 (ent->eonc_addr.s_addr>>16)&0xff, 225 (ent->eonc_addr.s_addr>>8)&0xff, 226 (ent->eonc_addr.s_addr)&0xff, 227 ((ent->eonc_status & EON_ESLINK_UP)?"ES^": 228 (ent->eonc_status & EON_ESLINK_DOWN)?"es*": " "), 229 ((ent->eonc_status & EON_ISLINK_UP)?"IS^": 230 (ent->eonc_status & EON_ISLINK_DOWN)?"is*": " ") 231 ); 232 dump_buf(ent, sizeof(struct eon_centry) ); 233 234 { /* ent = ent.next: */ 235 register struct qhdr *q; 236 237 q = centrytoq(ent, off)->link; 238 if( q == hdr) 239 break; 240 if( q == (struct qhdr *)0) /* panic */ { 241 printf("eon0: BAD Q HDR or CENTRY! q 0x%x ent 0x%x off 0x%x\n", 242 q, ent, off); 243 break; 244 } 245 ent = qtocentry( q, off ); 246 } 247 } 248 } 249 /* 250 * FUNCTION: eon_initcache 251 * 252 * PURPOSE: allocs a bunch of free cache entries 253 * 254 * RETURNS: 0 255 */ 256 257 eon_initcache() 258 { 259 static struct eon_centry eoncache[EON_CACHESIZE]; 260 register int i; 261 register struct eon_centry *ent; 262 263 bzero( eoncache, EON_CACHESIZE*sizeof(struct eon_centry)); 264 INITQ( &eon_FREE_hdr ); 265 INITQ( &eon_LINK_hdr ); 266 INITQ( &eon_IS_hdr ); 267 INITQ( &eon_ES_hdr ); 268 269 ent = eoncache; 270 271 for(i=0; i< EON_CACHESIZE; i++,ent++) { 272 _insque( centrytoq(ent, _offsetof( struct eon_centry, eonc_q_LINK)), 273 &eon_FREE_hdr); 274 } 275 printf("eon0: cache initialized\n"); 276 } 277 278 /* 279 * FUNCTION: eonprobe 280 * 281 * PURPOSE: filler for device configuration 282 * 283 * RETURNS: PROBE_OK 284 */ 285 286 int int_level, int_irq; 287 eonprobe() 288 { 289 extern int int_level, int_irq; 290 291 printf("eonprobe() \n"); 292 int_level = int_irq = 0x3; /* pick something - anything but -1 */ 293 return PROBE_OK; 294 } 295 296 /* 297 * FUNCTION: eonattach 298 * 299 * PURPOSE: autoconf attach routine 300 * 301 * RETURNS: void 302 */ 303 304 eonattach(iod) 305 register struct iocc_device *iod; 306 { 307 register struct ifnet *ifp = &eonif[iod->iod_unit]; 308 309 IFDEBUG(D_EON) 310 printf("eonattach()\n"); 311 ENDDEBUG 312 ifp->if_unit = iod->iod_unit; 313 ifp->if_name = "eon"; 314 ifp->if_mtu = ETHERMTU; 315 /* since everything will go out over ether or token ring */ 316 317 ifp->if_init = eoninit; 318 ifp->if_ioctl = eonioctl; 319 ifp->if_output = eonoutput; 320 ifp->if_type = IFT_EON; 321 ifp->if_addrlen = 5; 322 ifp->if_hdrlen = EONIPLEN; 323 ifp->if_flags = IFF_BROADCAST; 324 if_attach(ifp); 325 326 IFDEBUG(D_EON) 327 printf("eonattach()\n"); 328 ENDDEBUG 329 eon_initcache(); 330 IFDEBUG(D_EON) 331 printf("eon%d: attached\n", iod->iod_unit); 332 ENDDEBUG 333 } 334 335 static struct eon_centry * 336 find_oldent( ea ) 337 struct sockaddr_eon *ea; 338 { 339 register int offset = 340 _offsetof( struct eon_centry, eonc_q_LINK); 341 register struct eon_centry *ent, *oent; 342 343 oent = ent = qtocentry(eon_LINK_hdr.link, offset); 344 IFDEBUG(D_EON) 345 printf("eon: find_oldent() ipaddr: %d.%d.%d.%d\n", 346 (ea->seon_ipaddr>>24)&0xff, 347 (ea->seon_ipaddr>>16)&0xff, 348 (ea->seon_ipaddr>>8)&0xff, 349 (ea->seon_ipaddr)&0xff ); 350 ENDDEBUG 351 do { 352 if( ent->eonc_addr.s_addr == ea->seon_ipaddr ) 353 return ent; 354 ent = qtocentry(ent->eonc_nextLINK, offset); 355 } while (ent != oent); 356 return (struct eon_centry *)0; 357 } 358 359 /* 360 * FUNCTION: eonioctl 361 * 362 * PURPOSE: io controls - ifconfig 363 * need commands to 364 * link-UP (core addr) (flags: ES, IS) 365 * link-DOWN (core addr) (flags: ES, IS) 366 * must be callable from kernel or user 367 * 368 * RETURNS: nothing 369 */ 370 eonioctl(ifp, cmd, data) 371 register struct ifnet *ifp; 372 register int cmd; 373 register caddr_t data; 374 { 375 struct iso_ifreq *ifr = (struct iso_ifreq *)data; 376 register struct sockaddr_eon *eoa = 377 (struct sockaddr_eon *)&(ifr->ifr_Addr); 378 register int s = splimp(); 379 register int error = 0; 380 381 IFDEBUG(D_EON) 382 printf("eonioctl (cmd 0x%x) \n", cmd); 383 ENDDEBUG 384 385 switch (cmd){ 386 case SIOCSEONCORE: { 387 /* add pt-pt link to the set of core addrs */ 388 register struct eon_centry *ent, *oldent; 389 register u_short which; 390 391 /* "which" tells which lists to put these guys in - don't 392 * want to insert something in a list if it's already there 393 */ 394 #define LEGIT_EONADDR(a)\ 395 ((a->seon_family == AF_ISO) && (a->seon_afi == AFI_RFC986) &&\ 396 (a->seon_idi[0] == 0) && (a->seon_idi[1] == 6) \ 397 && (a->seon_vers == EON_986_VERSION) && (a->seon_adrlen == 0x14)) 398 399 if( ! LEGIT_EONADDR(eoa) ) { 400 error = EADDRNOTAVAIL; 401 break; 402 } 403 404 oldent = find_oldent( eoa ); 405 IFDEBUG(D_EON) 406 printf("eonioctl legit seon_status 0x%x oldent %s\n", 407 eoa->seon_status, oldent?"found":"not found"); 408 ENDDEBUG 409 410 if( eoa->seon_status & UPBITS ) { 411 if (!oldent) { 412 /* doesn't exist - need to create one */ 413 if (eon_FREE_hdr.link == eon_FREE_hdr.rlink) 414 return ENOBUFS; 415 ent = qtocentry(eon_FREE_hdr.link, 416 _offsetof( struct eon_centry, eonc_q_LINK)); 417 remque( &(ent->eonc_q_LINK) ); 418 ent->eonc_addr.s_addr = eoa->seon_ipaddr; 419 insque( &(ent->eonc_q_LINK), (&eon_LINK_hdr)); 420 oldent = ent; 421 } 422 423 which = (eoa->seon_status ^ oldent->eonc_status) & 424 eoa->seon_status & UPBITS; 425 426 oldent->eonc_status |= (eoa->seon_status & UPBITS); 427 428 if( which & EON_ESLINK_UP ) 429 insque( &oldent->eonc_q_ES, (&eon_ES_hdr)); 430 if( which & EON_ISLINK_UP ) 431 insque( &oldent->eonc_q_IS, (&eon_IS_hdr)); 432 } 433 434 if( eoa->seon_status & DOWNBITS ) { 435 if(!oldent) { 436 return ENOENT; /* no such entry */ 437 } 438 which = (eoa->seon_status ^ oldent->eonc_status) & 439 eoa->seon_status & DOWNBITS; 440 441 oldent->eonc_status |= (eoa->seon_status & DOWNBITS); 442 443 if( which & EON_ESLINK_DOWN ) 444 remque( &(oldent->eonc_q_ES) ); 445 if( which & EON_ISLINK_DOWN ) 446 remque( &(oldent->eonc_q_IS) ); 447 } 448 449 IFDEBUG(D_EON) 450 printf("at end status 0x%x\n", oldent->eonc_status); 451 ENDDEBUG 452 break; 453 } 454 455 case SIOCGEONCORE: 456 { 457 register struct eon_centry *oldent; 458 459 oldent = find_oldent( eoa ); 460 if( oldent == (struct eon_centry *)0 ) 461 error = EADDRNOTAVAIL; 462 else 463 eoa->seon_status = oldent->eonc_status; 464 } 465 break; 466 467 case SIOCSIFADDR: 468 ifp->if_flags |= IFF_UP; 469 break; 470 471 case SIOCSIFFLAGS: 472 if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & 473 IFF_RUNNING){ 474 ifp->if_flags &= ~IFF_RUNNING; 475 } else if (ifp->if_flags & IFF_UP && (ifp->if_flags & 476 IFF_RUNNING) == 0) 477 eoninit(ifp->if_unit); 478 break; 479 default: 480 error = EINVAL; 481 } 482 splx(s); 483 return(error); 484 } 485 486 /* 487 * FUNCTION: eoninit 488 * 489 * PURPOSE: initialization 490 * 491 * RETURNS: nothing 492 */ 493 494 eoninit(unit) 495 int unit; 496 { 497 printf("eon driver-init eon%d\n", unit); 498 } 499 500 501 /* 502 * FUNCTION: eonint 503 * 504 * PURPOSE: filler for device configuration 505 * 506 * RETURNS: nothing 507 * 508 * NOTES: *should* never get called - for debugging it's here 509 */ 510 511 eonint() 512 { 513 /* silent - so no more stray interrupt messages from the aed! yay 514 printf("eonint() called - BOGUS INTERRUPT\n"); 515 */ 516 } 517 518 519 /* 520 * FUNCTION: eonoutput 521 * 522 * PURPOSE: prepend an eon header and hand to IP 523 * ARGUMENTS: (ifp) is points to the ifnet structure for this unit/device 524 * (m) is an mbuf *, *m is a CLNL packet 525 * (dst) is a destination address - have to interp. as 526 * multicast or broadcast or real address. 527 * 528 * RETURNS: unix error code 529 * 530 * NOTES: 531 * 532 */ 533 eonoutput(ifp, morig, dst) 534 struct ifnet *ifp; 535 register struct mbuf *morig; /* packet */ 536 struct sockaddr_iso *dst; /* destination addr */ 537 { 538 int s; 539 struct eon_hdr *eonhdr; 540 struct ip *iphdr; 541 struct mbuf *mh; 542 int error = 0; 543 register int datalen; 544 caddr_t dstipaddrloc; 545 int single = 0, class, qoffset = 0, snpalen; 546 register struct eon_centry *ent; 547 register struct sockaddr_eon *eoa; 548 struct qhdr *q; 549 char edst[6]; 550 551 IFDEBUG(D_EON) 552 printf("eonoutput \n" ); 553 ENDDEBUG 554 555 if( dst->siso_family != AF_ISO ) { 556 einval: 557 error = EINVAL; 558 goto flush; 559 } 560 if ((morig->m_flags & M_PKTHDR) == 0) { 561 printf("eon: got non headered packet\n"); 562 goto einval; 563 } 564 eoa = (struct sockaddr_eon *)dst; 565 if (LEGIT_EONADDR(eoa)) { 566 class = eoa->seon_protoid; 567 dstipaddrloc = (caddr_t)&(eoa->seon_ipaddr); 568 } else if (eoa->seon_afi == AFI_SNA) { 569 dstipaddrloc = (caddr_t)&(dst->siso_data[1]); 570 if (dst->siso_nlen == 6) { 571 class = dst->siso_data[5]; 572 } else if (dst->siso_nlen == 7) { 573 if (bcmp(dstipaddrloc, all_is.sc_snpa, 6)) 574 class = EON_MULTICAST_ES; 575 else if (bcmp(dstipaddrloc, all_es.sc_snpa, 6)) 576 class = EON_MULTICAST_IS; 577 else 578 goto einval; 579 } else 580 goto einval; 581 } else if (0 == iso_snparesolve(ifp, dst, edst, &snpalen)) { 582 dstipaddrloc = (caddr_t)edst; 583 class = edst[4]; 584 } else { 585 error = EINVAL; 586 goto flush; 587 } 588 switch (class) { 589 case EON_NORMAL_ADDR: 590 IncStat(es_out_normal); 591 single = 1; 592 break; 593 594 case EON_BROADCAST: 595 IncStat(es_out_broad); 596 if(eon_LINK_hdr.link == eon_LINK_hdr.rlink) { 597 error = EADDRNOTAVAIL; 598 } else { 599 qoffset = _offsetof( struct eon_centry, eonc_q_LINK); 600 ent = qtocentry(eon_LINK_hdr.link, qoffset); 601 dstipaddrloc = (caddr_t) &(ent->eonc_addr); 602 } 603 break; 604 case EON_MULTICAST_ES: 605 IncStat(es_out_multi_es); 606 if (eon_ES_hdr.link == eon_ES_hdr.rlink) { 607 error = EADDRNOTAVAIL; 608 } else { 609 qoffset = _offsetof( struct eon_centry, eonc_q_ES); 610 ent = qtocentry(eon_ES_hdr.link, qoffset); 611 dstipaddrloc = (caddr_t) &(ent->eonc_addr); 612 } 613 break; 614 case EON_MULTICAST_IS: 615 IncStat(es_out_multi_is); 616 if (eon_IS_hdr.link == eon_IS_hdr.rlink) { 617 error = EADDRNOTAVAIL; 618 } else { 619 qoffset = _offsetof( struct eon_centry, eonc_q_LINK); 620 ent = qtocentry(eon_IS_hdr.link, qoffset); 621 dstipaddrloc = (caddr_t) &(ent->eonc_addr); 622 } 623 break; 624 default: 625 printf("bad class value; treated as EON_NORMAL_ADDR\n"); 626 class = EON_NORMAL_ADDR; 627 single = 1; 628 break; 629 } 630 if( error ) 631 goto done; 632 633 /* get data length -- needed later */ 634 datalen = morig->m_pkthdr.len; 635 IFDEBUG(D_EON) 636 printf("eonoutput : m_datalen returns %d\n", datalen); 637 ENDDEBUG 638 639 MGETHDR(mh, M_DONTWAIT, MT_HEADER); 640 if(mh == (struct mbuf *)0) 641 goto done; 642 643 /* put an eon_hdr in the buffer, prepended by an ip header */ 644 mh->m_len = sizeof(struct eon_hdr); 645 MH_ALIGN(mh, sizeof(struct eon_hdr)); 646 mh->m_next = morig; 647 eonhdr = mtod(mh, struct eon_hdr *); 648 eonhdr->eonh_class = class; 649 eonhdr->eonh_vers = EON_VERSION; 650 eonhdr->eonh_csum = 0; 651 652 IFDEBUG(D_EON) 653 printf("eonoutput : gen csum (0x%x, offset %d, datalen %d)\n", 654 mh, _offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr)); 655 ENDDEBUG 656 iso_gen_csum(mh, 657 _offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr)); 658 659 mh->m_data -= sizeof(*iphdr); 660 mh->m_len += sizeof(*iphdr); 661 iphdr = mtod(mh, struct ip *); 662 bzero((caddr_t)iphdr, sizeof (*iphdr)); 663 664 iphdr->ip_p = IPPROTO_EON; 665 iphdr->ip_len = (u_short)(mh->m_pkthdr.len = EONIPLEN + datalen); 666 iphdr->ip_ttl = MAXTTL; 667 iphdr->ip_src.s_addr = INADDR_ANY; 668 669 IFDEBUG(D_EON) 670 printf("eonoutput : after gen csum: ip_len %d/0x%x\n", 671 mh->m_pkthdr.len, mh->m_pkthdr.len); 672 ENDDEBUG 673 674 morig = mh; 675 676 for(;;) { 677 678 if( !single ) { 679 /* make a copy to send */ 680 IFDEBUG(D_EON) 681 printf("eonoutput : m_copy (0x%x, 0, 0x%x)\n", 682 morig, iphdr->ip_len); 683 ENDDEBUG 684 if (((mh = m_copy(morig, 0, morig->m_pkthdr.len)) == 0) || 685 ((mh = m_pullup(mh, sizeof(struct ip))) == 0)) { 686 error = ENOBUFS; 687 goto done; 688 } 689 iphdr = mtod(mh, struct ip *); 690 } 691 IFDEBUG(D_EON) 692 printf("eonoutput : bcopy 0x%x to 0x%x length %d\n", 693 dstipaddrloc, 694 (caddr_t)&(iphdr->ip_dst.s_addr), 695 sizeof(iphdr->ip_dst.s_addr)); 696 ENDDEBUG 697 bcopy(dstipaddrloc, (caddr_t)&(iphdr->ip_dst.s_addr), 698 sizeof(iphdr->ip_dst.s_addr)); 699 IFDEBUG(D_EON) 700 printf("eonoutput : dst ip addr : %d.%d.%d.%d", 701 (iphdr->ip_dst.s_addr>>24)&0xff, 702 (iphdr->ip_dst.s_addr>>16)&0xff, 703 (iphdr->ip_dst.s_addr>>8)&0xff, 704 (iphdr->ip_dst.s_addr)&0xff ); 705 ENDDEBUG 706 707 IFDEBUG(D_EON) 708 printf("eonoutput ip_output : eon header:\n"); 709 dump_buf(eonhdr, sizeof(struct eon_hdr)); 710 printf("ip header:\n"); 711 dump_buf(iphdr, sizeof(struct ip)); 712 ENDDEBUG 713 714 IncStat(es_ipout); 715 if( error = ip_output(mh, (struct mbuf *)0, (struct route *)0, 0) ) 716 break; 717 718 IFDEBUG(D_EON) 719 printf("eonoutput ip_output returns 0x%x; single %d\n", 720 error, single); 721 ENDDEBUG 722 723 if(single) 724 break; 725 726 q = centrytoq(ent, qoffset)->link; 727 if( q == (struct qhdr *)0) 728 break; 729 ent = qtocentry( q, qoffset ); 730 IFDEBUG(D_EON) 731 printf("eonoutput : get next entry: 0x%x\n", ent); 732 ENDDEBUG 733 dstipaddrloc = (caddr_t) &(ent->eonc_addr); 734 IFDEBUG(D_EON) 735 printf("eonoutput : dump of eon_centry 0x%x:\n", ent ); 736 dump_buf(ent, sizeof(struct eon_centry) ); 737 ENDDEBUG 738 } 739 done: 740 if( !single ) { 741 IFDEBUG(D_EON) 742 printf("eonoutput : freeing morig 0x%x\n", morig); 743 ENDDEBUG 744 flush: 745 m_freem(morig); 746 } 747 return error; 748 } 749 750 eoninput(m, iphlen) 751 register struct mbuf *m; 752 int iphlen; 753 { 754 register struct eon_hdr *eonhdr; 755 register struct ip *iphdr; 756 struct ifnet *eonifp; 757 int s; 758 759 eonifp = &eonif[0]; /* kludge - really want to give CLNP 760 * the ifp for eon, not for the real device 761 */ 762 763 IFDEBUG(D_EON) 764 printf("eoninput() 0x%x m_data 0x%x m_len 0x%x dequeued\n", 765 m, m?m->m_data:0, m?m->m_len:0); 766 ENDDEBUG 767 768 if (m == 0) 769 return; 770 if (iphlen > sizeof (struct ip)) 771 ip_stripoptions(m, (struct mbuf *)0); 772 if (m->m_len < EONIPLEN) { 773 if ((m = m_pullup(m, EONIPLEN)) == 0) { 774 IncStat(es_badhdr); 775 drop: 776 IFDEBUG(D_EON) 777 printf("eoninput: DROP \n" ); 778 ENDDEBUG 779 eonifp->if_ierrors ++; 780 m_freem(m); 781 return; 782 } 783 } 784 iphdr = mtod(m, struct ip *); 785 /* do a few checks for debugging */ 786 if( iphdr->ip_p != IPPROTO_EON ) { 787 IncStat(es_badhdr); 788 goto drop; 789 } 790 /* temporarily drop ip header from the mbuf */ 791 m->m_data += sizeof(struct ip); 792 eonhdr = mtod(m, struct eon_hdr *); 793 if( iso_check_csum( m, sizeof(struct eon_hdr) ) != EOK ) { 794 IncStat(es_badcsum); 795 goto drop; 796 } 797 m->m_data -= sizeof(struct ip); 798 799 IFDEBUG(D_EON) 800 printf("eoninput csum ok class 0x%x\n", eonhdr->eonh_class ); 801 printf("eoninput: eon header:\n"); 802 dump_buf(eonhdr, sizeof(struct eon_hdr)); 803 ENDDEBUG 804 805 /* checks for debugging */ 806 if( eonhdr->eonh_vers != EON_VERSION) { 807 IncStat(es_badhdr); 808 goto drop; 809 } 810 m->m_flags &= ~(M_BCAST|M_MCAST); 811 switch( eonhdr->eonh_class) { 812 case EON_BROADCAST: 813 IncStat(es_in_broad); 814 m->m_flags |= M_BCAST; 815 break; 816 case EON_NORMAL_ADDR: 817 IncStat(es_in_normal); 818 break; 819 case EON_MULTICAST_ES: 820 IncStat(es_in_multi_es); 821 m->m_flags |= M_MCAST; 822 break; 823 case EON_MULTICAST_IS: 824 IncStat(es_in_multi_is); 825 m->m_flags |= M_MCAST; 826 break; 827 } 828 eonifp->if_ipackets ++; 829 830 { 831 /* put it on the CLNP queue and set soft interrupt */ 832 struct ifqueue *ifq; 833 extern struct ifqueue clnlintrq; 834 835 m->m_pkthdr.rcvif = eonifp; /* KLUDGE */ 836 IFDEBUG(D_EON) 837 printf("eoninput to clnl IFQ\n"); 838 ENDDEBUG 839 ifq = &clnlintrq; 840 s = splimp(); 841 if (IF_QFULL(ifq)) { 842 IF_DROP(ifq); 843 m_freem(m); 844 eonifp->if_ierrors ++; 845 splx(s); 846 return; 847 } 848 IF_ENQUEUE(ifq, m); 849 IFDEBUG(D_EON) 850 printf( 851 "0x%x enqueued on clnp Q: m_len 0x%x m_type 0x%x m_data 0x%x\n", 852 m, m->m_len, m->m_type, m->m_data); 853 dump_buf(mtod(m, caddr_t), m->m_len); 854 ENDDEBUG 855 schednetisr(NETISR_ISO); 856 splx(s); 857 } 858 } 859 860 int 861 eonctlinput(cmd, sin) 862 int cmd; 863 struct sockaddr_in *sin; 864 { 865 extern u_char inetctlerrmap[]; 866 867 IFDEBUG(D_EON) 868 printf("eonctlinput: cmd 0x%x addr: ", cmd); 869 dump_isoaddr(sin); 870 printf("\n"); 871 ENDDEBUG 872 873 if (cmd < 0 || cmd > PRC_NCMDS) 874 return 0; 875 876 IncStat(es_icmp[cmd]); 877 switch (cmd) { 878 879 case PRC_QUENCH: 880 case PRC_QUENCH2: 881 /* TODO: set the dec bit */ 882 break; 883 case PRC_TIMXCEED_REASS: 884 case PRC_ROUTEDEAD: 885 case PRC_HOSTUNREACH: 886 case PRC_UNREACH_NET: 887 case PRC_IFDOWN: 888 case PRC_UNREACH_HOST: 889 case PRC_HOSTDEAD: 890 case PRC_TIMXCEED_INTRANS: 891 /* TODO: mark the link down */ 892 break; 893 894 case PRC_UNREACH_PROTOCOL: 895 case PRC_UNREACH_PORT: 896 case PRC_UNREACH_NEEDFRAG: 897 case PRC_UNREACH_SRCFAIL: 898 case PRC_REDIRECT_NET: 899 case PRC_REDIRECT_HOST: 900 case PRC_REDIRECT_TOSNET: 901 case PRC_REDIRECT_TOSHOST: 902 case PRC_MSGSIZE: 903 case PRC_PARAMPROB: 904 printf("eonctlinput: ICMP cmd 0x%x\n", cmd ); 905 break; 906 } 907 return 0; 908 } 909 910 #endif 911