summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Rutherford <john.rutherford@dektech.com.au>2019-08-06 22:52:29 -0400
committerDavid S. Miller <davem@davemloft.net>2019-08-09 01:11:39 -0400
commit6c9081a3915dc0782a8f1424343b794f2cf53d9c (patch)
treef4f751d693daadfe7794648c529958b1da1b7b5b
parent2339ef1cf32744713ba56cd44ab75b0969fd79e1 (diff)
tipc: add loopback device tracking
Since node internal messages are passed directly to the socket, it is not possible to observe those messages via tcpdump or wireshark. We now remedy this by making it possible to clone such messages and send the clones to the loopback interface. The clones are dropped at reception and have no functional role except making the traffic visible. The feature is enabled if network taps are active for the loopback device. pcap filtering restrictions require the messages to be presented to the receiving side of the loopback device. v3 - Function dev_nit_active used to check for network taps. - Procedure netif_rx_ni used to send cloned messages to loopback device. Signed-off-by: John Rutherford <john.rutherford@dektech.com.au> Acked-by: Jon Maloy <jon.maloy@ericsson.com> Acked-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/tipc/bcast.c4
-rw-r--r--net/tipc/bearer.c64
-rw-r--r--net/tipc/bearer.h10
-rw-r--r--net/tipc/core.c5
-rw-r--r--net/tipc/core.h3
-rw-r--r--net/tipc/node.c1
-rw-r--r--net/tipc/topsrv.c2
7 files changed, 88 insertions, 1 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index 1336f3cdad38..34f3e5641438 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -406,8 +406,10 @@ int tipc_mcast_xmit(struct net *net, struct sk_buff_head *pkts,
406 rc = tipc_bcast_xmit(net, pkts, cong_link_cnt); 406 rc = tipc_bcast_xmit(net, pkts, cong_link_cnt);
407 } 407 }
408 408
409 if (dests->local) 409 if (dests->local) {
410 tipc_loopback_trace(net, &localq);
410 tipc_sk_mcast_rcv(net, &localq, &inputq); 411 tipc_sk_mcast_rcv(net, &localq, &inputq);
412 }
411exit: 413exit:
412 /* This queue should normally be empty by now */ 414 /* This queue should normally be empty by now */
413 __skb_queue_purge(pkts); 415 __skb_queue_purge(pkts);
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index a809c0ec8d15..0214aa1c4427 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -389,6 +389,11 @@ int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b,
389 dev_put(dev); 389 dev_put(dev);
390 return -EINVAL; 390 return -EINVAL;
391 } 391 }
392 if (dev == net->loopback_dev) {
393 dev_put(dev);
394 pr_info("Enabling <%s> not permitted\n", b->name);
395 return -EINVAL;
396 }
392 397
393 /* Autoconfigure own node identity if needed */ 398 /* Autoconfigure own node identity if needed */
394 if (!tipc_own_id(net) && hwaddr_len <= NODE_ID_LEN) { 399 if (!tipc_own_id(net) && hwaddr_len <= NODE_ID_LEN) {
@@ -674,6 +679,65 @@ void tipc_bearer_stop(struct net *net)
674 } 679 }
675} 680}
676 681
682void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts)
683{
684 struct net_device *dev = net->loopback_dev;
685 struct sk_buff *skb, *_skb;
686 int exp;
687
688 skb_queue_walk(pkts, _skb) {
689 skb = pskb_copy(_skb, GFP_ATOMIC);
690 if (!skb)
691 continue;
692
693 exp = SKB_DATA_ALIGN(dev->hard_header_len - skb_headroom(skb));
694 if (exp > 0 && pskb_expand_head(skb, exp, 0, GFP_ATOMIC)) {
695 kfree_skb(skb);
696 continue;
697 }
698
699 skb_reset_network_header(skb);
700 dev_hard_header(skb, dev, ETH_P_TIPC, dev->dev_addr,
701 dev->dev_addr, skb->len);
702 skb->dev = dev;
703 skb->pkt_type = PACKET_HOST;
704 skb->ip_summed = CHECKSUM_UNNECESSARY;
705 skb->protocol = eth_type_trans(skb, dev);
706 netif_rx_ni(skb);
707 }
708}
709
710static int tipc_loopback_rcv_pkt(struct sk_buff *skb, struct net_device *dev,
711 struct packet_type *pt, struct net_device *od)
712{
713 consume_skb(skb);
714 return NET_RX_SUCCESS;
715}
716
717int tipc_attach_loopback(struct net *net)
718{
719 struct net_device *dev = net->loopback_dev;
720 struct tipc_net *tn = tipc_net(net);
721
722 if (!dev)
723 return -ENODEV;
724
725 dev_hold(dev);
726 tn->loopback_pt.dev = dev;
727 tn->loopback_pt.type = htons(ETH_P_TIPC);
728 tn->loopback_pt.func = tipc_loopback_rcv_pkt;
729 dev_add_pack(&tn->loopback_pt);
730 return 0;
731}
732
733void tipc_detach_loopback(struct net *net)
734{
735 struct tipc_net *tn = tipc_net(net);
736
737 dev_remove_pack(&tn->loopback_pt);
738 dev_put(net->loopback_dev);
739}
740
677/* Caller should hold rtnl_lock to protect the bearer */ 741/* Caller should hold rtnl_lock to protect the bearer */
678static int __tipc_nl_add_bearer(struct tipc_nl_msg *msg, 742static int __tipc_nl_add_bearer(struct tipc_nl_msg *msg,
679 struct tipc_bearer *bearer, int nlflags) 743 struct tipc_bearer *bearer, int nlflags)
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index 7f4c569594a5..ea0f3c49cbed 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -232,6 +232,16 @@ void tipc_bearer_xmit(struct net *net, u32 bearer_id,
232 struct tipc_media_addr *dst); 232 struct tipc_media_addr *dst);
233void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, 233void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id,
234 struct sk_buff_head *xmitq); 234 struct sk_buff_head *xmitq);
235void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts);
236int tipc_attach_loopback(struct net *net);
237void tipc_detach_loopback(struct net *net);
238
239static inline void tipc_loopback_trace(struct net *net,
240 struct sk_buff_head *pkts)
241{
242 if (unlikely(dev_nit_active(net->loopback_dev)))
243 tipc_clone_to_loopback(net, pkts);
244}
235 245
236/* check if device MTU is too low for tipc headers */ 246/* check if device MTU is too low for tipc headers */
237static inline bool tipc_mtu_bad(struct net_device *dev, unsigned int reserve) 247static inline bool tipc_mtu_bad(struct net_device *dev, unsigned int reserve)
diff --git a/net/tipc/core.c b/net/tipc/core.c
index c8370722f0bb..23cb379a93d6 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -82,6 +82,10 @@ static int __net_init tipc_init_net(struct net *net)
82 if (err) 82 if (err)
83 goto out_bclink; 83 goto out_bclink;
84 84
85 err = tipc_attach_loopback(net);
86 if (err)
87 goto out_bclink;
88
85 return 0; 89 return 0;
86 90
87out_bclink: 91out_bclink:
@@ -94,6 +98,7 @@ out_sk_rht:
94 98
95static void __net_exit tipc_exit_net(struct net *net) 99static void __net_exit tipc_exit_net(struct net *net)
96{ 100{
101 tipc_detach_loopback(net);
97 tipc_net_stop(net); 102 tipc_net_stop(net);
98 tipc_bcast_stop(net); 103 tipc_bcast_stop(net);
99 tipc_nametbl_stop(net); 104 tipc_nametbl_stop(net);
diff --git a/net/tipc/core.h b/net/tipc/core.h
index 7a68e1b6a066..60d829581068 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -125,6 +125,9 @@ struct tipc_net {
125 125
126 /* Cluster capabilities */ 126 /* Cluster capabilities */
127 u16 capabilities; 127 u16 capabilities;
128
129 /* Tracing of node internal messages */
130 struct packet_type loopback_pt;
128}; 131};
129 132
130static inline struct tipc_net *tipc_net(struct net *net) 133static inline struct tipc_net *tipc_net(struct net *net)
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 7ca019001f7c..1bdcf0fc1a4d 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -1443,6 +1443,7 @@ int tipc_node_xmit(struct net *net, struct sk_buff_head *list,
1443 int rc; 1443 int rc;
1444 1444
1445 if (in_own_node(net, dnode)) { 1445 if (in_own_node(net, dnode)) {
1446 tipc_loopback_trace(net, list);
1446 tipc_sk_rcv(net, list); 1447 tipc_sk_rcv(net, list);
1447 return 0; 1448 return 0;
1448 } 1449 }
diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c
index ca8ac96d22a9..3a12fc18239b 100644
--- a/net/tipc/topsrv.c
+++ b/net/tipc/topsrv.c
@@ -40,6 +40,7 @@
40#include "socket.h" 40#include "socket.h"
41#include "addr.h" 41#include "addr.h"
42#include "msg.h" 42#include "msg.h"
43#include "bearer.h"
43#include <net/sock.h> 44#include <net/sock.h>
44#include <linux/module.h> 45#include <linux/module.h>
45 46
@@ -608,6 +609,7 @@ static void tipc_topsrv_kern_evt(struct net *net, struct tipc_event *evt)
608 memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt)); 609 memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt));
609 skb_queue_head_init(&evtq); 610 skb_queue_head_init(&evtq);
610 __skb_queue_tail(&evtq, skb); 611 __skb_queue_tail(&evtq, skb);
612 tipc_loopback_trace(net, &evtq);
611 tipc_sk_rcv(net, &evtq); 613 tipc_sk_rcv(net, &evtq);
612} 614}
613 615