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