root/net/netfilter/nfnetlink.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nfnl_lock
  2. nfnl_unlock
  3. lockdep_nfnl_is_held
  4. nfnetlink_subsys_register
  5. nfnetlink_subsys_unregister
  6. nfnetlink_get_subsys
  7. nfnetlink_find_client
  8. nfnetlink_has_listeners
  9. nfnetlink_send
  10. nfnetlink_set_err
  11. nfnetlink_unicast
  12. nfnetlink_rcv_msg
  13. nfnl_err_add
  14. nfnl_err_del
  15. nfnl_err_reset
  16. nfnl_err_deliver
  17. nfnetlink_rcv_batch
  18. nfnetlink_rcv_skb_batch
  19. nfnetlink_rcv
  20. nfnetlink_bind
  21. nfnetlink_net_init
  22. nfnetlink_net_exit_batch
  23. nfnetlink_init
  24. nfnetlink_exit

   1 /* Netfilter messages via netlink socket. Allows for user space
   2  * protocol helpers and general trouble making from userspace.
   3  *
   4  * (C) 2001 by Jay Schulist <jschlst@samba.org>,
   5  * (C) 2002-2005 by Harald Welte <laforge@gnumonks.org>
   6  * (C) 2005-2017 by Pablo Neira Ayuso <pablo@netfilter.org>
   7  *
   8  * Initial netfilter messages via netlink development funded and
   9  * generally made possible by Network Robots, Inc. (www.networkrobots.com)
  10  *
  11  * Further development of this code funded by Astaro AG (http://www.astaro.com)
  12  *
  13  * This software may be used and distributed according to the terms
  14  * of the GNU General Public License, incorporated herein by reference.
  15  */
  16 
  17 #include <linux/module.h>
  18 #include <linux/types.h>
  19 #include <linux/socket.h>
  20 #include <linux/kernel.h>
  21 #include <linux/string.h>
  22 #include <linux/sockios.h>
  23 #include <linux/net.h>
  24 #include <linux/skbuff.h>
  25 #include <linux/uaccess.h>
  26 #include <net/sock.h>
  27 #include <linux/init.h>
  28 #include <linux/sched/signal.h>
  29 
  30 #include <net/netlink.h>
  31 #include <linux/netfilter/nfnetlink.h>
  32 
  33 MODULE_LICENSE("GPL");
  34 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
  35 MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER);
  36 
  37 #define nfnl_dereference_protected(id) \
  38         rcu_dereference_protected(table[(id)].subsys, \
  39                                   lockdep_nfnl_is_held((id)))
  40 
  41 #define NFNL_MAX_ATTR_COUNT     32
  42 
  43 static struct {
  44         struct mutex                            mutex;
  45         const struct nfnetlink_subsystem __rcu  *subsys;
  46 } table[NFNL_SUBSYS_COUNT];
  47 
  48 static const int nfnl_group2type[NFNLGRP_MAX+1] = {
  49         [NFNLGRP_CONNTRACK_NEW]         = NFNL_SUBSYS_CTNETLINK,
  50         [NFNLGRP_CONNTRACK_UPDATE]      = NFNL_SUBSYS_CTNETLINK,
  51         [NFNLGRP_CONNTRACK_DESTROY]     = NFNL_SUBSYS_CTNETLINK,
  52         [NFNLGRP_CONNTRACK_EXP_NEW]     = NFNL_SUBSYS_CTNETLINK_EXP,
  53         [NFNLGRP_CONNTRACK_EXP_UPDATE]  = NFNL_SUBSYS_CTNETLINK_EXP,
  54         [NFNLGRP_CONNTRACK_EXP_DESTROY] = NFNL_SUBSYS_CTNETLINK_EXP,
  55         [NFNLGRP_NFTABLES]              = NFNL_SUBSYS_NFTABLES,
  56         [NFNLGRP_ACCT_QUOTA]            = NFNL_SUBSYS_ACCT,
  57         [NFNLGRP_NFTRACE]               = NFNL_SUBSYS_NFTABLES,
  58 };
  59 
  60 void nfnl_lock(__u8 subsys_id)
  61 {
  62         mutex_lock(&table[subsys_id].mutex);
  63 }
  64 EXPORT_SYMBOL_GPL(nfnl_lock);
  65 
  66 void nfnl_unlock(__u8 subsys_id)
  67 {
  68         mutex_unlock(&table[subsys_id].mutex);
  69 }
  70 EXPORT_SYMBOL_GPL(nfnl_unlock);
  71 
  72 #ifdef CONFIG_PROVE_LOCKING
  73 bool lockdep_nfnl_is_held(u8 subsys_id)
  74 {
  75         return lockdep_is_held(&table[subsys_id].mutex);
  76 }
  77 EXPORT_SYMBOL_GPL(lockdep_nfnl_is_held);
  78 #endif
  79 
  80 int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n)
  81 {
  82         u8 cb_id;
  83 
  84         /* Sanity-check attr_count size to avoid stack buffer overflow. */
  85         for (cb_id = 0; cb_id < n->cb_count; cb_id++)
  86                 if (WARN_ON(n->cb[cb_id].attr_count > NFNL_MAX_ATTR_COUNT))
  87                         return -EINVAL;
  88 
  89         nfnl_lock(n->subsys_id);
  90         if (table[n->subsys_id].subsys) {
  91                 nfnl_unlock(n->subsys_id);
  92                 return -EBUSY;
  93         }
  94         rcu_assign_pointer(table[n->subsys_id].subsys, n);
  95         nfnl_unlock(n->subsys_id);
  96 
  97         return 0;
  98 }
  99 EXPORT_SYMBOL_GPL(nfnetlink_subsys_register);
 100 
 101 int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n)
 102 {
 103         nfnl_lock(n->subsys_id);
 104         table[n->subsys_id].subsys = NULL;
 105         nfnl_unlock(n->subsys_id);
 106         synchronize_rcu();
 107         return 0;
 108 }
 109 EXPORT_SYMBOL_GPL(nfnetlink_subsys_unregister);
 110 
 111 static inline const struct nfnetlink_subsystem *nfnetlink_get_subsys(u16 type)
 112 {
 113         u8 subsys_id = NFNL_SUBSYS_ID(type);
 114 
 115         if (subsys_id >= NFNL_SUBSYS_COUNT)
 116                 return NULL;
 117 
 118         return rcu_dereference(table[subsys_id].subsys);
 119 }
 120 
 121 static inline const struct nfnl_callback *
 122 nfnetlink_find_client(u16 type, const struct nfnetlink_subsystem *ss)
 123 {
 124         u8 cb_id = NFNL_MSG_TYPE(type);
 125 
 126         if (cb_id >= ss->cb_count)
 127                 return NULL;
 128 
 129         return &ss->cb[cb_id];
 130 }
 131 
 132 int nfnetlink_has_listeners(struct net *net, unsigned int group)
 133 {
 134         return netlink_has_listeners(net->nfnl, group);
 135 }
 136 EXPORT_SYMBOL_GPL(nfnetlink_has_listeners);
 137 
 138 int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 portid,
 139                    unsigned int group, int echo, gfp_t flags)
 140 {
 141         return nlmsg_notify(net->nfnl, skb, portid, group, echo, flags);
 142 }
 143 EXPORT_SYMBOL_GPL(nfnetlink_send);
 144 
 145 int nfnetlink_set_err(struct net *net, u32 portid, u32 group, int error)
 146 {
 147         return netlink_set_err(net->nfnl, portid, group, error);
 148 }
 149 EXPORT_SYMBOL_GPL(nfnetlink_set_err);
 150 
 151 int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u32 portid,
 152                       int flags)
 153 {
 154         return netlink_unicast(net->nfnl, skb, portid, flags);
 155 }
 156 EXPORT_SYMBOL_GPL(nfnetlink_unicast);
 157 
 158 /* Process one complete nfnetlink message. */
 159 static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
 160                              struct netlink_ext_ack *extack)
 161 {
 162         struct net *net = sock_net(skb->sk);
 163         const struct nfnl_callback *nc;
 164         const struct nfnetlink_subsystem *ss;
 165         int type, err;
 166 
 167         /* All the messages must at least contain nfgenmsg */
 168         if (nlmsg_len(nlh) < sizeof(struct nfgenmsg))
 169                 return 0;
 170 
 171         type = nlh->nlmsg_type;
 172 replay:
 173         rcu_read_lock();
 174         ss = nfnetlink_get_subsys(type);
 175         if (!ss) {
 176 #ifdef CONFIG_MODULES
 177                 rcu_read_unlock();
 178                 request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type));
 179                 rcu_read_lock();
 180                 ss = nfnetlink_get_subsys(type);
 181                 if (!ss)
 182 #endif
 183                 {
 184                         rcu_read_unlock();
 185                         return -EINVAL;
 186                 }
 187         }
 188 
 189         nc = nfnetlink_find_client(type, ss);
 190         if (!nc) {
 191                 rcu_read_unlock();
 192                 return -EINVAL;
 193         }
 194 
 195         {
 196                 int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
 197                 u8 cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type);
 198                 struct nlattr *cda[NFNL_MAX_ATTR_COUNT + 1];
 199                 struct nlattr *attr = (void *)nlh + min_len;
 200                 int attrlen = nlh->nlmsg_len - min_len;
 201                 __u8 subsys_id = NFNL_SUBSYS_ID(type);
 202 
 203                 /* Sanity-check NFNL_MAX_ATTR_COUNT */
 204                 if (ss->cb[cb_id].attr_count > NFNL_MAX_ATTR_COUNT) {
 205                         rcu_read_unlock();
 206                         return -ENOMEM;
 207                 }
 208 
 209                 err = nla_parse_deprecated(cda, ss->cb[cb_id].attr_count,
 210                                            attr, attrlen,
 211                                            ss->cb[cb_id].policy, extack);
 212                 if (err < 0) {
 213                         rcu_read_unlock();
 214                         return err;
 215                 }
 216 
 217                 if (nc->call_rcu) {
 218                         err = nc->call_rcu(net, net->nfnl, skb, nlh,
 219                                            (const struct nlattr **)cda,
 220                                            extack);
 221                         rcu_read_unlock();
 222                 } else {
 223                         rcu_read_unlock();
 224                         nfnl_lock(subsys_id);
 225                         if (nfnl_dereference_protected(subsys_id) != ss ||
 226                             nfnetlink_find_client(type, ss) != nc)
 227                                 err = -EAGAIN;
 228                         else if (nc->call)
 229                                 err = nc->call(net, net->nfnl, skb, nlh,
 230                                                (const struct nlattr **)cda,
 231                                                extack);
 232                         else
 233                                 err = -EINVAL;
 234                         nfnl_unlock(subsys_id);
 235                 }
 236                 if (err == -EAGAIN)
 237                         goto replay;
 238                 return err;
 239         }
 240 }
 241 
 242 struct nfnl_err {
 243         struct list_head        head;
 244         struct nlmsghdr         *nlh;
 245         int                     err;
 246         struct netlink_ext_ack  extack;
 247 };
 248 
 249 static int nfnl_err_add(struct list_head *list, struct nlmsghdr *nlh, int err,
 250                         const struct netlink_ext_ack *extack)
 251 {
 252         struct nfnl_err *nfnl_err;
 253 
 254         nfnl_err = kmalloc(sizeof(struct nfnl_err), GFP_KERNEL);
 255         if (nfnl_err == NULL)
 256                 return -ENOMEM;
 257 
 258         nfnl_err->nlh = nlh;
 259         nfnl_err->err = err;
 260         nfnl_err->extack = *extack;
 261         list_add_tail(&nfnl_err->head, list);
 262 
 263         return 0;
 264 }
 265 
 266 static void nfnl_err_del(struct nfnl_err *nfnl_err)
 267 {
 268         list_del(&nfnl_err->head);
 269         kfree(nfnl_err);
 270 }
 271 
 272 static void nfnl_err_reset(struct list_head *err_list)
 273 {
 274         struct nfnl_err *nfnl_err, *next;
 275 
 276         list_for_each_entry_safe(nfnl_err, next, err_list, head)
 277                 nfnl_err_del(nfnl_err);
 278 }
 279 
 280 static void nfnl_err_deliver(struct list_head *err_list, struct sk_buff *skb)
 281 {
 282         struct nfnl_err *nfnl_err, *next;
 283 
 284         list_for_each_entry_safe(nfnl_err, next, err_list, head) {
 285                 netlink_ack(skb, nfnl_err->nlh, nfnl_err->err,
 286                             &nfnl_err->extack);
 287                 nfnl_err_del(nfnl_err);
 288         }
 289 }
 290 
 291 enum {
 292         NFNL_BATCH_FAILURE      = (1 << 0),
 293         NFNL_BATCH_DONE         = (1 << 1),
 294         NFNL_BATCH_REPLAY       = (1 << 2),
 295 };
 296 
 297 static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,
 298                                 u16 subsys_id, u32 genid)
 299 {
 300         struct sk_buff *oskb = skb;
 301         struct net *net = sock_net(skb->sk);
 302         const struct nfnetlink_subsystem *ss;
 303         const struct nfnl_callback *nc;
 304         struct netlink_ext_ack extack;
 305         LIST_HEAD(err_list);
 306         u32 status;
 307         int err;
 308 
 309         if (subsys_id >= NFNL_SUBSYS_COUNT)
 310                 return netlink_ack(skb, nlh, -EINVAL, NULL);
 311 replay:
 312         status = 0;
 313 
 314         skb = netlink_skb_clone(oskb, GFP_KERNEL);
 315         if (!skb)
 316                 return netlink_ack(oskb, nlh, -ENOMEM, NULL);
 317 
 318         nfnl_lock(subsys_id);
 319         ss = nfnl_dereference_protected(subsys_id);
 320         if (!ss) {
 321 #ifdef CONFIG_MODULES
 322                 nfnl_unlock(subsys_id);
 323                 request_module("nfnetlink-subsys-%d", subsys_id);
 324                 nfnl_lock(subsys_id);
 325                 ss = nfnl_dereference_protected(subsys_id);
 326                 if (!ss)
 327 #endif
 328                 {
 329                         nfnl_unlock(subsys_id);
 330                         netlink_ack(oskb, nlh, -EOPNOTSUPP, NULL);
 331                         return kfree_skb(skb);
 332                 }
 333         }
 334 
 335         if (!ss->valid_genid || !ss->commit || !ss->abort) {
 336                 nfnl_unlock(subsys_id);
 337                 netlink_ack(oskb, nlh, -EOPNOTSUPP, NULL);
 338                 return kfree_skb(skb);
 339         }
 340 
 341         if (!try_module_get(ss->owner)) {
 342                 nfnl_unlock(subsys_id);
 343                 netlink_ack(oskb, nlh, -EOPNOTSUPP, NULL);
 344                 return kfree_skb(skb);
 345         }
 346 
 347         if (!ss->valid_genid(net, genid)) {
 348                 module_put(ss->owner);
 349                 nfnl_unlock(subsys_id);
 350                 netlink_ack(oskb, nlh, -ERESTART, NULL);
 351                 return kfree_skb(skb);
 352         }
 353 
 354         nfnl_unlock(subsys_id);
 355 
 356         while (skb->len >= nlmsg_total_size(0)) {
 357                 int msglen, type;
 358 
 359                 if (fatal_signal_pending(current)) {
 360                         nfnl_err_reset(&err_list);
 361                         err = -EINTR;
 362                         status = NFNL_BATCH_FAILURE;
 363                         goto done;
 364                 }
 365 
 366                 memset(&extack, 0, sizeof(extack));
 367                 nlh = nlmsg_hdr(skb);
 368                 err = 0;
 369 
 370                 if (nlh->nlmsg_len < NLMSG_HDRLEN ||
 371                     skb->len < nlh->nlmsg_len ||
 372                     nlmsg_len(nlh) < sizeof(struct nfgenmsg)) {
 373                         nfnl_err_reset(&err_list);
 374                         status |= NFNL_BATCH_FAILURE;
 375                         goto done;
 376                 }
 377 
 378                 /* Only requests are handled by the kernel */
 379                 if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) {
 380                         err = -EINVAL;
 381                         goto ack;
 382                 }
 383 
 384                 type = nlh->nlmsg_type;
 385                 if (type == NFNL_MSG_BATCH_BEGIN) {
 386                         /* Malformed: Batch begin twice */
 387                         nfnl_err_reset(&err_list);
 388                         status |= NFNL_BATCH_FAILURE;
 389                         goto done;
 390                 } else if (type == NFNL_MSG_BATCH_END) {
 391                         status |= NFNL_BATCH_DONE;
 392                         goto done;
 393                 } else if (type < NLMSG_MIN_TYPE) {
 394                         err = -EINVAL;
 395                         goto ack;
 396                 }
 397 
 398                 /* We only accept a batch with messages for the same
 399                  * subsystem.
 400                  */
 401                 if (NFNL_SUBSYS_ID(type) != subsys_id) {
 402                         err = -EINVAL;
 403                         goto ack;
 404                 }
 405 
 406                 nc = nfnetlink_find_client(type, ss);
 407                 if (!nc) {
 408                         err = -EINVAL;
 409                         goto ack;
 410                 }
 411 
 412                 {
 413                         int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
 414                         u8 cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type);
 415                         struct nlattr *cda[NFNL_MAX_ATTR_COUNT + 1];
 416                         struct nlattr *attr = (void *)nlh + min_len;
 417                         int attrlen = nlh->nlmsg_len - min_len;
 418 
 419                         /* Sanity-check NFTA_MAX_ATTR */
 420                         if (ss->cb[cb_id].attr_count > NFNL_MAX_ATTR_COUNT) {
 421                                 err = -ENOMEM;
 422                                 goto ack;
 423                         }
 424 
 425                         err = nla_parse_deprecated(cda,
 426                                                    ss->cb[cb_id].attr_count,
 427                                                    attr, attrlen,
 428                                                    ss->cb[cb_id].policy, NULL);
 429                         if (err < 0)
 430                                 goto ack;
 431 
 432                         if (nc->call_batch) {
 433                                 err = nc->call_batch(net, net->nfnl, skb, nlh,
 434                                                      (const struct nlattr **)cda,
 435                                                      &extack);
 436                         }
 437 
 438                         /* The lock was released to autoload some module, we
 439                          * have to abort and start from scratch using the
 440                          * original skb.
 441                          */
 442                         if (err == -EAGAIN) {
 443                                 status |= NFNL_BATCH_REPLAY;
 444                                 goto done;
 445                         }
 446                 }
 447 ack:
 448                 if (nlh->nlmsg_flags & NLM_F_ACK || err) {
 449                         /* Errors are delivered once the full batch has been
 450                          * processed, this avoids that the same error is
 451                          * reported several times when replaying the batch.
 452                          */
 453                         if (nfnl_err_add(&err_list, nlh, err, &extack) < 0) {
 454                                 /* We failed to enqueue an error, reset the
 455                                  * list of errors and send OOM to userspace
 456                                  * pointing to the batch header.
 457                                  */
 458                                 nfnl_err_reset(&err_list);
 459                                 netlink_ack(oskb, nlmsg_hdr(oskb), -ENOMEM,
 460                                             NULL);
 461                                 status |= NFNL_BATCH_FAILURE;
 462                                 goto done;
 463                         }
 464                         /* We don't stop processing the batch on errors, thus,
 465                          * userspace gets all the errors that the batch
 466                          * triggers.
 467                          */
 468                         if (err)
 469                                 status |= NFNL_BATCH_FAILURE;
 470                 }
 471 
 472                 msglen = NLMSG_ALIGN(nlh->nlmsg_len);
 473                 if (msglen > skb->len)
 474                         msglen = skb->len;
 475                 skb_pull(skb, msglen);
 476         }
 477 done:
 478         if (status & NFNL_BATCH_REPLAY) {
 479                 ss->abort(net, oskb, true);
 480                 nfnl_err_reset(&err_list);
 481                 kfree_skb(skb);
 482                 module_put(ss->owner);
 483                 goto replay;
 484         } else if (status == NFNL_BATCH_DONE) {
 485                 err = ss->commit(net, oskb);
 486                 if (err == -EAGAIN) {
 487                         status |= NFNL_BATCH_REPLAY;
 488                         goto done;
 489                 } else if (err) {
 490                         ss->abort(net, oskb, false);
 491                         netlink_ack(oskb, nlmsg_hdr(oskb), err, NULL);
 492                 }
 493         } else {
 494                 ss->abort(net, oskb, false);
 495         }
 496         if (ss->cleanup)
 497                 ss->cleanup(net);
 498 
 499         nfnl_err_deliver(&err_list, oskb);
 500         kfree_skb(skb);
 501         module_put(ss->owner);
 502 }
 503 
 504 static const struct nla_policy nfnl_batch_policy[NFNL_BATCH_MAX + 1] = {
 505         [NFNL_BATCH_GENID]      = { .type = NLA_U32 },
 506 };
 507 
 508 static void nfnetlink_rcv_skb_batch(struct sk_buff *skb, struct nlmsghdr *nlh)
 509 {
 510         int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
 511         struct nlattr *attr = (void *)nlh + min_len;
 512         struct nlattr *cda[NFNL_BATCH_MAX + 1];
 513         int attrlen = nlh->nlmsg_len - min_len;
 514         struct nfgenmsg *nfgenmsg;
 515         int msglen, err;
 516         u32 gen_id = 0;
 517         u16 res_id;
 518 
 519         msglen = NLMSG_ALIGN(nlh->nlmsg_len);
 520         if (msglen > skb->len)
 521                 msglen = skb->len;
 522 
 523         if (skb->len < NLMSG_HDRLEN + sizeof(struct nfgenmsg))
 524                 return;
 525 
 526         err = nla_parse_deprecated(cda, NFNL_BATCH_MAX, attr, attrlen,
 527                                    nfnl_batch_policy, NULL);
 528         if (err < 0) {
 529                 netlink_ack(skb, nlh, err, NULL);
 530                 return;
 531         }
 532         if (cda[NFNL_BATCH_GENID])
 533                 gen_id = ntohl(nla_get_be32(cda[NFNL_BATCH_GENID]));
 534 
 535         nfgenmsg = nlmsg_data(nlh);
 536         skb_pull(skb, msglen);
 537         /* Work around old nft using host byte order */
 538         if (nfgenmsg->res_id == NFNL_SUBSYS_NFTABLES)
 539                 res_id = NFNL_SUBSYS_NFTABLES;
 540         else
 541                 res_id = ntohs(nfgenmsg->res_id);
 542 
 543         nfnetlink_rcv_batch(skb, nlh, res_id, gen_id);
 544 }
 545 
 546 static void nfnetlink_rcv(struct sk_buff *skb)
 547 {
 548         struct nlmsghdr *nlh = nlmsg_hdr(skb);
 549 
 550         if (skb->len < NLMSG_HDRLEN ||
 551             nlh->nlmsg_len < NLMSG_HDRLEN ||
 552             skb->len < nlh->nlmsg_len)
 553                 return;
 554 
 555         if (!netlink_net_capable(skb, CAP_NET_ADMIN)) {
 556                 netlink_ack(skb, nlh, -EPERM, NULL);
 557                 return;
 558         }
 559 
 560         if (nlh->nlmsg_type == NFNL_MSG_BATCH_BEGIN)
 561                 nfnetlink_rcv_skb_batch(skb, nlh);
 562         else
 563                 netlink_rcv_skb(skb, nfnetlink_rcv_msg);
 564 }
 565 
 566 #ifdef CONFIG_MODULES
 567 static int nfnetlink_bind(struct net *net, int group)
 568 {
 569         const struct nfnetlink_subsystem *ss;
 570         int type;
 571 
 572         if (group <= NFNLGRP_NONE || group > NFNLGRP_MAX)
 573                 return 0;
 574 
 575         type = nfnl_group2type[group];
 576 
 577         rcu_read_lock();
 578         ss = nfnetlink_get_subsys(type << 8);
 579         rcu_read_unlock();
 580         if (!ss)
 581                 request_module_nowait("nfnetlink-subsys-%d", type);
 582         return 0;
 583 }
 584 #endif
 585 
 586 static int __net_init nfnetlink_net_init(struct net *net)
 587 {
 588         struct sock *nfnl;
 589         struct netlink_kernel_cfg cfg = {
 590                 .groups = NFNLGRP_MAX,
 591                 .input  = nfnetlink_rcv,
 592 #ifdef CONFIG_MODULES
 593                 .bind   = nfnetlink_bind,
 594 #endif
 595         };
 596 
 597         nfnl = netlink_kernel_create(net, NETLINK_NETFILTER, &cfg);
 598         if (!nfnl)
 599                 return -ENOMEM;
 600         net->nfnl_stash = nfnl;
 601         rcu_assign_pointer(net->nfnl, nfnl);
 602         return 0;
 603 }
 604 
 605 static void __net_exit nfnetlink_net_exit_batch(struct list_head *net_exit_list)
 606 {
 607         struct net *net;
 608 
 609         list_for_each_entry(net, net_exit_list, exit_list)
 610                 RCU_INIT_POINTER(net->nfnl, NULL);
 611         synchronize_net();
 612         list_for_each_entry(net, net_exit_list, exit_list)
 613                 netlink_kernel_release(net->nfnl_stash);
 614 }
 615 
 616 static struct pernet_operations nfnetlink_net_ops = {
 617         .init           = nfnetlink_net_init,
 618         .exit_batch     = nfnetlink_net_exit_batch,
 619 };
 620 
 621 static int __init nfnetlink_init(void)
 622 {
 623         int i;
 624 
 625         for (i = NFNLGRP_NONE + 1; i <= NFNLGRP_MAX; i++)
 626                 BUG_ON(nfnl_group2type[i] == NFNL_SUBSYS_NONE);
 627 
 628         for (i=0; i<NFNL_SUBSYS_COUNT; i++)
 629                 mutex_init(&table[i].mutex);
 630 
 631         return register_pernet_subsys(&nfnetlink_net_ops);
 632 }
 633 
 634 static void __exit nfnetlink_exit(void)
 635 {
 636         unregister_pernet_subsys(&nfnetlink_net_ops);
 637 }
 638 module_init(nfnetlink_init);
 639 module_exit(nfnetlink_exit);

/* [<][>][^][v][top][bottom][index][help] */