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