act_connmark.c (8c57a5e7b2820f349c95b8c8393fec1e0f4070d2) | act_connmark.c (a85a970af265f156740977168b542234511b28a8) |
---|---|
1/* 2 * net/sched/act_connmark.c netfilter connmark retriever action 3 * skb mark is over-written 4 * 5 * Copyright (c) 2011 Felix Fietkau <nbd@openwrt.org> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by --- 17 unchanged lines hidden (view full) --- 26 27#include <net/netfilter/nf_conntrack.h> 28#include <net/netfilter/nf_conntrack_core.h> 29#include <net/netfilter/nf_conntrack_zones.h> 30 31#define CONNMARK_TAB_MASK 3 32 33static int connmark_net_id; | 1/* 2 * net/sched/act_connmark.c netfilter connmark retriever action 3 * skb mark is over-written 4 * 5 * Copyright (c) 2011 Felix Fietkau <nbd@openwrt.org> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by --- 17 unchanged lines hidden (view full) --- 26 27#include <net/netfilter/nf_conntrack.h> 28#include <net/netfilter/nf_conntrack_core.h> 29#include <net/netfilter/nf_conntrack_zones.h> 30 31#define CONNMARK_TAB_MASK 3 32 33static int connmark_net_id; |
34static struct tc_action_ops act_connmark_ops; |
|
34 35static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a, 36 struct tcf_result *res) 37{ 38 const struct nf_conntrack_tuple_hash *thash; 39 struct nf_conntrack_tuple tuple; 40 enum ip_conntrack_info ctinfo; | 35 36static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a, 37 struct tcf_result *res) 38{ 39 const struct nf_conntrack_tuple_hash *thash; 40 struct nf_conntrack_tuple tuple; 41 enum ip_conntrack_info ctinfo; |
41 struct tcf_connmark_info *ca = a->priv; | 42 struct tcf_connmark_info *ca = to_connmark(a); |
42 struct nf_conntrack_zone zone; 43 struct nf_conn *c; 44 int proto; 45 46 spin_lock(&ca->tcf_lock); | 43 struct nf_conntrack_zone zone; 44 struct nf_conn *c; 45 int proto; 46 47 spin_lock(&ca->tcf_lock); |
47 ca->tcf_tm.lastuse = jiffies; | 48 tcf_lastuse_update(&ca->tcf_tm); |
48 bstats_update(&ca->tcf_bstats, skb); 49 50 if (skb->protocol == htons(ETH_P_IP)) { 51 if (skb->len < sizeof(struct iphdr)) 52 goto out; 53 54 proto = NFPROTO_IPV4; 55 } else if (skb->protocol == htons(ETH_P_IPV6)) { --- 35 unchanged lines hidden (view full) --- 91 return ca->tcf_action; 92} 93 94static const struct nla_policy connmark_policy[TCA_CONNMARK_MAX + 1] = { 95 [TCA_CONNMARK_PARMS] = { .len = sizeof(struct tc_connmark) }, 96}; 97 98static int tcf_connmark_init(struct net *net, struct nlattr *nla, | 49 bstats_update(&ca->tcf_bstats, skb); 50 51 if (skb->protocol == htons(ETH_P_IP)) { 52 if (skb->len < sizeof(struct iphdr)) 53 goto out; 54 55 proto = NFPROTO_IPV4; 56 } else if (skb->protocol == htons(ETH_P_IPV6)) { --- 35 unchanged lines hidden (view full) --- 92 return ca->tcf_action; 93} 94 95static const struct nla_policy connmark_policy[TCA_CONNMARK_MAX + 1] = { 96 [TCA_CONNMARK_PARMS] = { .len = sizeof(struct tc_connmark) }, 97}; 98 99static int tcf_connmark_init(struct net *net, struct nlattr *nla, |
99 struct nlattr *est, struct tc_action *a, | 100 struct nlattr *est, struct tc_action **a, |
100 int ovr, int bind) 101{ 102 struct tc_action_net *tn = net_generic(net, connmark_net_id); 103 struct nlattr *tb[TCA_CONNMARK_MAX + 1]; 104 struct tcf_connmark_info *ci; 105 struct tc_connmark *parm; 106 int ret = 0; 107 108 if (!nla) 109 return -EINVAL; 110 111 ret = nla_parse_nested(tb, TCA_CONNMARK_MAX, nla, connmark_policy); 112 if (ret < 0) 113 return ret; 114 115 parm = nla_data(tb[TCA_CONNMARK_PARMS]); 116 117 if (!tcf_hash_check(tn, parm->index, a, bind)) { 118 ret = tcf_hash_create(tn, parm->index, est, a, | 101 int ovr, int bind) 102{ 103 struct tc_action_net *tn = net_generic(net, connmark_net_id); 104 struct nlattr *tb[TCA_CONNMARK_MAX + 1]; 105 struct tcf_connmark_info *ci; 106 struct tc_connmark *parm; 107 int ret = 0; 108 109 if (!nla) 110 return -EINVAL; 111 112 ret = nla_parse_nested(tb, TCA_CONNMARK_MAX, nla, connmark_policy); 113 if (ret < 0) 114 return ret; 115 116 parm = nla_data(tb[TCA_CONNMARK_PARMS]); 117 118 if (!tcf_hash_check(tn, parm->index, a, bind)) { 119 ret = tcf_hash_create(tn, parm->index, est, a, |
119 sizeof(*ci), bind, false); | 120 &act_connmark_ops, bind, false); |
120 if (ret) 121 return ret; 122 | 121 if (ret) 122 return ret; 123 |
123 ci = to_connmark(a); | 124 ci = to_connmark(*a); |
124 ci->tcf_action = parm->action; 125 ci->net = net; 126 ci->zone = parm->zone; 127 | 125 ci->tcf_action = parm->action; 126 ci->net = net; 127 ci->zone = parm->zone; 128 |
128 tcf_hash_insert(tn, a); | 129 tcf_hash_insert(tn, *a); |
129 ret = ACT_P_CREATED; 130 } else { | 130 ret = ACT_P_CREATED; 131 } else { |
131 ci = to_connmark(a); | 132 ci = to_connmark(*a); |
132 if (bind) 133 return 0; | 133 if (bind) 134 return 0; |
134 tcf_hash_release(a, bind); | 135 tcf_hash_release(*a, bind); |
135 if (!ovr) 136 return -EEXIST; 137 /* replacing action and zone */ 138 ci->tcf_action = parm->action; 139 ci->zone = parm->zone; 140 } 141 142 return ret; 143} 144 145static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, 146 int bind, int ref) 147{ 148 unsigned char *b = skb_tail_pointer(skb); | 136 if (!ovr) 137 return -EEXIST; 138 /* replacing action and zone */ 139 ci->tcf_action = parm->action; 140 ci->zone = parm->zone; 141 } 142 143 return ret; 144} 145 146static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, 147 int bind, int ref) 148{ 149 unsigned char *b = skb_tail_pointer(skb); |
149 struct tcf_connmark_info *ci = a->priv; | 150 struct tcf_connmark_info *ci = to_connmark(a); |
150 151 struct tc_connmark opt = { 152 .index = ci->tcf_index, 153 .refcnt = ci->tcf_refcnt - ref, 154 .bindcnt = ci->tcf_bindcnt - bind, 155 .action = ci->tcf_action, 156 .zone = ci->zone, 157 }; 158 struct tcf_t t; 159 160 if (nla_put(skb, TCA_CONNMARK_PARMS, sizeof(opt), &opt)) 161 goto nla_put_failure; 162 | 151 152 struct tc_connmark opt = { 153 .index = ci->tcf_index, 154 .refcnt = ci->tcf_refcnt - ref, 155 .bindcnt = ci->tcf_bindcnt - bind, 156 .action = ci->tcf_action, 157 .zone = ci->zone, 158 }; 159 struct tcf_t t; 160 161 if (nla_put(skb, TCA_CONNMARK_PARMS, sizeof(opt), &opt)) 162 goto nla_put_failure; 163 |
163 t.install = jiffies_to_clock_t(jiffies - ci->tcf_tm.install); 164 t.lastuse = jiffies_to_clock_t(jiffies - ci->tcf_tm.lastuse); 165 t.expires = jiffies_to_clock_t(ci->tcf_tm.expires); 166 if (nla_put(skb, TCA_CONNMARK_TM, sizeof(t), &t)) | 164 tcf_tm_dump(&t, &ci->tcf_tm); 165 if (nla_put_64bit(skb, TCA_CONNMARK_TM, sizeof(t), &t, 166 TCA_CONNMARK_PAD)) |
167 goto nla_put_failure; 168 169 return skb->len; 170nla_put_failure: 171 nlmsg_trim(skb, b); 172 return -1; 173} 174 175static int tcf_connmark_walker(struct net *net, struct sk_buff *skb, 176 struct netlink_callback *cb, int type, | 167 goto nla_put_failure; 168 169 return skb->len; 170nla_put_failure: 171 nlmsg_trim(skb, b); 172 return -1; 173} 174 175static int tcf_connmark_walker(struct net *net, struct sk_buff *skb, 176 struct netlink_callback *cb, int type, |
177 struct tc_action *a) | 177 const struct tc_action_ops *ops) |
178{ 179 struct tc_action_net *tn = net_generic(net, connmark_net_id); 180 | 178{ 179 struct tc_action_net *tn = net_generic(net, connmark_net_id); 180 |
181 return tcf_generic_walker(tn, skb, cb, type, a); | 181 return tcf_generic_walker(tn, skb, cb, type, ops); |
182} 183 | 182} 183 |
184static int tcf_connmark_search(struct net *net, struct tc_action *a, u32 index) | 184static int tcf_connmark_search(struct net *net, struct tc_action **a, u32 index) |
185{ 186 struct tc_action_net *tn = net_generic(net, connmark_net_id); 187 188 return tcf_hash_search(tn, a, index); 189} 190 191static struct tc_action_ops act_connmark_ops = { 192 .kind = "connmark", 193 .type = TCA_ACT_CONNMARK, 194 .owner = THIS_MODULE, 195 .act = tcf_connmark, 196 .dump = tcf_connmark_dump, 197 .init = tcf_connmark_init, 198 .walk = tcf_connmark_walker, 199 .lookup = tcf_connmark_search, | 185{ 186 struct tc_action_net *tn = net_generic(net, connmark_net_id); 187 188 return tcf_hash_search(tn, a, index); 189} 190 191static struct tc_action_ops act_connmark_ops = { 192 .kind = "connmark", 193 .type = TCA_ACT_CONNMARK, 194 .owner = THIS_MODULE, 195 .act = tcf_connmark, 196 .dump = tcf_connmark_dump, 197 .init = tcf_connmark_init, 198 .walk = tcf_connmark_walker, 199 .lookup = tcf_connmark_search, |
200 .size = sizeof(struct tcf_connmark_info), |
|
200}; 201 202static __net_init int connmark_init_net(struct net *net) 203{ 204 struct tc_action_net *tn = net_generic(net, connmark_net_id); 205 206 return tc_action_net_init(tn, &act_connmark_ops, CONNMARK_TAB_MASK); 207} --- 31 unchanged lines hidden --- | 201}; 202 203static __net_init int connmark_init_net(struct net *net) 204{ 205 struct tc_action_net *tn = net_generic(net, connmark_net_id); 206 207 return tc_action_net_init(tn, &act_connmark_ops, CONNMARK_TAB_MASK); 208} --- 31 unchanged lines hidden --- |