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