|
|
1.1 ! root 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.10 (Berkeley) 6/20/90 * ! 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/if_types.h" ! 61: #include "../net/if_dl.h" ! 62: #include "../net/netisr.h" ! 63: #include "../net/route.h" ! 64: #include "machine/mtpr.h" ! 65: ! 66: #include "../netinet/in.h" ! 67: #include "../netinet/in_systm.h" ! 68: #include "../netinet/in_var.h" ! 69: #include "../netinet/ip.h" ! 70: #include "../netinet/ip_var.h" ! 71: #include "../netinet/if_ether.h" ! 72: ! 73: #include "iso.h" ! 74: #include "iso_var.h" ! 75: #include "iso_snpac.h" ! 76: #include "argo_debug.h" ! 77: #include "iso_errno.h" ! 78: #include "eonvar.h" ! 79: extern struct timeval time; ! 80: ! 81: #define EOK 0 ! 82: ! 83: int eoninput(); ! 84: int eonoutput(); ! 85: int eonioctl(); ! 86: int eonattach(); ! 87: int eoninit(); ! 88: int eonrtrequest(); ! 89: extern int ip_output(); ! 90: struct ifnet eonif[1]; ! 91: ! 92: eonprotoinit() { ! 93: (void) eonattach(); ! 94: } ! 95: ! 96: struct eon_llinfo eon_llinfo; ! 97: #define PROBE_OK 0; ! 98: ! 99: ! 100: /* ! 101: * FUNCTION: eonattach ! 102: * ! 103: * PURPOSE: autoconf attach routine ! 104: * ! 105: * RETURNS: void ! 106: */ ! 107: ! 108: eonattach() ! 109: { ! 110: register struct ifnet *ifp = eonif; ! 111: ! 112: IFDEBUG(D_EON) ! 113: printf("eonattach()\n"); ! 114: ENDDEBUG ! 115: ifp->if_unit = 0; ! 116: ifp->if_name = "eon"; ! 117: ifp->if_mtu = ETHERMTU; ! 118: /* since everything will go out over ether or token ring */ ! 119: ! 120: ifp->if_init = eoninit; ! 121: ifp->if_ioctl = eonioctl; ! 122: ifp->if_output = eonoutput; ! 123: ifp->if_type = IFT_EON; ! 124: ifp->if_addrlen = 5; ! 125: ifp->if_hdrlen = EONIPLEN; ! 126: ifp->if_flags = IFF_BROADCAST; ! 127: if_attach(ifp); ! 128: eonioctl(ifp, SIOCSIFADDR, (caddr_t)ifp->if_addrlist); ! 129: eon_llinfo.el_qhdr.link = ! 130: eon_llinfo.el_qhdr.rlink = &(eon_llinfo.el_qhdr); ! 131: ! 132: IFDEBUG(D_EON) ! 133: printf("eonattach()\n"); ! 134: ENDDEBUG ! 135: } ! 136: ! 137: ! 138: /* ! 139: * FUNCTION: eonioctl ! 140: * ! 141: * PURPOSE: io controls - ifconfig ! 142: * need commands to ! 143: * link-UP (core addr) (flags: ES, IS) ! 144: * link-DOWN (core addr) (flags: ES, IS) ! 145: * must be callable from kernel or user ! 146: * ! 147: * RETURNS: nothing ! 148: */ ! 149: eonioctl(ifp, cmd, data) ! 150: register struct ifnet *ifp; ! 151: int cmd; ! 152: register caddr_t data; ! 153: { ! 154: int s = splimp(); ! 155: register int error = 0; ! 156: ! 157: IFDEBUG(D_EON) ! 158: printf("eonioctl (cmd 0x%x) \n", cmd); ! 159: ENDDEBUG ! 160: ! 161: switch (cmd) { ! 162: register struct ifaddr *ifa; ! 163: ! 164: case SIOCSIFADDR: ! 165: if (ifa = (struct ifaddr *)data) { ! 166: ifp->if_flags |= IFF_UP; ! 167: if (ifa->ifa_addr->sa_family != AF_LINK) ! 168: ifa->ifa_rtrequest = eonrtrequest; ! 169: ifa->ifa_llinfolen = sizeof(struct eon_llinfo); ! 170: } ! 171: break; ! 172: } ! 173: splx(s); ! 174: return(error); ! 175: } ! 176: ! 177: ! 178: eoniphdr(hdr, loc, ro, class, zero) ! 179: struct route *ro; ! 180: register struct eon_iphdr *hdr; ! 181: caddr_t loc; ! 182: { ! 183: struct mbuf mhead; ! 184: register struct sockaddr_in *sin = (struct sockaddr_in *)&ro->ro_dst; ! 185: if (zero) { ! 186: bzero((caddr_t)hdr, sizeof (*hdr)); ! 187: bzero((caddr_t)ro, sizeof (*ro)); ! 188: } ! 189: sin->sin_family = AF_INET; ! 190: sin->sin_len = sizeof (*sin); ! 191: bcopy(loc, (caddr_t)&sin->sin_addr, sizeof(struct in_addr)); ! 192: hdr->ei_ip.ip_dst = sin->sin_addr; ! 193: hdr->ei_ip.ip_p = IPPROTO_EON; ! 194: hdr->ei_ip.ip_ttl = MAXTTL; ! 195: hdr->ei_eh.eonh_class = class; ! 196: hdr->ei_eh.eonh_vers = EON_VERSION; ! 197: hdr->ei_eh.eonh_csum = 0; ! 198: mhead.m_data = (caddr_t) &hdr->ei_eh; ! 199: mhead.m_len = sizeof(struct eon_hdr); ! 200: mhead.m_next = 0; ! 201: IFDEBUG(D_EON) ! 202: printf("eonoutput : gen csum (0x%x, offset %d, datalen %d)\n", ! 203: &mhead, ! 204: _offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr)); ! 205: ENDDEBUG ! 206: iso_gen_csum(&mhead, ! 207: _offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr)); ! 208: } ! 209: /* ! 210: * FUNCTION: eonrtrequest ! 211: * ! 212: * PURPOSE: maintains list of direct eon recipients. ! 213: * sets up IP route for rest. ! 214: * ! 215: * RETURNS: nothing ! 216: */ ! 217: eonrtrequest(cmd, rt, gate) ! 218: register struct rtentry *rt; ! 219: register struct sockaddr *gate; ! 220: { ! 221: unsigned long zerodst = 0; ! 222: caddr_t ipaddrloc = (caddr_t) &zerodst; ! 223: register struct eon_llinfo *el = (struct eon_llinfo *)rt->rt_llinfo; ! 224: ! 225: /* ! 226: * Common Housekeeping ! 227: */ ! 228: switch (cmd) { ! 229: case RTM_DELETE: ! 230: if (el) { ! 231: remque(&(el->el_qhdr)); ! 232: if (el->el_iproute.ro_rt) ! 233: RTFREE(el->el_iproute.ro_rt); ! 234: Free(el); ! 235: rt->rt_llinfo = 0; ! 236: } ! 237: return; ! 238: ! 239: case RTM_RESOLVE: ! 240: case RTM_ADD: ! 241: R_Malloc(el, struct eon_llinfo *, sizeof(*el)); ! 242: rt->rt_llinfo = (caddr_t)el; ! 243: if (el == 0) ! 244: return; ! 245: Bzero(el, sizeof(*el)); ! 246: insque(&(el->el_qhdr), &eon_llinfo.el_qhdr); ! 247: el->el_rt = rt; ! 248: break; ! 249: } ! 250: if (gate || (gate = rt->rt_gateway)) switch (gate->sa_family) { ! 251: case AF_LINK: ! 252: #define SDL(x) ((struct sockaddr_dl *)x) ! 253: if (SDL(gate)->sdl_alen = 1) ! 254: el->el_snpaoffset = *(u_char *)LLADDR(SDL(gate)); ! 255: else ! 256: ipaddrloc = LLADDR(SDL(gate)); ! 257: break; ! 258: case AF_INET: ! 259: #define SIN(x) ((struct sockaddr_in *)x) ! 260: ipaddrloc = (caddr_t) &SIN(gate)->sin_addr; ! 261: break; ! 262: default: ! 263: return; ! 264: } ! 265: el->el_flags |= RTF_UP; ! 266: eoniphdr(&el->el_ei, ipaddrloc, &el->el_iproute, EON_NORMAL_ADDR, 0); ! 267: } ! 268: ! 269: /* ! 270: * FUNCTION: eoninit ! 271: * ! 272: * PURPOSE: initialization ! 273: * ! 274: * RETURNS: nothing ! 275: */ ! 276: ! 277: eoninit(unit) ! 278: int unit; ! 279: { ! 280: printf("eon driver-init eon%d\n", unit); ! 281: } ! 282: ! 283: ! 284: /* ! 285: * FUNCTION: eonoutput ! 286: * ! 287: * PURPOSE: prepend an eon header and hand to IP ! 288: * ARGUMENTS: (ifp) is points to the ifnet structure for this unit/device ! 289: * (m) is an mbuf *, *m is a CLNL packet ! 290: * (dst) is a destination address - have to interp. as ! 291: * multicast or broadcast or real address. ! 292: * ! 293: * RETURNS: unix error code ! 294: * ! 295: * NOTES: ! 296: * ! 297: */ ! 298: eonoutput(ifp, m, dst, rt) ! 299: struct ifnet *ifp; ! 300: register struct mbuf *m; /* packet */ ! 301: struct sockaddr_iso *dst; /* destination addr */ ! 302: struct rtentry *rt; ! 303: { ! 304: register struct eon_llinfo *el; ! 305: register struct eon_iphdr *ei; ! 306: struct route *ro; ! 307: int datalen; ! 308: struct mbuf *mh; ! 309: int error = 0; ! 310: caddr_t ippaddrloc; ! 311: static struct eon_iphdr eon_iphdr; ! 312: static struct route route; ! 313: ! 314: IFDEBUG(D_EON) ! 315: printf("eonoutput \n" ); ! 316: ENDDEBUG ! 317: ! 318: ifp->if_lastchange = time; ! 319: ifp->if_opackets++; ! 320: if (rt == 0 || (el = (struct eon_llinfo *)rt->rt_llinfo) == 0) { ! 321: if (dst->siso_family == AF_LINK) { ! 322: register struct sockaddr_dl *sdl = (struct sockaddr_dl *)dst; ! 323: caddr_t ipaddrloc = LLADDR(sdl); ! 324: int class = (sdl->sdl_alen == 5) ? 4[(u_char *)ipaddrloc] : 0; ! 325: ! 326: if (sdl->sdl_alen == 4 || sdl->sdl_alen == 5) { ! 327: ro = &route; ! 328: ei = &eon_iphdr; ! 329: eoniphdr(ei, ipaddrloc, ro, class, 1); ! 330: goto send; ! 331: } ! 332: } ! 333: einval: ! 334: error = EINVAL; ! 335: goto flush; ! 336: } ! 337: if ((el->el_flags & RTF_UP) == 0) { ! 338: eonrtrequest(RTM_CHANGE, rt, (struct sockaddr *)0); ! 339: if ((el->el_flags & RTF_UP) == 0) { ! 340: error = EHOSTUNREACH; ! 341: goto flush; ! 342: } ! 343: } ! 344: if ((m->m_flags & M_PKTHDR) == 0) { ! 345: printf("eon: got non headered packet\n"); ! 346: goto einval; ! 347: } ! 348: ei = &el->el_ei; ! 349: ro = &el->el_iproute; ! 350: if (el->el_snpaoffset) { ! 351: if (dst->siso_family == AF_ISO) { ! 352: bcopy((caddr_t) &dst->siso_data[el->el_snpaoffset], ! 353: (caddr_t) &ei->ei_ip.ip_dst, sizeof(ei->ei_ip.ip_dst)); ! 354: } else ! 355: goto einval; ! 356: } ! 357: send: ! 358: /* put an eon_hdr in the buffer, prepended by an ip header */ ! 359: datalen = m->m_pkthdr.len + EONIPLEN; ! 360: MGETHDR(mh, M_DONTWAIT, MT_HEADER); ! 361: if(mh == (struct mbuf *)0) ! 362: goto flush; ! 363: mh->m_next = m; ! 364: m = mh; ! 365: MH_ALIGN(m, sizeof(struct eon_iphdr)); ! 366: m->m_len = sizeof(struct eon_iphdr); ! 367: ifp->if_obytes += ! 368: (ei->ei_ip.ip_len = (u_short)(m->m_pkthdr.len = datalen)); ! 369: *mtod(m, struct eon_iphdr *) = *ei; ! 370: ! 371: IFDEBUG(D_EON) ! 372: printf("eonoutput dst ip addr : %x\n", ei->ei_ip.ip_dst.s_addr); ! 373: printf("eonoutput ip_output : eonip header:\n"); ! 374: dump_buf(ei, sizeof(struct eon_iphdr)); ! 375: ENDDEBUG ! 376: ! 377: error = ip_output(m, (struct mbuf *)0, ro, 0); ! 378: m = 0; ! 379: if (error) { ! 380: ifp->if_oerrors++; ! 381: ifp->if_opackets--; ! 382: ifp->if_obytes -= datalen; ! 383: } ! 384: flush: ! 385: if (m) ! 386: m_freem(m); ! 387: return error; ! 388: } ! 389: ! 390: eoninput(m, iphlen) ! 391: register struct mbuf *m; ! 392: int iphlen; ! 393: { ! 394: register struct eon_hdr *eonhdr; ! 395: register struct ip *iphdr; ! 396: struct ifnet *eonifp; ! 397: int s; ! 398: ! 399: eonifp = &eonif[0]; /* kludge - really want to give CLNP ! 400: * the ifp for eon, not for the real device ! 401: */ ! 402: ! 403: IFDEBUG(D_EON) ! 404: printf("eoninput() 0x%x m_data 0x%x m_len 0x%x dequeued\n", ! 405: m, m?m->m_data:0, m?m->m_len:0); ! 406: ENDDEBUG ! 407: ! 408: if (m == 0) ! 409: return; ! 410: if (iphlen > sizeof (struct ip)) ! 411: ip_stripoptions(m, (struct mbuf *)0); ! 412: if (m->m_len < EONIPLEN) { ! 413: if ((m = m_pullup(m, EONIPLEN)) == 0) { ! 414: IncStat(es_badhdr); ! 415: drop: ! 416: IFDEBUG(D_EON) ! 417: printf("eoninput: DROP \n" ); ! 418: ENDDEBUG ! 419: eonifp->if_ierrors ++; ! 420: m_freem(m); ! 421: return; ! 422: } ! 423: } ! 424: eonif->if_ibytes += m->m_pkthdr.len; ! 425: eonif->if_lastchange = time; ! 426: iphdr = mtod(m, struct ip *); ! 427: /* do a few checks for debugging */ ! 428: if( iphdr->ip_p != IPPROTO_EON ) { ! 429: IncStat(es_badhdr); ! 430: goto drop; ! 431: } ! 432: /* temporarily drop ip header from the mbuf */ ! 433: m->m_data += sizeof(struct ip); ! 434: eonhdr = mtod(m, struct eon_hdr *); ! 435: if( iso_check_csum( m, sizeof(struct eon_hdr) ) != EOK ) { ! 436: IncStat(es_badcsum); ! 437: goto drop; ! 438: } ! 439: m->m_data -= sizeof(struct ip); ! 440: ! 441: IFDEBUG(D_EON) ! 442: printf("eoninput csum ok class 0x%x\n", eonhdr->eonh_class ); ! 443: printf("eoninput: eon header:\n"); ! 444: dump_buf(eonhdr, sizeof(struct eon_hdr)); ! 445: ENDDEBUG ! 446: ! 447: /* checks for debugging */ ! 448: if( eonhdr->eonh_vers != EON_VERSION) { ! 449: IncStat(es_badhdr); ! 450: goto drop; ! 451: } ! 452: m->m_flags &= ~(M_BCAST|M_MCAST); ! 453: switch( eonhdr->eonh_class) { ! 454: case EON_BROADCAST: ! 455: IncStat(es_in_broad); ! 456: m->m_flags |= M_BCAST; ! 457: break; ! 458: case EON_NORMAL_ADDR: ! 459: IncStat(es_in_normal); ! 460: break; ! 461: case EON_MULTICAST_ES: ! 462: IncStat(es_in_multi_es); ! 463: m->m_flags |= M_MCAST; ! 464: break; ! 465: case EON_MULTICAST_IS: ! 466: IncStat(es_in_multi_is); ! 467: m->m_flags |= M_MCAST; ! 468: break; ! 469: } ! 470: eonifp->if_ipackets++; ! 471: ! 472: { ! 473: /* put it on the CLNP queue and set soft interrupt */ ! 474: struct ifqueue *ifq; ! 475: extern struct ifqueue clnlintrq; ! 476: ! 477: m->m_pkthdr.rcvif = eonifp; /* KLUDGE */ ! 478: IFDEBUG(D_EON) ! 479: printf("eoninput to clnl IFQ\n"); ! 480: ENDDEBUG ! 481: ifq = &clnlintrq; ! 482: s = splimp(); ! 483: if (IF_QFULL(ifq)) { ! 484: IF_DROP(ifq); ! 485: m_freem(m); ! 486: eonifp->if_iqdrops++; ! 487: eonifp->if_ipackets--; ! 488: splx(s); ! 489: return; ! 490: } ! 491: IF_ENQUEUE(ifq, m); ! 492: IFDEBUG(D_EON) ! 493: printf( ! 494: "0x%x enqueued on clnp Q: m_len 0x%x m_type 0x%x m_data 0x%x\n", ! 495: m, m->m_len, m->m_type, m->m_data); ! 496: dump_buf(mtod(m, caddr_t), m->m_len); ! 497: ENDDEBUG ! 498: schednetisr(NETISR_ISO); ! 499: splx(s); ! 500: } ! 501: } ! 502: ! 503: int ! 504: eonctlinput(cmd, sin) ! 505: int cmd; ! 506: struct sockaddr_in *sin; ! 507: { ! 508: extern u_char inetctlerrmap[]; ! 509: ! 510: IFDEBUG(D_EON) ! 511: printf("eonctlinput: cmd 0x%x addr: ", cmd); ! 512: dump_isoaddr(sin); ! 513: printf("\n"); ! 514: ENDDEBUG ! 515: ! 516: if (cmd < 0 || cmd > PRC_NCMDS) ! 517: return 0; ! 518: ! 519: IncStat(es_icmp[cmd]); ! 520: switch (cmd) { ! 521: ! 522: case PRC_QUENCH: ! 523: case PRC_QUENCH2: ! 524: /* TODO: set the dec bit */ ! 525: break; ! 526: case PRC_TIMXCEED_REASS: ! 527: case PRC_ROUTEDEAD: ! 528: case PRC_HOSTUNREACH: ! 529: case PRC_UNREACH_NET: ! 530: case PRC_IFDOWN: ! 531: case PRC_UNREACH_HOST: ! 532: case PRC_HOSTDEAD: ! 533: case PRC_TIMXCEED_INTRANS: ! 534: /* TODO: mark the link down */ ! 535: break; ! 536: ! 537: case PRC_UNREACH_PROTOCOL: ! 538: case PRC_UNREACH_PORT: ! 539: case PRC_UNREACH_SRCFAIL: ! 540: case PRC_REDIRECT_NET: ! 541: case PRC_REDIRECT_HOST: ! 542: case PRC_REDIRECT_TOSNET: ! 543: case PRC_REDIRECT_TOSHOST: ! 544: case PRC_MSGSIZE: ! 545: case PRC_PARAMPROB: ! 546: printf("eonctlinput: ICMP cmd 0x%x\n", cmd ); ! 547: break; ! 548: } ! 549: return 0; ! 550: } ! 551: ! 552: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.