diff options
-rw-r--r-- | net/tipc/msg.c | 42 | ||||
-rw-r--r-- | net/tipc/msg.h | 9 | ||||
-rw-r--r-- | net/tipc/socket.c | 40 |
3 files changed, 48 insertions, 43 deletions
diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 940d74197b8c..697223a21240 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c | |||
@@ -411,43 +411,43 @@ bool tipc_msg_reverse(u32 own_addr, struct sk_buff *buf, u32 *dnode, | |||
411 | return true; | 411 | return true; |
412 | exit: | 412 | exit: |
413 | kfree_skb(buf); | 413 | kfree_skb(buf); |
414 | *dnode = 0; | ||
414 | return false; | 415 | return false; |
415 | } | 416 | } |
416 | 417 | ||
417 | /** | 418 | /** |
418 | * tipc_msg_eval: determine fate of message that found no destination | 419 | * tipc_msg_lookup_dest(): try to find new destination for named message |
419 | * @buf: the buffer containing the message. | 420 | * @skb: the buffer containing the message. |
420 | * @dnode: return value: next-hop node, if message to be forwarded | 421 | * @dnode: return value: next-hop node, if destination found |
421 | * @err: error code to use, if message to be rejected | 422 | * @err: return value: error code to use, if message to be rejected |
422 | * | ||
423 | * Does not consume buffer | 423 | * Does not consume buffer |
424 | * Returns 0 (TIPC_OK) if message ok and we can try again, -TIPC error | 424 | * Returns true if a destination is found, false otherwise |
425 | * code if message to be rejected | ||
426 | */ | 425 | */ |
427 | int tipc_msg_eval(struct net *net, struct sk_buff *buf, u32 *dnode) | 426 | bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, |
427 | u32 *dnode, int *err) | ||
428 | { | 428 | { |
429 | struct tipc_msg *msg = buf_msg(buf); | 429 | struct tipc_msg *msg = buf_msg(skb); |
430 | u32 dport; | 430 | u32 dport; |
431 | 431 | ||
432 | if (msg_type(msg) != TIPC_NAMED_MSG) | 432 | if (!msg_isdata(msg)) |
433 | return -TIPC_ERR_NO_PORT; | 433 | return false; |
434 | if (skb_linearize(buf)) | 434 | if (!msg_named(msg)) |
435 | return -TIPC_ERR_NO_NAME; | 435 | return false; |
436 | if (msg_data_sz(msg) > MAX_FORWARD_SIZE) | 436 | *err = -TIPC_ERR_NO_NAME; |
437 | return -TIPC_ERR_NO_NAME; | 437 | if (skb_linearize(skb)) |
438 | return false; | ||
438 | if (msg_reroute_cnt(msg) > 0) | 439 | if (msg_reroute_cnt(msg) > 0) |
439 | return -TIPC_ERR_NO_NAME; | 440 | return false; |
440 | |||
441 | *dnode = addr_domain(net, msg_lookup_scope(msg)); | 441 | *dnode = addr_domain(net, msg_lookup_scope(msg)); |
442 | dport = tipc_nametbl_translate(net, msg_nametype(msg), | 442 | dport = tipc_nametbl_translate(net, msg_nametype(msg), |
443 | msg_nameinst(msg), | 443 | msg_nameinst(msg), dnode); |
444 | dnode); | ||
445 | if (!dport) | 444 | if (!dport) |
446 | return -TIPC_ERR_NO_NAME; | 445 | return false; |
447 | msg_incr_reroute_cnt(msg); | 446 | msg_incr_reroute_cnt(msg); |
448 | msg_set_destnode(msg, *dnode); | 447 | msg_set_destnode(msg, *dnode); |
449 | msg_set_destport(msg, dport); | 448 | msg_set_destport(msg, dport); |
450 | return TIPC_OK; | 449 | *err = TIPC_OK; |
450 | return true; | ||
451 | } | 451 | } |
452 | 452 | ||
453 | /* tipc_msg_reassemble() - clone a buffer chain of fragments and | 453 | /* tipc_msg_reassemble() - clone a buffer chain of fragments and |
diff --git a/net/tipc/msg.h b/net/tipc/msg.h index f7ea95458c6f..60702992933d 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h | |||
@@ -750,18 +750,19 @@ static inline u32 msg_tot_origport(struct tipc_msg *m) | |||
750 | struct sk_buff *tipc_buf_acquire(u32 size); | 750 | struct sk_buff *tipc_buf_acquire(u32 size); |
751 | bool tipc_msg_reverse(u32 own_addr, struct sk_buff *buf, u32 *dnode, | 751 | bool tipc_msg_reverse(u32 own_addr, struct sk_buff *buf, u32 *dnode, |
752 | int err); | 752 | int err); |
753 | int tipc_msg_eval(struct net *net, struct sk_buff *buf, u32 *dnode); | ||
754 | void tipc_msg_init(u32 own_addr, struct tipc_msg *m, u32 user, u32 type, | 753 | void tipc_msg_init(u32 own_addr, struct tipc_msg *m, u32 user, u32 type, |
755 | u32 hsize, u32 destnode); | 754 | u32 hsize, u32 destnode); |
756 | struct sk_buff *tipc_msg_create(uint user, uint type, | 755 | struct sk_buff *tipc_msg_create(uint user, uint type, uint hdr_sz, |
757 | uint hdr_sz, uint data_sz, u32 dnode, | 756 | uint data_sz, u32 dnode, u32 onode, |
758 | u32 onode, u32 dport, u32 oport, int errcode); | 757 | u32 dport, u32 oport, int errcode); |
759 | int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf); | 758 | int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf); |
760 | bool tipc_msg_bundle(struct sk_buff_head *list, struct sk_buff *skb, u32 mtu); | 759 | bool tipc_msg_bundle(struct sk_buff_head *list, struct sk_buff *skb, u32 mtu); |
761 | bool tipc_msg_make_bundle(struct sk_buff_head *list, | 760 | bool tipc_msg_make_bundle(struct sk_buff_head *list, |
762 | struct sk_buff *skb, u32 mtu, u32 dnode); | 761 | struct sk_buff *skb, u32 mtu, u32 dnode); |
763 | int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, | 762 | int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, |
764 | int offset, int dsz, int mtu, struct sk_buff_head *list); | 763 | int offset, int dsz, int mtu, struct sk_buff_head *list); |
764 | bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, u32 *dnode, | ||
765 | int *err); | ||
765 | struct sk_buff *tipc_msg_reassemble(struct sk_buff_head *list); | 766 | struct sk_buff *tipc_msg_reassemble(struct sk_buff_head *list); |
766 | 767 | ||
767 | #endif | 768 | #endif |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 1d98bfcda6f6..e14b2aedb212 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -1739,7 +1739,7 @@ static int filter_rcv(struct sock *sk, struct sk_buff **skb) | |||
1739 | * @sk: socket | 1739 | * @sk: socket |
1740 | * @skb: message | 1740 | * @skb: message |
1741 | * | 1741 | * |
1742 | * Caller must hold socket lock, but not port lock. | 1742 | * Caller must hold socket lock |
1743 | * | 1743 | * |
1744 | * Returns 0 | 1744 | * Returns 0 |
1745 | */ | 1745 | */ |
@@ -1805,27 +1805,31 @@ int tipc_sk_rcv(struct net *net, struct sk_buff *skb) | |||
1805 | struct tipc_net *tn; | 1805 | struct tipc_net *tn; |
1806 | struct sock *sk; | 1806 | struct sock *sk; |
1807 | u32 dport = msg_destport(buf_msg(skb)); | 1807 | u32 dport = msg_destport(buf_msg(skb)); |
1808 | int err; | 1808 | int err = -TIPC_ERR_NO_PORT; |
1809 | u32 dnode; | 1809 | u32 dnode; |
1810 | 1810 | ||
1811 | /* Validate destination and message */ | 1811 | /* Find destination */ |
1812 | tsk = tipc_sk_lookup(net, dport); | 1812 | tsk = tipc_sk_lookup(net, dport); |
1813 | if (unlikely(!tsk)) { | 1813 | if (likely(tsk)) { |
1814 | err = tipc_msg_eval(net, skb, &dnode); | 1814 | sk = &tsk->sk; |
1815 | goto exit; | 1815 | spin_lock_bh(&sk->sk_lock.slock); |
1816 | } | 1816 | err = tipc_sk_enqueue_skb(sk, &skb); |
1817 | sk = &tsk->sk; | 1817 | spin_unlock_bh(&sk->sk_lock.slock); |
1818 | 1818 | sock_put(sk); | |
1819 | spin_lock_bh(&sk->sk_lock.slock); | ||
1820 | err = tipc_sk_enqueue_skb(sk, &skb); | ||
1821 | spin_unlock_bh(&sk->sk_lock.slock); | ||
1822 | sock_put(sk); | ||
1823 | exit: | ||
1824 | if (unlikely(skb)) { | ||
1825 | tn = net_generic(net, tipc_net_id); | ||
1826 | if (!err || tipc_msg_reverse(tn->own_addr, skb, &dnode, -err)) | ||
1827 | tipc_link_xmit_skb(net, skb, dnode, 0); | ||
1828 | } | 1819 | } |
1820 | if (likely(!skb)) | ||
1821 | return 0; | ||
1822 | if (tipc_msg_lookup_dest(net, skb, &dnode, &err)) | ||
1823 | goto xmit; | ||
1824 | if (!err) { | ||
1825 | dnode = msg_destnode(buf_msg(skb)); | ||
1826 | goto xmit; | ||
1827 | } | ||
1828 | tn = net_generic(net, tipc_net_id); | ||
1829 | if (!tipc_msg_reverse(tn->own_addr, skb, &dnode, -err)) | ||
1830 | return -EHOSTUNREACH; | ||
1831 | xmit: | ||
1832 | tipc_link_xmit_skb(net, skb, dnode, dport); | ||
1829 | return err ? -EHOSTUNREACH : 0; | 1833 | return err ? -EHOSTUNREACH : 0; |
1830 | } | 1834 | } |
1831 | 1835 | ||