Home | History | Annotate | Download | only in lib
      1 /*
      2  * libgenl.c	GENL library
      3  */
      4 
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 #include <unistd.h>
      8 
      9 #include <linux/genetlink.h>
     10 #include "libgenl.h"
     11 
     12 static int genl_parse_getfamily(struct nlmsghdr *nlh)
     13 {
     14 	struct rtattr *tb[CTRL_ATTR_MAX + 1];
     15 	struct genlmsghdr *ghdr = NLMSG_DATA(nlh);
     16 	int len = nlh->nlmsg_len;
     17 	struct rtattr *attrs;
     18 
     19 	if (nlh->nlmsg_type != GENL_ID_CTRL) {
     20 		fprintf(stderr, "Not a controller message, nlmsg_len=%d "
     21 			"nlmsg_type=0x%x\n", nlh->nlmsg_len, nlh->nlmsg_type);
     22 		return -1;
     23 	}
     24 
     25 	len -= NLMSG_LENGTH(GENL_HDRLEN);
     26 
     27 	if (len < 0) {
     28 		fprintf(stderr, "wrong controller message len %d\n", len);
     29 		return -1;
     30 	}
     31 
     32 	if (ghdr->cmd != CTRL_CMD_NEWFAMILY) {
     33 		fprintf(stderr, "Unknown controller command %d\n", ghdr->cmd);
     34 		return -1;
     35 	}
     36 
     37 	attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
     38 	parse_rtattr(tb, CTRL_ATTR_MAX, attrs, len);
     39 
     40 	if (tb[CTRL_ATTR_FAMILY_ID] == NULL) {
     41 		fprintf(stderr, "Missing family id TLV\n");
     42 		return -1;
     43 	}
     44 
     45 	return rta_getattr_u16(tb[CTRL_ATTR_FAMILY_ID]);
     46 }
     47 
     48 int genl_resolve_family(struct rtnl_handle *grth, const char *family)
     49 {
     50 	GENL_REQUEST(req, 1024, GENL_ID_CTRL, 0, 0, CTRL_CMD_GETFAMILY,
     51 		     NLM_F_REQUEST);
     52 
     53 	addattr_l(&req.n, sizeof(req), CTRL_ATTR_FAMILY_NAME,
     54 		  family, strlen(family) + 1);
     55 
     56 	if (rtnl_talk(grth, &req.n, &req.n, sizeof(req)) < 0) {
     57 		fprintf(stderr, "Error talking to the kernel\n");
     58 		return -2;
     59 	}
     60 
     61 	return genl_parse_getfamily(&req.n);
     62 }
     63 
     64 int genl_init_handle(struct rtnl_handle *grth, const char *family,
     65 		     int *genl_family)
     66 {
     67 	if (*genl_family >= 0)
     68 		return 0;
     69 
     70 	if (rtnl_open_byproto(grth, 0, NETLINK_GENERIC) < 0) {
     71 		fprintf(stderr, "Cannot open generic netlink socket\n");
     72 		return -1;
     73 	}
     74 
     75 	*genl_family = genl_resolve_family(grth, family);
     76 	if (*genl_family < 0)
     77 		return -1;
     78 
     79 	return 0;
     80 }
     81