]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/netlink/netlink_snl_route_parsers.h
zfs: merge openzfs/zfs@eb62221ff (zfs-2.1-release) into stable/13
[FreeBSD/FreeBSD.git] / sys / netlink / netlink_snl_route_parsers.h
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2023 Alexander V. Chernikov <melifaro@FreeBSD.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 #ifndef _NETLINK_NETLINK_SNL_ROUTE_PARSERS_H_
28 #define _NETLINK_NETLINK_SNL_ROUTE_PARSERS_H_
29
30 #include <netlink/netlink_snl.h>
31 #include <netlink/netlink_snl_route.h>
32
33 /* TODO: this file should be generated automatically */
34
35 /* RTM_<NEW|DEL|GET>ROUTE message parser */
36
37 struct rta_mpath_nh {
38         struct sockaddr *gw;
39         uint32_t        ifindex;
40         uint8_t         rtnh_flags;
41         uint8_t         rtnh_weight;
42         uint32_t        rtax_mtu;
43         uint32_t        rta_rtflags;
44 };
45
46 #define _IN(_field)     offsetof(struct rtnexthop, _field)
47 #define _OUT(_field)    offsetof(struct rta_mpath_nh, _field)
48 static const struct snl_attr_parser _nla_p_mp_nh_metrics[] = {
49         { .type = NL_RTAX_MTU, .off = _OUT(rtax_mtu), .cb = snl_attr_get_uint32 },
50 };
51 SNL_DECLARE_ATTR_PARSER(_metrics_mp_nh_parser, _nla_p_mp_nh_metrics);
52
53 static const struct snl_attr_parser _nla_p_mp_nh[] = {
54         { .type = NL_RTA_GATEWAY, .off = _OUT(gw), .cb = snl_attr_get_ip },
55         { .type = NL_RTA_METRICS, .arg = &_metrics_mp_nh_parser, .cb = snl_attr_get_nested },
56         { .type = NL_RTA_RTFLAGS, .off = _OUT(rta_rtflags), .cb = snl_attr_get_uint32 },
57         { .type = NL_RTA_VIA, .off = _OUT(gw), .cb = snl_attr_get_ipvia },
58 };
59
60 static const struct snl_field_parser _fp_p_mp_nh[] = {
61         { .off_in = _IN(rtnh_flags), .off_out = _OUT(rtnh_flags), .cb = snl_field_get_uint8 },
62         { .off_in = _IN(rtnh_hops), .off_out = _OUT(rtnh_weight), .cb = snl_field_get_uint8 },
63         { .off_in = _IN(rtnh_ifindex), .off_out = _OUT(ifindex), .cb = snl_field_get_uint32 },
64 };
65 #undef _IN
66 #undef _OUT
67 SNL_DECLARE_PARSER(_mpath_nh_parser, struct rtnexthop, _fp_p_mp_nh, _nla_p_mp_nh);
68
69 struct rta_mpath {
70         int num_nhops;
71         struct rta_mpath_nh nhops[0];
72 };
73
74 static bool
75 nlattr_get_multipath(struct snl_state *ss, struct nlattr *nla, const void *arg __unused,
76     void *target)
77 {
78         int data_len = nla->nla_len - sizeof(struct nlattr);
79         struct rtnexthop *rtnh;
80
81         int max_nhops = data_len / sizeof(struct rtnexthop);
82         size_t sz = (max_nhops + 2) * sizeof(struct rta_mpath_nh);
83
84         struct rta_mpath *mp = snl_allocz(ss, sz);
85         mp->num_nhops = 0;
86
87         for (rtnh = (struct rtnexthop *)(void *)(nla + 1); data_len > 0; ) {
88                 struct rta_mpath_nh *mpnh = &mp->nhops[mp->num_nhops++];
89
90                 if (!snl_parse_header(ss, rtnh, rtnh->rtnh_len, &_mpath_nh_parser, mpnh))
91                         return (false);
92
93                 int len = NL_ITEM_ALIGN(rtnh->rtnh_len);
94                 data_len -= len;
95                 rtnh = (struct rtnexthop *)(void *)((char *)rtnh + len);
96         }
97         if (data_len != 0 || mp->num_nhops == 0) {
98                 return (false);
99         }
100
101         *((struct rta_mpath **)target) = mp;
102         return (true);
103 }
104
105 struct snl_parsed_route {
106         struct sockaddr         *rta_dst;
107         struct sockaddr         *rta_gw;
108         struct nlattr           *rta_metrics;
109         struct rta_mpath        *rta_multipath;
110         uint32_t                rta_expires;
111         uint32_t                rta_oif;
112         uint32_t                rta_expire;
113         uint32_t                rta_table;
114         uint32_t                rta_knh_id;
115         uint32_t                rta_nh_id;
116         uint32_t                rta_rtflags;
117         uint32_t                rtax_mtu;
118         uint32_t                rtax_weight;
119         uint8_t                 rtm_family;
120         uint8_t                 rtm_type;
121         uint8_t                 rtm_protocol;
122         uint8_t                 rtm_dst_len;
123 };
124
125 #define _IN(_field)     offsetof(struct rtmsg, _field)
126 #define _OUT(_field)    offsetof(struct snl_parsed_route, _field)
127 static const struct snl_attr_parser _nla_p_rtmetrics[] = {
128         { .type = NL_RTAX_MTU, .off = _OUT(rtax_mtu), .cb = snl_attr_get_uint32 },
129 };
130 SNL_DECLARE_ATTR_PARSER(_metrics_parser, _nla_p_rtmetrics);
131
132 static const struct snl_attr_parser _nla_p_route[] = {
133         { .type = NL_RTA_DST, .off = _OUT(rta_dst), .cb = snl_attr_get_ip },
134         { .type = NL_RTA_OIF, .off = _OUT(rta_oif), .cb = snl_attr_get_uint32 },
135         { .type = NL_RTA_GATEWAY, .off = _OUT(rta_gw), .cb = snl_attr_get_ip },
136         { .type = NL_RTA_METRICS, .arg = &_metrics_parser, .cb = snl_attr_get_nested },
137         { .type = NL_RTA_MULTIPATH, .off = _OUT(rta_multipath), .cb = nlattr_get_multipath },
138         { .type = NL_RTA_KNH_ID, .off = _OUT(rta_knh_id), .cb = snl_attr_get_uint32 },
139         { .type = NL_RTA_WEIGHT, .off = _OUT(rtax_weight), .cb = snl_attr_get_uint32 },
140         { .type = NL_RTA_RTFLAGS, .off = _OUT(rta_rtflags), .cb = snl_attr_get_uint32 },
141         { .type = NL_RTA_TABLE, .off = _OUT(rta_table), .cb = snl_attr_get_uint32 },
142         { .type = NL_RTA_VIA, .off = _OUT(rta_gw), .cb = snl_attr_get_ipvia },
143         { .type = NL_RTA_EXPIRES, .off = _OUT(rta_expire), .cb = snl_attr_get_uint32 },
144         { .type = NL_RTA_NH_ID, .off = _OUT(rta_nh_id), .cb = snl_attr_get_uint32 },
145 };
146
147 static const struct snl_field_parser _fp_p_route[] = {
148         {.off_in = _IN(rtm_family), .off_out = _OUT(rtm_family), .cb = snl_field_get_uint8 },
149         {.off_in = _IN(rtm_type), .off_out = _OUT(rtm_type), .cb = snl_field_get_uint8 },
150         {.off_in = _IN(rtm_protocol), .off_out = _OUT(rtm_protocol), .cb = snl_field_get_uint8 },
151         {.off_in = _IN(rtm_dst_len), .off_out = _OUT(rtm_dst_len), .cb = snl_field_get_uint8 },
152 };
153 #undef _IN
154 #undef _OUT
155 SNL_DECLARE_PARSER(snl_rtm_route_parser, struct rtmsg, _fp_p_route, _nla_p_route);
156
157 /* RTM_<NEW|DEL|GET>LINK message parser */
158 struct snl_parsed_link {
159         uint32_t                        ifi_index;
160         uint32_t                        ifi_flags;
161         uint32_t                        ifi_change;
162         uint16_t                        ifi_type;
163         uint8_t                         ifla_operstate;
164         uint8_t                         ifla_carrier;
165         uint32_t                        ifla_mtu;
166         char                            *ifla_ifname;
167         struct nlattr                   *ifla_address;
168         struct nlattr                   *ifla_broadcast;
169         char                            *ifla_ifalias;
170         uint32_t                        ifla_promiscuity;
171         struct rtnl_link_stats64        *ifla_stats64;
172 };
173
174 #define _IN(_field)     offsetof(struct ifinfomsg, _field)
175 #define _OUT(_field)    offsetof(struct snl_parsed_link, _field)
176 static const struct snl_attr_parser _nla_p_link[] = {
177         { .type = IFLA_ADDRESS, .off = _OUT(ifla_address), .cb = snl_attr_get_nla },
178         { .type = IFLA_BROADCAST, .off = _OUT(ifla_broadcast), .cb = snl_attr_get_nla },
179         { .type = IFLA_IFNAME, .off = _OUT(ifla_ifname), .cb = snl_attr_get_string },
180         { .type = IFLA_MTU, .off = _OUT(ifla_mtu), .cb = snl_attr_get_uint32 },
181         { .type = IFLA_OPERSTATE, .off = _OUT(ifla_operstate), .cb = snl_attr_get_uint8 },
182         { .type = IFLA_IFALIAS, .off = _OUT(ifla_ifalias), .cb = snl_attr_get_string },
183         { .type = IFLA_STATS64, .off = _OUT(ifla_stats64), .cb = snl_attr_copy_struct },
184         { .type = IFLA_PROMISCUITY, .off = _OUT(ifla_promiscuity), .cb = snl_attr_get_uint32 },
185         { .type = IFLA_CARRIER, .off = _OUT(ifla_carrier), .cb = snl_attr_get_uint8 },
186 };
187 static const struct snl_field_parser _fp_p_link[] = {
188         {.off_in = _IN(ifi_index), .off_out = _OUT(ifi_index), .cb = snl_field_get_uint32 },
189         {.off_in = _IN(ifi_flags), .off_out = _OUT(ifi_flags), .cb = snl_field_get_uint32 },
190         {.off_in = _IN(ifi_change), .off_out = _OUT(ifi_change), .cb = snl_field_get_uint32 },
191         {.off_in = _IN(ifi_type), .off_out = _OUT(ifi_type), .cb = snl_field_get_uint16 },
192 };
193 #undef _IN
194 #undef _OUT
195 SNL_DECLARE_PARSER(snl_rtm_link_parser, struct ifinfomsg, _fp_p_link, _nla_p_link);
196
197 struct snl_parsed_link_simple {
198         uint32_t                ifi_index;
199         uint32_t                ifla_mtu;
200         uint16_t                ifi_type;
201         uint32_t                ifi_flags;
202         char                    *ifla_ifname;
203 };
204
205 #define _IN(_field)     offsetof(struct ifinfomsg, _field)
206 #define _OUT(_field)    offsetof(struct snl_parsed_link_simple, _field)
207 static struct snl_attr_parser _nla_p_link_s[] = {
208         { .type = IFLA_IFNAME, .off = _OUT(ifla_ifname), .cb = snl_attr_get_string },
209         { .type = IFLA_MTU, .off = _OUT(ifla_mtu), .cb = snl_attr_get_uint32 },
210 };
211 static struct snl_field_parser _fp_p_link_s[] = {
212         {.off_in = _IN(ifi_index), .off_out = _OUT(ifi_index), .cb = snl_field_get_uint32 },
213         {.off_in = _IN(ifi_type), .off_out = _OUT(ifi_type), .cb = snl_field_get_uint16 },
214         {.off_in = _IN(ifi_flags), .off_out = _OUT(ifi_flags), .cb = snl_field_get_uint32 },
215 };
216 #undef _IN
217 #undef _OUT
218 SNL_DECLARE_PARSER(snl_rtm_link_parser_simple, struct ifinfomsg, _fp_p_link_s, _nla_p_link_s);
219
220 struct snl_parsed_neigh {
221         uint8_t         ndm_family;
222         uint8_t         ndm_flags;
223         uint16_t        ndm_state;
224         uint32_t        nda_ifindex;
225         struct sockaddr *nda_dst;
226         struct nlattr   *nda_lladdr;
227 };
228
229 #define _IN(_field)     offsetof(struct ndmsg, _field)
230 #define _OUT(_field)    offsetof(struct snl_parsed_neigh, _field)
231 static struct snl_attr_parser _nla_p_neigh_s[] = {
232         { .type = NDA_DST, .off = _OUT(nda_dst), .cb = snl_attr_get_ip },
233         { .type = NDA_LLADDR , .off = _OUT(nda_lladdr), .cb = snl_attr_get_nla },
234         { .type = NDA_IFINDEX, .off = _OUT(nda_ifindex), .cb = snl_attr_get_uint32 },
235 };
236 static struct snl_field_parser _fp_p_neigh_s[] = {
237         {.off_in = _IN(ndm_family), .off_out = _OUT(ndm_family), .cb = snl_field_get_uint8 },
238         {.off_in = _IN(ndm_flags), .off_out = _OUT(ndm_flags), .cb = snl_field_get_uint8 },
239         {.off_in = _IN(ndm_state), .off_out = _OUT(ndm_state), .cb = snl_field_get_uint16 },
240 };
241 #undef _IN
242 #undef _OUT
243 SNL_DECLARE_PARSER(snl_rtm_neigh_parser, struct ndmsg, _fp_p_neigh_s, _nla_p_neigh_s);
244
245 struct snl_parsed_addr {
246         uint8_t         ifa_family;
247         uint8_t         ifa_prefixlen;
248         uint32_t        ifa_index;
249         struct sockaddr *ifa_local;
250         struct sockaddr *ifa_address;
251         struct sockaddr *ifa_broadcast;
252         char            *ifa_label;
253 };
254
255 #define _IN(_field)     offsetof(struct ifaddrmsg, _field)
256 #define _OUT(_field)    offsetof(struct snl_parsed_addr, _field)
257 static struct snl_attr_parser _nla_p_addr_s[] = {
258         { .type = IFA_ADDRESS, .off = _OUT(ifa_address), .cb = snl_attr_get_ip },
259         { .type = IFA_LOCAL, .off = _OUT(ifa_local), .cb = snl_attr_get_ip },
260         { .type = IFA_LABEL, .off = _OUT(ifa_label), .cb = snl_attr_get_string },
261         { .type = IFA_BROADCAST, .off = _OUT(ifa_broadcast), .cb = snl_attr_get_ip },
262 };
263 static struct snl_field_parser _fp_p_addr_s[] = {
264         {.off_in = _IN(ifa_family), .off_out = _OUT(ifa_family), .cb = snl_field_get_uint8 },
265         {.off_in = _IN(ifa_prefixlen), .off_out = _OUT(ifa_prefixlen), .cb = snl_field_get_uint8 },
266         {.off_in = _IN(ifa_index), .off_out = _OUT(ifa_index), .cb = snl_field_get_uint32 },
267 };
268 #undef _IN
269 #undef _OUT
270 SNL_DECLARE_PARSER(snl_rtm_addr_parser, struct ifaddrmsg, _fp_p_addr_s, _nla_p_addr_s);
271
272 static const struct snl_hdr_parser *snl_all_route_parsers[] = {
273         &_metrics_mp_nh_parser, &_mpath_nh_parser, &_metrics_parser, &snl_rtm_route_parser,
274         &snl_rtm_link_parser, &snl_rtm_link_parser_simple, &snl_rtm_neigh_parser,
275         &snl_rtm_addr_parser,
276 };
277
278 #endif