|
|
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.