xref: /freebsd/share/man/man3/snl.3 (revision f2c8381fce9b87695ea448591e4412cbed38aa77)
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