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