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