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