From 17019a2b2a16d8a719bdcd7a3f8aeaf05fdd2974 Mon Sep 17 00:00:00 2001 From: Michael Blizek Date: Tue, 20 Apr 2010 19:51:34 +0200 Subject: [PATCH] various bugfixes --- net/cor/kpacket_parse.c | 46 ++++++++++++++++++++++++++++++++-------------- net/cor/rcv.c | 11 +++++++++-- net/cor/snd.c | 8 ++++++-- 3 files changed, 47 insertions(+), 18 deletions(-) diff --git a/net/cor/kpacket_parse.c b/net/cor/kpacket_parse.c index f3c47ee8116..d5046d4da54 100644 --- a/net/cor/kpacket_parse.c +++ b/net/cor/kpacket_parse.c @@ -87,15 +87,28 @@ static __u16 pull_u16(struct sk_buff *skb, int convbo) return *ptr; } */ +static void discard_speed(struct neighbor *nb, struct sk_buff *skb) +{ + pull_u32(skb, 1); /* speed */ +} + #warning todo static void parse_speed(struct neighbor *nb, struct sk_buff *skb, - __u8 code, struct conn *rconn) + struct conn *rconn) { __u16 speed = pull_u32(skb, 1); } +static void discard_conn_success(struct neighbor *nb, struct sk_buff *skb) +{ + __u32 conn_id = pull_u32(skb, 1); + struct control_msg_out *cm = alloc_control_msg(); + if (cm != 0) + send_reset_conn(cm, nb, conn_id); +} + static void parse_conn_success(struct neighbor *nb, struct sk_buff *skb, - __u8 code, struct conn *rconn) + struct conn *rconn) { struct conn *sconn = rconn->reversedir; @@ -119,7 +132,7 @@ static void parse_conn_success(struct neighbor *nb, struct sk_buff *skb, } static void parse_reset(struct neighbor *nb, struct sk_buff *skb, - __u8 code, struct conn *rconn) + struct conn *rconn) { atomic_cmpxchg(&(rconn->reversedir->isreset), 0, 1); reset_conn(rconn); @@ -127,23 +140,28 @@ static void parse_reset(struct neighbor *nb, struct sk_buff *skb, static void conn_cmd(struct neighbor *nb, struct sk_buff *skb, __u8 code, void (*parsefunc)(struct neighbor *nb, struct sk_buff *skb, - __u8 code, struct conn *rconn)) + struct conn *rconn), void (*readdiscardfunc)( + struct neighbor *nb, struct sk_buff *skb)) { __u32 conn_id = pull_u32(skb, 1); struct conn *rconn = get_conn(conn_id); if (unlikely(rconn == 0)) - return; + goto err; BUG_ON(SOURCE_IN != rconn->sourcetype); BUG_ON(0 == rconn->reversedir); if (unlikely(rconn->source.in.nb != nb)) - goto out; + goto err; - parsefunc(nb, skb, code, rconn); -out: - kref_put(&(rconn->ref), free_conn); + parsefunc(nb, skb, rconn); + if (0) { +err: + readdiscardfunc(nb, skb); + } + if (rconn != 0) + kref_put(&(rconn->ref), free_conn); } static void parse_conndata(struct neighbor *nb, struct sk_buff *skb) @@ -184,7 +202,6 @@ static void parse_connect(struct neighbor *nb, struct sk_buff *skb) err: send_reset_conn(cm, nb, conn_id); } - kref_put(&(nb->ref), neighbor_free); } static void kernel_packet2(struct neighbor *nb, struct sk_buff *skb, @@ -211,7 +228,7 @@ static void kernel_packet2(struct neighbor *nb, struct sk_buff *skb, break; code = *codeptr; - + switch (code) { case KP_PADDING: break; @@ -236,7 +253,7 @@ static void kernel_packet2(struct neighbor *nb, struct sk_buff *skb, ack = 1; break; case KP_SPEED: - conn_cmd(nb, skb, code, parse_speed); + conn_cmd(nb, skb, code, parse_speed, discard_speed); ack = 1; break; case KP_CONNECT: @@ -244,7 +261,8 @@ static void kernel_packet2(struct neighbor *nb, struct sk_buff *skb, ack = 1; break; case KP_CONNECT_SUCCESS: - conn_cmd(nb, skb, code, parse_conn_success); + conn_cmd(nb, skb, code, parse_conn_success, + discard_conn_success); ack = 1; break; case KP_CONN_DATA: @@ -252,7 +270,7 @@ static void kernel_packet2(struct neighbor *nb, struct sk_buff *skb, ack = 1; break; case KP_RESET_CONN: - conn_cmd(nb, skb, code, parse_reset); + conn_cmd(nb, skb, code, parse_reset, 0); ack = 1; break; default: diff --git a/net/cor/rcv.c b/net/cor/rcv.c index 60a5e119e8c..75f1e9fd021 100644 --- a/net/cor/rcv.c +++ b/net/cor/rcv.c @@ -260,6 +260,10 @@ static int queue_rcv_processing(struct sk_buff *skb, struct net_device *dev, struct skb_procstate *ps = skb_pstate(skb); long queuelen; + if (skb->pkt_type == PACKET_OTHERHOST) + goto drop; + + BUG_ON(skb->next != 0); queuelen = atomic_inc_return(&packets_in_workqueue); @@ -268,13 +272,16 @@ static int queue_rcv_processing(struct sk_buff *skb, struct net_device *dev, if (queuelen > MAX_PACKETS_IN_RCVQUEUE) { atomic_dec(&packets_in_workqueue); - kfree_skb(skb); - return NET_RX_DROP; + goto drop; } INIT_WORK(&(ps->funcstate.rcv.work), rcv); queue_work(packet_wq, &(ps->funcstate.rcv.work)); return NET_RX_SUCCESS; + +drop: + kfree_skb(skb); + return NET_RX_DROP; } static struct packet_type ptype_cor = { diff --git a/net/cor/snd.c b/net/cor/snd.c index 8a02da78c93..ae13d103e07 100644 --- a/net/cor/snd.c +++ b/net/cor/snd.c @@ -178,7 +178,11 @@ void retransmit_timerfunc(unsigned long arg) struct sk_buff *skb = 0; unsigned long timeout; - int state = get_neigh_state(nb); + int nbstate; + + spin_lock_irqsave( &(nb->state_lock), iflags ); + nbstate = nb->state; + spin_unlock_irqrestore( &(nb->state_lock), iflags ); while (1) { spin_lock_irqsave( &(nb->retrans_lock), iflags ); @@ -187,7 +191,7 @@ void retransmit_timerfunc(unsigned long arg) if (0 == skb) goto out; - if (state == NEIGHBOR_STATE_KILLED) { + if (nbstate == NEIGHBOR_STATE_KILLED) { struct skb_procstate *ps = skb_pstate(skb); spin_unlock_irqrestore( &(nb->retrans_lock), iflags ); kref_put(&(ps->funcstate.retransmit_queue.nb->ref), -- 2.11.4.GIT