⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 genetlink.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	genl_unregister_mc_groups(family);	genl_lock();	list_for_each_entry(rc, genl_family_chain(family->id), family_list) {		if (family->id != rc->id || strcmp(rc->name, family->name))			continue;		list_del(&rc->family_list);		INIT_LIST_HEAD(&family->ops_list);		genl_unlock();		kfree(family->attrbuf);		genl_ctrl_event(CTRL_CMD_DELFAMILY, family);		return 0;	}	genl_unlock();	return -ENOENT;}static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh){	struct genl_ops *ops;	struct genl_family *family;	struct genl_info info;	struct genlmsghdr *hdr = nlmsg_data(nlh);	int hdrlen, err;	family = genl_family_find_byid(nlh->nlmsg_type);	if (family == NULL)		return -ENOENT;	hdrlen = GENL_HDRLEN + family->hdrsize;	if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))		return -EINVAL;	ops = genl_get_cmd(hdr->cmd, family);	if (ops == NULL)		return -EOPNOTSUPP;	if ((ops->flags & GENL_ADMIN_PERM) &&	    security_netlink_recv(skb, CAP_NET_ADMIN))		return -EPERM;	if (nlh->nlmsg_flags & NLM_F_DUMP) {		if (ops->dumpit == NULL)			return -EOPNOTSUPP;		return netlink_dump_start(genl_sock, skb, nlh,					  ops->dumpit, ops->done);	}	if (ops->doit == NULL)		return -EOPNOTSUPP;	if (family->attrbuf) {		err = nlmsg_parse(nlh, hdrlen, family->attrbuf, family->maxattr,				  ops->policy);		if (err < 0)			return err;	}	info.snd_seq = nlh->nlmsg_seq;	info.snd_pid = NETLINK_CB(skb).pid;	info.nlhdr = nlh;	info.genlhdr = nlmsg_data(nlh);	info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN;	info.attrs = family->attrbuf;	return ops->doit(skb, &info);}static void genl_rcv(struct sk_buff *skb){	genl_lock();	netlink_rcv_skb(skb, &genl_rcv_msg);	genl_unlock();}/************************************************************************** * Controller **************************************************************************/static struct genl_family genl_ctrl = {	.id = GENL_ID_CTRL,	.name = "nlctrl",	.version = 0x2,	.maxattr = CTRL_ATTR_MAX,};static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq,			  u32 flags, struct sk_buff *skb, u8 cmd){	void *hdr;	hdr = genlmsg_put(skb, pid, seq, &genl_ctrl, flags, cmd);	if (hdr == NULL)		return -1;	NLA_PUT_STRING(skb, CTRL_ATTR_FAMILY_NAME, family->name);	NLA_PUT_U16(skb, CTRL_ATTR_FAMILY_ID, family->id);	NLA_PUT_U32(skb, CTRL_ATTR_VERSION, family->version);	NLA_PUT_U32(skb, CTRL_ATTR_HDRSIZE, family->hdrsize);	NLA_PUT_U32(skb, CTRL_ATTR_MAXATTR, family->maxattr);	if (!list_empty(&family->ops_list)) {		struct nlattr *nla_ops;		struct genl_ops *ops;		int idx = 1;		nla_ops = nla_nest_start(skb, CTRL_ATTR_OPS);		if (nla_ops == NULL)			goto nla_put_failure;		list_for_each_entry(ops, &family->ops_list, ops_list) {			struct nlattr *nest;			nest = nla_nest_start(skb, idx++);			if (nest == NULL)				goto nla_put_failure;			NLA_PUT_U32(skb, CTRL_ATTR_OP_ID, ops->cmd);			NLA_PUT_U32(skb, CTRL_ATTR_OP_FLAGS, ops->flags);			nla_nest_end(skb, nest);		}		nla_nest_end(skb, nla_ops);	}	if (!list_empty(&family->mcast_groups)) {		struct genl_multicast_group *grp;		struct nlattr *nla_grps;		int idx = 1;		nla_grps = nla_nest_start(skb, CTRL_ATTR_MCAST_GROUPS);		if (nla_grps == NULL)			goto nla_put_failure;		list_for_each_entry(grp, &family->mcast_groups, list) {			struct nlattr *nest;			nest = nla_nest_start(skb, idx++);			if (nest == NULL)				goto nla_put_failure;			NLA_PUT_U32(skb, CTRL_ATTR_MCAST_GRP_ID, grp->id);			NLA_PUT_STRING(skb, CTRL_ATTR_MCAST_GRP_NAME,				       grp->name);			nla_nest_end(skb, nest);		}		nla_nest_end(skb, nla_grps);	}	return genlmsg_end(skb, hdr);nla_put_failure:	return genlmsg_cancel(skb, hdr);}static int ctrl_fill_mcgrp_info(struct genl_multicast_group *grp, u32 pid,				u32 seq, u32 flags, struct sk_buff *skb,				u8 cmd){	void *hdr;	struct nlattr *nla_grps;	struct nlattr *nest;	hdr = genlmsg_put(skb, pid, seq, &genl_ctrl, flags, cmd);	if (hdr == NULL)		return -1;	NLA_PUT_STRING(skb, CTRL_ATTR_FAMILY_NAME, grp->family->name);	NLA_PUT_U16(skb, CTRL_ATTR_FAMILY_ID, grp->family->id);	nla_grps = nla_nest_start(skb, CTRL_ATTR_MCAST_GROUPS);	if (nla_grps == NULL)		goto nla_put_failure;	nest = nla_nest_start(skb, 1);	if (nest == NULL)		goto nla_put_failure;	NLA_PUT_U32(skb, CTRL_ATTR_MCAST_GRP_ID, grp->id);	NLA_PUT_STRING(skb, CTRL_ATTR_MCAST_GRP_NAME,		       grp->name);	nla_nest_end(skb, nest);	nla_nest_end(skb, nla_grps);	return genlmsg_end(skb, hdr);nla_put_failure:	return genlmsg_cancel(skb, hdr);}static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb){	int i, n = 0;	struct genl_family *rt;	int chains_to_skip = cb->args[0];	int fams_to_skip = cb->args[1];	if (chains_to_skip != 0)		genl_lock();	for (i = 0; i < GENL_FAM_TAB_SIZE; i++) {		if (i < chains_to_skip)			continue;		n = 0;		list_for_each_entry(rt, genl_family_chain(i), family_list) {			if (++n < fams_to_skip)				continue;			if (ctrl_fill_info(rt, NETLINK_CB(cb->skb).pid,					   cb->nlh->nlmsg_seq, NLM_F_MULTI,					   skb, CTRL_CMD_NEWFAMILY) < 0)				goto errout;		}		fams_to_skip = 0;	}errout:	if (chains_to_skip != 0)		genl_unlock();	cb->args[0] = i;	cb->args[1] = n;	return skb->len;}static struct sk_buff *ctrl_build_family_msg(struct genl_family *family,					     u32 pid, int seq, u8 cmd){	struct sk_buff *skb;	int err;	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);	if (skb == NULL)		return ERR_PTR(-ENOBUFS);	err = ctrl_fill_info(family, pid, seq, 0, skb, cmd);	if (err < 0) {		nlmsg_free(skb);		return ERR_PTR(err);	}	return skb;}static struct sk_buff *ctrl_build_mcgrp_msg(struct genl_multicast_group *grp,					    u32 pid, int seq, u8 cmd){	struct sk_buff *skb;	int err;	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);	if (skb == NULL)		return ERR_PTR(-ENOBUFS);	err = ctrl_fill_mcgrp_info(grp, pid, seq, 0, skb, cmd);	if (err < 0) {		nlmsg_free(skb);		return ERR_PTR(err);	}	return skb;}static const struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {	[CTRL_ATTR_FAMILY_ID]	= { .type = NLA_U16 },	[CTRL_ATTR_FAMILY_NAME]	= { .type = NLA_NUL_STRING,				    .len = GENL_NAMSIZ - 1 },};static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info){	struct sk_buff *msg;	struct genl_family *res = NULL;	int err = -EINVAL;	if (info->attrs[CTRL_ATTR_FAMILY_ID]) {		u16 id = nla_get_u16(info->attrs[CTRL_ATTR_FAMILY_ID]);		res = genl_family_find_byid(id);	}	if (info->attrs[CTRL_ATTR_FAMILY_NAME]) {		char *name;		name = nla_data(info->attrs[CTRL_ATTR_FAMILY_NAME]);		res = genl_family_find_byname(name);	}	if (res == NULL) {		err = -ENOENT;		goto errout;	}	msg = ctrl_build_family_msg(res, info->snd_pid, info->snd_seq,				    CTRL_CMD_NEWFAMILY);	if (IS_ERR(msg)) {		err = PTR_ERR(msg);		goto errout;	}	err = genlmsg_reply(msg, info);errout:	return err;}static int genl_ctrl_event(int event, void *data){	struct sk_buff *msg;	if (genl_sock == NULL)		return 0;	switch (event) {	case CTRL_CMD_NEWFAMILY:	case CTRL_CMD_DELFAMILY:		msg = ctrl_build_family_msg(data, 0, 0, event);		if (IS_ERR(msg))			return PTR_ERR(msg);		genlmsg_multicast(msg, 0, GENL_ID_CTRL, GFP_KERNEL);		break;	case CTRL_CMD_NEWMCAST_GRP:	case CTRL_CMD_DELMCAST_GRP:		msg = ctrl_build_mcgrp_msg(data, 0, 0, event);		if (IS_ERR(msg))			return PTR_ERR(msg);		genlmsg_multicast(msg, 0, GENL_ID_CTRL, GFP_KERNEL);		break;	}	return 0;}static struct genl_ops genl_ctrl_ops = {	.cmd		= CTRL_CMD_GETFAMILY,	.doit		= ctrl_getfamily,	.dumpit		= ctrl_dumpfamily,	.policy		= ctrl_policy,};static struct genl_multicast_group notify_grp = {	.name		= "notify",};static int __init genl_init(void){	int i, err;	for (i = 0; i < GENL_FAM_TAB_SIZE; i++)		INIT_LIST_HEAD(&family_ht[i]);	err = genl_register_family(&genl_ctrl);	if (err < 0)		goto errout;	err = genl_register_ops(&genl_ctrl, &genl_ctrl_ops);	if (err < 0)		goto errout_register;	netlink_set_nonroot(NETLINK_GENERIC, NL_NONROOT_RECV);	/* we'll bump the group number right afterwards */	genl_sock = netlink_kernel_create(&init_net, NETLINK_GENERIC, 0,					  genl_rcv, NULL, THIS_MODULE);	if (genl_sock == NULL)		panic("GENL: Cannot initialize generic netlink\n");	err = genl_register_mc_group(&genl_ctrl, &notify_grp);	if (err < 0)		goto errout_register;	return 0;errout_register:	genl_unregister_family(&genl_ctrl);errout:	panic("GENL: Cannot register controller: %d\n", err);}subsys_initcall(genl_init);EXPORT_SYMBOL(genl_sock);EXPORT_SYMBOL(genl_register_ops);EXPORT_SYMBOL(genl_unregister_ops);EXPORT_SYMBOL(genl_register_family);EXPORT_SYMBOL(genl_unregister_family);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -