1 /*
2  * Copyright (c) 2021 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(net_virtual_mgmt, CONFIG_NET_L2_VIRTUAL_LOG_LEVEL);
9 
10 #include <errno.h>
11 
12 #include <zephyr/net/net_core.h>
13 #include <zephyr/net/net_if.h>
14 #include <zephyr/net/virtual_mgmt.h>
15 
virtual_interface_set_config(uint64_t mgmt_request,struct net_if * iface,void * data,size_t len)16 static int virtual_interface_set_config(uint64_t mgmt_request,
17 					struct net_if *iface,
18 					void *data, size_t len)
19 {
20 	struct virtual_interface_req_params *params =
21 				(struct virtual_interface_req_params *)data;
22 	const struct device *dev = net_if_get_device(iface);
23 	const struct virtual_interface_api *api = dev->api;
24 	struct virtual_interface_config config = { 0 };
25 	enum virtual_interface_config_type type;
26 
27 	if (!api) {
28 		return -ENOENT;
29 	}
30 
31 	if (!api->set_config) {
32 		return -ENOTSUP;
33 	}
34 
35 	if (!data || (len != sizeof(struct virtual_interface_req_params))) {
36 		return -EINVAL;
37 	}
38 
39 	if (mgmt_request == NET_REQUEST_VIRTUAL_INTERFACE_SET_PEER_ADDRESS) {
40 		if (net_if_is_up(iface)) {
41 			return -EACCES;
42 		}
43 
44 		config.family = params->family;
45 		memcpy(&config.peer6addr, &params->peer6addr,
46 		       sizeof(config.peer6addr));
47 		type = VIRTUAL_INTERFACE_CONFIG_TYPE_PEER_ADDRESS;
48 
49 	} else if (mgmt_request == NET_REQUEST_VIRTUAL_INTERFACE_SET_MTU) {
50 		if (net_if_is_up(iface)) {
51 			return -EACCES;
52 		}
53 
54 		config.family = params->family;
55 		config.mtu = params->mtu;
56 		type = VIRTUAL_INTERFACE_CONFIG_TYPE_MTU;
57 
58 	} else if (mgmt_request == NET_REQUEST_VIRTUAL_INTERFACE_SET_LINK_TYPE) {
59 		/* We can update the link types even if the interface is up */
60 		config.family = params->family;
61 		memcpy(&config.link_types, &params->link_types,
62 		       sizeof(config.link_types));
63 		type = VIRTUAL_INTERFACE_CONFIG_TYPE_LINK_TYPE;
64 
65 	} else if (mgmt_request == NET_REQUEST_VIRTUAL_INTERFACE_SET_PRIVATE_KEY) {
66 		if (net_if_is_up(iface)) {
67 			return -EACCES;
68 		}
69 
70 		config.private_key.len = params->private_key.len;
71 		config.private_key.data = params->private_key.data;
72 		type = VIRTUAL_INTERFACE_CONFIG_TYPE_PRIVATE_KEY;
73 	} else {
74 		return -EINVAL;
75 	}
76 
77 	return api->set_config(iface, type, &config);
78 }
79 
80 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_VIRTUAL_INTERFACE_SET_PEER_ADDRESS,
81 				  virtual_interface_set_config);
82 
83 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_VIRTUAL_INTERFACE_SET_MTU,
84 				  virtual_interface_set_config);
85 
86 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_VIRTUAL_INTERFACE_SET_LINK_TYPE,
87 				  virtual_interface_set_config);
88 
89 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_VIRTUAL_INTERFACE_SET_PRIVATE_KEY,
90 				  virtual_interface_set_config);
91 
virtual_interface_get_config(uint64_t mgmt_request,struct net_if * iface,void * data,size_t len)92 static int virtual_interface_get_config(uint64_t mgmt_request,
93 					struct net_if *iface,
94 					void *data, size_t len)
95 {
96 	struct virtual_interface_req_params *params =
97 				(struct virtual_interface_req_params *)data;
98 	const struct device *dev = net_if_get_device(iface);
99 	const struct virtual_interface_api *api = dev->api;
100 	struct virtual_interface_config config = { 0 };
101 	enum virtual_interface_config_type type;
102 	int ret = 0;
103 
104 	if (!api) {
105 		return -ENOENT;
106 	}
107 
108 	if (!api->get_config) {
109 		return -ENOTSUP;
110 	}
111 
112 	if (!data || (len != sizeof(struct virtual_interface_req_params))) {
113 		return -EINVAL;
114 	}
115 
116 	if (mgmt_request == NET_REQUEST_VIRTUAL_INTERFACE_GET_PEER_ADDRESS) {
117 		type = VIRTUAL_INTERFACE_CONFIG_TYPE_PEER_ADDRESS;
118 
119 		ret = api->get_config(iface, type, &config);
120 		if (ret) {
121 			return ret;
122 		}
123 
124 		params->family = config.family;
125 		memcpy(&params->peer6addr, &config.peer6addr,
126 		       sizeof(params->peer6addr));
127 
128 	} else if (mgmt_request == NET_REQUEST_VIRTUAL_INTERFACE_GET_MTU) {
129 		type = VIRTUAL_INTERFACE_CONFIG_TYPE_MTU;
130 
131 		ret = api->get_config(iface, type, &config);
132 		if (ret) {
133 			return ret;
134 		}
135 
136 		params->mtu = config.mtu;
137 
138 	} else if (mgmt_request == NET_REQUEST_VIRTUAL_INTERFACE_GET_LINK_TYPE) {
139 		type = VIRTUAL_INTERFACE_CONFIG_TYPE_LINK_TYPE;
140 
141 		ret = api->get_config(iface, type, &config);
142 		if (ret) {
143 			return ret;
144 		}
145 
146 		memcpy(&params->link_types, &config.link_types,
147 		       sizeof(params->link_types));
148 
149 	} else if (mgmt_request == NET_REQUEST_VIRTUAL_INTERFACE_GET_PUBLIC_KEY) {
150 		type = VIRTUAL_INTERFACE_CONFIG_TYPE_PUBLIC_KEY;
151 
152 		ret = api->get_config(iface, type, &config);
153 		if (ret) {
154 			return ret;
155 		}
156 
157 		params->public_key.len = config.public_key.len;
158 		memcpy(&params->public_key.data, &config.public_key.data,
159 		       MIN(sizeof(params->public_key.data),
160 			   params->public_key.len));
161 	} else {
162 		return -EINVAL;
163 	}
164 
165 	return ret;
166 }
167 
168 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_VIRTUAL_INTERFACE_GET_PEER_ADDRESS,
169 				  virtual_interface_get_config);
170 
171 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_VIRTUAL_INTERFACE_GET_MTU,
172 				  virtual_interface_get_config);
173 
174 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_VIRTUAL_INTERFACE_GET_LINK_TYPE,
175 				  virtual_interface_get_config);
176 
177 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_VIRTUAL_INTERFACE_GET_PUBLIC_KEY,
178 				  virtual_interface_get_config);
179