Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at c9a28fa7b9ac19b676deefa0a171ce7df8755c08 795 lines 18 kB view raw
1/* 2 * NETLINK Generic Netlink Family 3 * 4 * Authors: Jamal Hadi Salim 5 * Thomas Graf <tgraf@suug.ch> 6 * Johannes Berg <johannes@sipsolutions.net> 7 */ 8 9#include <linux/module.h> 10#include <linux/kernel.h> 11#include <linux/errno.h> 12#include <linux/types.h> 13#include <linux/socket.h> 14#include <linux/string.h> 15#include <linux/skbuff.h> 16#include <linux/mutex.h> 17#include <linux/bitmap.h> 18#include <net/sock.h> 19#include <net/genetlink.h> 20 21struct sock *genl_sock = NULL; 22 23static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */ 24 25static inline void genl_lock(void) 26{ 27 mutex_lock(&genl_mutex); 28} 29 30static inline void genl_unlock(void) 31{ 32 mutex_unlock(&genl_mutex); 33} 34 35#define GENL_FAM_TAB_SIZE 16 36#define GENL_FAM_TAB_MASK (GENL_FAM_TAB_SIZE - 1) 37 38static struct list_head family_ht[GENL_FAM_TAB_SIZE]; 39/* 40 * Bitmap of multicast groups that are currently in use. 41 * 42 * To avoid an allocation at boot of just one unsigned long, 43 * declare it global instead. 44 * Bit 0 is marked as already used since group 0 is invalid. 45 */ 46static unsigned long mc_group_start = 0x1; 47static unsigned long *mc_groups = &mc_group_start; 48static unsigned long mc_groups_longs = 1; 49 50static int genl_ctrl_event(int event, void *data); 51 52static inline unsigned int genl_family_hash(unsigned int id) 53{ 54 return id & GENL_FAM_TAB_MASK; 55} 56 57static inline struct list_head *genl_family_chain(unsigned int id) 58{ 59 return &family_ht[genl_family_hash(id)]; 60} 61 62static struct genl_family *genl_family_find_byid(unsigned int id) 63{ 64 struct genl_family *f; 65 66 list_for_each_entry(f, genl_family_chain(id), family_list) 67 if (f->id == id) 68 return f; 69 70 return NULL; 71} 72 73static struct genl_family *genl_family_find_byname(char *name) 74{ 75 struct genl_family *f; 76 int i; 77 78 for (i = 0; i < GENL_FAM_TAB_SIZE; i++) 79 list_for_each_entry(f, genl_family_chain(i), family_list) 80 if (strcmp(f->name, name) == 0) 81 return f; 82 83 return NULL; 84} 85 86static struct genl_ops *genl_get_cmd(u8 cmd, struct genl_family *family) 87{ 88 struct genl_ops *ops; 89 90 list_for_each_entry(ops, &family->ops_list, ops_list) 91 if (ops->cmd == cmd) 92 return ops; 93 94 return NULL; 95} 96 97/* Of course we are going to have problems once we hit 98 * 2^16 alive types, but that can only happen by year 2K 99*/ 100static inline u16 genl_generate_id(void) 101{ 102 static u16 id_gen_idx; 103 int overflowed = 0; 104 105 do { 106 if (id_gen_idx == 0) 107 id_gen_idx = GENL_MIN_ID; 108 109 if (++id_gen_idx > GENL_MAX_ID) { 110 if (!overflowed) { 111 overflowed = 1; 112 id_gen_idx = 0; 113 continue; 114 } else 115 return 0; 116 } 117 118 } while (genl_family_find_byid(id_gen_idx)); 119 120 return id_gen_idx; 121} 122 123static struct genl_multicast_group notify_grp; 124 125/** 126 * genl_register_mc_group - register a multicast group 127 * 128 * Registers the specified multicast group and notifies userspace 129 * about the new group. 130 * 131 * Returns 0 on success or a negative error code. 132 * 133 * @family: The generic netlink family the group shall be registered for. 134 * @grp: The group to register, must have a name. 135 */ 136int genl_register_mc_group(struct genl_family *family, 137 struct genl_multicast_group *grp) 138{ 139 int id; 140 unsigned long *new_groups; 141 int err; 142 143 BUG_ON(grp->name[0] == '\0'); 144 145 genl_lock(); 146 147 /* special-case our own group */ 148 if (grp == &notify_grp) 149 id = GENL_ID_CTRL; 150 else 151 id = find_first_zero_bit(mc_groups, 152 mc_groups_longs * BITS_PER_LONG); 153 154 155 if (id >= mc_groups_longs * BITS_PER_LONG) { 156 size_t nlen = (mc_groups_longs + 1) * sizeof(unsigned long); 157 158 if (mc_groups == &mc_group_start) { 159 new_groups = kzalloc(nlen, GFP_KERNEL); 160 if (!new_groups) { 161 err = -ENOMEM; 162 goto out; 163 } 164 mc_groups = new_groups; 165 *mc_groups = mc_group_start; 166 } else { 167 new_groups = krealloc(mc_groups, nlen, GFP_KERNEL); 168 if (!new_groups) { 169 err = -ENOMEM; 170 goto out; 171 } 172 mc_groups = new_groups; 173 mc_groups[mc_groups_longs] = 0; 174 } 175 mc_groups_longs++; 176 } 177 178 err = netlink_change_ngroups(genl_sock, 179 mc_groups_longs * BITS_PER_LONG); 180 if (err) 181 goto out; 182 183 grp->id = id; 184 set_bit(id, mc_groups); 185 list_add_tail(&grp->list, &family->mcast_groups); 186 grp->family = family; 187 188 genl_ctrl_event(CTRL_CMD_NEWMCAST_GRP, grp); 189 out: 190 genl_unlock(); 191 return err; 192} 193EXPORT_SYMBOL(genl_register_mc_group); 194 195static void __genl_unregister_mc_group(struct genl_family *family, 196 struct genl_multicast_group *grp) 197{ 198 BUG_ON(grp->family != family); 199 netlink_clear_multicast_users(genl_sock, grp->id); 200 clear_bit(grp->id, mc_groups); 201 list_del(&grp->list); 202 genl_ctrl_event(CTRL_CMD_DELMCAST_GRP, grp); 203 grp->id = 0; 204 grp->family = NULL; 205} 206 207/** 208 * genl_unregister_mc_group - unregister a multicast group 209 * 210 * Unregisters the specified multicast group and notifies userspace 211 * about it. All current listeners on the group are removed. 212 * 213 * Note: It is not necessary to unregister all multicast groups before 214 * unregistering the family, unregistering the family will cause 215 * all assigned multicast groups to be unregistered automatically. 216 * 217 * @family: Generic netlink family the group belongs to. 218 * @grp: The group to unregister, must have been registered successfully 219 * previously. 220 */ 221void genl_unregister_mc_group(struct genl_family *family, 222 struct genl_multicast_group *grp) 223{ 224 genl_lock(); 225 __genl_unregister_mc_group(family, grp); 226 genl_unlock(); 227} 228 229static void genl_unregister_mc_groups(struct genl_family *family) 230{ 231 struct genl_multicast_group *grp, *tmp; 232 233 genl_lock(); 234 list_for_each_entry_safe(grp, tmp, &family->mcast_groups, list) 235 __genl_unregister_mc_group(family, grp); 236 genl_unlock(); 237} 238 239/** 240 * genl_register_ops - register generic netlink operations 241 * @family: generic netlink family 242 * @ops: operations to be registered 243 * 244 * Registers the specified operations and assigns them to the specified 245 * family. Either a doit or dumpit callback must be specified or the 246 * operation will fail. Only one operation structure per command 247 * identifier may be registered. 248 * 249 * See include/net/genetlink.h for more documenation on the operations 250 * structure. 251 * 252 * Returns 0 on success or a negative error code. 253 */ 254int genl_register_ops(struct genl_family *family, struct genl_ops *ops) 255{ 256 int err = -EINVAL; 257 258 if (ops->dumpit == NULL && ops->doit == NULL) 259 goto errout; 260 261 if (genl_get_cmd(ops->cmd, family)) { 262 err = -EEXIST; 263 goto errout; 264 } 265 266 if (ops->dumpit) 267 ops->flags |= GENL_CMD_CAP_DUMP; 268 if (ops->doit) 269 ops->flags |= GENL_CMD_CAP_DO; 270 if (ops->policy) 271 ops->flags |= GENL_CMD_CAP_HASPOL; 272 273 genl_lock(); 274 list_add_tail(&ops->ops_list, &family->ops_list); 275 genl_unlock(); 276 277 genl_ctrl_event(CTRL_CMD_NEWOPS, ops); 278 err = 0; 279errout: 280 return err; 281} 282 283/** 284 * genl_unregister_ops - unregister generic netlink operations 285 * @family: generic netlink family 286 * @ops: operations to be unregistered 287 * 288 * Unregisters the specified operations and unassigns them from the 289 * specified family. The operation blocks until the current message 290 * processing has finished and doesn't start again until the 291 * unregister process has finished. 292 * 293 * Note: It is not necessary to unregister all operations before 294 * unregistering the family, unregistering the family will cause 295 * all assigned operations to be unregistered automatically. 296 * 297 * Returns 0 on success or a negative error code. 298 */ 299int genl_unregister_ops(struct genl_family *family, struct genl_ops *ops) 300{ 301 struct genl_ops *rc; 302 303 genl_lock(); 304 list_for_each_entry(rc, &family->ops_list, ops_list) { 305 if (rc == ops) { 306 list_del(&ops->ops_list); 307 genl_unlock(); 308 genl_ctrl_event(CTRL_CMD_DELOPS, ops); 309 return 0; 310 } 311 } 312 genl_unlock(); 313 314 return -ENOENT; 315} 316 317/** 318 * genl_register_family - register a generic netlink family 319 * @family: generic netlink family 320 * 321 * Registers the specified family after validating it first. Only one 322 * family may be registered with the same family name or identifier. 323 * The family id may equal GENL_ID_GENERATE causing an unique id to 324 * be automatically generated and assigned. 325 * 326 * Return 0 on success or a negative error code. 327 */ 328int genl_register_family(struct genl_family *family) 329{ 330 int err = -EINVAL; 331 332 if (family->id && family->id < GENL_MIN_ID) 333 goto errout; 334 335 if (family->id > GENL_MAX_ID) 336 goto errout; 337 338 INIT_LIST_HEAD(&family->ops_list); 339 INIT_LIST_HEAD(&family->mcast_groups); 340 341 genl_lock(); 342 343 if (genl_family_find_byname(family->name)) { 344 err = -EEXIST; 345 goto errout_locked; 346 } 347 348 if (genl_family_find_byid(family->id)) { 349 err = -EEXIST; 350 goto errout_locked; 351 } 352 353 if (family->id == GENL_ID_GENERATE) { 354 u16 newid = genl_generate_id(); 355 356 if (!newid) { 357 err = -ENOMEM; 358 goto errout_locked; 359 } 360 361 family->id = newid; 362 } 363 364 if (family->maxattr) { 365 family->attrbuf = kmalloc((family->maxattr+1) * 366 sizeof(struct nlattr *), GFP_KERNEL); 367 if (family->attrbuf == NULL) { 368 err = -ENOMEM; 369 goto errout_locked; 370 } 371 } else 372 family->attrbuf = NULL; 373 374 list_add_tail(&family->family_list, genl_family_chain(family->id)); 375 genl_unlock(); 376 377 genl_ctrl_event(CTRL_CMD_NEWFAMILY, family); 378 379 return 0; 380 381errout_locked: 382 genl_unlock(); 383errout: 384 return err; 385} 386 387/** 388 * genl_unregister_family - unregister generic netlink family 389 * @family: generic netlink family 390 * 391 * Unregisters the specified family. 392 * 393 * Returns 0 on success or a negative error code. 394 */ 395int genl_unregister_family(struct genl_family *family) 396{ 397 struct genl_family *rc; 398 399 genl_unregister_mc_groups(family); 400 401 genl_lock(); 402 403 list_for_each_entry(rc, genl_family_chain(family->id), family_list) { 404 if (family->id != rc->id || strcmp(rc->name, family->name)) 405 continue; 406 407 list_del(&rc->family_list); 408 INIT_LIST_HEAD(&family->ops_list); 409 genl_unlock(); 410 411 kfree(family->attrbuf); 412 genl_ctrl_event(CTRL_CMD_DELFAMILY, family); 413 return 0; 414 } 415 416 genl_unlock(); 417 418 return -ENOENT; 419} 420 421static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) 422{ 423 struct genl_ops *ops; 424 struct genl_family *family; 425 struct genl_info info; 426 struct genlmsghdr *hdr = nlmsg_data(nlh); 427 int hdrlen, err; 428 429 family = genl_family_find_byid(nlh->nlmsg_type); 430 if (family == NULL) 431 return -ENOENT; 432 433 hdrlen = GENL_HDRLEN + family->hdrsize; 434 if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen)) 435 return -EINVAL; 436 437 ops = genl_get_cmd(hdr->cmd, family); 438 if (ops == NULL) 439 return -EOPNOTSUPP; 440 441 if ((ops->flags & GENL_ADMIN_PERM) && 442 security_netlink_recv(skb, CAP_NET_ADMIN)) 443 return -EPERM; 444 445 if (nlh->nlmsg_flags & NLM_F_DUMP) { 446 if (ops->dumpit == NULL) 447 return -EOPNOTSUPP; 448 449 return netlink_dump_start(genl_sock, skb, nlh, 450 ops->dumpit, ops->done); 451 } 452 453 if (ops->doit == NULL) 454 return -EOPNOTSUPP; 455 456 if (family->attrbuf) { 457 err = nlmsg_parse(nlh, hdrlen, family->attrbuf, family->maxattr, 458 ops->policy); 459 if (err < 0) 460 return err; 461 } 462 463 info.snd_seq = nlh->nlmsg_seq; 464 info.snd_pid = NETLINK_CB(skb).pid; 465 info.nlhdr = nlh; 466 info.genlhdr = nlmsg_data(nlh); 467 info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN; 468 info.attrs = family->attrbuf; 469 470 return ops->doit(skb, &info); 471} 472 473static void genl_rcv(struct sk_buff *skb) 474{ 475 genl_lock(); 476 netlink_rcv_skb(skb, &genl_rcv_msg); 477 genl_unlock(); 478} 479 480/************************************************************************** 481 * Controller 482 **************************************************************************/ 483 484static struct genl_family genl_ctrl = { 485 .id = GENL_ID_CTRL, 486 .name = "nlctrl", 487 .version = 0x2, 488 .maxattr = CTRL_ATTR_MAX, 489}; 490 491static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq, 492 u32 flags, struct sk_buff *skb, u8 cmd) 493{ 494 void *hdr; 495 496 hdr = genlmsg_put(skb, pid, seq, &genl_ctrl, flags, cmd); 497 if (hdr == NULL) 498 return -1; 499 500 NLA_PUT_STRING(skb, CTRL_ATTR_FAMILY_NAME, family->name); 501 NLA_PUT_U16(skb, CTRL_ATTR_FAMILY_ID, family->id); 502 NLA_PUT_U32(skb, CTRL_ATTR_VERSION, family->version); 503 NLA_PUT_U32(skb, CTRL_ATTR_HDRSIZE, family->hdrsize); 504 NLA_PUT_U32(skb, CTRL_ATTR_MAXATTR, family->maxattr); 505 506 if (!list_empty(&family->ops_list)) { 507 struct nlattr *nla_ops; 508 struct genl_ops *ops; 509 int idx = 1; 510 511 nla_ops = nla_nest_start(skb, CTRL_ATTR_OPS); 512 if (nla_ops == NULL) 513 goto nla_put_failure; 514 515 list_for_each_entry(ops, &family->ops_list, ops_list) { 516 struct nlattr *nest; 517 518 nest = nla_nest_start(skb, idx++); 519 if (nest == NULL) 520 goto nla_put_failure; 521 522 NLA_PUT_U32(skb, CTRL_ATTR_OP_ID, ops->cmd); 523 NLA_PUT_U32(skb, CTRL_ATTR_OP_FLAGS, ops->flags); 524 525 nla_nest_end(skb, nest); 526 } 527 528 nla_nest_end(skb, nla_ops); 529 } 530 531 if (!list_empty(&family->mcast_groups)) { 532 struct genl_multicast_group *grp; 533 struct nlattr *nla_grps; 534 int idx = 1; 535 536 nla_grps = nla_nest_start(skb, CTRL_ATTR_MCAST_GROUPS); 537 if (nla_grps == NULL) 538 goto nla_put_failure; 539 540 list_for_each_entry(grp, &family->mcast_groups, list) { 541 struct nlattr *nest; 542 543 nest = nla_nest_start(skb, idx++); 544 if (nest == NULL) 545 goto nla_put_failure; 546 547 NLA_PUT_U32(skb, CTRL_ATTR_MCAST_GRP_ID, grp->id); 548 NLA_PUT_STRING(skb, CTRL_ATTR_MCAST_GRP_NAME, 549 grp->name); 550 551 nla_nest_end(skb, nest); 552 } 553 nla_nest_end(skb, nla_grps); 554 } 555 556 return genlmsg_end(skb, hdr); 557 558nla_put_failure: 559 return genlmsg_cancel(skb, hdr); 560} 561 562static int ctrl_fill_mcgrp_info(struct genl_multicast_group *grp, u32 pid, 563 u32 seq, u32 flags, struct sk_buff *skb, 564 u8 cmd) 565{ 566 void *hdr; 567 struct nlattr *nla_grps; 568 struct nlattr *nest; 569 570 hdr = genlmsg_put(skb, pid, seq, &genl_ctrl, flags, cmd); 571 if (hdr == NULL) 572 return -1; 573 574 NLA_PUT_STRING(skb, CTRL_ATTR_FAMILY_NAME, grp->family->name); 575 NLA_PUT_U16(skb, CTRL_ATTR_FAMILY_ID, grp->family->id); 576 577 nla_grps = nla_nest_start(skb, CTRL_ATTR_MCAST_GROUPS); 578 if (nla_grps == NULL) 579 goto nla_put_failure; 580 581 nest = nla_nest_start(skb, 1); 582 if (nest == NULL) 583 goto nla_put_failure; 584 585 NLA_PUT_U32(skb, CTRL_ATTR_MCAST_GRP_ID, grp->id); 586 NLA_PUT_STRING(skb, CTRL_ATTR_MCAST_GRP_NAME, 587 grp->name); 588 589 nla_nest_end(skb, nest); 590 nla_nest_end(skb, nla_grps); 591 592 return genlmsg_end(skb, hdr); 593 594nla_put_failure: 595 return genlmsg_cancel(skb, hdr); 596} 597 598static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb) 599{ 600 601 int i, n = 0; 602 struct genl_family *rt; 603 int chains_to_skip = cb->args[0]; 604 int fams_to_skip = cb->args[1]; 605 606 if (chains_to_skip != 0) 607 genl_lock(); 608 609 for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { 610 if (i < chains_to_skip) 611 continue; 612 n = 0; 613 list_for_each_entry(rt, genl_family_chain(i), family_list) { 614 if (++n < fams_to_skip) 615 continue; 616 if (ctrl_fill_info(rt, NETLINK_CB(cb->skb).pid, 617 cb->nlh->nlmsg_seq, NLM_F_MULTI, 618 skb, CTRL_CMD_NEWFAMILY) < 0) 619 goto errout; 620 } 621 622 fams_to_skip = 0; 623 } 624 625errout: 626 if (chains_to_skip != 0) 627 genl_unlock(); 628 629 cb->args[0] = i; 630 cb->args[1] = n; 631 632 return skb->len; 633} 634 635static struct sk_buff *ctrl_build_family_msg(struct genl_family *family, 636 u32 pid, int seq, u8 cmd) 637{ 638 struct sk_buff *skb; 639 int err; 640 641 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 642 if (skb == NULL) 643 return ERR_PTR(-ENOBUFS); 644 645 err = ctrl_fill_info(family, pid, seq, 0, skb, cmd); 646 if (err < 0) { 647 nlmsg_free(skb); 648 return ERR_PTR(err); 649 } 650 651 return skb; 652} 653 654static struct sk_buff *ctrl_build_mcgrp_msg(struct genl_multicast_group *grp, 655 u32 pid, int seq, u8 cmd) 656{ 657 struct sk_buff *skb; 658 int err; 659 660 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 661 if (skb == NULL) 662 return ERR_PTR(-ENOBUFS); 663 664 err = ctrl_fill_mcgrp_info(grp, pid, seq, 0, skb, cmd); 665 if (err < 0) { 666 nlmsg_free(skb); 667 return ERR_PTR(err); 668 } 669 670 return skb; 671} 672 673static const struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = { 674 [CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 }, 675 [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_NUL_STRING, 676 .len = GENL_NAMSIZ - 1 }, 677}; 678 679static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info) 680{ 681 struct sk_buff *msg; 682 struct genl_family *res = NULL; 683 int err = -EINVAL; 684 685 if (info->attrs[CTRL_ATTR_FAMILY_ID]) { 686 u16 id = nla_get_u16(info->attrs[CTRL_ATTR_FAMILY_ID]); 687 res = genl_family_find_byid(id); 688 } 689 690 if (info->attrs[CTRL_ATTR_FAMILY_NAME]) { 691 char *name; 692 693 name = nla_data(info->attrs[CTRL_ATTR_FAMILY_NAME]); 694 res = genl_family_find_byname(name); 695 } 696 697 if (res == NULL) { 698 err = -ENOENT; 699 goto errout; 700 } 701 702 msg = ctrl_build_family_msg(res, info->snd_pid, info->snd_seq, 703 CTRL_CMD_NEWFAMILY); 704 if (IS_ERR(msg)) { 705 err = PTR_ERR(msg); 706 goto errout; 707 } 708 709 err = genlmsg_reply(msg, info); 710errout: 711 return err; 712} 713 714static int genl_ctrl_event(int event, void *data) 715{ 716 struct sk_buff *msg; 717 718 if (genl_sock == NULL) 719 return 0; 720 721 switch (event) { 722 case CTRL_CMD_NEWFAMILY: 723 case CTRL_CMD_DELFAMILY: 724 msg = ctrl_build_family_msg(data, 0, 0, event); 725 if (IS_ERR(msg)) 726 return PTR_ERR(msg); 727 728 genlmsg_multicast(msg, 0, GENL_ID_CTRL, GFP_KERNEL); 729 break; 730 case CTRL_CMD_NEWMCAST_GRP: 731 case CTRL_CMD_DELMCAST_GRP: 732 msg = ctrl_build_mcgrp_msg(data, 0, 0, event); 733 if (IS_ERR(msg)) 734 return PTR_ERR(msg); 735 736 genlmsg_multicast(msg, 0, GENL_ID_CTRL, GFP_KERNEL); 737 break; 738 } 739 740 return 0; 741} 742 743static struct genl_ops genl_ctrl_ops = { 744 .cmd = CTRL_CMD_GETFAMILY, 745 .doit = ctrl_getfamily, 746 .dumpit = ctrl_dumpfamily, 747 .policy = ctrl_policy, 748}; 749 750static struct genl_multicast_group notify_grp = { 751 .name = "notify", 752}; 753 754static int __init genl_init(void) 755{ 756 int i, err; 757 758 for (i = 0; i < GENL_FAM_TAB_SIZE; i++) 759 INIT_LIST_HEAD(&family_ht[i]); 760 761 err = genl_register_family(&genl_ctrl); 762 if (err < 0) 763 goto errout; 764 765 err = genl_register_ops(&genl_ctrl, &genl_ctrl_ops); 766 if (err < 0) 767 goto errout_register; 768 769 netlink_set_nonroot(NETLINK_GENERIC, NL_NONROOT_RECV); 770 771 /* we'll bump the group number right afterwards */ 772 genl_sock = netlink_kernel_create(&init_net, NETLINK_GENERIC, 0, 773 genl_rcv, NULL, THIS_MODULE); 774 if (genl_sock == NULL) 775 panic("GENL: Cannot initialize generic netlink\n"); 776 777 err = genl_register_mc_group(&genl_ctrl, &notify_grp); 778 if (err < 0) 779 goto errout_register; 780 781 return 0; 782 783errout_register: 784 genl_unregister_family(&genl_ctrl); 785errout: 786 panic("GENL: Cannot register controller: %d\n", err); 787} 788 789subsys_initcall(genl_init); 790 791EXPORT_SYMBOL(genl_sock); 792EXPORT_SYMBOL(genl_register_ops); 793EXPORT_SYMBOL(genl_unregister_ops); 794EXPORT_SYMBOL(genl_register_family); 795EXPORT_SYMBOL(genl_unregister_family);