Path: blob/main/sys/netlink/netlink_snl_generic.h
105174 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2022 Alexander V. Chernikov <[email protected]>4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND15* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE16* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE17* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE18* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL19* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS20* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)21* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT22* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY23* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF24* SUCH DAMAGE.25*/26#ifndef _NETLINK_NETLINK_SNL_GENERIC_H_27#define _NETLINK_NETLINK_SNL_GENERIC_H_2829#include <netlink/netlink.h>30#include <netlink/netlink_generic.h>31#include <netlink/netlink_snl.h>3233/* Genetlink helpers */34static inline struct nlmsghdr *35snl_create_genl_msg_request(struct snl_writer *nw, uint16_t genl_family,36uint8_t genl_cmd)37{38struct nlmsghdr *hdr;39struct genlmsghdr *ghdr;4041assert(nw->hdr == NULL);4243hdr = snl_reserve_msg_object(nw, struct nlmsghdr);44if (__predict_false(hdr == NULL))45return (NULL);46hdr->nlmsg_type = genl_family;47hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;48ghdr = snl_reserve_msg_object(nw, struct genlmsghdr);49if (__predict_false(ghdr == NULL))50return (NULL);51ghdr->cmd = genl_cmd;52nw->hdr = hdr;5354return (hdr);55}5657static struct snl_field_parser snl_fp_genl[] = {};5859#define SNL_DECLARE_GENL_PARSER(_name, _np) SNL_DECLARE_PARSER(_name,\60struct genlmsghdr, snl_fp_genl, _np)6162struct _snl_genl_ctrl_mcast_group {63uint32_t mcast_grp_id;64const char *mcast_grp_name;65};6667struct _snl_genl_ctrl_mcast_groups {68uint32_t num_groups;69struct _snl_genl_ctrl_mcast_group **groups;70};7172#define _OUT(_field) offsetof(struct _snl_genl_ctrl_mcast_group, _field)73static struct snl_attr_parser _nla_p_getmc[] = {74{75.type = CTRL_ATTR_MCAST_GRP_NAME,76.off = _OUT(mcast_grp_name),77.cb = snl_attr_get_string,78},79{80.type = CTRL_ATTR_MCAST_GRP_ID,81.off = _OUT(mcast_grp_id),82.cb = snl_attr_get_uint32,83},84};85#undef _OUT86SNL_DECLARE_ATTR_PARSER_EXT(_genl_ctrl_mc_parser,87sizeof(struct _snl_genl_ctrl_mcast_group), _nla_p_getmc, NULL);8889struct _getfamily_attrs {90uint16_t family_id;91const char *family_name;92struct _snl_genl_ctrl_mcast_groups mcast_groups;93};9495#define _IN(_field) offsetof(struct genlmsghdr, _field)96#define _OUT(_field) offsetof(struct _getfamily_attrs, _field)97static struct snl_attr_parser _nla_p_getfam[] = {98{99.type = CTRL_ATTR_FAMILY_ID,100.off = _OUT(family_id),101.cb = snl_attr_get_uint16,102},103{104.type = CTRL_ATTR_FAMILY_NAME,105.off = _OUT(family_name),106.cb = snl_attr_get_string,107},108{109.type = CTRL_ATTR_MCAST_GROUPS,110.off = _OUT(mcast_groups),111.cb = snl_attr_get_parray,112.arg = &_genl_ctrl_mc_parser,113},114};115#undef _IN116#undef _OUT117SNL_DECLARE_GENL_PARSER(_genl_ctrl_getfam_parser, _nla_p_getfam);118119static bool120_snl_get_genl_family_info(struct snl_state *ss, const char *family_name,121struct _getfamily_attrs *attrs)122{123struct snl_writer nw;124struct nlmsghdr *hdr;125126memset(attrs, 0, sizeof(*attrs));127128snl_init_writer(ss, &nw);129snl_create_genl_msg_request(&nw, GENL_ID_CTRL, CTRL_CMD_GETFAMILY);130snl_add_msg_attr_string(&nw, CTRL_ATTR_FAMILY_NAME, family_name);131if ((hdr = snl_finalize_msg(&nw)) == NULL || !snl_send_message(ss, hdr))132return (false);133134hdr = snl_read_reply(ss, hdr->nlmsg_seq);135if (hdr != NULL && hdr->nlmsg_type != NLMSG_ERROR) {136if (snl_parse_nlmsg(ss, hdr, &_genl_ctrl_getfam_parser, attrs))137return (true);138}139140return (false);141}142143static inline uint16_t144snl_get_genl_family(struct snl_state *ss, const char *family_name)145{146struct _getfamily_attrs attrs = {};147148if (__predict_false(!_snl_get_genl_family_info(ss, family_name,149&attrs)))150return (0);151return (attrs.family_id);152}153154static inline uint16_t155snl_get_genl_mcast_group(struct snl_state *ss, const char *family_name,156const char *group_name, uint16_t *family_id)157{158struct _getfamily_attrs attrs = {};159160if (__predict_false(!_snl_get_genl_family_info(ss, family_name,161&attrs)))162return (0);163if (attrs.family_id == 0)164return (0);165if (family_id != NULL)166*family_id = attrs.family_id;167for (u_int i = 0; i < attrs.mcast_groups.num_groups; i++)168if (strcmp(attrs.mcast_groups.groups[i]->mcast_grp_name,169group_name) == 0)170return (attrs.mcast_groups.groups[i]->mcast_grp_id);171return (0);172}173174#endif175176177