1/* 2 * NET3: Support for 802.2 demultiplexing off Ethernet (Token ring 3 * is kept separate see p8022tr.c) 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * 9 * Demultiplex 802.2 encoded protocols. We match the entry by the 10 * SSAP/DSAP pair and then deliver to the registered datalink that 11 * matches. The control byte is ignored and handling of such items 12 * is up to the routine passed the frame. 13 * 14 * Unlike the 802.3 datalink we have a list of 802.2 entries as there 15 * are multiple protocols to demux. The list is currently short (3 or 16 * 4 entries at most). The current demux assumes this. 17 */ 18 19#include <linux/module.h> 20#include <linux/netdevice.h> 21#include <linux/skbuff.h> 22#include <net/datalink.h> 23#include <linux/mm.h> 24#include <linux/in.h> 25#include <linux/init.h> 26#include <net/p8022.h> 27 28static struct datalink_proto *p8022_list = NULL; 29 30/* 31 * We don't handle the loopback SAP stuff, the extended 32 * 802.2 command set, multicast SAP identifiers and non UI 33 * frames. We have the absolute minimum needed for IPX, 34 * IP and Appletalk phase 2. See the llc_* routines for 35 * support libraries if your protocol needs these. 36 */ 37 38static struct datalink_proto *find_8022_client(unsigned char type) 39{ 40 struct datalink_proto *proto; 41 42 for (proto = p8022_list; 43 ((proto != NULL) && (*(proto->type) != type)); 44 proto = proto->next) 45 ; 46 47 return proto; 48} 49 50int p8022_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) 51{ 52 struct datalink_proto *proto; 53 54 proto = find_8022_client(*(skb->h.raw)); 55 if (proto != NULL) 56 { 57 skb->h.raw += 3; 58 skb->nh.raw += 3; 59 skb_pull(skb,3); 60 return proto->rcvfunc(skb, dev, pt); 61 } 62 63 skb->sk = NULL; 64 kfree_skb(skb); 65 return 0; 66} 67 68static void p8022_datalink_header(struct datalink_proto *dl, 69 struct sk_buff *skb, unsigned char *dest_node) 70{ 71 struct net_device *dev = skb->dev; 72 unsigned char *rawp; 73 74 rawp = skb_push(skb,3); 75 *rawp++ = dl->type[0]; 76 *rawp++ = dl->type[0]; 77 *rawp = 0x03; /* UI */ 78 dev->hard_header(skb, dev, ETH_P_802_3, dest_node, NULL, skb->len); 79} 80 81static struct packet_type p8022_packet_type = 82{ 83 0, /* MUTTER ntohs(ETH_P_8022),*/ 84 NULL, /* All devices */ 85 p8022_rcv, 86 NULL, 87 NULL, 88}; 89 90EXPORT_SYMBOL(register_8022_client); 91EXPORT_SYMBOL(unregister_8022_client); 92 93static int __init p8022_init(void) 94{ 95 p8022_packet_type.type=htons(ETH_P_802_2); 96 dev_add_pack(&p8022_packet_type); 97 return 0; 98} 99 100module_init(p8022_init); 101 102struct datalink_proto *register_8022_client(unsigned char type, int (*rcvfunc)(struct sk_buff *, struct net_device *, struct packet_type *)) 103{ 104 struct datalink_proto *proto; 105 106 if (find_8022_client(type) != NULL) 107 return NULL; 108 109 proto = (struct datalink_proto *) kmalloc(sizeof(*proto), GFP_ATOMIC); 110 if (proto != NULL) { 111 proto->type[0] = type; 112 proto->type_len = 1; 113 proto->rcvfunc = rcvfunc; 114 proto->header_length = 3; 115 proto->datalink_header = p8022_datalink_header; 116 proto->string_name = "802.2"; 117 proto->next = p8022_list; 118 p8022_list = proto; 119 } 120 121 return proto; 122} 123 124void unregister_8022_client(unsigned char type) 125{ 126 struct datalink_proto *tmp, **clients = &p8022_list; 127 unsigned long flags; 128 129 save_flags(flags); 130 cli(); 131 132 while ((tmp = *clients) != NULL) 133 { 134 if (tmp->type[0] == type) { 135 *clients = tmp->next; 136 kfree(tmp); 137 break; 138 } else { 139 clients = &tmp->next; 140 } 141 } 142 143 restore_flags(flags); 144} 145