Commit 091e0662 authored by David S. Miller's avatar David S. Miller

Merge branch 'genetlink_mcast'

Johannes Berg says:

====================
genetlink: clean up multicast group APIs

The generic netlink multicast group registration doesn't have to
be dynamic, and can thus be simplified just like I did with the
ops. This removes some complexity in registration code.

Additionally, two users of generic netlink already use multicast
groups in a wrong way, add workarounds for those two to keep the
userspace API working, but at the same time make them not clash
with other users of multicast groups as might happen now.

While making it all a bit easier, also prevent such abuse by adding
checks to the APIs so each family can only use the groups it owns.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents dbde4979 2a94fe48
......@@ -78,15 +78,17 @@ enum {
#define ACPI_GENL_VERSION 0x01
#define ACPI_GENL_MCAST_GROUP_NAME "acpi_mc_group"
static const struct genl_multicast_group acpi_event_mcgrps[] = {
{ .name = ACPI_GENL_MCAST_GROUP_NAME, },
};
static struct genl_family acpi_event_genl_family = {
.id = GENL_ID_GENERATE,
.name = ACPI_GENL_FAMILY_NAME,
.version = ACPI_GENL_VERSION,
.maxattr = ACPI_GENL_ATTR_MAX,
};
static struct genl_multicast_group acpi_event_mcgrp = {
.name = ACPI_GENL_MCAST_GROUP_NAME,
.mcgrps = acpi_event_mcgrps,
.n_mcgrps = ARRAY_SIZE(acpi_event_mcgrps),
};
int acpi_bus_generate_netlink_event(const char *device_class,
......@@ -146,7 +148,7 @@ int acpi_bus_generate_netlink_event(const char *device_class,
return result;
}
genlmsg_multicast(skb, 0, acpi_event_mcgrp.id, GFP_ATOMIC);
genlmsg_multicast(&acpi_event_genl_family, skb, 0, 0, GFP_ATOMIC);
return 0;
}
......@@ -154,18 +156,7 @@ EXPORT_SYMBOL(acpi_bus_generate_netlink_event);
static int acpi_event_genetlink_init(void)
{
int result;
result = genl_register_family(&acpi_event_genl_family);
if (result)
return result;
result = genl_register_mc_group(&acpi_event_genl_family,
&acpi_event_mcgrp);
if (result)
genl_unregister_family(&acpi_event_genl_family);
return result;
return genl_register_family(&acpi_event_genl_family);
}
#else
......
......@@ -2670,15 +2670,15 @@ static const struct genl_ops team_nl_ops[] = {
},
};
static struct genl_multicast_group team_change_event_mcgrp = {
.name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME,
static const struct genl_multicast_group team_nl_mcgrps[] = {
{ .name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME, },
};
static int team_nl_send_multicast(struct sk_buff *skb,
struct team *team, u32 portid)
{
return genlmsg_multicast_netns(dev_net(team->dev), skb, 0,
team_change_event_mcgrp.id, GFP_KERNEL);
return genlmsg_multicast_netns(&team_nl_family, dev_net(team->dev),
skb, 0, 0, GFP_KERNEL);
}
static int team_nl_send_event_options_get(struct team *team,
......@@ -2697,23 +2697,8 @@ static int team_nl_send_event_port_get(struct team *team,
static int team_nl_init(void)
{
int err;
err = genl_register_family_with_ops(&team_nl_family, team_nl_ops,
ARRAY_SIZE(team_nl_ops));
if (err)
return err;
err = genl_register_mc_group(&team_nl_family, &team_change_event_mcgrp);
if (err)
goto err_change_event_grp_reg;
return 0;
err_change_event_grp_reg:
genl_unregister_family(&team_nl_family);
return err;
return genl_register_family_with_ops_groups(&team_nl_family, team_nl_ops,
team_nl_mcgrps);
}
static void team_nl_fini(void)
......
......@@ -2148,8 +2148,7 @@ static int hwsim_init_netlink(void)
printk(KERN_INFO "mac80211_hwsim: initializing netlink\n");
rc = genl_register_family_with_ops(&hwsim_genl_family,
hwsim_ops, ARRAY_SIZE(hwsim_ops));
rc = genl_register_family_with_ops(&hwsim_genl_family, hwsim_ops);
if (rc)
goto failure;
......
......@@ -1512,7 +1512,8 @@ static int pmcraid_notify_aen(
}
result =
genlmsg_multicast(skb, 0, pmcraid_event_family.id, GFP_ATOMIC);
genlmsg_multicast(&pmcraid_event_family, skb, 0,
pmcraid_event_family.id, GFP_ATOMIC);
/* If there are no listeners, genlmsg_multicast may return non-zero
* value.
......
......@@ -1606,15 +1606,17 @@ struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name)
EXPORT_SYMBOL_GPL(thermal_zone_get_zone_by_name);
#ifdef CONFIG_NET
static const struct genl_multicast_group thermal_event_mcgrps[] = {
{ .name = THERMAL_GENL_MCAST_GROUP_NAME, },
};
static struct genl_family thermal_event_genl_family = {
.id = GENL_ID_GENERATE,
.name = THERMAL_GENL_FAMILY_NAME,
.version = THERMAL_GENL_VERSION,
.maxattr = THERMAL_GENL_ATTR_MAX,
};
static struct genl_multicast_group thermal_event_mcgrp = {
.name = THERMAL_GENL_MCAST_GROUP_NAME,
.mcgrps = thermal_event_mcgrps,
.n_mcgrps = ARRAY_SIZE(thermal_event_mcgrps),
};
int thermal_generate_netlink_event(struct thermal_zone_device *tz,
......@@ -1675,7 +1677,8 @@ int thermal_generate_netlink_event(struct thermal_zone_device *tz,
return result;
}
result = genlmsg_multicast(skb, 0, thermal_event_mcgrp.id, GFP_ATOMIC);
result = genlmsg_multicast(&thermal_event_genl_family, skb, 0,
0, GFP_ATOMIC);
if (result)
dev_err(&tz->device, "Failed to send netlink event:%d", result);
......@@ -1685,17 +1688,7 @@ EXPORT_SYMBOL_GPL(thermal_generate_netlink_event);
static int genetlink_init(void)
{
int result;
result = genl_register_family(&thermal_event_genl_family);
if (result)
return result;
result = genl_register_mc_group(&thermal_event_genl_family,
&thermal_event_mcgrp);
if (result)
genl_unregister_family(&thermal_event_genl_family);
return result;
return genl_register_family(&thermal_event_genl_family);
}
static void genetlink_exit(void)
......
......@@ -74,14 +74,16 @@ static int user_cmd(struct sk_buff *skb, struct genl_info *info)
return 0;
}
static struct genl_ops dlm_nl_ops = {
static struct genl_ops dlm_nl_ops[] = {
{
.cmd = DLM_CMD_HELLO,
.doit = user_cmd,
},
};
int __init dlm_netlink_init(void)
{
return genl_register_family_with_ops(&family, &dlm_nl_ops, 1);
return genl_register_family_with_ops(&family, dlm_nl_ops);
}
void dlm_netlink_exit(void)
......
......@@ -9,13 +9,25 @@
#include <net/netlink.h>
#include <net/genetlink.h>
static const struct genl_multicast_group quota_mcgrps[] = {
{ .name = "events", },
};
/* Netlink family structure for quota */
static struct genl_family quota_genl_family = {
.id = GENL_ID_GENERATE,
/*
* Needed due to multicast group ID abuse - old code assumed
* the family ID was also a valid multicast group ID (which
* isn't true) and userspace might thus rely on it. Assign a
* static ID for this group to make dealing with that easier.
*/
.id = GENL_ID_VFS_DQUOT,
.hdrsize = 0,
.name = "VFS_DQUOT",
.version = 1,
.maxattr = QUOTA_NL_A_MAX,
.mcgrps = quota_mcgrps,
.n_mcgrps = ARRAY_SIZE(quota_mcgrps),
};
/**
......@@ -78,7 +90,7 @@ void quota_send_warning(struct kqid qid, dev_t dev,
goto attr_err_out;
genlmsg_end(skb, msg_head);
genlmsg_multicast(skb, 0, quota_genl_family.id, GFP_NOFS);
genlmsg_multicast(&quota_genl_family, skb, 0, 0, GFP_NOFS);
return;
attr_err_out:
printk(KERN_ERR "VFS: Not enough space to compose quota message!\n");
......
......@@ -273,49 +273,40 @@ static struct genl_family ZZZ_genl_family __read_mostly = {
* Magic: define multicast groups
* Magic: define multicast group registration helper
*/
#define ZZZ_genl_mcgrps CONCAT_(GENL_MAGIC_FAMILY, _genl_mcgrps)
static const struct genl_multicast_group ZZZ_genl_mcgrps[] = {
#undef GENL_mc_group
#define GENL_mc_group(group) { .name = #group, },
#include GENL_MAGIC_INCLUDE_FILE
};
enum CONCAT_(GENL_MAGIC_FAMILY, group_ids) {
#undef GENL_mc_group
#define GENL_mc_group(group) CONCAT_(GENL_MAGIC_FAMILY, _group_ ## group),
#include GENL_MAGIC_INCLUDE_FILE
};
#undef GENL_mc_group
#define GENL_mc_group(group) \
static struct genl_multicast_group \
CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group) __read_mostly = { \
.name = #group, \
}; \
static int CONCAT_(GENL_MAGIC_FAMILY, _genl_multicast_ ## group)( \
struct sk_buff *skb, gfp_t flags) \
{ \
unsigned int group_id = \
CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group).id; \
if (!group_id) \
return -EINVAL; \
return genlmsg_multicast(skb, 0, group_id, flags); \
CONCAT_(GENL_MAGIC_FAMILY, _group_ ## group); \
return genlmsg_multicast(&ZZZ_genl_family, skb, 0, \
group_id, flags); \
}
#include GENL_MAGIC_INCLUDE_FILE
int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void)
{
int err = genl_register_family_with_ops(&ZZZ_genl_family,
ZZZ_genl_ops, ARRAY_SIZE(ZZZ_genl_ops));
if (err)
return err;
#undef GENL_mc_group
#define GENL_mc_group(group) \
err = genl_register_mc_group(&ZZZ_genl_family, \
&CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group)); \
if (err) \
goto fail; \
else \
pr_info("%s: mcg %s: %u\n", #group, \
__stringify(GENL_MAGIC_FAMILY), \
CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group).id);
#include GENL_MAGIC_INCLUDE_FILE
#undef GENL_mc_group
#define GENL_mc_group(group)
return 0;
fail:
genl_unregister_family(&ZZZ_genl_family);
return err;
int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void)
{
return genl_register_family_with_ops_groups(&ZZZ_genl_family, \
ZZZ_genl_ops, \
ZZZ_genl_mcgrps);
}
void CONCAT_(GENL_MAGIC_FAMILY, _genl_unregister)(void)
......
......@@ -10,16 +10,9 @@
/**
* struct genl_multicast_group - generic netlink multicast group
* @name: name of the multicast group, names are per-family
* @id: multicast group ID, assigned by the core, to use with
* genlmsg_multicast().
* @list: list entry for linking
* @family: pointer to family, need not be set before registering
*/
struct genl_multicast_group {
struct genl_family *family; /* private */
struct list_head list; /* private */
char name[GENL_NAMSIZ];
u32 id;
};
struct genl_ops;
......@@ -40,7 +33,9 @@ struct genl_info;
* undo operations done by pre_doit, for example release locks
* @attrbuf: buffer to store parsed attributes
* @family_list: family list
* @mcast_groups: multicast groups list
* @mcgrps: multicast groups used by this family (private)
* @n_mcgrps: number of multicast groups (private)
* @mcgrp_offset: starting number of multicast group IDs in this family
* @ops: the operations supported by this family (private)
* @n_ops: number of operations supported by this family (private)
*/
......@@ -60,9 +55,11 @@ struct genl_family {
struct genl_info *info);
struct nlattr ** attrbuf; /* private */
const struct genl_ops * ops; /* private */
const struct genl_multicast_group *mcgrps; /* private */
unsigned int n_ops; /* private */
unsigned int n_mcgrps; /* private */
unsigned int mcgrp_offset; /* private */
struct list_head family_list; /* private */
struct list_head mcast_groups; /* private */
struct module *module;
};
......@@ -152,21 +149,32 @@ static inline int genl_register_family(struct genl_family *family)
*
* Return 0 on success or a negative error code.
*/
static inline int genl_register_family_with_ops(struct genl_family *family,
const struct genl_ops *ops, size_t n_ops)
static inline int
_genl_register_family_with_ops_grps(struct genl_family *family,
const struct genl_ops *ops, size_t n_ops,
const struct genl_multicast_group *mcgrps,
size_t n_mcgrps)
{
family->module = THIS_MODULE;
family->ops = ops;
family->n_ops = n_ops;
family->mcgrps = mcgrps;
family->n_mcgrps = n_mcgrps;
return __genl_register_family(family);
}
#define genl_register_family_with_ops(family, ops) \
_genl_register_family_with_ops_grps((family), \
(ops), ARRAY_SIZE(ops), \
NULL, 0)
#define genl_register_family_with_ops_groups(family, ops, grps) \
_genl_register_family_with_ops_grps((family), \
(ops), ARRAY_SIZE(ops), \
(grps), ARRAY_SIZE(grps))
int genl_unregister_family(struct genl_family *family);
int genl_register_mc_group(struct genl_family *family,
struct genl_multicast_group *grp);
void genl_unregister_mc_group(struct genl_family *family,
struct genl_multicast_group *grp);
void genl_notify(struct sk_buff *skb, struct net *net, u32 portid,
void genl_notify(struct genl_family *family,
struct sk_buff *skb, struct net *net, u32 portid,
u32 group, struct nlmsghdr *nlh, gfp_t flags);
void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
......@@ -246,41 +254,54 @@ static inline void genlmsg_cancel(struct sk_buff *skb, void *hdr)
/**
* genlmsg_multicast_netns - multicast a netlink message to a specific netns
* @family: the generic netlink family
* @net: the net namespace
* @skb: netlink message as socket buffer
* @portid: own netlink portid to avoid sending to yourself
* @group: multicast group id
* @group: offset of multicast group in groups array
* @flags: allocation flags
*/
static inline int genlmsg_multicast_netns(struct net *net, struct sk_buff *skb,
static inline int genlmsg_multicast_netns(struct genl_family *family,
struct net *net, struct sk_buff *skb,
u32 portid, unsigned int group, gfp_t flags)
{
if (group >= family->n_mcgrps)
return -EINVAL;
group = family->mcgrp_offset + group;
return nlmsg_multicast(net->genl_sock, skb, portid, group, flags);
}
/**
* genlmsg_multicast - multicast a netlink message to the default netns
* @family: the generic netlink family
* @skb: netlink message as socket buffer
* @portid: own netlink portid to avoid sending to yourself
* @group: multicast group id
* @group: offset of multicast group in groups array
* @flags: allocation flags
*/
static inline int genlmsg_multicast(struct sk_buff *skb, u32 portid,
static inline int genlmsg_multicast(struct genl_family *family,
struct sk_buff *skb, u32 portid,
unsigned int group, gfp_t flags)
{
return genlmsg_multicast_netns(&init_net, skb, portid, group, flags);
if (group >= family->n_mcgrps)
return -EINVAL;
group = family->mcgrp_offset + group;
return genlmsg_multicast_netns(family, &init_net, skb,
portid, group, flags);
}
/**
* genlmsg_multicast_allns - multicast a netlink message to all net namespaces
* @family: the generic netlink family
* @skb: netlink message as socket buffer
* @portid: own netlink portid to avoid sending to yourself
* @group: multicast group id
* @group: offset of multicast group in groups array
* @flags: allocation flags
*
* This function must hold the RTNL or rcu_read_lock().
*/
int genlmsg_multicast_allns(struct sk_buff *skb, u32 portid,
int genlmsg_multicast_allns(struct genl_family *family,
struct sk_buff *skb, u32 portid,
unsigned int group, gfp_t flags);
/**
......@@ -351,5 +372,22 @@ static inline struct sk_buff *genlmsg_new(size_t payload, gfp_t flags)
return nlmsg_new(genlmsg_total_size(payload), flags);
}
/**
* genl_set_err - report error to genetlink broadcast listeners
* @family: the generic netlink family
* @net: the network namespace to report the error to
* @portid: the PORTID of a process that we want to skip (if any)
* @group: the broadcast group that will notice the error
* (this is the offset of the multicast group in the groups array)
* @code: error code, must be negative (as usual in kernelspace)
*
* This function returns the number of broadcast listeners that have set the
* NETLINK_RECV_NO_ENOBUFS socket option.
*/
static inline int genl_set_err(struct genl_family *family, struct net *net,
u32 portid, u32 group, int code)
{
return netlink_set_err(net->genl_sock, portid, group, code);
}
#endif /* __NET_GENERIC_NETLINK_H */
......@@ -27,6 +27,7 @@ struct genlmsghdr {
*/
#define GENL_ID_GENERATE 0
#define GENL_ID_CTRL NLMSG_MIN_TYPE
#define GENL_ID_VFS_DQUOT (NLMSG_MIN_TYPE + 1)
/**************************************************************************
* Controller
......
......@@ -703,8 +703,7 @@ static int __init taskstats_init(void)
{
int rc;
rc = genl_register_family_with_ops(&family, taskstats_ops,
ARRAY_SIZE(taskstats_ops));
rc = genl_register_family_with_ops(&family, taskstats_ops);
if (rc)
return rc;
......
......@@ -106,6 +106,10 @@ static struct sk_buff *reset_per_cpu_data(struct per_cpu_dm_data *data)
return skb;
}
static struct genl_multicast_group dropmon_mcgrps[] = {
{ .name = "events", },
};
static void send_dm_alert(struct work_struct *work)
{
struct sk_buff *skb;
......@@ -116,7 +120,8 @@ static void send_dm_alert(struct work_struct *work)
skb = reset_per_cpu_data(data);
if (skb)
genlmsg_multicast(skb, 0, NET_DM_GRP_ALERT, GFP_KERNEL);
genlmsg_multicast(&net_drop_monitor_family, skb, 0,
0, GFP_KERNEL);
}
/*
......@@ -364,13 +369,13 @@ static int __init init_net_drop_monitor(void)
return -ENOSPC;
}
rc = genl_register_family_with_ops(&net_drop_monitor_family,
dropmon_ops,
ARRAY_SIZE(dropmon_ops));
rc = genl_register_family_with_ops_groups(&net_drop_monitor_family,
dropmon_ops, dropmon_mcgrps);
if (rc) {
pr_err("Could not create drop monitor netlink family\n");
return rc;
}
WARN_ON(net_drop_monitor_family.mcgrp_offset != NET_DM_GRP_ALERT);
rc = register_netdevice_notifier(&dropmon_net_notifier);
if (rc < 0) {
......
......@@ -90,8 +90,8 @@ static struct genl_family hsr_genl_family = {
.maxattr = HSR_A_MAX,
};
static struct genl_multicast_group hsr_network_genl_mcgrp = {
.name = "hsr-network",
static const struct genl_multicast_group hsr_mcgrps[] = {
{ .name = "hsr-network", },
};
......@@ -129,7 +129,7 @@ void hsr_nl_ringerror(struct hsr_priv *hsr_priv, unsigned char addr[ETH_ALEN],
goto nla_put_failure;
genlmsg_end(skb, msg_head);
genlmsg_multicast(skb, 0, hsr_network_genl_mcgrp.id, GFP_ATOMIC);
genlmsg_multicast(&hsr_genl_family, skb, 0, 0, GFP_ATOMIC);
return;
......@@ -163,7 +163,7 @@ void hsr_nl_nodedown(struct hsr_priv *hsr_priv, unsigned char addr[ETH_ALEN])
goto nla_put_failure;
genlmsg_end(skb, msg_head);
genlmsg_multicast(skb, 0, hsr_network_genl_mcgrp.id, GFP_ATOMIC);
genlmsg_multicast(&hsr_genl_family, skb, 0, 0, GFP_ATOMIC);
return;
......@@ -414,19 +414,13 @@ int __init hsr_netlink_init(void)
if (rc)
goto fail_rtnl_link_register;
rc = genl_register_family_with_ops(&hsr_genl_family, hsr_ops,
ARRAY_SIZE(hsr_ops));
rc = genl_register_family_with_ops_groups(&hsr_genl_family, hsr_ops,
hsr_mcgrps);
if (rc)
goto fail_genl_register_family;
rc = genl_register_mc_group(&hsr_genl_family, &hsr_network_genl_mcgrp);
if (rc)
goto fail_genl_register_mc_group;
return 0;
fail_genl_register_mc_group:
genl_unregister_family(&hsr_genl_family);
fail_genl_register_family:
rtnl_link_unregister(&hsr_link_ops);
fail_rtnl_link_register:
......@@ -436,9 +430,7 @@ int __init hsr_netlink_init(void)
void __exit hsr_netlink_exit(void)
{
genl_unregister_mc_group(&hsr_genl_family, &hsr_network_genl_mcgrp);
genl_unregister_family(&hsr_genl_family);
rtnl_link_unregister(&hsr_link_ops);
}
......
......@@ -54,8 +54,10 @@ int ieee802154_dump_phy(struct sk_buff *skb, struct netlink_callback *cb);
int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info);
int ieee802154_del_iface(struct sk_buff *skb, struct genl_info *info);
extern struct genl_multicast_group ieee802154_coord_mcgrp;
extern struct genl_multicast_group ieee802154_beacon_mcgrp;
enum ieee802154_mcgrp_ids {
IEEE802154_COORD_MCGRP,
IEEE802154_BEACON_MCGRP,
};
int ieee802154_associate_req(struct sk_buff *skb, struct genl_info *info);
int ieee802154_associate_resp(struct sk_buff *skb, struct genl_info *info);
......
......@@ -70,7 +70,7 @@ int ieee802154_nl_mcast(struct sk_buff *msg, unsigned int group)
if (genlmsg_end(msg, hdr) < 0)
goto out;
return genlmsg_multicast(msg, 0, group, GFP_ATOMIC);
return genlmsg_multicast(&nl802154_family, msg, 0, group, GFP_ATOMIC);
out:
nlmsg_free(msg);
return -ENOBUFS;
......@@ -125,26 +125,17 @@ static const struct genl_ops ieee8021154_ops[] = {
ieee802154_dump_iface),
};
static const struct genl_multicast_group ieee802154_mcgrps[] = {
[IEEE802154_COORD_MCGRP] = { .name = IEEE802154_MCAST_COORD_NAME, },
[IEEE802154_BEACON_MCGRP] = { .name = IEEE802154_MCAST_BEACON_NAME, },
};
int __init ieee802154_nl_init(void)
{
int rc;
rc = genl_register_family_with_ops(&nl802154_family, ieee8021154_ops,
ARRAY_SIZE(ieee8021154_ops));
if (rc)
return rc;
rc = genl_register_mc_group(&nl802154_family, &ieee802154_coord_mcgrp);
if (rc)
goto fail;
rc = genl_register_mc_group(&nl802154_family, &ieee802154_beacon_mcgrp);
if (rc)
goto fail;
return 0;
fail:
genl_unregister_family(&nl802154_family);
return rc;
return genl_register_family_with_ops_groups(&nl802154_family,
ieee8021154_ops,
ieee802154_mcgrps);
}
void __exit ieee802154_nl_exit(void)
......
......@@ -39,14 +39,6 @@
#include "ieee802154.h"
struct genl_multicast_group ieee802154_coord_mcgrp = {
.name = IEEE802154_MCAST_COORD_NAME,
};
struct genl_multicast_group ieee802154_beacon_mcgrp = {
.name = IEEE802154_MCAST_BEACON_NAME,
};
int ieee802154_nl_assoc_indic(struct net_device *dev,
struct ieee802154_addr *addr, u8 cap)
{
......@@ -72,7 +64,7 @@ int ieee802154_nl_assoc_indic(struct net_device *dev,
nla_put_u8(msg, IEEE802154_ATTR_CAPABILITY, cap))
goto nla_put_failure;
return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id);
return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
nla_put_failure:
nlmsg_free(msg);
......@@ -98,7 +90,7 @@ int ieee802154_nl_assoc_confirm(struct net_device *dev, u16 short_addr,
nla_put_u16(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) ||
nla_put_u8(msg, IEEE802154_ATTR_STATUS, status))
goto nla_put_failure;
return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id);
return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
nla_put_failure:
nlmsg_free(msg);
......@@ -133,7 +125,7 @@ int ieee802154_nl_disassoc_indic(struct net_device *dev,
}
if (nla_put_u8(msg, IEEE802154_ATTR_REASON, reason))
goto nla_put_failure;
return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id);
return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
nla_put_failure:
nlmsg_free(msg);
......@@ -157,7 +149,7 @@ int ieee802154_nl_disassoc_confirm(struct net_device *dev, u8 status)
dev->dev_addr) ||
nla_put_u8(msg, IEEE802154_ATTR_STATUS, status))
goto nla_put_failure;
return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id);
return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
nla_put_failure:
nlmsg_free(msg);
......@@ -183,7 +175,7 @@ int ieee802154_nl_beacon_indic(struct net_device *dev,
nla_put_u16(msg, IEEE802154_ATTR_COORD_SHORT_ADDR, coord_addr) ||
nla_put_u16(msg, IEEE802154_ATTR_COORD_PAN_ID, panid))
goto nla_put_failure;
return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id);
return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
nla_put_failure:
nlmsg_free(msg);
......@@ -214,7 +206,7 @@ int ieee802154_nl_scan_confirm(struct net_device *dev,
(edl &&
nla_put(msg, IEEE802154_ATTR_ED_LIST, 27, edl)))
goto nla_put_failure;
return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id);
return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
nla_put_failure:
nlmsg_free(msg);
......@@ -238,7 +230,7 @@ int ieee802154_nl_start_confirm(struct net_device *dev, u8 status)
dev->dev_addr) ||
nla_put_u8(msg, IEEE802154_ATTR_STATUS, status))
goto nla_put_failure;
return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id);
return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
nla_put_failure:
nlmsg_free(msg);
......
......@@ -1082,8 +1082,7 @@ void __init tcp_metrics_init(void)
if (ret < 0)
goto cleanup;
ret = genl_register_family_with_ops(&tcp_metrics_nl_family,
tcp_metrics_nl_ops,
ARRAY_SIZE(tcp_metrics_nl_ops));
tcp_metrics_nl_ops);
if (ret < 0)
goto cleanup_subsys;
return;
......
......@@ -149,8 +149,7 @@ static const struct genl_ops irda_nl_ops[] = {
int irda_nl_register(void)
{
return genl_register_family_with_ops(&irda_nl_family,
irda_nl_ops, ARRAY_SIZE(irda_nl_ops));
return genl_register_family_with_ops(&irda_nl_family, irda_nl_ops);
}
void irda_nl_unregister(void)
......
......@@ -887,13 +887,8 @@ EXPORT_SYMBOL_GPL(l2tp_nl_unregister_ops);
static int l2tp_nl_init(void)
{
int err;
pr_info("L2TP netlink interface\n");
err = genl_register_family_with_ops(&l2tp_nl_family, l2tp_nl_ops,
ARRAY_SIZE(l2tp_nl_ops));
return err;
return genl_register_family_with_ops(&l2tp_nl_family, l2tp_nl_ops);
}
static void l2tp_nl_cleanup(void)
......
......@@ -3666,7 +3666,7 @@ static const struct genl_ops ip_vs_genl_ops[] __read_mostly = {
static int __init ip_vs_genl_register(void)
{
return genl_register_family_with_ops(&ip_vs_genl_family,
ip_vs_genl_ops, ARRAY_SIZE(ip_vs_genl_ops));
ip_vs_genl_ops);
}
static void ip_vs_genl_unregister(void)
......
......@@ -783,5 +783,5 @@ static const struct genl_ops netlbl_cipsov4_ops[] = {
int __init netlbl_cipsov4_genl_init(void)
{
return genl_register_family_with_ops(&netlbl_cipsov4_gnl_family,
netlbl_cipsov4_ops, ARRAY_SIZE(netlbl_cipsov4_ops));
netlbl_cipsov4_ops);
}
......@@ -779,5 +779,5 @@ static const struct genl_ops netlbl_mgmt_genl_ops[] = {
int __init netlbl_mgmt_genl_init(void)
{
return genl_register_family_with_ops(&netlbl_mgmt_gnl_family,
netlbl_mgmt_genl_ops, ARRAY_SIZE(netlbl_mgmt_genl_ops));
netlbl_mgmt_genl_ops);
}
......@@ -1397,7 +1397,7 @@ static const struct genl_ops netlbl_unlabel_genl_ops[] = {
int __init netlbl_unlabel_genl_init(void)
{
return genl_register_family_with_ops(&netlbl_unlabel_gnl_family,
netlbl_unlabel_genl_ops, ARRAY_SIZE(netlbl_unlabel_genl_ops));
netlbl_unlabel_genl_ops);
}
/*
......
This diff is collapsed.
......@@ -30,8 +30,8 @@
#include "nfc.h"
#include "llcp.h"
static struct genl_multicast_group nfc_genl_event_mcgrp = {
.name = NFC_GENL_MCAST_EVENT_NAME,
static const struct genl_multicast_group nfc_genl_mcgrps[] = {
{ .name = NFC_GENL_MCAST_EVENT_NAME, },
};
static struct genl_family nfc_genl_family = {
......@@ -194,7 +194,7 @@ int nfc_genl_targets_found(struct nfc_dev *dev)
genlmsg_end(msg, hdr);
return genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC);
return genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_ATOMIC);
nla_put_failure:
genlmsg_cancel(msg, hdr);
......@@ -223,7 +223,7 @@ int nfc_genl_target_lost(struct nfc_dev *dev, u32 target_idx)
genlmsg_end(msg, hdr);
genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL);
return 0;
......@@ -255,7 +255,7 @@ int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol)
genlmsg_end(msg, hdr);
genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL);
return 0;
......@@ -285,7 +285,7 @@ int nfc_genl_tm_deactivated(struct nfc_dev *dev)
genlmsg_end(msg, hdr);
genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL);
return 0;
......@@ -318,7 +318,7 @@ int nfc_genl_device_added(struct nfc_dev *dev)
genlmsg_end(msg, hdr);
genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL);
return 0;
......@@ -348,7 +348,7 @@ int nfc_genl_device_removed(struct nfc_dev *dev)
genlmsg_end(msg, hdr);
genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL);
return 0;
......@@ -414,7 +414,7 @@ int nfc_genl_llc_send_sdres(struct nfc_dev *dev, struct hlist_head *sdres_list)
genlmsg_end(msg, hdr);
return genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC);
return genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_ATOMIC);
nla_put_failure:
genlmsg_cancel(msg, hdr);
......@@ -448,7 +448,7 @@ int nfc_genl_se_added(struct nfc_dev *dev, u32 se_idx, u16 type)
genlmsg_end(msg, hdr);
genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL);
return 0;
......@@ -479,7 +479,7 @@ int nfc_genl_se_removed(struct nfc_dev *dev, u32 se_idx)
genlmsg_end(msg, hdr);
genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL);
return 0;
......@@ -600,7 +600,7 @@ int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx,
dev->dep_link_up = true;
genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC);
genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_ATOMIC);
return 0;
......@@ -632,7 +632,7 @@ int nfc_genl_dep_link_down_event(struct nfc_dev *dev)
genlmsg_end(msg, hdr);
genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC);
genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_ATOMIC);
return 0;
......@@ -1137,7 +1137,7 @@ int nfc_genl_fw_download_done(struct nfc_dev *dev, const char *firmware_name,
genlmsg_end(msg, hdr);
genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL);
return 0;
......@@ -1308,7 +1308,7 @@ static void se_io_cb(void *context, u8 *apdu, size_t apdu_len, int err)
genlmsg_end(msg, hdr);
genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL);
kfree(ctx);
......@@ -1536,16 +1536,15 @@ int __init nfc_genl_init(void)
{
int rc;
rc = genl_register_family_with_ops(&nfc_genl_family, nfc_genl_ops,
ARRAY_SIZE(nfc_genl_ops));
rc = genl_register_family_with_ops_groups(&nfc_genl_family,
nfc_genl_ops,
nfc_genl_mcgrps);
if (rc)
return rc;
rc = genl_register_mc_group(&nfc_genl_family, &nfc_genl_event_mcgrp);
netlink_register_notifier(&nl_notifier);
return rc;
return 0;
}
/**
......
......@@ -61,11 +61,11 @@
int ovs_net_id __read_mostly;
static void ovs_notify(struct sk_buff *skb, struct genl_info *info,
struct genl_multicast_group *grp)
static void ovs_notify(struct genl_family *family,
struct sk_buff *skb, struct genl_info *info)
{
genl_notify(skb, genl_info_net(info), info->snd_portid,
grp->id, info->nlhdr, GFP_KERNEL);
genl_notify(family, skb, genl_info_net(info), info->snd_portid,
0, info->nlhdr, GFP_KERNEL);
}
/**
......@@ -877,10 +877,10 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
ovs_unlock();
if (!IS_ERR(reply))
ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
ovs_notify(&dp_flow_genl_family, reply, info);
else
netlink_set_err(sock_net(skb->sk)->genl_sock, 0,
ovs_dp_flow_multicast_group.id, PTR_ERR(reply));
genl_set_err(&dp_flow_genl_family, sock_net(skb->sk), 0,
0, PTR_ERR(reply));
return 0;
err_flow_free:
......@@ -990,7 +990,7 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
ovs_flow_free(flow, true);
ovs_unlock();
ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
ovs_notify(&dp_flow_genl_family, reply, info);
return 0;
unlock:
ovs_unlock();
......@@ -1237,7 +1237,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
ovs_unlock();
ovs_notify(reply, info, &ovs_dp_datapath_multicast_group);
ovs_notify(&dp_datapath_genl_family, reply, info);
return 0;
err_destroy_local_port:
......@@ -1302,7 +1302,7 @@ static int ovs_dp_cmd_del(struct sk_buff *skb, struct genl_info *info)
__dp_destroy(dp);
ovs_unlock();
ovs_notify(reply, info, &ovs_dp_datapath_multicast_group);
ovs_notify(&dp_datapath_genl_family, reply, info);
return 0;
unlock:
......@@ -1326,14 +1326,14 @@ static int ovs_dp_cmd_set(struct sk_buff *skb, struct genl_info *info)
info->snd_seq, OVS_DP_CMD_NEW);
if (IS_ERR(reply)) {
err = PTR_ERR(reply);
netlink_set_err(sock_net(skb->sk)->genl_sock, 0,
ovs_dp_datapath_multicast_group.id, err);
genl_set_err(&dp_datapath_genl_family, sock_net(skb->sk), 0,
0, err);
err = 0;
goto unlock;
}
ovs_unlock();
ovs_notify(reply, info, &ovs_dp_datapath_multicast_group);
ovs_notify(&dp_datapath_genl_family, reply, info);
return 0;
unlock:
......@@ -1425,7 +1425,7 @@ static const struct nla_policy vport_policy[OVS_VPORT_ATTR_MAX + 1] = {
[OVS_VPORT_ATTR_OPTIONS] = { .type = NLA_NESTED },
};
static struct genl_family dp_vport_genl_family = {
struct genl_family dp_vport_genl_family = {
.id = GENL_ID_GENERATE,
.hdrsize = sizeof(struct ovs_header),
.name = OVS_VPORT_FAMILY,
......@@ -1595,7 +1595,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
goto exit_unlock;
}
ovs_notify(reply, info, &ovs_dp_vport_multicast_group);
ovs_notify(&dp_vport_genl_family, reply, info);
exit_unlock:
ovs_unlock();
......@@ -1642,7 +1642,7 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
BUG_ON(err < 0);
ovs_unlock();
ovs_notify(reply, info, &ovs_dp_vport_multicast_group);
ovs_notify(&dp_vport_genl_family, reply, info);
return 0;
exit_free:
......@@ -1679,7 +1679,7 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)
err = 0;
ovs_dp_detach_port(vport);
ovs_notify(reply, info, &ovs_dp_vport_multicast_group);
ovs_notify(&dp_vport_genl_family, reply, info);
exit_unlock:
ovs_unlock();
......@@ -1781,7 +1781,7 @@ struct genl_family_and_ops {
struct genl_family *family;
const struct genl_ops *ops;
int n_ops;
struct genl_multicast_group *group;
const struct genl_multicast_group *group;
};
static const struct genl_family_and_ops dp_genl_families[] = {
......@@ -1817,17 +1817,14 @@ static int dp_register_genl(void)
for (i = 0; i < ARRAY_SIZE(dp_genl_families); i++) {
const struct genl_family_and_ops *f = &dp_genl_families[i];
err = genl_register_family_with_ops(f->family, f->ops,
f->n_ops);
f->family->ops = f->ops;
f->family->n_ops = f->n_ops;
f->family->mcgrps = f->group;
f->family->n_mcgrps = f->group ? 1 : 0;
err = genl_register_family(f->family);
if (err)
goto error;
n_registered++;
if (f->group) {
err = genl_register_mc_group(f->family, f->group);
if (err)
goto error;
}
}
return 0;
......
......@@ -177,6 +177,7 @@ static inline struct vport *ovs_vport_ovsl(const struct datapath *dp, int port_n
}
extern struct notifier_block ovs_dp_device_notifier;
extern struct genl_family dp_vport_genl_family;
extern struct genl_multicast_group ovs_dp_vport_multicast_group;
void ovs_dp_process_received_packet(struct vport *, struct sk_buff *);
......
......@@ -34,15 +34,14 @@ static void dp_detach_port_notify(struct vport *vport)
OVS_VPORT_CMD_DEL);
ovs_dp_detach_port(vport);
if (IS_ERR(notify)) {
netlink_set_err(ovs_dp_get_net(dp)->genl_sock, 0,
ovs_dp_vport_multicast_group.id,
PTR_ERR(notify));
genl_set_err(&dp_vport_genl_family, ovs_dp_get_net(dp), 0,
0, PTR_ERR(notify));
return;
}
genlmsg_multicast_netns(ovs_dp_get_net(dp), notify, 0,
ovs_dp_vport_multicast_group.id,
GFP_KERNEL);
genlmsg_multicast_netns(&dp_vport_genl_family,
ovs_dp_get_net(dp), notify, 0,
0, GFP_KERNEL);
}
void ovs_dp_notify_wq(struct work_struct *work)
......
......@@ -76,9 +76,11 @@ static struct genl_family tipc_genl_family = {
.maxattr = 0,
};
static struct genl_ops tipc_genl_ops = {
static struct genl_ops tipc_genl_ops[] = {
{
.cmd = TIPC_GENL_CMD,
.doit = handle_cmd,
},
};
static int tipc_genl_family_registered;
......@@ -87,8 +89,7 @@ int tipc_netlink_start(void)
{
int res;
res = genl_register_family_with_ops(&tipc_genl_family,
&tipc_genl_ops, 1);
res = genl_register_family_with_ops(&tipc_genl_family, tipc_genl_ops);
if (res) {
pr_err("Failed to register netlink interface\n");
return res;
......
......@@ -279,7 +279,7 @@ int wimax_msg_send(struct wimax_dev *wimax_dev, struct sk_buff *skb)
d_printf(1, dev, "CTX: wimax msg, %zu bytes\n", size);
d_dump(2, dev, msg, size);
genlmsg_multicast(skb, 0, wimax_gnl_mcg.id, GFP_KERNEL);
genlmsg_multicast(&wimax_gnl_family, skb, 0, 0, GFP_KERNEL);
d_printf(1, dev, "CTX: genl multicast done\n");
return 0;
}
......
......@@ -116,8 +116,9 @@ struct sk_buff *wimax_gnl_re_state_change_alloc(
dev_err(dev, "RE_STCH: can't create message\n");
goto error_new;
}
data = genlmsg_put(report_skb, 0, wimax_gnl_mcg.id, &wimax_gnl_family,
0, WIMAX_GNL_RE_STATE_CHANGE);
/* FIXME: sending a group ID as the seq is wrong */
data = genlmsg_put(report_skb, 0, wimax_gnl_family.mcgrp_offset,
&wimax_gnl_family, 0, WIMAX_GNL_RE_STATE_CHANGE);
if (data == NULL) {
dev_err(dev, "RE_STCH: can't put data into message\n");
goto error_put;
......@@ -177,7 +178,7 @@ int wimax_gnl_re_state_change_send(
goto out;
}
genlmsg_end(report_skb, header);
genlmsg_multicast(report_skb, 0, wimax_gnl_mcg.id, GFP_KERNEL);
genlmsg_multicast(&wimax_gnl_family, report_skb, 0, 0, GFP_KERNEL);
out:
d_fnend(3, dev, "(wimax_dev %p report_skb %p) = %d\n",
wimax_dev, report_skb, result);
......@@ -579,8 +580,8 @@ struct genl_family wimax_gnl_family = {
.maxattr = WIMAX_GNL_ATTR_MAX,
};
struct genl_multicast_group wimax_gnl_mcg = {
.name = "msg",
static const struct genl_multicast_group wimax_gnl_mcgrps[] = {
{ .name = "msg", },
};
......@@ -597,21 +598,18 @@ int __init wimax_subsys_init(void)
snprintf(wimax_gnl_family.name, sizeof(wimax_gnl_family.name),
"WiMAX");
result = genl_register_family_with_ops(&wimax_gnl_family, wimax_gnl_ops,
ARRAY_SIZE(wimax_gnl_ops));
result = genl_register_family_with_ops_groups(&wimax_gnl_family,
wimax_gnl_ops,
wimax_gnl_mcgrps);
if (unlikely(result < 0)) {
printk(KERN_ERR "cannot register generic netlink family: %d\n",
result);
goto error_register_family;
}
result = genl_register_mc_group(&wimax_gnl_family, &wimax_gnl_mcg);
if (result < 0)
goto error_mc_group;
d_fnend(4, NULL, "() = 0\n");
return 0;
error_mc_group:
genl_unregister_family(&wimax_gnl_family);
error_register_family:
d_fnend(4, NULL, "() = %d\n", result);
......
......@@ -86,7 +86,6 @@ void wimax_rfkill_rm(struct wimax_dev *);
/* generic netlink */
extern struct genl_family wimax_gnl_family;
extern struct genl_multicast_group wimax_gnl_mcg;
/* ops */
int wimax_gnl_doit_msg_from_user(struct sk_buff *skb, struct genl_info *info);
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment