|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (C) Dirk Husemann, Computer Science Department IV, ! 24: * University of Erlangen-Nuremberg, Germany, 1990, 1991, 1992 ! 25: * Copyright (c) 1992, 1993 ! 26: * The Regents of the University of California. All rights reserved. ! 27: * ! 28: * This code is derived from software contributed to Berkeley by ! 29: * Dirk Husemann and the Computer Science Department (IV) of ! 30: * the University of Erlangen-Nuremberg, Germany. ! 31: * ! 32: * Redistribution and use in source and binary forms, with or without ! 33: * modification, are permitted provided that the following conditions ! 34: * are met: ! 35: * 1. Redistributions of source code must retain the above copyright ! 36: * notice, this list of conditions and the following disclaimer. ! 37: * 2. Redistributions in binary form must reproduce the above copyright ! 38: * notice, this list of conditions and the following disclaimer in the ! 39: * documentation and/or other materials provided with the distribution. ! 40: * 3. All advertising materials mentioning features or use of this software ! 41: * must display the following acknowledgement: ! 42: * This product includes software developed by the University of ! 43: * California, Berkeley and its contributors. ! 44: * 4. Neither the name of the University nor the names of its contributors ! 45: * may be used to endorse or promote products derived from this software ! 46: * without specific prior written permission. ! 47: * ! 48: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 49: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 50: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 51: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 52: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 53: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 54: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 55: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 56: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 57: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 58: * SUCH DAMAGE. ! 59: * ! 60: * @(#)llc_input.c 8.1 (Berkeley) 6/10/93 ! 61: */ ! 62: ! 63: #include <sys/param.h> ! 64: #include <sys/systm.h> ! 65: #include <sys/mbuf.h> ! 66: #include <sys/domain.h> ! 67: #include <sys/socket.h> ! 68: #include <sys/protosw.h> ! 69: #include <sys/errno.h> ! 70: #include <sys/time.h> ! 71: #include <sys/kernel.h> ! 72: ! 73: #include <net/if.h> ! 74: #include <net/if_dl.h> ! 75: #include <net/if_llc.h> ! 76: #include <net/route.h> ! 77: ! 78: #include <netccitt/dll.h> ! 79: #include <netccitt/llc_var.h> ! 80: ! 81: /* ! 82: * This module implements LLC as specified by ISO 8802-2. ! 83: */ ! 84: ! 85: ! 86: /* ! 87: * llcintr() handles all LLC frames (except ISO CLNS ones for the time being) ! 88: * and tries to pass them on to the appropriate network layer entity. ! 89: */ ! 90: void ! 91: llcintr() ! 92: { ! 93: register struct mbuf *m; ! 94: register int i; ! 95: register int frame_kind; ! 96: register u_char cmdrsp; ! 97: struct llc_linkcb *linkp; ! 98: struct rtentry *sirt; ! 99: struct npaidbentry *sapinfo; ! 100: struct sdl_hdr *sdlhdr; ! 101: struct llc *frame; ! 102: char *c; ! 103: long expected_len; ! 104: ! 105: struct ifnet *ifp; ! 106: struct rtentry *llrt; ! 107: struct rtentry *nlrt; ! 108: ! 109: for (;;) { ! 110: i = splimp(); ! 111: IF_DEQUEUE(&llcintrq, m); ! 112: splx(i); ! 113: if (m == 0) ! 114: break; ! 115: #if DIAGNOSTIC ! 116: if ((m->m_flags & M_PKTHDR) == 0) ! 117: panic("llcintr no HDR"); ! 118: #endif ! 119: /* ! 120: * Get ifp this packet was received on ! 121: */ ! 122: ifp = m->m_pkthdr.rcvif; ! 123: ! 124: sdlhdr = mtod(m, struct sdl_hdr *); ! 125: ! 126: /* ! 127: * [Copied from net/ip_input.c] ! 128: * ! 129: * Check that the amount of data in the buffers is ! 130: * at least as much as the LLC header tells us. ! 131: * Trim mbufs if longer than expected. ! 132: * Drop packets if shorter than we think they are. ! 133: * ! 134: * Layout of mbuf chain at this point: ! 135: * ! 136: * +-------------------------------+----+ -\ ! 137: * | sockaddr_dl src - sdlhdr_src | 20 | \ ! 138: * +-------------------------------+----+ | ! 139: * | sockaddr_dl dst - sdlhdr_dst | 20 | > sizeof(struct sdl_hdr) == 44 ! 140: * +-------------------------------+----+ | ! 141: * | LLC frame len - sdlhdr_len | 04 | / ! 142: * +-------------------------------+----+ -/ ! 143: * / ! 144: * | m_next ! 145: * \ ! 146: * +----------------------------+----+ -\ ! 147: * | llc DSAP | 01 | \ ! 148: * +----------------------------+----+ | ! 149: * | llc SSAP | 01 | | ! 150: * +----------------------------+----+ > sdlhdr_len ! 151: * | llc control | 01 | | ! 152: * +----------------------------+----+ | ! 153: * | ... | | / ! 154: * -/ ! 155: * ! 156: * Thus the we expect to have exactly ! 157: * (sdlhdr->sdlhdr_len+sizeof(struct sdl_hdr)) in the mbuf chain ! 158: */ ! 159: expected_len = sdlhdr->sdlhdr_len + sizeof(struct sdl_hdr); ! 160: ! 161: if (m->m_pkthdr.len < expected_len) { ! 162: m_freem(m); ! 163: continue; ! 164: } ! 165: if (m->m_pkthdr.len > expected_len) { ! 166: if (m->m_len == m->m_pkthdr.len) { ! 167: m->m_len = expected_len; ! 168: m->m_pkthdr.len = expected_len; ! 169: } else ! 170: m_adj(m, expected_len - m->m_pkthdr.len); ! 171: } ! 172: ! 173: /* ! 174: * Get llc header ! 175: */ ! 176: if (m->m_len > sizeof(struct sdl_hdr)) ! 177: frame = mtod((struct mbuf *)((struct sdl_hdr*)(m+1)), ! 178: struct llc *); ! 179: else frame = mtod(m->m_next, struct llc *); ! 180: if (frame == (struct llc *) NULL) ! 181: panic("llcintr no llc header"); ! 182: ! 183: /* ! 184: * Now check for bogus I/S frame, i.e. those with a control ! 185: * field telling us they're an I/S frame yet their length ! 186: * is less than the established I/S frame length (DSAP + SSAP + ! 187: * control + N(R)&P/F = 4) --- we drop those suckers ! 188: */ ! 189: if (((frame->llc_control & 0x03) != 0x03) ! 190: && ((expected_len - sizeof(struct sdl_hdr)) < LLC_ISFRAMELEN)) { ! 191: m_freem(m); ! 192: printf("llc: hurz error\n"); ! 193: continue; ! 194: } ! 195: ! 196: /* ! 197: * Get link control block for the addressed link connection. ! 198: * If there is none we take care of it later on. ! 199: */ ! 200: cmdrsp = (frame->llc_ssap & 0x01); ! 201: frame->llc_ssap &= ~0x01; ! 202: if (llrt = rtalloc1((struct sockaddr *)&sdlhdr->sdlhdr_src, 0)) ! 203: llrt->rt_refcnt--; ! 204: #ifdef notyet ! 205: else llrt = npaidb_enter(&sdlhdr->sdlhdr_src, 0, 0, 0); ! 206: #endif /* notyet */ ! 207: else { ! 208: /* ! 209: * We cannot do anything currently here as we ! 210: * don't `know' this link --- drop it ! 211: */ ! 212: m_freem(m); ! 213: continue; ! 214: } ! 215: linkp = ((struct npaidbentry *)(llrt->rt_llinfo))->np_link; ! 216: nlrt = ((struct npaidbentry *)(llrt->rt_llinfo))->np_rt; ! 217: ! 218: /* ! 219: * If the link is not existing right now, we can try and look up ! 220: * the SAP info block. ! 221: */ ! 222: if ((linkp == 0) && frame->llc_ssap) ! 223: sapinfo = llc_getsapinfo(frame->llc_dsap, ifp); ! 224: ! 225: /* ! 226: * Handle XID and TEST frames ! 227: * XID: if DLSAP == 0, return type-of-services ! 228: * window-0 ! 229: * DLSAP-0 ! 230: * format-identifier-? ! 231: * if DLSAP != 0, locate sapcb and return ! 232: * type-of-services ! 233: * SAP-window ! 234: * format-identifier-? ! 235: * TEST: swap (snpah_dst, snpah_src) and return frame ! 236: * ! 237: * Also toggle the CMD/RESP bit ! 238: * ! 239: * Is this behaviour correct? Check ISO 8802-2 (90)! ! 240: */ ! 241: frame_kind = llc_decode(frame, (struct llc_linkcb *)0); ! 242: switch(frame_kind) { ! 243: case LLCFT_XID: ! 244: if (linkp || sapinfo) { ! 245: if (linkp) ! 246: frame->llc_window = linkp->llcl_window; ! 247: else frame->llc_window = sapinfo->si_window; ! 248: frame->llc_fid = 9; /* XXX */ ! 249: frame->llc_class = sapinfo->si_class; ! 250: frame->llc_ssap = frame->llc_dsap; ! 251: } else { ! 252: frame->llc_window = 0; ! 253: frame->llc_fid = 9; ! 254: frame->llc_class = 1; ! 255: frame->llc_dsap = frame->llc_ssap = 0; ! 256: } ! 257: ! 258: /* fall thru to */ ! 259: case LLCFT_TEST: ! 260: sdl_swapaddr(&(mtod(m, struct sdl_hdr *)->sdlhdr_dst), ! 261: &(mtod(m, struct sdl_hdr *)->sdlhdr_src)); ! 262: ! 263: /* Now set the CMD/RESP bit */ ! 264: frame->llc_ssap |= (cmdrsp == 0x0 ? 0x1 : 0x0); ! 265: ! 266: /* Ship it out again */ ! 267: (*ifp->if_output)(ifp, m, ! 268: (struct sockaddr *) &(mtod(m, struct sdl_hdr *)->sdlhdr_dst), ! 269: (struct rtentry *) 0); ! 270: continue; ! 271: } ! 272: ! 273: /* ! 274: * Create link control block in case it is not existing ! 275: */ ! 276: if (linkp == 0 && sapinfo) { ! 277: if ((linkp = llc_newlink(&sdlhdr->sdlhdr_src, ifp, nlrt, ! 278: (nlrt == 0) ? 0 : nlrt->rt_llinfo, ! 279: llrt)) == 0) { ! 280: printf("llcintr: couldn't create new link\n"); ! 281: m_freem(m); ! 282: continue; ! 283: } ! 284: ((struct npaidbentry *)llrt->rt_llinfo)->np_link = linkp; ! 285: } else if (linkp == 0) { ! 286: /* The link is not known to us, drop the frame and continue */ ! 287: m_freem(m); ! 288: continue; ! 289: } ! 290: ! 291: /* ! 292: * Drop SNPA header and get rid of empty mbuf at the ! 293: * front of the mbuf chain (I don't like 'em) ! 294: */ ! 295: m_adj(m, sizeof(struct sdl_hdr)); ! 296: /* ! 297: * LLC_UFRAMELEN is sufficient, m_pullup() will pull up ! 298: * the min(m->m_len, maxprotohdr_len [=40]) thus doing ! 299: * the trick ... ! 300: */ ! 301: if ((m = m_pullup(m, LLC_UFRAMELEN))) ! 302: /* ! 303: * Pass it on thru the elements of procedure ! 304: */ ! 305: llc_input(linkp, m, cmdrsp); ! 306: } ! 307: return; ! 308: } ! 309: ! 310: /* ! 311: * llc_input() --- We deal with the various incoming frames here. ! 312: * Basically we (indirectly) call the appropriate ! 313: * state handler function that's pointed to by ! 314: * llcl_statehandler. ! 315: * ! 316: * The statehandler returns an action code --- ! 317: * further actions like ! 318: * o notify network layer ! 319: * o block further sending ! 320: * o deblock link ! 321: * o ... ! 322: * are then enacted accordingly. ! 323: */ ! 324: llc_input(struct llc_linkcb *linkp, struct mbuf *m, u_char cmdrsp) ! 325: { ! 326: int frame_kind; ! 327: int pollfinal; ! 328: int action = 0; ! 329: struct llc *frame; ! 330: struct ifnet *ifp = linkp->llcl_if; ! 331: ! 332: if ((frame = mtod(m, struct llc *)) == (struct llc *) 0) { ! 333: m_freem(m); ! 334: return 0; ! 335: } ! 336: pollfinal = ((frame->llc_control & 0x03) == 0x03) ? ! 337: LLCGBITS(frame->llc_control, u_pf) : ! 338: LLCGBITS(frame->llc_control_ext, s_pf); ! 339: ! 340: /* ! 341: * first decode the frame ! 342: */ ! 343: frame_kind = llc_decode(frame, linkp); ! 344: ! 345: switch (action = llc_statehandler(linkp, frame, frame_kind, cmdrsp, ! 346: pollfinal)) { ! 347: case LLC_DATA_INDICATION: ! 348: m_adj(m, LLC_ISFRAMELEN); ! 349: if (m = m_pullup(m, NLHDRSIZEGUESS)) { ! 350: m->m_pkthdr.rcvif = (struct ifnet *)linkp->llcl_nlnext; ! 351: (*linkp->llcl_sapinfo->si_input)(m); ! 352: } ! 353: break; ! 354: } ! 355: ! 356: /* release mbuf if not an info frame */ ! 357: if (action != LLC_DATA_INDICATION && m) ! 358: m_freem(m); ! 359: ! 360: /* try to get frames out ... */ ! 361: llc_start(linkp); ! 362: ! 363: return 0; ! 364: } ! 365: ! 366: /* ! 367: * This routine is called by configuration setup. It sets up a station control ! 368: * block and notifies all registered upper level protocols. ! 369: */ ! 370: caddr_t ! 371: llc_ctlinput(int prc, struct sockaddr *addr, caddr_t info) ! 372: { ! 373: struct ifnet *ifp; ! 374: struct ifaddr *ifa; ! 375: struct dll_ctlinfo *ctlinfo = (struct dll_ctlinfo *)info; ! 376: u_char sap; ! 377: struct dllconfig *config; ! 378: caddr_t pcb; ! 379: struct rtentry *nlrt; ! 380: struct rtentry *llrt; ! 381: struct llc_linkcb *linkp; ! 382: register int i; ! 383: ! 384: /* info must point to something valid at all times */ ! 385: if (info == 0) ! 386: return 0; ! 387: ! 388: if (prc == PRC_IFUP || prc == PRC_IFDOWN) { ! 389: /* we use either this set ... */ ! 390: ifa = ifa_ifwithaddr(addr); ! 391: ifp = ifa ? ifa->ifa_ifp : 0; ! 392: if (ifp == 0) ! 393: return 0; ! 394: ! 395: sap = ctlinfo->dlcti_lsap; ! 396: config = ctlinfo->dlcti_cfg; ! 397: pcb = (caddr_t) 0; ! 398: nlrt = (struct rtentry *) 0; ! 399: } else { ! 400: /* or this one */ ! 401: sap = 0; ! 402: config = (struct dllconfig *) 0; ! 403: pcb = ctlinfo->dlcti_pcb; ! 404: nlrt = ctlinfo->dlcti_rt; ! 405: ! 406: if ((llrt = rtalloc1(nlrt->rt_gateway, 0))) ! 407: llrt->rt_refcnt--; ! 408: else return 0; ! 409: ! 410: linkp = ((struct npaidbentry *)llrt->rt_llinfo)->np_link; ! 411: } ! 412: ! 413: switch (prc) { ! 414: case PRC_IFUP: ! 415: (void) llc_setsapinfo(ifp, addr->sa_family, sap, config); ! 416: return 0; ! 417: ! 418: case PRC_IFDOWN: { ! 419: register struct llc_linkcb *linkp; ! 420: register struct llc_linkcb *nlinkp; ! 421: register int i; ! 422: ! 423: /* ! 424: * All links are accessible over the doubly linked list llccb_q ! 425: */ ! 426: if (!LQEMPTY) { ! 427: /* ! 428: * A for-loop is not that great an idea as the linkp ! 429: * will get deleted by llc_timer() ! 430: */ ! 431: linkp = LQFIRST; ! 432: while (LQVALID(linkp)) { ! 433: nlinkp = LQNEXT(linkp); ! 434: if (linkp->llcl_if = ifp) { ! 435: i = splimp(); ! 436: (void)llc_statehandler(linkp, (struct llc *)0, ! 437: NL_DISCONNECT_REQUEST, ! 438: 0, 1); ! 439: splx(i); ! 440: } ! 441: linkp = nlinkp; ! 442: } ! 443: } ! 444: } ! 445: ! 446: case PRC_CONNECT_REQUEST: ! 447: if (linkp == 0) { ! 448: if ((linkp = llc_newlink((struct sockaddr_dl *) nlrt->rt_gateway, ! 449: nlrt->rt_ifp, nlrt, ! 450: pcb, llrt)) == 0) ! 451: return (0); ! 452: ((struct npaidbentry *)llrt->rt_llinfo)->np_link = linkp; ! 453: i = splimp(); ! 454: (void)llc_statehandler(linkp, (struct llc *) 0, ! 455: NL_CONNECT_REQUEST, 0, 1); ! 456: splx(i); ! 457: } ! 458: return ((caddr_t)linkp); ! 459: ! 460: case PRC_DISCONNECT_REQUEST: ! 461: if (linkp == 0) ! 462: panic("no link control block!"); ! 463: ! 464: i = splimp(); ! 465: (void)llc_statehandler(linkp, (struct llc *) 0, ! 466: NL_DISCONNECT_REQUEST, 0, 1); ! 467: splx(i); ! 468: ! 469: /* ! 470: * The actual removal of the link control block is done by the ! 471: * cleaning neutrum (i.e. llc_timer()). ! 472: */ ! 473: break; ! 474: ! 475: case PRC_RESET_REQUEST: ! 476: if (linkp == 0) ! 477: panic("no link control block!"); ! 478: ! 479: i = splimp(); ! 480: (void)llc_statehandler(linkp, (struct llc *) 0, ! 481: NL_RESET_REQUEST, 0, 1); ! 482: splx(i); ! 483: ! 484: break; ! 485: ! 486: } ! 487: ! 488: return 0; ! 489: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.