neighbor free after disconnect
[cor_2_6_31.git] / net / cor / kpacket_parse.c
blob43e6c22e1ee5ab5c7ad2bfdef8d33ba04fe849bd
1 /*
2 * Connection oriented routing
3 * Copyright (C) 2007-2008 Michael Blizek
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA.
21 #include <asm/byteorder.h>
23 #include "cor.h"
25 /* not used, avoid compiler warning
26 * static __u64 pull_u64(struct sk_buff *skb, int convbo)
28 char *ptr = cor_pull_skb(skb, 8);
30 __u64 ret = 0;
32 BUG_ON(0 == ptr);
34 ((char *)&ret)[0] = ptr[0];
35 ((char *)&ret)[1] = ptr[1];
36 ((char *)&ret)[2] = ptr[2];
37 ((char *)&ret)[3] = ptr[3];
38 ((char *)&ret)[4] = ptr[4];
39 ((char *)&ret)[5] = ptr[5];
40 ((char *)&ret)[6] = ptr[6];
41 ((char *)&ret)[7] = ptr[7];
43 if (convbo)
44 return be64_to_cpu(ret);
45 return ret;
46 } */
48 static __u32 pull_u32(struct sk_buff *skb, int convbo)
50 char *ptr = cor_pull_skb(skb, 4);
52 __u32 ret = 0;
54 BUG_ON(0 == ptr);
56 ((char *)&ret)[0] = ptr[0];
57 ((char *)&ret)[1] = ptr[1];
58 ((char *)&ret)[2] = ptr[2];
59 ((char *)&ret)[3] = ptr[3];
61 if (convbo)
62 return be32_to_cpu(ret);
63 return ret;
66 static __u16 pull_u16(struct sk_buff *skb, int convbo)
68 char *ptr = cor_pull_skb(skb, 2);
70 __u16 ret = 0;
72 BUG_ON(0 == ptr);
74 ((char *)&ret)[0] = ptr[0];
75 ((char *)&ret)[1] = ptr[1];
77 if (convbo)
78 return be16_to_cpu(ret);
79 return ret;
82 /* not used, avoid compiler warning
83 * static __u8 pull_u8(struct sk_buff *skb)
85 char *ptr = cor_pull_skb(skb, 1);
86 BUG_ON(0 == ptr);
87 return *ptr;
88 } */
90 #warning todo
91 static void parse_speed(struct neighbor *nb, struct sk_buff *skb,
92 __u8 code, struct conn *rconn)
94 __u16 speed = pull_u32(skb, 1);
97 static void parse_conn_success(struct neighbor *nb, struct sk_buff *skb,
98 __u8 code, struct conn *rconn)
100 struct conn *sconn = rconn->reversedir;
102 __u32 conn_id = pull_u32(skb, 1);
104 BUG_ON(sconn == 0);
106 if (unlikely(unlikely(sconn->targettype != TARGET_OUT) ||
107 unlikely(sconn->target.out.nb != nb) ||
108 unlikely(sconn->target.out.conn_id != 0))) {
109 struct control_msg_out *cm = alloc_control_msg();
110 if (likely(cm != 0))
111 send_reset_conn(cm, nb, conn_id);
112 return;
115 mutex_lock(&(sconn->rcv_lock));
116 sconn->target.out.conn_id = conn_id;
117 flush_out(sconn);
118 mutex_unlock(&(sconn->rcv_lock));
121 static void parse_reset(struct neighbor *nb, struct sk_buff *skb,
122 __u8 code, struct conn *rconn)
124 rconn->reversedir->isreset = 1;
125 reset_conn(rconn);
128 static void conn_cmd(struct neighbor *nb, struct sk_buff *skb, __u8 code,
129 void (*parsefunc)(struct neighbor *nb, struct sk_buff *skb,
130 __u8 code, struct conn *rconn))
132 __u32 conn_id = pull_u32(skb, 1);
133 struct conn *rconn = get_conn(conn_id);
135 if (unlikely(rconn == 0))
136 return;
138 BUG_ON(SOURCE_IN != rconn->sourcetype);
139 BUG_ON(0 == rconn->reversedir);
141 if (unlikely(rconn->source.in.nb != nb))
142 return;
144 parsefunc(nb, skb, code, rconn);
147 static void parse_conndata(struct neighbor *nb, struct sk_buff *skb)
149 __u32 conn_id = pull_u32(skb, 1);
150 __u32 seqno = pull_u32(skb, 1);
151 __u16 datalength = pull_u16(skb, 1);
152 char *data = cor_pull_skb(skb, datalength);
154 BUG_ON(data == 0);
156 conn_rcv_buildskb(data, datalength, conn_id, seqno);
159 static void parse_connect(struct neighbor *nb, struct sk_buff *skb)
161 struct conn *rconn;
162 __u32 conn_id = pull_u32(skb, 1);
163 struct control_msg_out *cm = alloc_control_msg();
165 if (unlikely(cm == 0))
166 return;
168 rconn = alloc_conn(GFP_KERNEL);
170 if (unlikely(rconn == 0))
171 goto err;
173 if (conn_init_out(rconn->reversedir, nb))
174 goto err;
176 rconn->reversedir->target.out.conn_id = conn_id;
178 send_connect_success(cm, nb, rconn->reversedir->target.out.conn_id,
179 rconn->source.in.conn_id);
181 if (0) {
182 err:
183 send_reset_conn(cm, nb, conn_id);
187 static void kernel_packet2(struct neighbor *nb, struct sk_buff *skb,
188 __u32 seqno)
190 struct control_msg_out *cm = alloc_control_msg();
191 int ack = 0;
193 if (unlikely(cm == 0))
194 return;
196 while (1) {
197 struct control_msg_out *cm_tmp;
198 __u32 cookie;
199 __u32 respdelay;
201 __u32 conn_id;
202 __u32 seqno;
204 __u8 *codeptr = cor_pull_skb(skb, 1);
205 __u8 code;
207 if (codeptr == 0)
208 break;
210 code = *codeptr;
212 switch (code) {
213 case KP_PADDING:
214 break;
215 case KP_PING:
216 cookie = pull_u32(skb, 0);
217 cm_tmp = alloc_control_msg();
218 if (likely(cm != 0)) {
219 send_pong(cm_tmp, nb, cookie);
221 break;
222 case KP_PONG:
223 cookie = pull_u32(skb, 0);
224 respdelay = pull_u32(skb, 1);
225 ping_resp(nb, cookie, respdelay);
226 ack = 1;
227 break;
228 case KP_ACK:
229 conn_id = pull_u32(skb, 1);
230 seqno = pull_u32(skb, 1);
231 ack_received(nb, conn_id, seqno);
232 if (conn_id != 0)
233 ack = 1;
234 break;
235 case KP_SPEED:
236 conn_cmd(nb, skb, code, parse_speed);
237 ack = 1;
238 break;
239 case KP_CONNECT:
240 parse_connect(nb, skb);
241 ack = 1;
242 break;
243 case KP_CONNECT_SUCCESS:
244 conn_cmd(nb, skb, code, parse_conn_success);
245 ack = 1;
246 break;
247 case KP_CONN_DATA:
248 parse_conndata(nb, skb);
249 ack = 1;
250 break;
251 case KP_RESET_CONN:
252 conn_cmd(nb, skb, code, parse_reset);
253 ack = 1;
254 break;
255 default:
256 BUG();
260 if (ack)
261 send_ack(cm, nb, 0, seqno);
262 else
263 free_control_msg(cm);
266 void kernel_packet(struct neighbor *nb, struct sk_buff *skb, __u32 seqno)
268 struct sk_buff *skb2 = skb_clone(skb, __GFP_DMA | GFP_KERNEL);
270 while (1) {
271 __u8 *codeptr = cor_pull_skb(skb2, 1);
272 __u8 code;
274 char *lengthptr;
275 __u32 length;
277 if (codeptr == 0)
278 break;
279 code = *codeptr;
281 switch (code) {
282 case KP_PADDING:
283 break;
284 case KP_PING:
285 if (cor_pull_skb(skb2, 4) == 0)
286 goto discard;
287 break;
288 case KP_PONG:
289 if (cor_pull_skb(skb2, 8) == 0)
290 goto discard;
291 break;
292 case KP_ACK:
293 if (cor_pull_skb(skb2, 8) == 0)
294 goto discard;
295 break;
296 case KP_SPEED:
297 if (cor_pull_skb(skb2, 6) == 0)
298 goto discard;
299 break;
300 case KP_CONNECT:
301 if (cor_pull_skb(skb2, 4) == 0)
302 goto discard;
303 break;
304 case KP_CONNECT_SUCCESS:
305 if (cor_pull_skb(skb2, 8) == 0)
306 goto discard;
307 break;
308 case KP_CONN_DATA:
309 if (cor_pull_skb(skb2, 8) == 0)
310 goto discard;
311 lengthptr = cor_pull_skb(skb2, 2);
312 if (lengthptr == 0)
313 goto discard;
314 length = ntohs(*((__u16 *)lengthptr));
315 if (cor_pull_skb(skb2, length) == 0)
316 goto discard;
317 break;
318 case KP_RESET_CONN:
319 if (cor_pull_skb(skb2, 4) == 0)
320 goto discard;
321 break;
322 default:
323 goto discard;
326 kfree_skb(skb2);
327 kernel_packet2(nb, skb, seqno);
328 kfree_skb(skb);
329 return;
330 discard:
331 kfree_skb(skb2);
332 kfree_skb(skb);