2 * NET An implementation of the IEEE 802.2 LLC protocol for the
3 * LINUX operating system. LLC is implemented as a set of
4 * state machines and callbacks for higher networking layers.
6 * Code for initialization, termination, registration and
9 * Written by Tim Alpaerts, Tim_Alpaerts@toyota-motor-europe.com
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version
14 * 2 of the License, or (at your option) any later version.
17 * Alan Cox : Chainsawed to Linux format
19 * Started restructuring handlers
21 * Horst von Brand : Add #include <linux/string.h>
24 #include <linux/module.h>
25 #include <linux/version.h>
26 #include <linux/kernel.h>
27 #include <linux/slab.h>
28 #include <linux/unistd.h>
29 #include <linux/string.h>
30 #include <linux/netdevice.h>
31 #include <linux/init.h>
32 #include <net/p8022.h>
34 #include <asm/byteorder.h>
36 #include <net/llc_frame.h>
40 * All incoming frames pass thru mac_data_indicate().
41 * On entry the llc structure related to the frame is passed as parameter.
42 * The received sk_buffs with pdus other than I_CMD and I_RSP
43 * are freed by mac_data_indicate() after processing,
44 * the I pdu buffers are freed by the cl2llc client when it no longer needs
48 int llc_mac_data_indicate(llcptr lp, struct sk_buff *skb)
50 int ll; /* logical length == 802.3 length field */
59 * Truncate buffer to true 802.3 length
60 * [FIXME: move to 802.2 demux]
63 ll = *(skb->data -2) * 256 + *(skb->data -1);
66 fr = (frameptr) skb->data;
67 type = llc_decode_frametype( fr );
73 * PDU is of the type 2 set
75 if ((lp->llc_mode == MODE_ABM)||(type == SABME_CMD))
76 llc_process_otype2_frame(lp, skb, type);
82 * PDU belongs to type 1 set
84 p_flag = fr->u_hdr.u_pflag;
88 llc_sendpdu(lp, TEST_RSP, 0,ll -3,
92 lp->llc_callbacks|=LLC_TEST_INDICATION;
98 * Basic format XID is handled by LLC itself
99 * Doc 5.4.1.1.2 p 48/49
102 if ((ll == 6)&&(fr->u_hdr.u_info[0] == 0x81))
104 lp->k = fr->u_hdr.u_info[2];
105 llc_sendpdu(lp, XID_RSP,
106 fr->u_hdr.u_pflag, ll -3,
112 if( ll == 6 && fr->u_hdr.u_info[0] == 0x81 )
114 lp->k = fr->u_hdr.u_info[2];
116 lp->llc_callbacks|=LLC_XID_INDICATION;
122 lp->llc_callbacks|=LLC_UI_DATA;
130 * All other type 1 pdus ignored for now
135 if (free&&(!(IS_IFRAME(fr))))
138 * No auto free for I pdus
144 if(lp->llc_callbacks)
146 if ( lp->llc_event != NULL ) lp->llc_event(lp);
154 * Create an LLC client. As it is the job of the caller to clean up
155 * LLC's on device down, the device list must be locked before this call.
158 int register_cl2llc_client(llcptr lp, const char *device, void (*event)(llcptr), u8 *rmac, u8 ssap, u8 dsap)
160 char eye_init[] = "LLC\0";
162 memset(lp, 0, sizeof(*lp));
163 lp->dev = __dev_get_by_name(device);
166 memcpy(lp->eye, eye_init, sizeof(lp->eye));
171 lp->timer_interval[P_TIMER] = HZ; /* 1 sec */
172 lp->timer_interval[REJ_TIMER] = HZ/8;
173 lp->timer_interval[ACK_TIMER] = HZ/8;
174 lp->timer_interval[BUSY_TIMER] = HZ*2;
175 lp->local_sap = ssap;
176 lp->llc_event = event;
177 memcpy(lp->remote_mac, rmac, sizeof(lp->remote_mac));
179 lp->llc_mode = MODE_ADM;
180 lp->remote_sap = dsap;
181 skb_queue_head_init(&lp->atq);
182 skb_queue_head_init(&lp->rtq);
188 void unregister_cl2llc_client(llcptr lp)
190 llc_cancel_timers(lp);
196 EXPORT_SYMBOL(register_cl2llc_client);
197 EXPORT_SYMBOL(unregister_cl2llc_client);
198 EXPORT_SYMBOL(llc_data_request);
199 EXPORT_SYMBOL(llc_unit_data_request);
200 EXPORT_SYMBOL(llc_test_request);
201 EXPORT_SYMBOL(llc_xid_request);
202 EXPORT_SYMBOL(llc_mac_data_indicate);
203 EXPORT_SYMBOL(llc_cancel_timers);
205 #define ALL_TYPES_8022 0
207 static int __init llc_init(void)
209 printk(KERN_NOTICE "IEEE 802.2 LLC for Linux 2.1 (c) 1996 Tim Alpaerts\n");
214 module_init(llc_init);