Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/netlink/netlink_snl_route.h
39475 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2022 Alexander V. Chernikov <[email protected]>
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_H_
28
#define _NETLINK_NETLINK_SNL_ROUTE_H_
29
30
#include <netlink/netlink_snl.h>
31
#include <netlink/netlink_route.h>
32
#include <netinet/in.h>
33
34
/*
35
* Simple Netlink Library - NETLINK_ROUTE helpers
36
*/
37
38
static inline struct sockaddr *
39
parse_rta_ip4(struct snl_state *ss, void *rta_data, int *perror)
40
{
41
struct sockaddr_in *sin;
42
43
sin = (struct sockaddr_in *)snl_allocz(ss, sizeof(struct sockaddr_in));
44
if (sin == NULL) {
45
*perror = ENOBUFS;
46
return (NULL);
47
}
48
sin->sin_len = sizeof(struct sockaddr_in);
49
sin->sin_family = AF_INET;
50
memcpy(&sin->sin_addr, rta_data, sizeof(struct in_addr));
51
return ((struct sockaddr *)sin);
52
}
53
54
static inline struct sockaddr *
55
parse_rta_ip6(struct snl_state *ss, void *rta_data, int *perror)
56
{
57
struct sockaddr_in6 *sin6;
58
59
sin6 = (struct sockaddr_in6 *)snl_allocz(ss, sizeof(struct sockaddr_in6));
60
if (sin6 == NULL) {
61
*perror = ENOBUFS;
62
return (NULL);
63
}
64
sin6->sin6_len = sizeof(struct sockaddr_in6);
65
sin6->sin6_family = AF_INET6;
66
memcpy(&sin6->sin6_addr, rta_data, sizeof(struct in6_addr));
67
return ((struct sockaddr *)sin6);
68
}
69
70
static inline struct sockaddr *
71
parse_rta_ip(struct snl_state *ss, struct rtattr *rta, int *perror)
72
{
73
void *rta_data = NL_RTA_DATA(rta);
74
int rta_len = NL_RTA_DATA_LEN(rta);
75
76
if (rta_len == sizeof(struct in_addr)) {
77
return (parse_rta_ip4(ss, rta_data, perror));
78
} else if (rta_len == sizeof(struct in6_addr)) {
79
return (parse_rta_ip6(ss, rta_data, perror));
80
} else {
81
*perror = ENOTSUP;
82
return (NULL);
83
}
84
return (NULL);
85
}
86
87
static inline bool
88
snl_attr_get_ip(struct snl_state *ss, struct nlattr *nla,
89
const void *arg __unused, void *target)
90
{
91
int error = 0;
92
struct sockaddr *sa = parse_rta_ip(ss, (struct rtattr *)nla, &error);
93
if (error == 0) {
94
*((struct sockaddr **)target) = sa;
95
return (true);
96
}
97
return (false);
98
}
99
100
static inline struct sockaddr *
101
parse_rta_via(struct snl_state *ss, struct rtattr *rta, int *perror)
102
{
103
struct rtvia *via = (struct rtvia *)NL_RTA_DATA(rta);
104
105
switch (via->rtvia_family) {
106
case AF_INET:
107
return (parse_rta_ip4(ss, via->rtvia_addr, perror));
108
case AF_INET6:
109
return (parse_rta_ip6(ss, via->rtvia_addr, perror));
110
default:
111
*perror = ENOTSUP;
112
return (NULL);
113
}
114
}
115
116
static inline bool
117
snl_attr_get_ipvia(struct snl_state *ss, struct nlattr *nla,
118
const void *arg __unused, void *target)
119
{
120
int error = 0;
121
122
struct sockaddr *sa = parse_rta_via(ss, (struct rtattr *)nla, &error);
123
if (error == 0) {
124
*((struct sockaddr **)target) = sa;
125
return (true);
126
}
127
return (false);
128
}
129
130
static inline bool
131
snl_add_msg_attr_ip4(struct snl_writer *nw, int attrtype, const struct in_addr *addr)
132
{
133
return (snl_add_msg_attr(nw, attrtype, 4, addr));
134
}
135
136
static inline bool
137
snl_add_msg_attr_ip6(struct snl_writer *nw, int attrtype, const struct in6_addr *addr)
138
{
139
return (snl_add_msg_attr(nw, attrtype, 16, addr));
140
}
141
142
static inline bool
143
snl_add_msg_attr_ip(struct snl_writer *nw, int attrtype, const struct sockaddr *sa)
144
{
145
const void *addr;
146
147
switch (sa->sa_family) {
148
case AF_INET:
149
addr = &((const struct sockaddr_in *)(const void *)sa)->sin_addr;
150
return (snl_add_msg_attr(nw, attrtype, 4, addr));
151
case AF_INET6:
152
addr = &((const struct sockaddr_in6 *)(const void *)sa)->sin6_addr;
153
return (snl_add_msg_attr(nw, attrtype, 16, addr));
154
}
155
156
return (false);
157
}
158
159
static inline bool
160
snl_add_msg_attr_ipvia(struct snl_writer *nw, int attrtype, const struct sockaddr *sa)
161
{
162
char buf[17];
163
164
buf[0] = sa->sa_family;
165
166
switch (sa->sa_family) {
167
case AF_INET:
168
memcpy(&buf[1], &((const struct sockaddr_in *)(const void *)sa)->sin_addr, 4);
169
return (snl_add_msg_attr(nw, attrtype, 5, buf));
170
case AF_INET6:
171
memcpy(&buf[1], &((const struct sockaddr_in6 *)(const void *)sa)->sin6_addr, 16);
172
return (snl_add_msg_attr(nw, attrtype, 17, buf));
173
}
174
175
return (false);
176
}
177
178
static inline bool
179
snl_attr_get_in_addr(struct snl_state *ss __unused, struct nlattr *nla,
180
const void *arg __unused, void *target)
181
{
182
if (NLA_DATA_LEN(nla) != sizeof(struct in_addr))
183
return (false);
184
185
memcpy(target, NLA_DATA_CONST(nla), sizeof(struct in_addr));
186
return (true);
187
}
188
189
static inline bool
190
snl_attr_get_in6_addr(struct snl_state *ss __unused, struct nlattr *nla,
191
const void *arg __unused, void *target)
192
{
193
if (NLA_DATA_LEN(nla) != sizeof(struct in6_addr))
194
return (false);
195
196
memcpy(target, NLA_DATA_CONST(nla), sizeof(struct in6_addr));
197
return (true);
198
}
199
200
201
#endif
202
203