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