This source file includes following definitions.
- find_8022tr_client
- p8022tr_rcv
- p8022tr_datalink_header
- p8022tr_proto_init
- register_8022tr_client
- unregister_8022tr_client
1 #include <linux/module.h>
2 #include <linux/netdevice.h>
3 #include <linux/skbuff.h>
4 #include <net/datalink.h>
5 #include <linux/mm.h>
6 #include <linux/in.h>
7 #include <net/p8022tr.h>
8
9 #define SNAP_HEADER_LEN 8
10
11 static struct datalink_proto *p8022tr_list = NULL;
12
13
14
15
16
17
18
19
20 static struct datalink_proto *
21 find_8022tr_client(unsigned char type)
22 {
23 struct datalink_proto *proto;
24
25 for (proto = p8022tr_list;
26 ((proto != NULL) && (*(proto->type) != type));
27 proto = proto->next)
28 ;
29
30 return proto;
31 }
32
33 int
34 p8022tr_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
35 {
36 struct datalink_proto *proto;
37
38 proto = find_8022tr_client(*(skb->h.raw));
39 if (proto != NULL) {
40 skb->h.raw += 3;
41 skb_pull(skb,3);
42 return proto->rcvfunc(skb, dev, pt);
43 }
44
45 skb->sk = NULL;
46 kfree_skb(skb, FREE_READ);
47 return 0;
48 }
49
50 static void
51 p8022tr_datalink_header(struct datalink_proto *dl,
52 struct sk_buff *skb, unsigned char *dest_node)
53 {
54 struct device *dev = skb->dev;
55 unsigned char *rawp;
56 unsigned char *olddata;
57 unsigned char *newdata;
58
59 rawp = skb_push(skb,3);
60 *rawp++ = dl->type[0];
61 *rawp++ = dl->type[0];
62 *rawp = 0x03;
63 dev->hard_header(skb, dev, ETH_P_802_3, dest_node, NULL, skb->len);
64 olddata = skb->data;
65 newdata = skb_pull(skb, SNAP_HEADER_LEN);
66 memmove(newdata, olddata, dev->hard_header_len - SNAP_HEADER_LEN);
67 }
68
69 static struct packet_type p8022tr_packet_type =
70 {
71 0,
72 NULL,
73 p8022tr_rcv,
74 NULL,
75 NULL,
76 };
77
78
79 static struct symbol_table p8022tr_proto_syms = {
80 #include <linux/symtab_begin.h>
81 X(register_8022tr_client),
82 X(unregister_8022tr_client),
83 #include <linux/symtab_end.h>
84 };
85
86 void p8022tr_proto_init(struct net_proto *pro)
87 {
88 p8022tr_packet_type.type=htons(ETH_P_TR_802_2);
89 dev_add_pack(&p8022tr_packet_type);
90 register_symtab(&p8022tr_proto_syms);
91 }
92
93 struct datalink_proto *
94 register_8022tr_client(unsigned char type, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *))
95 {
96 struct datalink_proto *proto;
97
98 if (find_8022tr_client(type) != NULL)
99 return NULL;
100
101 proto = (struct datalink_proto *) kmalloc(sizeof(*proto), GFP_ATOMIC);
102 if (proto != NULL) {
103 proto->type[0] = type;
104 proto->type_len = 1;
105 proto->rcvfunc = rcvfunc;
106 proto->header_length = 3;
107 proto->datalink_header = p8022tr_datalink_header;
108 proto->string_name = "802.2TR";
109 proto->next = p8022tr_list;
110 p8022tr_list = proto;
111 }
112
113 return proto;
114 }
115
116 void unregister_8022tr_client(unsigned char type)
117 {
118 struct datalink_proto *tmp, **clients = &p8022tr_list;
119 unsigned long flags;
120
121 save_flags(flags);
122 cli();
123
124 while ((tmp = *clients) != NULL)
125 {
126 if (tmp->type[0] == type) {
127 *clients = tmp->next;
128 kfree_s(tmp, sizeof(struct datalink_proto));
129 break;
130 } else {
131 clients = &tmp->next;
132 }
133 }
134
135 restore_flags(flags);
136 }
137