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