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