libnl 3.7.0
ipvlan.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2015 Cong Wang <cwang@twopensource.com>
4 */
5
6/**
7 * @ingroup link
8 * @defgroup ipvlan IPVLAN
9 * IP-based Virtual LAN link module
10 *
11 * @details
12 * \b Link Type Name: "ipvlan"
13 *
14 * @route_doc{link_ipvlan, IPVLAN Documentation}
15 *
16 * @{
17 */
18
19#include <netlink-private/netlink.h>
20#include <netlink/netlink.h>
21#include <netlink/attr.h>
22#include <netlink/utils.h>
23#include <netlink/object.h>
24#include <netlink/route/rtnl.h>
25#include <netlink-private/route/link/api.h>
26#include <netlink/route/link/ipvlan.h>
27
28#include <linux/if_link.h>
29
30/** @cond SKIP */
31#define IPVLAN_HAS_MODE (1<<0)
32
33struct ipvlan_info
34{
35 uint16_t ipi_mode;
36 uint32_t ipi_mask;
37};
38
39/** @endcond */
40
41static struct nla_policy ipvlan_policy[IFLA_IPVLAN_MAX+1] = {
42 [IFLA_IPVLAN_MODE] = { .type = NLA_U16 },
43};
44
45static int ipvlan_alloc(struct rtnl_link *link)
46{
47 struct ipvlan_info *ipi;
48
49 if (link->l_info)
50 memset(link->l_info, 0, sizeof(*ipi));
51 else {
52 if ((ipi = calloc(1, sizeof(*ipi))) == NULL)
53 return -NLE_NOMEM;
54
55 link->l_info = ipi;
56 }
57
58 return 0;
59}
60
61static int ipvlan_parse(struct rtnl_link *link, struct nlattr *data,
62 struct nlattr *xstats)
63{
64 struct nlattr *tb[IFLA_IPVLAN_MAX+1];
65 struct ipvlan_info *ipi;
66 int err;
67
68 NL_DBG(3, "Parsing IPVLAN link info\n");
69
70 if ((err = nla_parse_nested(tb, IFLA_IPVLAN_MAX, data, ipvlan_policy)) < 0)
71 goto errout;
72
73 if ((err = ipvlan_alloc(link)) < 0)
74 goto errout;
75
76 ipi = link->l_info;
77
78 if (tb[IFLA_IPVLAN_MODE]) {
79 ipi->ipi_mode = nla_get_u16(tb[IFLA_IPVLAN_MODE]);
80 ipi->ipi_mask |= IPVLAN_HAS_MODE;
81 }
82
83 err = 0;
84errout:
85 return err;
86}
87
88static void ipvlan_free(struct rtnl_link *link)
89{
90 free(link->l_info);
91 link->l_info = NULL;
92}
93
94static void ipvlan_dump(struct rtnl_link *link, struct nl_dump_params *p)
95{
96 char buf[64];
97 struct ipvlan_info *ipi = link->l_info;
98
99 if (ipi->ipi_mask & IPVLAN_HAS_MODE) {
100 rtnl_link_ipvlan_mode2str(ipi->ipi_mode, buf, sizeof(buf));
101 nl_dump(p, "ipvlan-mode %s", buf);
102 }
103}
104
105static int ipvlan_clone(struct rtnl_link *dst, struct rtnl_link *src)
106{
107 struct ipvlan_info *vdst, *vsrc = src->l_info;
108 int err;
109
110 dst->l_info = NULL;
111 if ((err = rtnl_link_set_type(dst, "ipvlan")) < 0)
112 return err;
113 vdst = dst->l_info;
114
115 if (!vdst || !vsrc)
116 return -NLE_NOMEM;
117
118 memcpy(vdst, vsrc, sizeof(struct ipvlan_info));
119
120 return 0;
121}
122
123static int ipvlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
124{
125 struct ipvlan_info *ipi = link->l_info;
126 struct nlattr *data;
127
128 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
129 return -NLE_MSGSIZE;
130
131 if (ipi->ipi_mask & IPVLAN_HAS_MODE)
132 NLA_PUT_U16(msg, IFLA_IPVLAN_MODE, ipi->ipi_mode);
133
134 nla_nest_end(msg, data);
135
136nla_put_failure:
137
138 return 0;
139}
140
141static struct rtnl_link_info_ops ipvlan_info_ops = {
142 .io_name = "ipvlan",
143 .io_alloc = ipvlan_alloc,
144 .io_parse = ipvlan_parse,
145 .io_dump = {
146 [NL_DUMP_LINE] = ipvlan_dump,
147 [NL_DUMP_DETAILS] = ipvlan_dump,
148 },
149 .io_clone = ipvlan_clone,
150 .io_put_attrs = ipvlan_put_attrs,
151 .io_free = ipvlan_free,
152};
153
154/** @cond SKIP */
155#define IS_IPVLAN_LINK_ASSERT(link) \
156 if ((link)->l_info_ops != &ipvlan_info_ops) { \
157 APPBUG("Link is not a ipvlan link. set type \"ipvlan\" first."); \
158 return -NLE_OPNOTSUPP; \
159 }
160/** @endcond */
161
162/**
163 * @name IPVLAN Object
164 * @{
165 */
166
167/**
168 * Allocate link object of type IPVLAN
169 *
170 * @return Allocated link object or NULL.
171 */
173{
174 struct rtnl_link *link;
175
176 if (!(link = rtnl_link_alloc()))
177 return NULL;
178
179 if (rtnl_link_set_type(link, "ipvlan") < 0) {
180 rtnl_link_put(link);
181 return NULL;
182 }
183
184 return link;
185}
186
187/**
188 * Check if link is a IPVLAN link
189 * @arg link Link object
190 *
191 * @return True if link is a IPVLAN link, otherwise false is returned.
192 */
194{
195 return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "ipvlan");
196}
197
198/**
199 * Set IPVLAN MODE
200 * @arg link Link object
201 * @arg mode IPVLAN mode
202 *
203 * @return 0 on success or a negative error code
204 */
205int rtnl_link_ipvlan_set_mode(struct rtnl_link *link, uint16_t mode)
206{
207 struct ipvlan_info *ipi = link->l_info;
208
209 IS_IPVLAN_LINK_ASSERT(link);
210
211 ipi->ipi_mode = mode;
212 ipi->ipi_mask |= IPVLAN_HAS_MODE;
213
214 return 0;
215}
216
217/**
218 * Get IPVLAN Mode
219 * @arg link Link object
220 * @arg out_mode on success, return the mode
221 *
222 * @return 0 on success or a negative error code.
223 */
224int rtnl_link_ipvlan_get_mode(struct rtnl_link *link, uint16_t *out_mode)
225{
226 struct ipvlan_info *ipi = link->l_info;
227
228 IS_IPVLAN_LINK_ASSERT(link);
229
230 if (!(ipi->ipi_mask & IPVLAN_HAS_MODE))
231 return -NLE_INVAL;
232 *out_mode = ipi->ipi_mode;
233 return 0;
234}
235
236/** @} */
237
238static const struct trans_tbl ipvlan_modes[] = {
239 __ADD(IPVLAN_MODE_L2, l2),
240 __ADD(IPVLAN_MODE_L3, l3),
241};
242
243/**
244 * @name Mode Translation
245 * @{
246 */
247
248char *rtnl_link_ipvlan_mode2str(int mode, char *buf, size_t len)
249{
250 return __type2str(mode, buf, len, ipvlan_modes, ARRAY_SIZE(ipvlan_modes));
251}
252
253int rtnl_link_ipvlan_str2mode(const char *name)
254{
255 return __str2type(name, ipvlan_modes, ARRAY_SIZE(ipvlan_modes));
256}
257
258/** @} */
259
260static void __init ipvlan_init(void)
261{
262 rtnl_link_register_info(&ipvlan_info_ops);
263}
264
265static void __exit ipvlan_exit(void)
266{
267 rtnl_link_unregister_info(&ipvlan_info_ops);
268}
269
270/** @} */
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition: attr.c:652
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
Definition: attr.h:212
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition: attr.c:898
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
Definition: attr.c:1016
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition: attr.c:961
@ NLA_U16
16 bit integer
Definition: attr.h:36
int rtnl_link_ipvlan_set_mode(struct rtnl_link *link, uint16_t mode)
Set IPVLAN MODE.
Definition: ipvlan.c:205
int rtnl_link_ipvlan_get_mode(struct rtnl_link *link, uint16_t *out_mode)
Get IPVLAN Mode.
Definition: ipvlan.c:224
struct rtnl_link * rtnl_link_ipvlan_alloc(void)
Allocate link object of type IPVLAN.
Definition: ipvlan.c:172
int rtnl_link_is_ipvlan(struct rtnl_link *link)
Check if link is a IPVLAN link.
Definition: ipvlan.c:193
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:955
@ NL_DUMP_LINE
Dump object briefly on one line.
Definition: types.h:16
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Definition: types.h:17
Dumping parameters.
Definition: types.h:28
Attribute validation policy.
Definition: attr.h:63
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:65