ctrl.c revision 26328fc3933f377c47fb8b06feabbde5e12ed650
165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim/*
265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim * ctrl.c	generic netlink controller
365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim *
465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim *		This program is free software; you can distribute it and/or
565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim *		modify it under the terms of the GNU General Public License
665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim *		as published by the Free Software Foundation; either version
765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim *		2 of the License, or (at your option) any later version.
865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim *
965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim * Authors:  J Hadi Salim (hadi@cyberus.ca)
1065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim */
1165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
1265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <stdio.h>
1365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <stdlib.h>
1465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <unistd.h>
1565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <syslog.h>
1665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <fcntl.h>
1765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <sys/socket.h>
1865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <netinet/in.h>
1965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <arpa/inet.h>
2065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <string.h>
2165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
2265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include "utils.h"
2365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include "genl_utils.h"
2465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
2526328fc3933f377c47fb8b06feabbde5e12ed650jamal#define GENL_MAX_FAM_OPS	256
2665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimstatic int usage(void)
2765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim{
2865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	fprintf(stderr,"Usage: ctrl <CMD>\n" \
2965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		       "CMD   := get <PARMS> | list | monitor\n" \
3065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		       "PARMS := name <name> | id <id>\n" \
3165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		       "Examples:\n" \
3265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		       "\tctrl ls\n" \
3365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		       "\tctrl monitor\n" \
3465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		       "\tctrl get name foobar\n" \
3565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		       "\tctrl get id 0xF\n");
3665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	return -1;
3765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim}
3865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
3965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimint genl_ctrl_resolve_family(const char *family)
4065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim{
4165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	struct rtnl_handle rth;
4265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	struct nlmsghdr *nlh;
4365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	struct genlmsghdr *ghdr;
4465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	int ret = 0;
4565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	struct {
4665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		struct nlmsghdr         n;
4765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		char                    buf[4096];
4865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	} req;
4965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
5065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	memset(&req, 0, sizeof(req));
5165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
5265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	nlh = &req.n;
5365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
5465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
5565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	nlh->nlmsg_type = GENL_ID_CTRL;
5665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
5765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	ghdr = NLMSG_DATA(&req.n);
5865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	ghdr->cmd = CTRL_CMD_GETFAMILY;
5965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
6065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC) < 0) {
6165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		fprintf(stderr, "Cannot open generic netlink socket\n");
6265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		exit(1);
6365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	}
6465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
6565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	addattr_l(nlh, 128, CTRL_ATTR_FAMILY_NAME, family, strlen(family) + 1);
6665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
6765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL) < 0) {
6865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		fprintf(stderr, "Error talking to the kernel\n");
6965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		goto errout;
7065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	}
7165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
7265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	{
7365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		struct rtattr *tb[CTRL_ATTR_MAX + 1];
7465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		struct genlmsghdr *ghdr = NLMSG_DATA(nlh);
7565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		int len = nlh->nlmsg_len;
7665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		struct rtattr *attrs;
7765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
7865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		if (nlh->nlmsg_type !=  GENL_ID_CTRL) {
7965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			fprintf(stderr, "Not a controller message, nlmsg_len=%d "
8065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim				"nlmsg_type=0x%x\n", nlh->nlmsg_len, nlh->nlmsg_type);
8165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			goto errout;
8265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		}
8365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
8465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		if (ghdr->cmd != CTRL_CMD_NEWFAMILY) {
8565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			fprintf(stderr, "Unkown controller command %d\n", ghdr->cmd);
8665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			goto errout;
8765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		}
8865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
8965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		len -= NLMSG_LENGTH(GENL_HDRLEN);
9065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
9165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		if (len < 0) {
9265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			fprintf(stderr, "wrong controller message len %d\n", len);
9365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			return -1;
9465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		}
9565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
9665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
9765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		parse_rtattr(tb, CTRL_ATTR_MAX, attrs, len);
9865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
9965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		if (tb[CTRL_ATTR_FAMILY_ID] == NULL) {
10065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			fprintf(stderr, "Missing family id TLV\n");
10165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			goto errout;
10265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		}
10365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
10465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		ret = *(__u16 *) RTA_DATA(tb[CTRL_ATTR_FAMILY_ID]);
10565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	}
10665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
10765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimerrout:
10865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	rtnl_close(&rth);
10965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	return ret;
11065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim}
11165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
11226328fc3933f377c47fb8b06feabbde5e12ed650jamalvoid print_ctrl_cmd_flags(FILE *fp, __u32 fl)
11326328fc3933f377c47fb8b06feabbde5e12ed650jamal{
11426328fc3933f377c47fb8b06feabbde5e12ed650jamal	fprintf(fp, "\n\t\tCapabilities (0x%x):\n ", fl);
11526328fc3933f377c47fb8b06feabbde5e12ed650jamal	if (!fl) {
11626328fc3933f377c47fb8b06feabbde5e12ed650jamal		fprintf(fp, "\n");
11726328fc3933f377c47fb8b06feabbde5e12ed650jamal		return;
11826328fc3933f377c47fb8b06feabbde5e12ed650jamal	}
11926328fc3933f377c47fb8b06feabbde5e12ed650jamal	fprintf(fp, "\t\t ");
12026328fc3933f377c47fb8b06feabbde5e12ed650jamal
12126328fc3933f377c47fb8b06feabbde5e12ed650jamal	if (fl & GENL_ADMIN_PERM)
12226328fc3933f377c47fb8b06feabbde5e12ed650jamal		fprintf(fp, " requires admin permission;");
12326328fc3933f377c47fb8b06feabbde5e12ed650jamal	if (fl & GENL_CMD_CAP_DO)
12426328fc3933f377c47fb8b06feabbde5e12ed650jamal		fprintf(fp, " can doit;");
12526328fc3933f377c47fb8b06feabbde5e12ed650jamal	if (fl & GENL_CMD_CAP_DUMP)
12626328fc3933f377c47fb8b06feabbde5e12ed650jamal		fprintf(fp, " can dumpit;");
12726328fc3933f377c47fb8b06feabbde5e12ed650jamal	if (fl & GENL_CMD_CAP_HASPOL)
12826328fc3933f377c47fb8b06feabbde5e12ed650jamal		fprintf(fp, " has policy");
12926328fc3933f377c47fb8b06feabbde5e12ed650jamal
13026328fc3933f377c47fb8b06feabbde5e12ed650jamal	fprintf(fp, "\n");
13126328fc3933f377c47fb8b06feabbde5e12ed650jamal}
13226328fc3933f377c47fb8b06feabbde5e12ed650jamal
13326328fc3933f377c47fb8b06feabbde5e12ed650jamalstatic int print_ctrl_cmds(FILE *fp, struct rtattr *arg, __u32 ctrl_ver)
13426328fc3933f377c47fb8b06feabbde5e12ed650jamal{
13526328fc3933f377c47fb8b06feabbde5e12ed650jamal	struct rtattr *tb[CTRL_ATTR_OP_MAX + 1];
13626328fc3933f377c47fb8b06feabbde5e12ed650jamal
13726328fc3933f377c47fb8b06feabbde5e12ed650jamal	if (arg == NULL)
13826328fc3933f377c47fb8b06feabbde5e12ed650jamal		return -1;
13926328fc3933f377c47fb8b06feabbde5e12ed650jamal
14026328fc3933f377c47fb8b06feabbde5e12ed650jamal	parse_rtattr_nested(tb, CTRL_ATTR_OP_MAX, arg);
14126328fc3933f377c47fb8b06feabbde5e12ed650jamal	if (tb[CTRL_ATTR_OP_ID]) {
14226328fc3933f377c47fb8b06feabbde5e12ed650jamal		__u32 *id = RTA_DATA(tb[CTRL_ATTR_OP_ID]);
14326328fc3933f377c47fb8b06feabbde5e12ed650jamal		fprintf(fp, " ID-0x%x ",*id);
14426328fc3933f377c47fb8b06feabbde5e12ed650jamal	}
14526328fc3933f377c47fb8b06feabbde5e12ed650jamal	/* we are only gonna do this for newer version of the controller */
14626328fc3933f377c47fb8b06feabbde5e12ed650jamal	if (tb[CTRL_ATTR_OP_FLAGS] && ctrl_ver >= 0x2) {
14726328fc3933f377c47fb8b06feabbde5e12ed650jamal		__u32 *fl = RTA_DATA(tb[CTRL_ATTR_OP_FLAGS]);
14826328fc3933f377c47fb8b06feabbde5e12ed650jamal		print_ctrl_cmd_flags(fp, *fl);
14926328fc3933f377c47fb8b06feabbde5e12ed650jamal	}
15026328fc3933f377c47fb8b06feabbde5e12ed650jamal	return 0;
15126328fc3933f377c47fb8b06feabbde5e12ed650jamal
15226328fc3933f377c47fb8b06feabbde5e12ed650jamal}
15326328fc3933f377c47fb8b06feabbde5e12ed650jamal
15426328fc3933f377c47fb8b06feabbde5e12ed650jamal/*
15526328fc3933f377c47fb8b06feabbde5e12ed650jamal * The controller sends one nlmsg per family
15626328fc3933f377c47fb8b06feabbde5e12ed650jamal*/
15765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimstatic int print_ctrl(const struct sockaddr_nl *who, struct nlmsghdr *n,
15865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		      void *arg)
15965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim{
16065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	struct rtattr *tb[CTRL_ATTR_MAX + 1];
16165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	struct genlmsghdr *ghdr = NLMSG_DATA(n);
16265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	int len = n->nlmsg_len;
16365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	struct rtattr *attrs;
16465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	FILE *fp = (FILE *) arg;
16526328fc3933f377c47fb8b06feabbde5e12ed650jamal	__u32 ctrl_v = 0x1;
16665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
16765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	if (n->nlmsg_type !=  GENL_ID_CTRL) {
16865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		fprintf(stderr, "Not a controller message, nlmsg_len=%d "
16965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			"nlmsg_type=0x%x\n", n->nlmsg_len, n->nlmsg_type);
17065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		return 0;
17165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	}
17265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
17365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	if (ghdr->cmd != CTRL_CMD_GETFAMILY &&
17465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	    ghdr->cmd != CTRL_CMD_DELFAMILY &&
17565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	    ghdr->cmd != CTRL_CMD_NEWFAMILY) {
17665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		fprintf(stderr, "Unkown controller command %d\n", ghdr->cmd);
17765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		return 0;
17865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	}
17965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
18065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	len -= NLMSG_LENGTH(GENL_HDRLEN);
18165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
18265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	if (len < 0) {
18365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		fprintf(stderr, "wrong controller message len %d\n", len);
18465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		return -1;
18565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	}
18665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
18765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
18865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	parse_rtattr(tb, CTRL_ATTR_MAX, attrs, len);
18965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
19065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	if (tb[CTRL_ATTR_FAMILY_NAME]) {
19165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		char *name = RTA_DATA(tb[CTRL_ATTR_FAMILY_NAME]);
19226328fc3933f377c47fb8b06feabbde5e12ed650jamal		fprintf(fp, "\nName: %s\n",name);
19365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	}
19465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	if (tb[CTRL_ATTR_FAMILY_ID]) {
19565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		__u16 *id = RTA_DATA(tb[CTRL_ATTR_FAMILY_ID]);
19626328fc3933f377c47fb8b06feabbde5e12ed650jamal		fprintf(fp, "\tID: 0x%x ",*id);
19726328fc3933f377c47fb8b06feabbde5e12ed650jamal	}
19826328fc3933f377c47fb8b06feabbde5e12ed650jamal	if (tb[CTRL_ATTR_VERSION]) {
19926328fc3933f377c47fb8b06feabbde5e12ed650jamal		__u32 *v = RTA_DATA(tb[CTRL_ATTR_VERSION]);
20026328fc3933f377c47fb8b06feabbde5e12ed650jamal		fprintf(fp, " Version: 0x%x ",*v);
20126328fc3933f377c47fb8b06feabbde5e12ed650jamal		ctrl_v = *v;
20265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	}
20326328fc3933f377c47fb8b06feabbde5e12ed650jamal	if (tb[CTRL_ATTR_HDRSIZE]) {
20426328fc3933f377c47fb8b06feabbde5e12ed650jamal		__u32 *h = RTA_DATA(tb[CTRL_ATTR_HDRSIZE]);
20526328fc3933f377c47fb8b06feabbde5e12ed650jamal		fprintf(fp, " header size: %d ",*h);
20626328fc3933f377c47fb8b06feabbde5e12ed650jamal	}
20726328fc3933f377c47fb8b06feabbde5e12ed650jamal	if (tb[CTRL_ATTR_MAXATTR]) {
20826328fc3933f377c47fb8b06feabbde5e12ed650jamal		__u32 *ma = RTA_DATA(tb[CTRL_ATTR_MAXATTR]);
20926328fc3933f377c47fb8b06feabbde5e12ed650jamal		fprintf(fp, " max attribs: %d ",*ma);
21026328fc3933f377c47fb8b06feabbde5e12ed650jamal	}
21126328fc3933f377c47fb8b06feabbde5e12ed650jamal	/* end of family definitions .. */
21226328fc3933f377c47fb8b06feabbde5e12ed650jamal	fprintf(fp,"\n");
21326328fc3933f377c47fb8b06feabbde5e12ed650jamal	if (tb[CTRL_ATTR_OPS]) {
21426328fc3933f377c47fb8b06feabbde5e12ed650jamal		struct rtattr *tb2[GENL_MAX_FAM_OPS];
21526328fc3933f377c47fb8b06feabbde5e12ed650jamal		int i=0;
21626328fc3933f377c47fb8b06feabbde5e12ed650jamal		parse_rtattr_nested(tb2, GENL_MAX_FAM_OPS, tb[CTRL_ATTR_OPS]);
21726328fc3933f377c47fb8b06feabbde5e12ed650jamal		fprintf(fp, "\tcommands supported: \n");
21826328fc3933f377c47fb8b06feabbde5e12ed650jamal		for (i = 0; i < GENL_MAX_FAM_OPS; i++) {
21926328fc3933f377c47fb8b06feabbde5e12ed650jamal			if (tb2[i]) {
22026328fc3933f377c47fb8b06feabbde5e12ed650jamal				fprintf(fp, "\t\t#%d: ", i);
22126328fc3933f377c47fb8b06feabbde5e12ed650jamal				if (0 > print_ctrl_cmds(fp, tb2[i], ctrl_v)) {
22226328fc3933f377c47fb8b06feabbde5e12ed650jamal					fprintf(fp, "Error printing command\n");
22326328fc3933f377c47fb8b06feabbde5e12ed650jamal				}
22426328fc3933f377c47fb8b06feabbde5e12ed650jamal				/* for next command */
22526328fc3933f377c47fb8b06feabbde5e12ed650jamal				fprintf(fp,"\n");
22626328fc3933f377c47fb8b06feabbde5e12ed650jamal			}
22726328fc3933f377c47fb8b06feabbde5e12ed650jamal		}
22865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
22926328fc3933f377c47fb8b06feabbde5e12ed650jamal		/* end of family::cmds definitions .. */
23026328fc3933f377c47fb8b06feabbde5e12ed650jamal		fprintf(fp,"\n");
23126328fc3933f377c47fb8b06feabbde5e12ed650jamal	}
23265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	fflush(fp);
23365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	return 0;
23465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim}
23565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
23665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimstatic int ctrl_list(int cmd, int argc, char **argv)
23765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim{
23865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	struct rtnl_handle rth;
23965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	struct nlmsghdr *nlh;
24065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	struct genlmsghdr *ghdr;
24165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	int ret = -1;
24265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	char d[GENL_NAMSIZ];
24365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	struct {
24465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		struct nlmsghdr         n;
24565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		char                    buf[4096];
24665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	} req;
24765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
24865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	memset(&req, 0, sizeof(req));
24965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
25065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	nlh = &req.n;
25165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
25265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
25365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	nlh->nlmsg_type = GENL_ID_CTRL;
25465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
25565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	ghdr = NLMSG_DATA(&req.n);
25665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	ghdr->cmd = CTRL_CMD_GETFAMILY;
25765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
25865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC) < 0) {
25965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		fprintf(stderr, "Cannot open generic netlink socket\n");
26065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		exit(1);
26165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	}
26265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
26365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	if (cmd == CTRL_CMD_GETFAMILY) {
26465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		if (argc != 2) {
26565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			fprintf(stderr, "Wrong number of params\n");
26665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			return -1;
26765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		}
26865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
26965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		if (matches(*argv, "name") == 0) {
27065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			NEXT_ARG();
27165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			strncpy(d, *argv, sizeof (d) - 1);
27265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			addattr_l(nlh, 128, CTRL_ATTR_FAMILY_NAME,
27365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim				  d, strlen(d) + 1);
27465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		} else if (matches(*argv, "id") == 0) {
27565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			__u16 id;
27665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			NEXT_ARG();
27765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			if (get_u16(&id, *argv, 0)) {
27865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim				fprintf(stderr, "Illegal \"id\"\n");
27965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim				goto ctrl_done;
28065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			}
28165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
28265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			addattr_l(nlh, 128, CTRL_ATTR_FAMILY_ID, &id, 2);
28365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
28465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		} else {
28565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			fprintf(stderr, "Wrong params\n");
28665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			goto ctrl_done;
28765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		}
28865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
28965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL) < 0) {
29065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			fprintf(stderr, "Error talking to the kernel\n");
29165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			goto ctrl_done;
29265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		}
29365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
29465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		if (print_ctrl(NULL, nlh, (void *) stdout) < 0) {
29565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			fprintf(stderr, "Dump terminated\n");
29665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			goto ctrl_done;
29765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		}
29865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
29965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	}
30065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
30165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	if (cmd == CTRL_CMD_UNSPEC) {
30265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		nlh->nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
30365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		nlh->nlmsg_seq = rth.dump = ++rth.seq;
30465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
30565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		if (rtnl_send(&rth, (const char *) nlh, nlh->nlmsg_len) < 0) {
30665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			perror("Failed to send dump request\n");
30765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			goto ctrl_done;
30865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		}
30965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
31065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		rtnl_dump_filter(&rth, print_ctrl, stdout, NULL, NULL);
31165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
31265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim        }
31365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
31465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	ret = 0;
31565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimctrl_done:
31665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	rtnl_close(&rth);
31765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	return ret;
31865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim}
31965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
32065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimstatic int ctrl_listen(int argc, char **argv)
32165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim{
32265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	struct rtnl_handle rth;
32365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
32465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	if (rtnl_open_byproto(&rth, nl_mgrp(GENL_ID_CTRL), NETLINK_GENERIC) < 0) {
32565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		fprintf(stderr, "Canot open generic netlink socket\n");
32665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		return -1;
32765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	}
32865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
32965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	if (rtnl_listen(&rth, print_ctrl, (void *) stdout) < 0)
33065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		return -1;
33165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
33265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	return 0;
33365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim}
33465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
33565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimstatic int parse_ctrl(struct genl_util *a, int argc, char **argv)
33665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim{
33765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	argv++;
33865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	if (--argc <= 0) {
33965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		fprintf(stderr, "wrong controller params\n");
34065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		return -1;
34165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	}
34265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
34365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	if (matches(*argv, "monitor") == 0)
34465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		return ctrl_listen(argc-1, argv+1);
34565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	if (matches(*argv, "get") == 0)
34665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		return ctrl_list(CTRL_CMD_GETFAMILY, argc-1, argv+1);
34765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	if (matches(*argv, "list") == 0 ||
34865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	    matches(*argv, "show") == 0 ||
34965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	    matches(*argv, "lst") == 0)
35065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		return ctrl_list(CTRL_CMD_UNSPEC, argc-1, argv+1);
35165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	if (matches(*argv, "help") == 0)
35265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		return usage();
35365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
35465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	fprintf(stderr, "ctrl command \"%s\" is unknown, try \"ctrl -help\".\n",
35565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		*argv);
35665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
35765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	return -1;
35865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim}
35965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
36065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimstruct genl_util ctrl_genl_util = {
36165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	.name = "ctrl",
36265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	.parse_genlopt = parse_ctrl,
36365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	.print_genlopt = print_ctrl,
36465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim};
365