1f2c8381fSAlexander V. Chernikov.\" 2f2c8381fSAlexander V. Chernikov.\" Copyright (C) 2022 Alexander Chernikov <melifaro@FreeBSD.org>. 3f2c8381fSAlexander V. Chernikov.\" 4f2c8381fSAlexander V. Chernikov.\" Redistribution and use in source and binary forms, with or without 5f2c8381fSAlexander V. Chernikov.\" modification, are permitted provided that the following conditions 6f2c8381fSAlexander V. Chernikov.\" are met: 7f2c8381fSAlexander V. Chernikov.\" 1. Redistributions of source code must retain the above copyright 8f2c8381fSAlexander V. Chernikov.\" notice, this list of conditions and the following disclaimer. 9f2c8381fSAlexander V. Chernikov.\" 2. Redistributions in binary form must reproduce the above copyright 10f2c8381fSAlexander V. Chernikov.\" notice, this list of conditions and the following disclaimer in the 11f2c8381fSAlexander V. Chernikov.\" documentation and/or other materials provided with the distribution. 12f2c8381fSAlexander V. Chernikov.\" 13f2c8381fSAlexander V. Chernikov.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14f2c8381fSAlexander V. Chernikov.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15f2c8381fSAlexander V. Chernikov.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16f2c8381fSAlexander V. Chernikov.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17f2c8381fSAlexander V. Chernikov.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18f2c8381fSAlexander V. Chernikov.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19f2c8381fSAlexander V. Chernikov.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20f2c8381fSAlexander V. Chernikov.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21f2c8381fSAlexander V. Chernikov.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22f2c8381fSAlexander V. Chernikov.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23f2c8381fSAlexander V. Chernikov.\" SUCH DAMAGE. 24f2c8381fSAlexander V. Chernikov.\" 25f2c8381fSAlexander V. Chernikov.\" $FreeBSD$ 26f2c8381fSAlexander V. Chernikov.Dd December 16, 2022 27f2c8381fSAlexander V. Chernikov.Dt SNL 3 28f2c8381fSAlexander V. Chernikov.Os 29f2c8381fSAlexander V. Chernikov.Sh NAME 30f2c8381fSAlexander V. Chernikov.Nm snl_init , 31f2c8381fSAlexander V. Chernikov.Nm snl_free , 32f2c8381fSAlexander V. Chernikov.Nm snl_read_message , 33f2c8381fSAlexander V. Chernikov.Nm snl_send , 34f2c8381fSAlexander V. Chernikov.Nm snl_get_seq , 35f2c8381fSAlexander V. Chernikov.Nm snl_allocz , 36f2c8381fSAlexander V. Chernikov.Nm snl_clear_lb , 37f2c8381fSAlexander V. Chernikov.Nm snl_parse_nlmsg , 38f2c8381fSAlexander V. Chernikov.Nm snl_parse_header , 39f2c8381fSAlexander V. Chernikov.Nm snl_parse_attrs , 40f2c8381fSAlexander V. Chernikov.Nm snl_parse_attrs_raw , 41f2c8381fSAlexander V. Chernikov.Nm snl_attr_get_flag , 42f2c8381fSAlexander V. Chernikov.Nm snl_attr_get_ip , 43f2c8381fSAlexander V. Chernikov.Nm snl_attr_get_uint16 , 44f2c8381fSAlexander V. Chernikov.Nm snl_attr_get_uint32 , 45f2c8381fSAlexander V. Chernikov.Nm snl_attr_get_string , 46f2c8381fSAlexander V. Chernikov.Nm snl_attr_get_stringn , 47f2c8381fSAlexander V. Chernikov.Nm snl_attr_get_nla , 48f2c8381fSAlexander V. Chernikov.Nm snl_field_get_uint8 , 49f2c8381fSAlexander V. Chernikov.Nm snl_field_get_uint16 , 50f2c8381fSAlexander V. Chernikov.Nm snl_field_get_uint32 51f2c8381fSAlexander V. Chernikov.Nd "simple netlink library" 52f2c8381fSAlexander V. Chernikov.Sh SYNOPSIS 53f2c8381fSAlexander V. Chernikov.In netlink/netlink_snl.h 54f2c8381fSAlexander V. Chernikov.In netlink/netlink_snl_route.h 55f2c8381fSAlexander V. Chernikov.Ft "bool" 56f2c8381fSAlexander V. Chernikov.Fn snl_init "struct snl_state *ss" "int netlink_family" 57f2c8381fSAlexander V. Chernikov.Fn snl_free "struct snl_state *ss" 58f2c8381fSAlexander V. Chernikov.Ft "struct nlmsghdr *" 59f2c8381fSAlexander V. Chernikov.Fn snl_read_message "struct snl_state *ss" 60f2c8381fSAlexander V. Chernikov.Ft "bool" 61f2c8381fSAlexander V. Chernikov.Fn snl_send "struct snl_state *ss" "void *data" "int sz" 62f2c8381fSAlexander V. Chernikov.Ft "uint32_t" 63f2c8381fSAlexander V. Chernikov.Fn snl_get_seq "struct snl_state *ss" 64f2c8381fSAlexander V. Chernikov.Ft "void *" 65f2c8381fSAlexander V. Chernikov.Fn snl_allocz "struct snl_state *ss" "int len" 66f2c8381fSAlexander V. Chernikov.Fn snl_clear_lb "struct snl_state *ss" 67f2c8381fSAlexander V. Chernikov.Ft "bool" 68f2c8381fSAlexander V. Chernikov.Fn snl_parse_nlmsg "struct snl_state *ss" "struct nlmsghdr *hdr" "const struct snl_hdr_parser *ps" "void *target" 69f2c8381fSAlexander V. Chernikov.Ft "bool" 70f2c8381fSAlexander V. Chernikov.Fn snl_parse_header "struct snl_state *ss" "void *hdr" "int len" "const struct snl_hdr_parser *ps" "int pslen" "void *target" 71f2c8381fSAlexander V. Chernikov.Ft "bool" 72f2c8381fSAlexander V. Chernikov.Fn snl_parse_attrs "struct snl_state *ss" "struct nlmsghdr *hdr" "int hdrlen" "const struct snl_attr_parser *ps" "int pslen" "void *target" 73f2c8381fSAlexander V. Chernikov.Ft "bool" 74f2c8381fSAlexander V. Chernikov.Fn snl_parse_attrs_raw "struct snl_state *ss" "struct nlattr *nla_head" "int len" "const struct snl_attr_parser *ps" "int pslen" "void *target" 75f2c8381fSAlexander V. Chernikov.Ft "bool" 76f2c8381fSAlexander V. Chernikov.Fn snl_attr_get_flag "struct snl_state *ss" "struct nlattr *nla" "void *target" 77f2c8381fSAlexander V. Chernikov.Ft "bool" 7861507ae3SAlexander V. Chernikov.Fn snl_attr_get_uint8 "struct snl_state *ss" "struct nlattr *nla" "void *target" 7961507ae3SAlexander V. Chernikov.Ft "bool" 80f2c8381fSAlexander V. Chernikov.Fn snl_attr_get_uint16 "struct snl_state *ss" "struct nlattr *nla" "void *target" 81f2c8381fSAlexander V. Chernikov.Ft "bool" 82f2c8381fSAlexander V. Chernikov.Fn snl_attr_get_uint32 "struct snl_state *ss" "struct nlattr *nla" "void *target" 83f2c8381fSAlexander V. Chernikov.Ft "bool" 8461507ae3SAlexander V. Chernikov.Fn snl_attr_get_uint64 "struct snl_state *ss" "struct nlattr *nla" "void *target" 8561507ae3SAlexander V. Chernikov.Ft "bool" 86f2c8381fSAlexander V. Chernikov.Fn snl_attr_get_string "struct snl_state *ss" "struct nlattr *nla" "void *target" 87f2c8381fSAlexander V. Chernikov.Ft "bool" 88f2c8381fSAlexander V. Chernikov.Fn snl_attr_get_stringn "struct snl_state *ss" "struct nlattr *nla" "void *target" 89f2c8381fSAlexander V. Chernikov.Ft "bool" 90f2c8381fSAlexander V. Chernikov.Fn snl_attr_get_nla "struct snl_state *ss" "struct nlattr *nla" "void *target" 91f2c8381fSAlexander V. Chernikov.Ft "bool" 92f2c8381fSAlexander V. Chernikov.Fn snl_attr_get_ip "struct snl_state *ss" "struct nlattr *nla" "void *target" 93f2c8381fSAlexander V. Chernikov.Ft "bool" 94f2c8381fSAlexander V. Chernikov.Fn snl_attr_get_ipvia "struct snl_state *ss" "struct nlattr *nla" "void *target" 95f2c8381fSAlexander V. Chernikov.Sh DESCRIPTION 96f2c8381fSAlexander V. ChernikovThe 97f2c8381fSAlexander V. Chernikov.Xr snl 3 98f2c8381fSAlexander V. Chernikovlibrary provides an easy way of sending and receiving Netlink messages, 99f2c8381fSAlexander V. Chernikovtaking care of serialisation and deserialisation. 100f2c8381fSAlexander V. Chernikov.Ss INITIALISATION 101f2c8381fSAlexander V. ChernikovCall 102f2c8381fSAlexander V. Chernikov.Fn snl_init 103f2c8381fSAlexander V. Chernikovwith a pointer to the 104f2c8381fSAlexander V. Chernikov.Dv struct snl_state 105f2c8381fSAlexander V. Chernikovand the desired Netlink family to initialise the library instance. 106f2c8381fSAlexander V. ChernikovTo free the library instance, call 107f2c8381fSAlexander V. Chernikov.Fn snl_free . 108f2c8381fSAlexander V. Chernikov.Pp 109f2c8381fSAlexander V. ChernikovThe library functions are NOT multithread-safe. 110f2c8381fSAlexander V. ChernikovIf multithreading is desired, consider initializing an instance 111f2c8381fSAlexander V. Chernikovper thread. 112f2c8381fSAlexander V. Chernikov.Ss MEMORY ALLOCATION 113f2c8381fSAlexander V. ChernikovThe library uses pre-allocated extendable memory buffers to handle message parsing. 114f2c8381fSAlexander V. ChernikovThe typical usage pattern is to allocate the necessary data structures during the 115f2c8381fSAlexander V. Chernikovmessage parsing or writing process via 116f2c8381fSAlexander V. Chernikov.Fn snl_allocz 117f2c8381fSAlexander V. Chernikovand free all allocated data at once using 118f2c8381fSAlexander V. Chernikov.Fn snl_clear_lb 119f2c8381fSAlexander V. Chernikovafter handling the message. 120f2c8381fSAlexander V. Chernikov.Ss COMPOSING AND SENDING MESSAGES 121f2c8381fSAlexander V. ChernikovThe library does not currently offer any wrappers for writing netlink messages. 122f2c8381fSAlexander V. ChernikovSimple request messages can be composed by filling in all needed fields directly. 123f2c8381fSAlexander V. ChernikovExample for constructing an interface dump request: 124f2c8381fSAlexander V. Chernikov.Bd -literal 125f2c8381fSAlexander V. Chernikov struct { 126f2c8381fSAlexander V. Chernikov struct nlmsghdr hdr; 127f2c8381fSAlexander V. Chernikov struct ifinfomsg ifmsg; 128f2c8381fSAlexander V. Chernikov } msg = { 129f2c8381fSAlexander V. Chernikov .hdr.nlmsg_type = RTM_GETLINK, 130f2c8381fSAlexander V. Chernikov .hdr.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, 131f2c8381fSAlexander V. Chernikov .hdr.nlmsg_seq = snl_get_seq(ss), 132f2c8381fSAlexander V. Chernikov }; 133f2c8381fSAlexander V. Chernikov msg.hdr.nlmsg_len = sizeof(msg); 134f2c8381fSAlexander V. Chernikov.Ed 135f2c8381fSAlexander V. Chernikov.Fn snl_get_seq 136f2c8381fSAlexander V. Chernikovcan be used to generate a unique message number. 137f2c8381fSAlexander V. ChernikovTo send the resulting message, 138f2c8381fSAlexander V. Chernikov.Fn snl_send 139f2c8381fSAlexander V. Chernikovcan be used. 140f2c8381fSAlexander V. Chernikov.Ss RECEIVING AND PARSING MESSAGES 141f2c8381fSAlexander V. ChernikovTo receive a message, use 142f2c8381fSAlexander V. Chernikov.Fn snl_read_message . 143f2c8381fSAlexander V. ChernikovCurrently, this call is blocking. 144f2c8381fSAlexander V. Chernikov.Pp 145f2c8381fSAlexander V. ChernikovThe library provides an easy way to convert the message to the pre-defined C 146f2c8381fSAlexander V. Chernikovstructure. 147f2c8381fSAlexander V. ChernikovFor each message type, one needs to define rules, converting the protocol header 148f2c8381fSAlexander V. Chernikovfields and the desired attributes to the specified structure. 149f2c8381fSAlexander V. ChernikovIt can be accomplished by using message parsers. 150f2c8381fSAlexander V. ChernikovEach message parser consists of an array of attribute getters and an array of 151f2c8381fSAlexander V. Chernikovheader field getters. 152f2c8381fSAlexander V. ChernikovThe former array needs to be sorted by the attribute type. 153f2c8381fSAlexander V. ChernikovThere is a 154f2c8381fSAlexander V. Chernikov.Fn SNL_VERIFY_PARSERS 155f2c8381fSAlexander V. Chernikovmacro to check if the order is correct. 156f2c8381fSAlexander V. Chernikov.Fn SNL_DECLARE_PARSER "parser_name" "family header type" "struct snl_field_parser[]" "struct snl_attr_parser[]" 157f2c8381fSAlexander V. Chernikovcan be used to create a new parser. 158f2c8381fSAlexander V. Chernikov.Fn SNL_DECLARE_ATTR_PARSER "parser_name" "struct snl_field_parser[]" 159f2c8381fSAlexander V. Chernikovcan be used to create an attribute-only message parser. 160f2c8381fSAlexander V. Chernikov.Pp 161f2c8381fSAlexander V. ChernikovEach attribute getter needs to be embedded in the following structure: 162f2c8381fSAlexander V. Chernikov.Bd -literal 163f2c8381fSAlexander V. Chernikovtypedef bool snl_parse_attr_f(struct snl_state *ss, struct nlattr *attr, const void *arg, void *target); 164f2c8381fSAlexander V. Chernikovstruct snl_attr_parser { 165f2c8381fSAlexander V. Chernikov uint16_t type; /* Attribute type */ 166f2c8381fSAlexander V. Chernikov uint16_t off; /* field offset in the target structure */ 167f2c8381fSAlexander V. Chernikov snl_parse_attr_f *cb; /* getter function to call */ 168f2c8381fSAlexander V. Chernikov const void *arg; /* getter function custom argument */ 169f2c8381fSAlexander V. Chernikov}; 170f2c8381fSAlexander V. Chernikov.Ed 171f2c8381fSAlexander V. ChernikovThe generic attribute getter has the following signature: 172f2c8381fSAlexander V. Chernikov.Ft "bool" 173f2c8381fSAlexander V. Chernikov.Fn snl_attr_get_<type> "struct snl_state *ss" "struct nlattr *nla" "const void *arg" "void *target" . 174f2c8381fSAlexander V. Chernikovnla contains the pointer of the attribute to use as the datasource. 175f2c8381fSAlexander V. ChernikovThe target field is the pointer to the field in the target structure. 176f2c8381fSAlexander V. ChernikovIt is up to the getter to know the type of the target field. 177f2c8381fSAlexander V. ChernikovThe getter must check the input attribute and return 178f2c8381fSAlexander V. Chernikovfalse if the attribute is not formed correctly. 179f2c8381fSAlexander V. ChernikovOtherwise, the getter fetches the attribute value and stores it in the target, 180f2c8381fSAlexander V. Chernikovthen returns true. 181f2c8381fSAlexander V. ChernikovIt is possible to use 182f2c8381fSAlexander V. Chernikov.Fn snl_allocz 183f2c8381fSAlexander V. Chernikovto create the desired data structure . 184f2c8381fSAlexander V. ChernikovA number of predefined getters for the common data types exist. 185f2c8381fSAlexander V. Chernikov.Fn snl_attr_get_flag 186f2c8381fSAlexander V. Chernikovconverts a flag-type attribute to an uint8_t value of 1 or 0, depending on the 187f2c8381fSAlexander V. Chernikovattribute presence. 18861507ae3SAlexander V. Chernikov.Fn snl_attr_get_uint8 18961507ae3SAlexander V. Chernikovstores a uint8_t type attribute into the uint8_t target field. 190f2c8381fSAlexander V. Chernikov.Fn snl_attr_get_uint16 191f2c8381fSAlexander V. Chernikovstores a uint16_t type attribute into the uint16_t target field. 192f2c8381fSAlexander V. Chernikov.Fn snl_attr_get_uint32 193f2c8381fSAlexander V. Chernikovstores a uint32_t type attribute into the uint32_t target field. 19461507ae3SAlexander V. Chernikov.Fn snl_attr_get_uint64 19561507ae3SAlexander V. Chernikovstores a uint64_t type attribute into the uint64_t target field. 196f2c8381fSAlexander V. Chernikov.Fn snl_attr_get_ip 197f2c8381fSAlexander V. Chernikovand 198f2c8381fSAlexander V. Chernikov.Fn snl_attr_get_ipvia 199f2c8381fSAlexander V. Chernikovstores a pointer to the sockaddr structure with the IPv4/IPv6 address contained 200f2c8381fSAlexander V. Chernikovin the attribute. 201f2c8381fSAlexander V. ChernikovSockaddr is allocated using 202f2c8381fSAlexander V. Chernikov.Fn snl_allocz . 203f2c8381fSAlexander V. Chernikov.Fn snl_attr_get_string 204f2c8381fSAlexander V. Chernikovstores a pointer to the NULL-terminated string. 205f2c8381fSAlexander V. ChernikovThe string itself is allocated using 206f2c8381fSAlexander V. Chernikov.Fn snl_allocz . 207f2c8381fSAlexander V. Chernikov.Fn snl_attr_get_nla 208f2c8381fSAlexander V. Chernikovstores a pointer to the specified attribute. 209f2c8381fSAlexander V. Chernikov.Fn snl_attr_get_stringn 210f2c8381fSAlexander V. Chernikovstores a pointer to the non-NULL-terminated string. 211f2c8381fSAlexander V. Chernikov.Pp 212f2c8381fSAlexander V. ChernikovSimilarly, each family header getter needs to be embedded in the following structure: 213f2c8381fSAlexander V. Chernikov.Bd -literal 214f2c8381fSAlexander V. Chernikovtypedef void snl_parse_field_f(struct snl_state *ss, void *hdr, void *target); 215f2c8381fSAlexander V. Chernikovstruct snl_field_parser { 216f2c8381fSAlexander V. Chernikov uint16_t off_in; /* field offset in the input structure */ 217f2c8381fSAlexander V. Chernikov uint16_t off_out;/* field offset in the target structure */ 218f2c8381fSAlexander V. Chernikov snl_parse_field_f *cb; /* getter function to call */ 219f2c8381fSAlexander V. Chernikov}; 220f2c8381fSAlexander V. Chernikov.Ed 221f2c8381fSAlexander V. ChernikovThe generic field getter has the following signature: 222f2c8381fSAlexander V. Chernikov.Ft "void" 223f2c8381fSAlexander V. Chernikovsnl_field_get_<type> "struct snl_state *ss" "void *src" "void *target" . 224f2c8381fSAlexander V. ChernikovA number of pre-defined getters for the common data types exist. 225f2c8381fSAlexander V. Chernikov.Fn "snl_field_get_uint8" 226f2c8381fSAlexander V. Chernikovfetches an uint8_t value and stores it in the target. 227f2c8381fSAlexander V. Chernikov.Fn "snl_field_get_uint16" 228f2c8381fSAlexander V. Chernikovfetches an uint8_t value and stores it in the target. 229f2c8381fSAlexander V. Chernikov.Fn "snl_field_get_uint32" 230f2c8381fSAlexander V. Chernikovfetches an uint32_t value and stores it in the target. 231f2c8381fSAlexander V. Chernikov.Sh EXAMPLES 232f2c8381fSAlexander V. ChernikovThe following example demonstrates how to list all system interfaces 233f2c8381fSAlexander V. Chernikovusing netlink. 234f2c8381fSAlexander V. Chernikov.Bd -literal 235f2c8381fSAlexander V. Chernikov#include <stdio.h> 236f2c8381fSAlexander V. Chernikov 237f2c8381fSAlexander V. Chernikov#include <netlink/netlink.h> 238f2c8381fSAlexander V. Chernikov#include <netlink/netlink_route.h> 239f2c8381fSAlexander V. Chernikov#include "netlink/netlink_snl.h" 240f2c8381fSAlexander V. Chernikov#include "netlink/netlink_snl_route.h" 241f2c8381fSAlexander V. Chernikov 242f2c8381fSAlexander V. Chernikovstruct nl_parsed_link { 243f2c8381fSAlexander V. Chernikov uint32_t ifi_index; 244f2c8381fSAlexander V. Chernikov uint32_t ifla_mtu; 245f2c8381fSAlexander V. Chernikov char *ifla_ifname; 246f2c8381fSAlexander V. Chernikov}; 247f2c8381fSAlexander V. Chernikov 248f2c8381fSAlexander V. Chernikov#define _IN(_field) offsetof(struct ifinfomsg, _field) 249f2c8381fSAlexander V. Chernikov#define _OUT(_field) offsetof(struct nl_parsed_link, _field) 250f2c8381fSAlexander V. Chernikovstatic const struct snl_attr_parser ap_link[] = { 251f2c8381fSAlexander V. Chernikov { .type = IFLA_IFNAME, .off = _OUT(ifla_ifname), .cb = snl_attr_get_string }, 252f2c8381fSAlexander V. Chernikov { .type = IFLA_MTU, .off = _OUT(ifla_mtu), .cb = snl_attr_get_uint32 }, 253f2c8381fSAlexander V. Chernikov}; 254f2c8381fSAlexander V. Chernikovstatic const struct snl_field_parser fp_link[] = { 255f2c8381fSAlexander V. Chernikov {.off_in = _IN(ifi_index), .off_out = _OUT(ifi_index), .cb = snl_field_get_uint32 }, 256f2c8381fSAlexander V. Chernikov}; 257f2c8381fSAlexander V. Chernikov#undef _IN 258f2c8381fSAlexander V. Chernikov#undef _OUT 259f2c8381fSAlexander V. ChernikovSNL_DECLARE_PARSER(link_parser, struct ifinfomsg, fp_link, ap_link); 260f2c8381fSAlexander V. Chernikov 261f2c8381fSAlexander V. Chernikov 262f2c8381fSAlexander V. Chernikovint 263f2c8381fSAlexander V. Chernikovmain(int ac, char *argv[]) 264f2c8381fSAlexander V. Chernikov{ 265f2c8381fSAlexander V. Chernikov struct snl_state ss; 266f2c8381fSAlexander V. Chernikov 267f2c8381fSAlexander V. Chernikov if (!snl_init(&ss, NETLINK_ROUTE)) 268f2c8381fSAlexander V. Chernikov return (1); 269f2c8381fSAlexander V. Chernikov 270f2c8381fSAlexander V. Chernikov struct { 271f2c8381fSAlexander V. Chernikov struct nlmsghdr hdr; 272f2c8381fSAlexander V. Chernikov struct ifinfomsg ifmsg; 273f2c8381fSAlexander V. Chernikov } msg = { 274f2c8381fSAlexander V. Chernikov .hdr.nlmsg_type = RTM_GETLINK, 275f2c8381fSAlexander V. Chernikov .hdr.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, 276f2c8381fSAlexander V. Chernikov .hdr.nlmsg_seq = snl_get_seq(&ss), 277f2c8381fSAlexander V. Chernikov }; 278f2c8381fSAlexander V. Chernikov msg.hdr.nlmsg_len = sizeof(msg); 279f2c8381fSAlexander V. Chernikov 280f2c8381fSAlexander V. Chernikov if (!snl_send(&ss, &msg, sizeof(msg))) { 281f2c8381fSAlexander V. Chernikov snl_free(&ss); 282f2c8381fSAlexander V. Chernikov return (1); 283f2c8381fSAlexander V. Chernikov } 284f2c8381fSAlexander V. Chernikov 285f2c8381fSAlexander V. Chernikov struct nlmsghdr *hdr; 286f2c8381fSAlexander V. Chernikov while ((hdr = snl_read_message(&ss)) != NULL && hdr->nlmsg_type != NLMSG_DONE) { 287f2c8381fSAlexander V. Chernikov if (hdr->nlmsg_seq != msg.hdr.nlmsg_seq) 288f2c8381fSAlexander V. Chernikov break; 289f2c8381fSAlexander V. Chernikov 290f2c8381fSAlexander V. Chernikov struct nl_parsed_link link = {}; 291f2c8381fSAlexander V. Chernikov if (!snl_parse_nlmsg(&ss, hdr, &link_parser, &link)) 292f2c8381fSAlexander V. Chernikov continue; 293f2c8381fSAlexander V. Chernikov printf("Link#%u %s mtu %u\n", link.ifi_index, link.ifla_ifname, link.ifla_mtu); 294f2c8381fSAlexander V. Chernikov } 295f2c8381fSAlexander V. Chernikov 296f2c8381fSAlexander V. Chernikov return (0); 297f2c8381fSAlexander V. Chernikov} 298f2c8381fSAlexander V. Chernikov.Ed 299f2c8381fSAlexander V. Chernikov.Sh SEE ALSO 300f2c8381fSAlexander V. Chernikov.Xr genetlink 4 , 301f2c8381fSAlexander V. Chernikov.Xr netlink 4 , 302f2c8381fSAlexander V. Chernikovand 303f2c8381fSAlexander V. Chernikov.Xr rtnetlink 4 304f2c8381fSAlexander V. Chernikov.Sh HISTORY 305f2c8381fSAlexander V. ChernikovThe 306f2c8381fSAlexander V. Chernikov.Dv SNL 307f2c8381fSAlexander V. Chernikovlibrary appeared in 308*6d2feb39STom Hukins.Fx 13.2 . 309f2c8381fSAlexander V. Chernikov.Sh AUTHORS 310f2c8381fSAlexander V. ChernikovThis library was implemented by 311f2c8381fSAlexander V. Chernikov.An Alexander Chernikov Aq Mt melifaro@FreeBSD.org . 312