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 * 980c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg * Authors: J Hadi Salim (hadi@cyberus.ca) 1080c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg * Johannes Berg (johannes@sipsolutions.net) 1165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim */ 1265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 1365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <stdio.h> 1465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <stdlib.h> 1565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <unistd.h> 1665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <syslog.h> 1765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <fcntl.h> 1865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <sys/socket.h> 1965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <netinet/in.h> 2065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <arpa/inet.h> 2165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <string.h> 2265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 2365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include "utils.h" 2465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include "genl_utils.h" 2565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 2626328fc3933f377c47fb8b06feabbde5e12ed650jamal#define GENL_MAX_FAM_OPS 256 2780c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg#define GENL_MAX_FAM_GRPS 256 2880c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg 2965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimstatic int usage(void) 3065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim{ 3165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim fprintf(stderr,"Usage: ctrl <CMD>\n" \ 3265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim "CMD := get <PARMS> | list | monitor\n" \ 3365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim "PARMS := name <name> | id <id>\n" \ 3465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim "Examples:\n" \ 3565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim "\tctrl ls\n" \ 3665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim "\tctrl monitor\n" \ 3765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim "\tctrl get name foobar\n" \ 3865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim "\tctrl get id 0xF\n"); 3965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim return -1; 4065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim} 4165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 4265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimint genl_ctrl_resolve_family(const char *family) 4365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim{ 4465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim struct rtnl_handle rth; 4565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim struct nlmsghdr *nlh; 4665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim struct genlmsghdr *ghdr; 4765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim int ret = 0; 4865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim struct { 4965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim struct nlmsghdr n; 5065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim char buf[4096]; 5165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } req; 5265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 5365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim memset(&req, 0, sizeof(req)); 5465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 5565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim nlh = &req.n; 5665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN); 5765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; 5865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim nlh->nlmsg_type = GENL_ID_CTRL; 5965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 6065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim ghdr = NLMSG_DATA(&req.n); 6165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim ghdr->cmd = CTRL_CMD_GETFAMILY; 6265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 6365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC) < 0) { 6465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim fprintf(stderr, "Cannot open generic netlink socket\n"); 6565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim exit(1); 6665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 6765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 6865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim addattr_l(nlh, 128, CTRL_ATTR_FAMILY_NAME, family, strlen(family) + 1); 6965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 70cd70f3f522e04b4d2fa80ae10292379bf223a53bStephen Hemminger if (rtnl_talk(&rth, nlh, 0, 0, nlh) < 0) { 7165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim fprintf(stderr, "Error talking to the kernel\n"); 7265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim goto errout; 7365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 7465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 7565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim { 7665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim struct rtattr *tb[CTRL_ATTR_MAX + 1]; 7765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim struct genlmsghdr *ghdr = NLMSG_DATA(nlh); 7865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim int len = nlh->nlmsg_len; 7965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim struct rtattr *attrs; 8065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 8165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (nlh->nlmsg_type != GENL_ID_CTRL) { 8265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim fprintf(stderr, "Not a controller message, nlmsg_len=%d " 8365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim "nlmsg_type=0x%x\n", nlh->nlmsg_len, nlh->nlmsg_type); 8465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim goto errout; 8565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 8665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 8765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (ghdr->cmd != CTRL_CMD_NEWFAMILY) { 8880c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg fprintf(stderr, "Unknown controller command %d\n", ghdr->cmd); 8965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim goto errout; 9065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 9165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 9265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim len -= NLMSG_LENGTH(GENL_HDRLEN); 9365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 9465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (len < 0) { 9565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim fprintf(stderr, "wrong controller message len %d\n", len); 9665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim return -1; 9765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 9865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 9965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN); 10065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim parse_rtattr(tb, CTRL_ATTR_MAX, attrs, len); 10165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 10265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (tb[CTRL_ATTR_FAMILY_ID] == NULL) { 10365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim fprintf(stderr, "Missing family id TLV\n"); 10465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim goto errout; 10565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 10665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 107ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger ret = rta_getattr_u16(tb[CTRL_ATTR_FAMILY_ID]); 10865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 10965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 11065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimerrout: 11165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim rtnl_close(&rth); 11265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim return ret; 11365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim} 11465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 11526328fc3933f377c47fb8b06feabbde5e12ed650jamalvoid print_ctrl_cmd_flags(FILE *fp, __u32 fl) 11626328fc3933f377c47fb8b06feabbde5e12ed650jamal{ 11726328fc3933f377c47fb8b06feabbde5e12ed650jamal fprintf(fp, "\n\t\tCapabilities (0x%x):\n ", fl); 11826328fc3933f377c47fb8b06feabbde5e12ed650jamal if (!fl) { 11926328fc3933f377c47fb8b06feabbde5e12ed650jamal fprintf(fp, "\n"); 12026328fc3933f377c47fb8b06feabbde5e12ed650jamal return; 12126328fc3933f377c47fb8b06feabbde5e12ed650jamal } 12226328fc3933f377c47fb8b06feabbde5e12ed650jamal fprintf(fp, "\t\t "); 12326328fc3933f377c47fb8b06feabbde5e12ed650jamal 12426328fc3933f377c47fb8b06feabbde5e12ed650jamal if (fl & GENL_ADMIN_PERM) 12526328fc3933f377c47fb8b06feabbde5e12ed650jamal fprintf(fp, " requires admin permission;"); 12626328fc3933f377c47fb8b06feabbde5e12ed650jamal if (fl & GENL_CMD_CAP_DO) 12726328fc3933f377c47fb8b06feabbde5e12ed650jamal fprintf(fp, " can doit;"); 12826328fc3933f377c47fb8b06feabbde5e12ed650jamal if (fl & GENL_CMD_CAP_DUMP) 12926328fc3933f377c47fb8b06feabbde5e12ed650jamal fprintf(fp, " can dumpit;"); 13026328fc3933f377c47fb8b06feabbde5e12ed650jamal if (fl & GENL_CMD_CAP_HASPOL) 13126328fc3933f377c47fb8b06feabbde5e12ed650jamal fprintf(fp, " has policy"); 13226328fc3933f377c47fb8b06feabbde5e12ed650jamal 13326328fc3933f377c47fb8b06feabbde5e12ed650jamal fprintf(fp, "\n"); 13426328fc3933f377c47fb8b06feabbde5e12ed650jamal} 13526328fc3933f377c47fb8b06feabbde5e12ed650jamal 13626328fc3933f377c47fb8b06feabbde5e12ed650jamalstatic int print_ctrl_cmds(FILE *fp, struct rtattr *arg, __u32 ctrl_ver) 13726328fc3933f377c47fb8b06feabbde5e12ed650jamal{ 13826328fc3933f377c47fb8b06feabbde5e12ed650jamal struct rtattr *tb[CTRL_ATTR_OP_MAX + 1]; 13926328fc3933f377c47fb8b06feabbde5e12ed650jamal 14026328fc3933f377c47fb8b06feabbde5e12ed650jamal if (arg == NULL) 14126328fc3933f377c47fb8b06feabbde5e12ed650jamal return -1; 14226328fc3933f377c47fb8b06feabbde5e12ed650jamal 14326328fc3933f377c47fb8b06feabbde5e12ed650jamal parse_rtattr_nested(tb, CTRL_ATTR_OP_MAX, arg); 14426328fc3933f377c47fb8b06feabbde5e12ed650jamal if (tb[CTRL_ATTR_OP_ID]) { 14526328fc3933f377c47fb8b06feabbde5e12ed650jamal __u32 *id = RTA_DATA(tb[CTRL_ATTR_OP_ID]); 14626328fc3933f377c47fb8b06feabbde5e12ed650jamal fprintf(fp, " ID-0x%x ",*id); 14726328fc3933f377c47fb8b06feabbde5e12ed650jamal } 14826328fc3933f377c47fb8b06feabbde5e12ed650jamal /* we are only gonna do this for newer version of the controller */ 14926328fc3933f377c47fb8b06feabbde5e12ed650jamal if (tb[CTRL_ATTR_OP_FLAGS] && ctrl_ver >= 0x2) { 15026328fc3933f377c47fb8b06feabbde5e12ed650jamal __u32 *fl = RTA_DATA(tb[CTRL_ATTR_OP_FLAGS]); 15126328fc3933f377c47fb8b06feabbde5e12ed650jamal print_ctrl_cmd_flags(fp, *fl); 15226328fc3933f377c47fb8b06feabbde5e12ed650jamal } 15326328fc3933f377c47fb8b06feabbde5e12ed650jamal return 0; 15426328fc3933f377c47fb8b06feabbde5e12ed650jamal 15526328fc3933f377c47fb8b06feabbde5e12ed650jamal} 15626328fc3933f377c47fb8b06feabbde5e12ed650jamal 15780c05b0976be86308e92b2837e0a94c484e388b4Johannes Bergstatic int print_ctrl_grp(FILE *fp, struct rtattr *arg, __u32 ctrl_ver) 15880c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg{ 15980c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg struct rtattr *tb[CTRL_ATTR_MCAST_GRP_MAX + 1]; 16080c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg 16180c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg if (arg == NULL) 16280c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg return -1; 16380c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg 16480c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg parse_rtattr_nested(tb, CTRL_ATTR_MCAST_GRP_MAX, arg); 16580c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg if (tb[2]) { 16680c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg __u32 *id = RTA_DATA(tb[CTRL_ATTR_MCAST_GRP_ID]); 16780c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg fprintf(fp, " ID-0x%x ",*id); 16880c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg } 16980c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg if (tb[1]) { 17080c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg char *name = RTA_DATA(tb[CTRL_ATTR_MCAST_GRP_NAME]); 17180c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg fprintf(fp, " name: %s ", name); 17280c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg } 17380c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg return 0; 17480c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg 17580c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg} 17680c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg 17726328fc3933f377c47fb8b06feabbde5e12ed650jamal/* 17826328fc3933f377c47fb8b06feabbde5e12ed650jamal * The controller sends one nlmsg per family 17926328fc3933f377c47fb8b06feabbde5e12ed650jamal*/ 18065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimstatic int print_ctrl(const struct sockaddr_nl *who, struct nlmsghdr *n, 18165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim void *arg) 18265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim{ 18365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim struct rtattr *tb[CTRL_ATTR_MAX + 1]; 18465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim struct genlmsghdr *ghdr = NLMSG_DATA(n); 18565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim int len = n->nlmsg_len; 18665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim struct rtattr *attrs; 18765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim FILE *fp = (FILE *) arg; 18881c61790d5927dc6ca168b2183000a3efc7bc493Stephen Hemminger __u32 ctrl_v = 0x1; 18965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 19065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (n->nlmsg_type != GENL_ID_CTRL) { 19165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim fprintf(stderr, "Not a controller message, nlmsg_len=%d " 19265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim "nlmsg_type=0x%x\n", n->nlmsg_len, n->nlmsg_type); 19365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim return 0; 19465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 19565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 19665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (ghdr->cmd != CTRL_CMD_GETFAMILY && 19765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim ghdr->cmd != CTRL_CMD_DELFAMILY && 19880c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg ghdr->cmd != CTRL_CMD_NEWFAMILY && 19980c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg ghdr->cmd != CTRL_CMD_NEWMCAST_GRP && 20080c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg ghdr->cmd != CTRL_CMD_DELMCAST_GRP) { 20180c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg fprintf(stderr, "Unknown controller command %d\n", ghdr->cmd); 20265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim return 0; 20365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 20465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 20565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim len -= NLMSG_LENGTH(GENL_HDRLEN); 20665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 20765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (len < 0) { 20865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim fprintf(stderr, "wrong controller message len %d\n", len); 20965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim return -1; 21065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 21165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 21265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN); 21365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim parse_rtattr(tb, CTRL_ATTR_MAX, attrs, len); 21465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 21565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (tb[CTRL_ATTR_FAMILY_NAME]) { 21665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim char *name = RTA_DATA(tb[CTRL_ATTR_FAMILY_NAME]); 21726328fc3933f377c47fb8b06feabbde5e12ed650jamal fprintf(fp, "\nName: %s\n",name); 21865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 21965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (tb[CTRL_ATTR_FAMILY_ID]) { 22065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim __u16 *id = RTA_DATA(tb[CTRL_ATTR_FAMILY_ID]); 22126328fc3933f377c47fb8b06feabbde5e12ed650jamal fprintf(fp, "\tID: 0x%x ",*id); 22226328fc3933f377c47fb8b06feabbde5e12ed650jamal } 22326328fc3933f377c47fb8b06feabbde5e12ed650jamal if (tb[CTRL_ATTR_VERSION]) { 22426328fc3933f377c47fb8b06feabbde5e12ed650jamal __u32 *v = RTA_DATA(tb[CTRL_ATTR_VERSION]); 22526328fc3933f377c47fb8b06feabbde5e12ed650jamal fprintf(fp, " Version: 0x%x ",*v); 22626328fc3933f377c47fb8b06feabbde5e12ed650jamal ctrl_v = *v; 22765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 22826328fc3933f377c47fb8b06feabbde5e12ed650jamal if (tb[CTRL_ATTR_HDRSIZE]) { 22926328fc3933f377c47fb8b06feabbde5e12ed650jamal __u32 *h = RTA_DATA(tb[CTRL_ATTR_HDRSIZE]); 23026328fc3933f377c47fb8b06feabbde5e12ed650jamal fprintf(fp, " header size: %d ",*h); 23126328fc3933f377c47fb8b06feabbde5e12ed650jamal } 23226328fc3933f377c47fb8b06feabbde5e12ed650jamal if (tb[CTRL_ATTR_MAXATTR]) { 23326328fc3933f377c47fb8b06feabbde5e12ed650jamal __u32 *ma = RTA_DATA(tb[CTRL_ATTR_MAXATTR]); 23426328fc3933f377c47fb8b06feabbde5e12ed650jamal fprintf(fp, " max attribs: %d ",*ma); 23526328fc3933f377c47fb8b06feabbde5e12ed650jamal } 23626328fc3933f377c47fb8b06feabbde5e12ed650jamal /* end of family definitions .. */ 23726328fc3933f377c47fb8b06feabbde5e12ed650jamal fprintf(fp,"\n"); 23826328fc3933f377c47fb8b06feabbde5e12ed650jamal if (tb[CTRL_ATTR_OPS]) { 23926328fc3933f377c47fb8b06feabbde5e12ed650jamal struct rtattr *tb2[GENL_MAX_FAM_OPS]; 24026328fc3933f377c47fb8b06feabbde5e12ed650jamal int i=0; 24126328fc3933f377c47fb8b06feabbde5e12ed650jamal parse_rtattr_nested(tb2, GENL_MAX_FAM_OPS, tb[CTRL_ATTR_OPS]); 24226328fc3933f377c47fb8b06feabbde5e12ed650jamal fprintf(fp, "\tcommands supported: \n"); 24326328fc3933f377c47fb8b06feabbde5e12ed650jamal for (i = 0; i < GENL_MAX_FAM_OPS; i++) { 24426328fc3933f377c47fb8b06feabbde5e12ed650jamal if (tb2[i]) { 24526328fc3933f377c47fb8b06feabbde5e12ed650jamal fprintf(fp, "\t\t#%d: ", i); 24626328fc3933f377c47fb8b06feabbde5e12ed650jamal if (0 > print_ctrl_cmds(fp, tb2[i], ctrl_v)) { 24726328fc3933f377c47fb8b06feabbde5e12ed650jamal fprintf(fp, "Error printing command\n"); 24826328fc3933f377c47fb8b06feabbde5e12ed650jamal } 24926328fc3933f377c47fb8b06feabbde5e12ed650jamal /* for next command */ 25026328fc3933f377c47fb8b06feabbde5e12ed650jamal fprintf(fp,"\n"); 25126328fc3933f377c47fb8b06feabbde5e12ed650jamal } 25226328fc3933f377c47fb8b06feabbde5e12ed650jamal } 25365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 25426328fc3933f377c47fb8b06feabbde5e12ed650jamal /* end of family::cmds definitions .. */ 25526328fc3933f377c47fb8b06feabbde5e12ed650jamal fprintf(fp,"\n"); 25626328fc3933f377c47fb8b06feabbde5e12ed650jamal } 25780c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg 25880c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg if (tb[CTRL_ATTR_MCAST_GROUPS]) { 25980c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg struct rtattr *tb2[GENL_MAX_FAM_GRPS + 1]; 26080c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg int i; 26180c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg 26280c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg parse_rtattr_nested(tb2, GENL_MAX_FAM_GRPS, 26380c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg tb[CTRL_ATTR_MCAST_GROUPS]); 26480c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg fprintf(fp, "\tmulticast groups:\n"); 26580c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg 26680c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg for (i = 0; i < GENL_MAX_FAM_GRPS; i++) { 26780c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg if (tb2[i]) { 26880c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg fprintf(fp, "\t\t#%d: ", i); 26980c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg if (0 > print_ctrl_grp(fp, tb2[i], ctrl_v)) 27080c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg fprintf(fp, "Error printing group\n"); 27180c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg /* for next group */ 27280c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg fprintf(fp,"\n"); 27380c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg } 27480c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg } 27580c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg 27680c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg /* end of family::groups definitions .. */ 27780c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg fprintf(fp,"\n"); 27880c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg } 27980c05b0976be86308e92b2837e0a94c484e388b4Johannes Berg 28065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim fflush(fp); 28165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim return 0; 28265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim} 28365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 28465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimstatic int ctrl_list(int cmd, int argc, char **argv) 28565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim{ 28665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim struct rtnl_handle rth; 28765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim struct nlmsghdr *nlh; 28865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim struct genlmsghdr *ghdr; 28965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim int ret = -1; 29065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim char d[GENL_NAMSIZ]; 29165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim struct { 29265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim struct nlmsghdr n; 29365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim char buf[4096]; 29465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } req; 29565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 29665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim memset(&req, 0, sizeof(req)); 29765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 29865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim nlh = &req.n; 29965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN); 30065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; 30165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim nlh->nlmsg_type = GENL_ID_CTRL; 30265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 30365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim ghdr = NLMSG_DATA(&req.n); 30465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim ghdr->cmd = CTRL_CMD_GETFAMILY; 30565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 30665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC) < 0) { 30765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim fprintf(stderr, "Cannot open generic netlink socket\n"); 30865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim exit(1); 30965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 31065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 31165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (cmd == CTRL_CMD_GETFAMILY) { 31265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (argc != 2) { 31365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim fprintf(stderr, "Wrong number of params\n"); 31465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim return -1; 31565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 31665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 31765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (matches(*argv, "name") == 0) { 31865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim NEXT_ARG(); 31965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim strncpy(d, *argv, sizeof (d) - 1); 32065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim addattr_l(nlh, 128, CTRL_ATTR_FAMILY_NAME, 32165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim d, strlen(d) + 1); 32265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } else if (matches(*argv, "id") == 0) { 32365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim __u16 id; 32465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim NEXT_ARG(); 32565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (get_u16(&id, *argv, 0)) { 32665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim fprintf(stderr, "Illegal \"id\"\n"); 32765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim goto ctrl_done; 32865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 32965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 33065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim addattr_l(nlh, 128, CTRL_ATTR_FAMILY_ID, &id, 2); 33165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 33265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } else { 33365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim fprintf(stderr, "Wrong params\n"); 33465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim goto ctrl_done; 33565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 33665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 337cd70f3f522e04b4d2fa80ae10292379bf223a53bStephen Hemminger if (rtnl_talk(&rth, nlh, 0, 0, nlh) < 0) { 33865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim fprintf(stderr, "Error talking to the kernel\n"); 33965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim goto ctrl_done; 34065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 34165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 34265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (print_ctrl(NULL, nlh, (void *) stdout) < 0) { 34365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim fprintf(stderr, "Dump terminated\n"); 34465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim goto ctrl_done; 34565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 34665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 34765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 34865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 34965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (cmd == CTRL_CMD_UNSPEC) { 35065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim nlh->nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; 35165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim nlh->nlmsg_seq = rth.dump = ++rth.seq; 35265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 3536cf8398f5f487762586801c25539d8fe5bb33b39Stephen Hemminger if (rtnl_send(&rth, nlh, nlh->nlmsg_len) < 0) { 35465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim perror("Failed to send dump request\n"); 35565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim goto ctrl_done; 35665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 35765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 358cd70f3f522e04b4d2fa80ae10292379bf223a53bStephen Hemminger rtnl_dump_filter(&rth, print_ctrl, stdout); 35965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 36065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 36165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 36265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim ret = 0; 36365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimctrl_done: 36465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim rtnl_close(&rth); 36565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim return ret; 36665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim} 36765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 36865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimstatic int ctrl_listen(int argc, char **argv) 36965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim{ 37065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim struct rtnl_handle rth; 37165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 37265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (rtnl_open_byproto(&rth, nl_mgrp(GENL_ID_CTRL), NETLINK_GENERIC) < 0) { 37365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim fprintf(stderr, "Canot open generic netlink socket\n"); 37465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim return -1; 37565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 37665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 37765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (rtnl_listen(&rth, print_ctrl, (void *) stdout) < 0) 37865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim return -1; 37965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 38065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim return 0; 38165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim} 38265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 38365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimstatic int parse_ctrl(struct genl_util *a, int argc, char **argv) 38465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim{ 38565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim argv++; 38665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (--argc <= 0) { 38765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim fprintf(stderr, "wrong controller params\n"); 38865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim return -1; 38965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim } 39065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 39165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (matches(*argv, "monitor") == 0) 39265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim return ctrl_listen(argc-1, argv+1); 39365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (matches(*argv, "get") == 0) 39465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim return ctrl_list(CTRL_CMD_GETFAMILY, argc-1, argv+1); 39565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (matches(*argv, "list") == 0 || 39665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim matches(*argv, "show") == 0 || 39765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim matches(*argv, "lst") == 0) 39865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim return ctrl_list(CTRL_CMD_UNSPEC, argc-1, argv+1); 39965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim if (matches(*argv, "help") == 0) 40065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim return usage(); 40165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 40265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim fprintf(stderr, "ctrl command \"%s\" is unknown, try \"ctrl -help\".\n", 40365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim *argv); 40465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 40565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim return -1; 40665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim} 40765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim 40865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimstruct genl_util ctrl_genl_util = { 40965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim .name = "ctrl", 41065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim .parse_genlopt = parse_ctrl, 41165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim .print_genlopt = print_ctrl, 41265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim}; 413