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