double send_reset race, free_ack_conns on reset, lock both conn sides on reset, skip...
[cor_2_6_31.git] / net / cor / kpacket_parse.c
blob825d6f56e1dfcbc316969bf1249a930c9e3a0201
1 /**
2 * Connection oriented routing
3 * Copyright (C) 2007-2011 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 /*static __u64 pull_u64(struct sk_buff *skb, int convbo)
27 char *ptr = cor_pull_skb(skb, 8);
29 __u64 ret = 0;
31 BUG_ON(0 == ptr);
33 ((char *)&ret)[0] = ptr[0];
34 ((char *)&ret)[1] = ptr[1];
35 ((char *)&ret)[2] = ptr[2];
36 ((char *)&ret)[3] = ptr[3];
37 ((char *)&ret)[4] = ptr[4];
38 ((char *)&ret)[5] = ptr[5];
39 ((char *)&ret)[6] = ptr[6];
40 ((char *)&ret)[7] = ptr[7];
42 if (convbo)
43 return be64_to_cpu(ret);
44 return ret;
45 }*/
47 static __u32 pull_u32(struct sk_buff *skb, int convbo)
49 char *ptr = cor_pull_skb(skb, 4);
51 __u32 ret = 0;
53 BUG_ON(0 == ptr);
55 ((char *)&ret)[0] = ptr[0];
56 ((char *)&ret)[1] = ptr[1];
57 ((char *)&ret)[2] = ptr[2];
58 ((char *)&ret)[3] = ptr[3];
60 if (convbo)
61 return be32_to_cpu(ret);
62 return ret;
65 static __u16 pull_u16(struct sk_buff *skb, int convbo)
67 char *ptr = cor_pull_skb(skb, 2);
69 __u16 ret = 0;
71 BUG_ON(0 == ptr);
73 ((char *)&ret)[0] = ptr[0];
74 ((char *)&ret)[1] = ptr[1];
76 if (convbo)
77 return be16_to_cpu(ret);
78 return ret;
81 static __u8 pull_u8(struct sk_buff *skb)
83 char *ptr = cor_pull_skb(skb, 1);
84 BUG_ON(0 == ptr);
85 return *ptr;
88 static void parse_ack_conn(struct neighbor *nb, struct sk_buff *skb)
90 __u32 conn_id = pull_u32(skb, 1);
91 __u8 flags = pull_u8(skb);
93 struct conn *src_in = get_conn(conn_id);
95 if ((flags & KP_ACK_CONN_FLAGS_SEQNO) != 0) {
96 __u32 seqno = pull_u32(skb, 1);
97 int setwindow = 0;
98 __u8 window = 0;
100 if ((flags & KP_ACK_CONN_FLAGS_WINDOW) != 0) {
101 setwindow = 1;
102 window = pull_u8(skb);
105 if (likely(src_in != 0))
106 conn_ack_rcvd(nb, conn_id, src_in->reversedir, seqno,
107 setwindow, window);
110 if (ooolen(flags) != 0) {
111 __u32 seqno_ooo = pull_u32(skb, 1);
112 __u32 ooo_len;
114 if (ooolen(flags) == 1) {
115 ooo_len = pull_u8(skb);
116 } else if (ooolen(flags) == 2) {
117 ooo_len = pull_u16(skb, 1);
118 } else if (ooolen(flags) == 4) {
119 ooo_len = pull_u32(skb, 1);
120 } else {
121 BUG();
124 if (likely(src_in != 0))
125 conn_ack_ooo_rcvd(nb, conn_id, src_in->reversedir,
126 seqno_ooo, ooo_len);
129 if (flags & KP_ACK_CONN_FLAGS_CREDITS) {
130 __u16 value = pull_u16(skb, 1);
132 __u8 seqno = value >> 10;
133 __u16 decaytime = value & 1023;
135 BUG_ON(seqno >= 64);
136 BUG_ON(decaytime >= 1024);
138 if (likely(src_in != 0))
139 set_conn_in_decaytime(nb, conn_id, src_in, seqno,
140 decaytime);
143 if (unlikely(src_in == 0)) {
144 send_connid_unknown(nb, conn_id);
145 return;
148 mutex_lock(&(src_in->rcv_lock));
150 if (unlikely(is_conn_in(src_in, nb, conn_id) == 0)) {
151 send_connid_unknown(nb, conn_id);
152 } else {
153 set_last_act(src_in);
156 mutex_unlock(&(src_in->rcv_lock));
158 kref_put(&(src_in->ref), free_conn);
161 static void parse_connect(struct neighbor *nb, struct sk_buff *skb)
163 struct conn *src_in;
164 __u32 conn_id = pull_u32(skb, 1);
165 __u32 init_seqno = pull_u32(skb, 1);
166 __u8 window = pull_u8(skb);
167 __u16 credits = pull_u16(skb, 1);
168 __u8 credits_seqno = credits >> 10;
169 __u16 decaytime = credits & 1023;
170 struct control_msg_out *cm = alloc_control_msg(nb, ACM_PRIORITY_MED);
171 __u32 gen_conn_id;
172 __u32 gen_seqno;
174 if (unlikely(cm == 0))
175 goto err;
177 #warning todo use credits for conn alloclimit
178 src_in = alloc_conn(GFP_KERNEL);
180 if (unlikely(src_in == 0))
181 goto err;
183 src_in->is_client = 1;
185 mutex_lock(&(src_in->rcv_lock));
186 mutex_lock(&(src_in->reversedir->rcv_lock));
187 if (unlikely(conn_init_out(src_in->reversedir, nb))) {
188 mutex_unlock(&(src_in->reversedir->rcv_lock));
189 mutex_unlock(&(src_in->rcv_lock));
190 kref_put(&(src_in->reversedir->ref), free_conn);
191 kref_put(&(src_in->ref), free_conn);
192 goto err;
195 gen_conn_id = src_in->source.in.conn_id;
196 gen_seqno = src_in->source.in.next_seqno;
198 src_in->reversedir->target.out.conn_id = conn_id;
200 src_in->reversedir->target.out.seqno_nextsend = init_seqno;
201 src_in->reversedir->target.out.seqno_acked = init_seqno;
202 reset_seqno(src_in->reversedir, init_seqno);
204 src_in->reversedir->target.out.seqno_windowlimit =
205 src_in->reversedir->target.out.seqno_nextsend +
206 dec_log_64_11(window);
207 insert_reverse_connid(src_in->reversedir);
208 mutex_unlock(&(src_in->reversedir->rcv_lock));
209 mutex_unlock(&(src_in->rcv_lock));
211 BUG_ON(credits_seqno >= 64);
212 BUG_ON(decaytime >= 1024);
213 set_conn_in_decaytime(nb, gen_conn_id, src_in, credits_seqno,
214 decaytime);
216 send_connect_success(cm, conn_id, gen_conn_id, gen_seqno, src_in);
218 if (0) {
219 err:
220 if (cm != 0) {
221 free_control_msg(cm);
223 send_reset_conn(nb, conn_id, 0, 0);
227 static void parse_conn_success(struct neighbor *nb, struct sk_buff *skb)
229 __u32 conn_id1 = pull_u32(skb, 1);
230 __u32 conn_id2 = pull_u32(skb, 1);
231 __u32 init_seqno = pull_u32(skb, 1);
232 __u8 window = pull_u8(skb);
233 __u16 credits = pull_u16(skb, 1);
235 __u8 credits_seqno = credits >> 10;
236 __u16 decaytime = credits & 1023;
238 int set = 0;
240 struct conn *src_in = get_conn(conn_id1);
242 if (unlikely(src_in == 0))
243 goto err;
245 if (unlikely(src_in->is_client != 0))
246 goto err;
249 mutex_lock(&(src_in->reversedir->rcv_lock));
250 mutex_lock(&(src_in->rcv_lock));
252 if (unlikely(is_conn_in(src_in, nb, conn_id1) == 0))
253 goto err_unlock;
255 if (unlikely(unlikely(src_in->reversedir->targettype != TARGET_OUT) ||
256 unlikely(src_in->reversedir->target.out.nb != nb) ||
257 unlikely(src_in->reversedir->target.out.conn_id != 0 &&
258 src_in->reversedir->target.out.conn_id != conn_id2)))
259 goto err_unlock;
261 if (unlikely(src_in->reversedir->isreset != 0))
262 goto err_unlock;
264 set_last_act(src_in);
266 if (likely(src_in->reversedir->target.out.conn_id == 0)) {
267 src_in->reversedir->target.out.conn_id = conn_id2;
268 src_in->reversedir->target.out.seqno_nextsend = init_seqno;
269 src_in->reversedir->target.out.seqno_acked = init_seqno;
270 src_in->reversedir->target.out.decaytime_send_allowed = 1;
271 reset_seqno(src_in->reversedir, init_seqno);
273 src_in->reversedir->target.out.seqno_windowlimit =
274 src_in->reversedir->target.out.seqno_nextsend +
275 dec_log_64_11(window);
277 insert_reverse_connid(src_in->reversedir);
279 set = 1;
282 mutex_unlock(&(src_in->reversedir->rcv_lock));
283 mutex_unlock(&(src_in->rcv_lock));
285 BUG_ON(credits_seqno >= 64);
286 BUG_ON(decaytime >= 1024);
287 if (set)
288 set_conn_in_decaytime(nb, conn_id1, src_in, credits_seqno,
289 decaytime);
291 flush_buf(src_in->reversedir);
293 if (0) {
294 err_unlock:
295 mutex_unlock(&(src_in->reversedir->rcv_lock));
296 mutex_unlock(&(src_in->rcv_lock));
297 err:
298 send_reset_conn(nb, conn_id2, conn_id1, 0);
301 if (likely(src_in != 0))
302 kref_put(&(src_in->ref), free_conn);
305 static void parse_conndata(struct neighbor *nb, struct sk_buff *skb)
307 __u32 conn_id = pull_u32(skb, 1);
308 __u32 seqno = pull_u32(skb, 1);
309 __u16 datalength = pull_u16(skb, 1);
310 char *data = cor_pull_skb(skb, datalength);
312 BUG_ON(data == 0);
314 conn_rcv_buildskb(nb, data, datalength, conn_id, seqno);
317 static void parse_reset(struct neighbor *nb, struct sk_buff *skb)
319 __u32 conn_id = pull_u32(skb, 1);
321 int send;
323 struct conn *src_in = get_conn(conn_id);
324 if (src_in == 0)
325 return;
327 if (src_in->is_client) {
328 mutex_lock(&(src_in->rcv_lock));
329 mutex_lock(&(src_in->reversedir->rcv_lock));
330 } else {
331 mutex_lock(&(src_in->reversedir->rcv_lock));
332 mutex_lock(&(src_in->rcv_lock));
335 send = unlikely(is_conn_in(src_in, nb, conn_id));
336 if (send && src_in->reversedir->isreset == 0)
337 src_in->reversedir->isreset = 1;
339 if (src_in->is_client) {
340 mutex_unlock(&(src_in->rcv_lock));
341 mutex_unlock(&(src_in->reversedir->rcv_lock));
342 } else {
343 mutex_unlock(&(src_in->reversedir->rcv_lock));
344 mutex_unlock(&(src_in->rcv_lock));
347 if (send)
348 reset_conn(src_in);
350 kref_put(&(src_in->ref), free_conn);
353 static void parse_connid_unknown(struct neighbor *nb, struct sk_buff *skb)
355 __u32 conn_id = pull_u32(skb, 1);
356 struct conn *trgt_out = get_conn_reverse(nb, conn_id);
357 if (trgt_out == 0)
358 return;
360 mutex_lock(&(trgt_out->rcv_lock));
362 if (unlikely(trgt_out->targettype != TARGET_OUT))
363 goto err;
364 if (unlikely((trgt_out->target.out.nb != nb)))
365 goto err;
366 if (unlikely((trgt_out->target.out.conn_id != conn_id)))
367 goto err;
369 if (trgt_out->isreset == 0)
370 trgt_out->isreset = 1;
372 mutex_unlock(&(trgt_out->rcv_lock));
374 reset_conn(trgt_out);
376 if (0) {
377 err:
378 mutex_unlock(&(trgt_out->rcv_lock));
380 kref_put(&(trgt_out->ref), free_conn);
383 static void kernel_packet2(struct neighbor *nb, struct sk_buff *skb,
384 __u32 seqno1)
386 int ack = 0;
388 while (1) {
389 __u32 seqno2;
391 __u32 cookie;
392 __u32 respdelay;
394 __u32 max_cmsg_dly;
396 __u8 *codeptr = cor_pull_skb(skb, 1);
397 __u8 code;
399 if (codeptr == 0)
400 break;
402 code = *codeptr;
404 switch (code) {
405 case KP_PADDING:
406 break;
407 case KP_PING:
408 cookie = pull_u32(skb, 0);
409 send_pong(nb, cookie);
410 break;
411 case KP_PONG:
412 cookie = pull_u32(skb, 0);
413 respdelay = pull_u32(skb, 1);
414 ping_resp(nb, cookie, respdelay);
415 ack = 1;
416 break;
417 case KP_ACK:
418 seqno2 = pull_u32(skb, 1);
419 kern_ack_rcvd(nb, seqno2);
420 break;
421 case KP_ACK_CONN:
422 parse_ack_conn(nb, skb);
423 ack = 1;
424 break;
425 case KP_CONNECT:
426 parse_connect(nb, skb);
427 ack = 1;
428 break;
429 case KP_CONNECT_SUCCESS:
430 parse_conn_success(nb, skb);
431 ack = 1;
432 break;
433 case KP_CONN_DATA:
434 parse_conndata(nb, skb);
435 break;
436 case KP_RESET_CONN:
437 parse_reset(nb, skb);
438 ack = 1;
439 break;
440 case KP_CONNID_UNKNOWN:
441 parse_connid_unknown(nb, skb);
442 ack = 1;
443 break;
444 case KP_SET_MAX_CMSG_DELAY:
445 max_cmsg_dly = pull_u32(skb, 1);
446 if (((__u64) max_cmsg_dly) * 1000 > ((__u64)
447 (max_cmsg_dly * 1000)))
448 max_cmsg_dly = 400000000;
449 else
450 max_cmsg_dly *= 100;
451 atomic_set(&(nb->max_remote_cmsg_delay), max_cmsg_dly);
452 ack = 1;
453 break;
454 default:
455 BUG();
459 if (ack)
460 send_ack(nb, seqno1);
463 void kernel_packet(struct neighbor *nb, struct sk_buff *skb, __u32 seqno)
465 struct sk_buff *skb2 = skb_clone(skb, __GFP_DMA | GFP_KERNEL);
467 while (1) {
468 __u8 *codeptr = cor_pull_skb(skb2, 1);
469 __u8 code;
470 __u8 *flags;
472 char *lengthptr;
473 __u32 length;
475 if (codeptr == 0)
476 break;
477 code = *codeptr;
479 switch (code) {
480 case KP_PADDING:
481 break;
482 case KP_PING:
483 if (cor_pull_skb(skb2, 4) == 0)
484 goto discard;
485 break;
486 case KP_PONG:
487 if (cor_pull_skb(skb2, 8) == 0)
488 goto discard;
489 break;
490 case KP_ACK:
491 if (cor_pull_skb(skb2, 4) == 0)
492 goto discard;
493 break;
494 case KP_ACK_CONN:
495 if (cor_pull_skb(skb2, 4) == 0)
496 goto discard;
497 flags = cor_pull_skb(skb2, 1);
498 if (flags == 0)
499 goto discard;
500 if (cor_pull_skb(skb2, ack_conn_len(*flags)) == 0)
501 goto discard;
502 break;
503 case KP_CONNECT:
504 if (cor_pull_skb(skb2, 11) == 0)
505 goto discard;
506 break;
507 case KP_CONNECT_SUCCESS:
508 if (cor_pull_skb(skb2, 15) == 0)
509 goto discard;
510 break;
511 case KP_CONN_DATA:
512 if (cor_pull_skb(skb2, 8) == 0)
513 goto discard;
514 lengthptr = cor_pull_skb(skb2, 2);
515 if (lengthptr == 0)
516 goto discard;
517 length = ntohs(*((__u16 *)lengthptr));
518 if (cor_pull_skb(skb2, length) == 0)
519 goto discard;
520 break;
521 case KP_RESET_CONN:
522 case KP_CONNID_UNKNOWN:
523 if (cor_pull_skb(skb2, 4) == 0)
524 goto discard;
525 break;
526 case KP_SET_MAX_CMSG_DELAY:
527 if (cor_pull_skb(skb2, 4) == 0)
528 goto discard;
529 break;
530 default:
531 goto discard;
534 kfree_skb(skb2);
535 kernel_packet2(nb, skb, seqno);
536 kfree_skb(skb);
537 return;
538 discard:
539 kfree_skb(skb2);
540 kfree_skb(skb);
543 MODULE_LICENSE("GPL");