nfnetlink_cttimeout.c revision 50978462300f74dc48aea4a38471cb69bdf741a5
1/* 2 * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org> 3 * (C) 2012 by Vyatta Inc. <http://www.vyatta.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation (or any later at your option). 8 */ 9#include <linux/init.h> 10#include <linux/module.h> 11#include <linux/kernel.h> 12#include <linux/rculist.h> 13#include <linux/rculist_nulls.h> 14#include <linux/types.h> 15#include <linux/timer.h> 16#include <linux/security.h> 17#include <linux/skbuff.h> 18#include <linux/errno.h> 19#include <linux/netlink.h> 20#include <linux/spinlock.h> 21#include <linux/interrupt.h> 22#include <linux/slab.h> 23 24#include <linux/netfilter.h> 25#include <net/netlink.h> 26#include <net/sock.h> 27#include <net/netfilter/nf_conntrack.h> 28#include <net/netfilter/nf_conntrack_core.h> 29#include <net/netfilter/nf_conntrack_l3proto.h> 30#include <net/netfilter/nf_conntrack_l4proto.h> 31#include <net/netfilter/nf_conntrack_tuple.h> 32 33#include <linux/netfilter/nfnetlink.h> 34#include <linux/netfilter/nfnetlink_cttimeout.h> 35 36MODULE_LICENSE("GPL"); 37MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); 38MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tuning"); 39 40struct ctnl_timeout { 41 struct list_head head; 42 struct rcu_head rcu_head; 43 atomic_t refcnt; 44 char name[CTNL_TIMEOUT_NAME_MAX]; 45 __u16 l3num; 46 __u8 l4num; 47 char data[0]; 48}; 49 50static LIST_HEAD(cttimeout_list); 51 52static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = { 53 [CTA_TIMEOUT_NAME] = { .type = NLA_NUL_STRING }, 54 [CTA_TIMEOUT_L3PROTO] = { .type = NLA_U16 }, 55 [CTA_TIMEOUT_L4PROTO] = { .type = NLA_U8 }, 56 [CTA_TIMEOUT_DATA] = { .type = NLA_NESTED }, 57}; 58 59static int 60ctnl_timeout_parse_policy(struct ctnl_timeout *timeout, 61 struct nf_conntrack_l4proto *l4proto, 62 const struct nlattr *attr) 63{ 64 int ret = 0; 65 66 if (likely(l4proto->ctnl_timeout.nlattr_to_obj)) { 67 struct nlattr *tb[l4proto->ctnl_timeout.nlattr_max+1]; 68 69 nla_parse_nested(tb, l4proto->ctnl_timeout.nlattr_max, 70 attr, l4proto->ctnl_timeout.nla_policy); 71 72 ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, &timeout->data); 73 } 74 return ret; 75} 76 77static int 78cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb, 79 const struct nlmsghdr *nlh, 80 const struct nlattr * const cda[]) 81{ 82 __u16 l3num; 83 __u8 l4num; 84 struct nf_conntrack_l4proto *l4proto; 85 struct ctnl_timeout *timeout, *matching = NULL; 86 char *name; 87 int ret; 88 89 if (!cda[CTA_TIMEOUT_NAME] || 90 !cda[CTA_TIMEOUT_L3PROTO] || 91 !cda[CTA_TIMEOUT_L4PROTO] || 92 !cda[CTA_TIMEOUT_DATA]) 93 return -EINVAL; 94 95 name = nla_data(cda[CTA_TIMEOUT_NAME]); 96 l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO])); 97 l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]); 98 99 list_for_each_entry(timeout, &cttimeout_list, head) { 100 if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0) 101 continue; 102 103 if (nlh->nlmsg_flags & NLM_F_EXCL) 104 return -EEXIST; 105 106 matching = timeout; 107 break; 108 } 109 110 l4proto = __nf_ct_l4proto_find(l3num, l4num); 111 112 /* This protocol is not supportted, skip. */ 113 if (l4proto->l4proto != l4num) 114 return -EOPNOTSUPP; 115 116 if (matching) { 117 if (nlh->nlmsg_flags & NLM_F_REPLACE) { 118 /* You cannot replace one timeout policy by another of 119 * different kind, sorry. 120 */ 121 if (matching->l3num != l3num || 122 matching->l4num != l4num) 123 return -EINVAL; 124 125 ret = ctnl_timeout_parse_policy(matching, l4proto, 126 cda[CTA_TIMEOUT_DATA]); 127 return ret; 128 } 129 return -EBUSY; 130 } 131 132 timeout = kzalloc(sizeof(struct ctnl_timeout) + 133 l4proto->ctnl_timeout.obj_size, GFP_KERNEL); 134 if (timeout == NULL) 135 return -ENOMEM; 136 137 ret = ctnl_timeout_parse_policy(timeout, l4proto, 138 cda[CTA_TIMEOUT_DATA]); 139 if (ret < 0) 140 goto err; 141 142 strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME])); 143 timeout->l3num = l3num; 144 timeout->l4num = l4num; 145 atomic_set(&timeout->refcnt, 1); 146 list_add_tail_rcu(&timeout->head, &cttimeout_list); 147 148 return 0; 149err: 150 kfree(timeout); 151 return ret; 152} 153 154static int 155ctnl_timeout_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type, 156 int event, struct ctnl_timeout *timeout) 157{ 158 struct nlmsghdr *nlh; 159 struct nfgenmsg *nfmsg; 160 unsigned int flags = pid ? NLM_F_MULTI : 0; 161 struct nf_conntrack_l4proto *l4proto; 162 163 event |= NFNL_SUBSYS_CTNETLINK_TIMEOUT << 8; 164 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags); 165 if (nlh == NULL) 166 goto nlmsg_failure; 167 168 nfmsg = nlmsg_data(nlh); 169 nfmsg->nfgen_family = AF_UNSPEC; 170 nfmsg->version = NFNETLINK_V0; 171 nfmsg->res_id = 0; 172 173 NLA_PUT_STRING(skb, CTA_TIMEOUT_NAME, timeout->name); 174 NLA_PUT_BE16(skb, CTA_TIMEOUT_L3PROTO, htons(timeout->l3num)); 175 NLA_PUT_U8(skb, CTA_TIMEOUT_L4PROTO, timeout->l4num); 176 NLA_PUT_BE32(skb, CTA_TIMEOUT_USE, 177 htonl(atomic_read(&timeout->refcnt))); 178 179 l4proto = __nf_ct_l4proto_find(timeout->l3num, timeout->l4num); 180 181 /* If the timeout object does not match the layer 4 protocol tracker, 182 * then skip dumping the data part since we don't know how to 183 * interpret it. This may happen for UPDlite, SCTP and DCCP since 184 * you can unload the module. 185 */ 186 if (timeout->l4num != l4proto->l4proto) 187 goto out; 188 189 if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) { 190 struct nlattr *nest_parms; 191 int ret; 192 193 nest_parms = nla_nest_start(skb, 194 CTA_TIMEOUT_DATA | NLA_F_NESTED); 195 if (!nest_parms) 196 goto nla_put_failure; 197 198 ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, &timeout->data); 199 if (ret < 0) 200 goto nla_put_failure; 201 202 nla_nest_end(skb, nest_parms); 203 } 204out: 205 nlmsg_end(skb, nlh); 206 return skb->len; 207 208nlmsg_failure: 209nla_put_failure: 210 nlmsg_cancel(skb, nlh); 211 return -1; 212} 213 214static int 215ctnl_timeout_dump(struct sk_buff *skb, struct netlink_callback *cb) 216{ 217 struct ctnl_timeout *cur, *last; 218 219 if (cb->args[2]) 220 return 0; 221 222 last = (struct ctnl_timeout *)cb->args[1]; 223 if (cb->args[1]) 224 cb->args[1] = 0; 225 226 rcu_read_lock(); 227 list_for_each_entry_rcu(cur, &cttimeout_list, head) { 228 if (last && cur != last) 229 continue; 230 231 if (ctnl_timeout_fill_info(skb, NETLINK_CB(cb->skb).pid, 232 cb->nlh->nlmsg_seq, 233 NFNL_MSG_TYPE(cb->nlh->nlmsg_type), 234 IPCTNL_MSG_TIMEOUT_NEW, cur) < 0) { 235 cb->args[1] = (unsigned long)cur; 236 break; 237 } 238 } 239 if (!cb->args[1]) 240 cb->args[2] = 1; 241 rcu_read_unlock(); 242 return skb->len; 243} 244 245static int 246cttimeout_get_timeout(struct sock *ctnl, struct sk_buff *skb, 247 const struct nlmsghdr *nlh, 248 const struct nlattr * const cda[]) 249{ 250 int ret = -ENOENT; 251 char *name; 252 struct ctnl_timeout *cur; 253 254 if (nlh->nlmsg_flags & NLM_F_DUMP) { 255 struct netlink_dump_control c = { 256 .dump = ctnl_timeout_dump, 257 }; 258 return netlink_dump_start(ctnl, skb, nlh, &c); 259 } 260 261 if (!cda[CTA_TIMEOUT_NAME]) 262 return -EINVAL; 263 name = nla_data(cda[CTA_TIMEOUT_NAME]); 264 265 list_for_each_entry(cur, &cttimeout_list, head) { 266 struct sk_buff *skb2; 267 268 if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0) 269 continue; 270 271 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 272 if (skb2 == NULL) { 273 ret = -ENOMEM; 274 break; 275 } 276 277 ret = ctnl_timeout_fill_info(skb2, NETLINK_CB(skb).pid, 278 nlh->nlmsg_seq, 279 NFNL_MSG_TYPE(nlh->nlmsg_type), 280 IPCTNL_MSG_TIMEOUT_NEW, cur); 281 if (ret <= 0) { 282 kfree_skb(skb2); 283 break; 284 } 285 ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, 286 MSG_DONTWAIT); 287 if (ret > 0) 288 ret = 0; 289 290 /* this avoids a loop in nfnetlink. */ 291 return ret == -EAGAIN ? -ENOBUFS : ret; 292 } 293 return ret; 294} 295 296/* try to delete object, fail if it is still in use. */ 297static int ctnl_timeout_try_del(struct ctnl_timeout *timeout) 298{ 299 int ret = 0; 300 301 /* we want to avoid races with nf_ct_timeout_find_get. */ 302 if (atomic_dec_and_test(&timeout->refcnt)) { 303 /* We are protected by nfnl mutex. */ 304 list_del_rcu(&timeout->head); 305 kfree_rcu(timeout, rcu_head); 306 } else { 307 /* still in use, restore reference counter. */ 308 atomic_inc(&timeout->refcnt); 309 ret = -EBUSY; 310 } 311 return ret; 312} 313 314static int 315cttimeout_del_timeout(struct sock *ctnl, struct sk_buff *skb, 316 const struct nlmsghdr *nlh, 317 const struct nlattr * const cda[]) 318{ 319 char *name; 320 struct ctnl_timeout *cur; 321 int ret = -ENOENT; 322 323 if (!cda[CTA_TIMEOUT_NAME]) { 324 list_for_each_entry(cur, &cttimeout_list, head) 325 ctnl_timeout_try_del(cur); 326 327 return 0; 328 } 329 name = nla_data(cda[CTA_TIMEOUT_NAME]); 330 331 list_for_each_entry(cur, &cttimeout_list, head) { 332 if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0) 333 continue; 334 335 ret = ctnl_timeout_try_del(cur); 336 if (ret < 0) 337 return ret; 338 339 break; 340 } 341 return ret; 342} 343 344static const struct nfnl_callback cttimeout_cb[IPCTNL_MSG_TIMEOUT_MAX] = { 345 [IPCTNL_MSG_TIMEOUT_NEW] = { .call = cttimeout_new_timeout, 346 .attr_count = CTA_TIMEOUT_MAX, 347 .policy = cttimeout_nla_policy }, 348 [IPCTNL_MSG_TIMEOUT_GET] = { .call = cttimeout_get_timeout, 349 .attr_count = CTA_TIMEOUT_MAX, 350 .policy = cttimeout_nla_policy }, 351 [IPCTNL_MSG_TIMEOUT_DELETE] = { .call = cttimeout_del_timeout, 352 .attr_count = CTA_TIMEOUT_MAX, 353 .policy = cttimeout_nla_policy }, 354}; 355 356static const struct nfnetlink_subsystem cttimeout_subsys = { 357 .name = "conntrack_timeout", 358 .subsys_id = NFNL_SUBSYS_CTNETLINK_TIMEOUT, 359 .cb_count = IPCTNL_MSG_TIMEOUT_MAX, 360 .cb = cttimeout_cb, 361}; 362 363MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_TIMEOUT); 364 365static int __init cttimeout_init(void) 366{ 367 int ret; 368 369 ret = nfnetlink_subsys_register(&cttimeout_subsys); 370 if (ret < 0) { 371 pr_err("cttimeout_init: cannot register cttimeout with " 372 "nfnetlink.\n"); 373 goto err_out; 374 } 375 return 0; 376 377err_out: 378 return ret; 379} 380 381static void __exit cttimeout_exit(void) 382{ 383 struct ctnl_timeout *cur, *tmp; 384 385 pr_info("cttimeout: unregistering from nfnetlink.\n"); 386 387 nfnetlink_subsys_unregister(&cttimeout_subsys); 388 list_for_each_entry_safe(cur, tmp, &cttimeout_list, head) { 389 list_del_rcu(&cur->head); 390 /* We are sure that our objects have no clients at this point, 391 * it's safe to release them all without checking refcnt. 392 */ 393 kfree_rcu(cur, rcu_head); 394 } 395} 396 397module_init(cttimeout_init); 398module_exit(cttimeout_exit); 399