struct net_device *dev;
struct net *net;
struct list_head next;
+ struct list_head up_next;
struct socket *sock;
__be16 dst_port;
};
/* per-network namespace private data for this module */
struct stt_net {
struct list_head stt_list;
+ struct list_head stt_up_list; /* Devices which are in IFF_UP state. */
int n_tunnels;
};
static void clean_percpu(struct work_struct *work);
static DECLARE_DELAYED_WORK(clean_percpu_wq, clean_percpu);
-static struct stt_dev *stt_find_sock(struct net *net, __be16 port)
+static struct stt_dev *stt_find_up_dev(struct net *net, __be16 port)
{
struct stt_net *sn = net_generic(net, stt_net_id);
struct stt_dev *stt_dev;
- list_for_each_entry_rcu(stt_dev, &sn->stt_list, next) {
+ list_for_each_entry_rcu(stt_dev, &sn->stt_up_list, up_next) {
if (stt_dev->dst_port == port)
return stt_dev;
}
skb_set_transport_header(skb, ip_hdr_len);
- stt_dev = stt_find_sock(dev_net(skb->dev), tcp_hdr(skb)->dest);
+ stt_dev = stt_find_up_dev(dev_net(skb->dev), tcp_hdr(skb)->dest);
if (!stt_dev)
return NF_ACCEPT;
{
struct stt_dev *stt = netdev_priv(dev);
struct net *net = stt->net;
+ struct stt_net *sn = net_generic(net, stt_net_id);
int err;
err = stt_start(net);
err = tcp_sock_create4(net, stt->dst_port, &stt->sock);
if (err)
return err;
+ list_add_rcu(&stt->up_next, &sn->stt_up_list);
return 0;
}
struct stt_dev *stt_dev = netdev_priv(dev);
struct net *net = stt_dev->net;
+ list_del_rcu(&stt_dev->up_next);
tcp_sock_release(stt_dev->sock);
stt_dev->sock = NULL;
stt_cleanup(net);
if (err)
return err;
- list_add_rcu(&stt->next, &sn->stt_list);
+ list_add(&stt->next, &sn->stt_list);
return 0;
}
{
struct stt_dev *stt = netdev_priv(dev);
- list_del_rcu(&stt->next);
+ list_del(&stt->next);
unregister_netdevice_queue(dev, head);
}
struct stt_net *sn = net_generic(net, stt_net_id);
INIT_LIST_HEAD(&sn->stt_list);
+ INIT_LIST_HEAD(&sn->stt_up_list);
return 0;
}