18afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov/* 28afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov * libgenl.c GENL library 38afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov */ 48afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov 58afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov#include <stdio.h> 68afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov#include <stdlib.h> 78afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov#include <unistd.h> 88afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov 98afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov#include <linux/genetlink.h> 108afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov#include "libgenl.h" 118afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov 128afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasovstatic int genl_parse_getfamily(struct nlmsghdr *nlh) 138afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov{ 148afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov struct rtattr *tb[CTRL_ATTR_MAX + 1]; 158afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov struct genlmsghdr *ghdr = NLMSG_DATA(nlh); 168afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov int len = nlh->nlmsg_len; 178afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov struct rtattr *attrs; 188afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov 198afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov if (nlh->nlmsg_type != GENL_ID_CTRL) { 208afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov fprintf(stderr, "Not a controller message, nlmsg_len=%d " 218afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov "nlmsg_type=0x%x\n", nlh->nlmsg_len, nlh->nlmsg_type); 228afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov return -1; 238afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov } 248afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov 258afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov len -= NLMSG_LENGTH(GENL_HDRLEN); 268afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov 278afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov if (len < 0) { 288afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov fprintf(stderr, "wrong controller message len %d\n", len); 298afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov return -1; 308afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov } 318afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov 328afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov if (ghdr->cmd != CTRL_CMD_NEWFAMILY) { 338afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov fprintf(stderr, "Unknown controller command %d\n", ghdr->cmd); 348afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov return -1; 358afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov } 368afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov 378afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN); 388afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov parse_rtattr(tb, CTRL_ATTR_MAX, attrs, len); 398afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov 408afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov if (tb[CTRL_ATTR_FAMILY_ID] == NULL) { 418afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov fprintf(stderr, "Missing family id TLV\n"); 428afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov return -1; 438afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov } 448afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov 458afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov return rta_getattr_u16(tb[CTRL_ATTR_FAMILY_ID]); 468afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov} 478afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov 488afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasovint genl_resolve_family(struct rtnl_handle *grth, const char *family) 498afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov{ 50328d482c4884a1009c420a8b9b0367f329e1d560Julian Anastasov GENL_REQUEST(req, 1024, GENL_ID_CTRL, 0, 0, CTRL_CMD_GETFAMILY, 51328d482c4884a1009c420a8b9b0367f329e1d560Julian Anastasov NLM_F_REQUEST); 528afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov 53328d482c4884a1009c420a8b9b0367f329e1d560Julian Anastasov addattr_l(&req.n, sizeof(req), CTRL_ATTR_FAMILY_NAME, 548afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov family, strlen(family) + 1); 558afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov 56c079e121a73af5eb49e003b13607e8a690331df6Stephen Hemminger if (rtnl_talk(grth, &req.n, &req.n, sizeof(req)) < 0) { 578afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov fprintf(stderr, "Error talking to the kernel\n"); 588afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov return -2; 598afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov } 608afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov 618afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov return genl_parse_getfamily(&req.n); 628afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov} 638afcc28879c10001d96412c43c586be8ba1d4467Julian Anastasov 64