blob: a5147e2cf1530decad8559dc626828b63a99f267 [file] [log] [blame]
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -06001/******************************************************************************
2
3 L I B R M N E T C T L . C
4
Subash Abhinov Kasiviswanathancf715082015-04-14 13:51:59 -06005Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -06006
7Redistribution and use in source and binary forms, with or without
8modification, are permitted provided that the following conditions are
9met:
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above
13 copyright notice, this list of conditions and the following
14 disclaimer in the documentation and/or other materials provided
15 with the distribution.
16 * Neither the name of The Linux Foundation nor the names of its
17 contributors may be used to endorse or promote products derived
18 from this software without specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32******************************************************************************/
33
34/*!
35* @file librmnetctl.c
Subash Abhinov Kasiviswanathancf715082015-04-14 13:51:59 -060036* @brief rmnet control API's implementation file
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -060037*/
38
39/*===========================================================================
40 INCLUDE FILES
41===========================================================================*/
42
43#include <sys/socket.h>
44#include <stdint.h>
45#include <linux/netlink.h>
46#include <string.h>
47#include <stdio.h>
48#include <unistd.h>
49#include <stdlib.h>
50#include <linux/rmnet_data.h>
51#include "librmnetctl_hndl.h"
52#include "librmnetctl.h"
53
Harout Hedeshian04d69732013-10-02 09:29:11 -060054#ifdef USE_GLIB
55#include <glib.h>
56#define strlcpy g_strlcpy
57#endif
58
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -060059#define RMNETCTL_SOCK_FLAG 0
60#define ROOT_USER_ID 0
61#define MIN_VALID_PROCESS_ID 0
62#define MIN_VALID_SOCKET_FD 0
63#define KERNEL_PROCESS_ID 0
64#define UNICAST 0
65#define MAX_BUF_SIZE sizeof(struct nlmsghdr) + sizeof(struct rmnet_nl_msg_s)
Harout Hedeshian77825572014-02-17 10:47:14 +020066#define INGRESS_FLAGS_MASK (RMNET_INGRESS_FIX_ETHERNET | \
67 RMNET_INGRESS_FORMAT_MAP | \
68 RMNET_INGRESS_FORMAT_DEAGGREGATION | \
69 RMNET_INGRESS_FORMAT_DEMUXING | \
Sivan Reinsteinc22a0d82014-07-13 16:58:21 +030070 RMNET_INGRESS_FORMAT_MAP_COMMANDS | \
Subash Abhinov Kasiviswanathan21e5e442015-09-03 20:07:53 -060071 RMNET_INGRESS_FORMAT_MAP_CKSUMV3 | \
72 RMNET_INGRESS_FORMAT_MAP_CKSUMV4)
Harout Hedeshian77825572014-02-17 10:47:14 +020073#define EGRESS_FLAGS_MASK (RMNET_EGRESS_FORMAT__RESERVED__ | \
74 RMNET_EGRESS_FORMAT_MAP | \
75 RMNET_EGRESS_FORMAT_AGGREGATION | \
Sivan Reinsteina3c57172014-09-10 14:11:58 +030076 RMNET_EGRESS_FORMAT_MUXING | \
Subash Abhinov Kasiviswanathan21e5e442015-09-03 20:07:53 -060077 RMNET_EGRESS_FORMAT_MAP_CKSUMV3 | \
78 RMNET_EGRESS_FORMAT_MAP_CKSUMV4)
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -060079
Harout Hedeshian77825572014-02-17 10:47:14 +020080#define min(a, b) (((a) < (b)) ? (a) : (b))
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -060081/*===========================================================================
82 LOCAL FUNCTION DEFINITIONS
83===========================================================================*/
84/*!
85* @brief Synchronous method to send and receive messages to and from the kernel
86* using netlink sockets
87* @details Increments the transaction id for each message sent to the kernel.
88* Sends the netlink message to the kernel and receives the response from the
89* kernel.
90* @param *hndl RmNet handle for this transaction
91* @param request Message to be sent to the kernel
92* @param response Message received from the kernel
93* @return RMNETCTL_API_SUCCESS if successfully able to send and receive message
94* from the kernel
95* @return RMNETCTL_API_ERR_HNDL_INVALID if RmNet handle for the transaction was
96* NULL
97* @return RMNETCTL_API_ERR_REQUEST_NULL not enough memory to create buffer for
98* sending the message
99* @return RMNETCTL_API_ERR_MESSAGE_SEND if could not send the message to kernel
100* @return RMNETCTL_API_ERR_MESSAGE_RECEIVE if could not receive message from the
101* kernel
102* @return RMNETCTL_API_ERR_MESSAGE_TYPE if the request and response type do not
103* match
104*/
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700105static uint16_t rmnetctl_transact(rmnetctl_hndl_t *hndl,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600106 struct rmnet_nl_msg_s *request,
107 struct rmnet_nl_msg_s *response) {
108 uint8_t *request_buf, *response_buf;
109 struct nlmsghdr *nlmsghdr_val;
110 struct rmnet_nl_msg_s *rmnet_nl_msg_s_val;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700111 ssize_t bytes_read = -1;
112 uint16_t return_code = RMNETCTL_API_ERR_HNDL_INVALID;
113 struct sockaddr_nl* __attribute__((__may_alias__)) saddr_ptr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600114 request_buf = NULL;
115 response_buf = NULL;
116 nlmsghdr_val = NULL;
117 rmnet_nl_msg_s_val = NULL;
118 do {
119 if (!hndl){
120 break;
121 }
122 if (!request){
123 return_code = RMNETCTL_API_ERR_REQUEST_NULL;
124 break;
125 }
126 if (!response){
127 return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
128 break;
129 }
130 request_buf = (uint8_t *)malloc(MAX_BUF_SIZE * sizeof(uint8_t));
131 if (!request_buf){
132 return_code = RMNETCTL_API_ERR_REQUEST_NULL;
133 break;
134 }
135
136 response_buf = (uint8_t *)malloc(MAX_BUF_SIZE * sizeof(uint8_t));
137 if (!response_buf) {
138 free(request_buf);
139 return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
140 break;
141 }
142
143 nlmsghdr_val = (struct nlmsghdr *)request_buf;
144 rmnet_nl_msg_s_val = (struct rmnet_nl_msg_s *)NLMSG_DATA(request_buf);
145
146 memset(request_buf, 0, MAX_BUF_SIZE*sizeof(uint8_t));
147 memset(response_buf, 0, MAX_BUF_SIZE*sizeof(uint8_t));
148
149 nlmsghdr_val->nlmsg_seq = hndl->transaction_id;
150 nlmsghdr_val->nlmsg_pid = hndl->pid;
151 nlmsghdr_val->nlmsg_len = MAX_BUF_SIZE;
152
153 memcpy((void *)NLMSG_DATA(request_buf), request,
154 sizeof(struct rmnet_nl_msg_s));
155
156 rmnet_nl_msg_s_val->crd = RMNET_NETLINK_MSG_COMMAND;
157 hndl->transaction_id++;
158
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700159 saddr_ptr = &hndl->dest_addr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600160 socklen_t addrlen = sizeof(struct sockaddr_nl);
161 if (sendto(hndl->netlink_fd,
162 request_buf,
163 MAX_BUF_SIZE,
164 RMNETCTL_SOCK_FLAG,
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700165 (struct sockaddr*)saddr_ptr,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600166 sizeof(struct sockaddr_nl)) < 0) {
167 return_code = RMNETCTL_API_ERR_MESSAGE_SEND;
168 free(request_buf);
169 free(response_buf);
170 break;
171 }
172
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700173 saddr_ptr = &hndl->src_addr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600174 bytes_read = recvfrom(hndl->netlink_fd,
175 response_buf,
176 MAX_BUF_SIZE,
177 RMNETCTL_SOCK_FLAG,
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700178 (struct sockaddr*)saddr_ptr,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600179 &addrlen);
180 if (bytes_read < 0) {
181 return_code = RMNETCTL_API_ERR_MESSAGE_RECEIVE;
182 free(request_buf);
183 free(response_buf);
184 break;
185 }
186
187 memcpy(response, (void *)NLMSG_DATA(response_buf),
188 sizeof(struct rmnet_nl_msg_s));
189 if (sizeof(*response) < sizeof(struct rmnet_nl_msg_s)) {
190 return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
191 free(request_buf);
192 free(response_buf);
193 break;
194 }
195
196 if (request->message_type != response->message_type) {
197 return_code = RMNETCTL_API_ERR_MESSAGE_TYPE;
198 free(request_buf);
199 free(response_buf);
200 break;
201 }
202 return_code = RMNETCTL_SUCCESS;
203 } while(0);
Harout Hedeshian77825572014-02-17 10:47:14 +0200204 free(request_buf);
205 free(response_buf);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600206 return return_code;
207}
208
209/*!
210* @brief Static function to check the dev name
211* @details Checks if the name is not NULL and if the name is less than the
212* RMNET_MAX_STR_LEN
213* @param dev_name Name of the device
214* @return RMNETCTL_SUCCESS if successful
215* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
216*/
217static inline int _rmnetctl_check_dev_name(const char *dev_name) {
218 int return_code = RMNETCTL_INVALID_ARG;
219 do {
220 if (!dev_name)
221 break;
222 if (strlen(dev_name) >= RMNET_MAX_STR_LEN)
223 break;
224 return_code = RMNETCTL_SUCCESS;
225 } while(0);
226 return return_code;
227}
228
229/*!
230* @brief Static function to check the string length after a copy
231* @details Checks if the string length is not lesser than zero and lesser than
232* RMNET_MAX_STR_LEN
233* @param str_len length of the string after a copy
234* @param error_code Status code of this operation
235* @return RMNETCTL_SUCCESS if successful
236* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
237*/
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700238static inline int _rmnetctl_check_len(size_t str_len, uint16_t *error_code) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600239 int return_code = RMNETCTL_LIB_ERR;
240 do {
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700241 if (str_len > RMNET_MAX_STR_LEN) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600242 *error_code = RMNETCTL_API_ERR_STRING_TRUNCATION;
243 break;
244 }
245 return_code = RMNETCTL_SUCCESS;
246 } while(0);
247 return return_code;
248}
249
250/*!
251* @brief Static function to check the response type
252* @details Checks if the response type of this message was return code
253* @param crd The crd field passed
254* @param error_code Status code of this operation
255* @return RMNETCTL_SUCCESS if successful
256* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
257*/
258static inline int _rmnetctl_check_code(int crd, uint16_t *error_code) {
259 int return_code = RMNETCTL_LIB_ERR;
260 do {
261 if (crd != RMNET_NETLINK_MSG_RETURNCODE) {
262 *error_code = RMNETCTL_API_ERR_RETURN_TYPE;
263 break;
264 }
265 return_code = RMNETCTL_SUCCESS;
266 } while(0);
267 return return_code;
268}
269
270/*!
271* @brief Static function to check the response type
272* @details Checks if the response type of this message was data
273* @param crd The crd field passed
274* @param error_code Status code of this operation
275* @return RMNETCTL_SUCCESS if successful
276* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
277*/
278static inline int _rmnetctl_check_data(int crd, uint16_t *error_code) {
279 int return_code = RMNETCTL_LIB_ERR;
280 do {
281 if (crd != RMNET_NETLINK_MSG_RETURNDATA) {
282 *error_code = RMNETCTL_API_ERR_RETURN_TYPE;
283 break;
284 }
285 return_code = RMNETCTL_SUCCESS;
286 } while(0);
287 return return_code;
288}
289
290/*!
291* @brief Static function to set the return value
292* @details Checks if the error_code from the transaction is zero for a return
293* code type message and sets the message type as RMNETCTL_SUCCESS
294* @param crd The crd field passed
295* @param error_code Status code of this operation
296* @return RMNETCTL_SUCCESS if successful
297* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
298* Check error_code
299*/
300static inline int _rmnetctl_set_codes(int error_val, uint16_t *error_code) {
301 int return_code = RMNETCTL_KERNEL_ERR;
Harout Hedeshian77825572014-02-17 10:47:14 +0200302 if (error_val == RMNET_CONFIG_OK)
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600303 return_code = RMNETCTL_SUCCESS;
Harout Hedeshian77825572014-02-17 10:47:14 +0200304 else
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700305 *error_code = (uint16_t)error_val + RMNETCTL_KERNEL_FIRST_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600306 return return_code;
307}
308
309/*===========================================================================
310 EXPOSED API
311===========================================================================*/
312
313int rmnetctl_init(rmnetctl_hndl_t **hndl, uint16_t *error_code)
314{
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700315 pid_t pid = 0;
316 int netlink_fd = -1, return_code = RMNETCTL_LIB_ERR;
317 struct sockaddr_nl* __attribute__((__may_alias__)) saddr_ptr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600318 do {
319 if ((!hndl) || (!error_code)){
320 return_code = RMNETCTL_INVALID_ARG;
321 break;
322 }
323
324 *hndl = (rmnetctl_hndl_t *)malloc(sizeof(rmnetctl_hndl_t));
325 if (!*hndl) {
326 *error_code = RMNETCTL_API_ERR_HNDL_INVALID;
327 break;
328 }
329
330 memset(*hndl, 0, sizeof(rmnetctl_hndl_t));
331
332 pid = getpid();
333 if (pid < MIN_VALID_PROCESS_ID) {
334 free(*hndl);
335 *error_code = RMNETCTL_INIT_ERR_PROCESS_ID;
336 break;
337 }
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700338 (*hndl)->pid = (uint32_t)pid;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600339 netlink_fd = socket(PF_NETLINK, SOCK_RAW, RMNET_NETLINK_PROTO);
340 if (netlink_fd < MIN_VALID_SOCKET_FD) {
341 free(*hndl);
342 *error_code = RMNETCTL_INIT_ERR_NETLINK_FD;
343 break;
344 }
345
346 (*hndl)->netlink_fd = netlink_fd;
347
348 memset(&(*hndl)->src_addr, 0, sizeof(struct sockaddr_nl));
349
350 (*hndl)->src_addr.nl_family = AF_NETLINK;
351 (*hndl)->src_addr.nl_pid = (*hndl)->pid;
352
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700353 saddr_ptr = &(*hndl)->src_addr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600354 if (bind((*hndl)->netlink_fd,
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700355 (struct sockaddr*)saddr_ptr,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600356 sizeof(struct sockaddr_nl)) < 0) {
357 close((*hndl)->netlink_fd);
358 free(*hndl);
359 *error_code = RMNETCTL_INIT_ERR_BIND;
360 break;
361 }
362
363 memset(&(*hndl)->dest_addr, 0, sizeof(struct sockaddr_nl));
364
365 (*hndl)->dest_addr.nl_family = AF_NETLINK;
366 (*hndl)->dest_addr.nl_pid = KERNEL_PROCESS_ID;
367 (*hndl)->dest_addr.nl_groups = UNICAST;
368
369 return_code = RMNETCTL_SUCCESS;
370 } while(0);
371 return return_code;
372}
373
374void rmnetctl_cleanup(rmnetctl_hndl_t *hndl)
375{
376 if (!hndl)
377 return;
378 close(hndl->netlink_fd);
379 free(hndl);
380}
381
382int rmnet_associate_network_device(rmnetctl_hndl_t *hndl,
383 const char *dev_name,
384 uint16_t *error_code,
385 uint8_t assoc_dev)
386{
387 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700388 size_t str_len = 0;
389 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600390 do {
391 if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name) ||
392 ((assoc_dev != RMNETCTL_DEVICE_ASSOCIATE) &&
393 (assoc_dev != RMNETCTL_DEVICE_UNASSOCIATE))) {
394 return_code = RMNETCTL_INVALID_ARG;
395 break;
396 }
397
398 if (assoc_dev == RMNETCTL_DEVICE_ASSOCIATE)
399 request.message_type = RMNET_NETLINK_ASSOCIATE_NETWORK_DEVICE;
400 else
401 request.message_type = RMNET_NETLINK_UNASSOCIATE_NETWORK_DEVICE;
402
403 request.arg_length = RMNET_MAX_STR_LEN;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700404 str_len = strlcpy((char *)(request.data), dev_name, (size_t)RMNET_MAX_STR_LEN);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600405 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
406 break;
407
408 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
409 != RMNETCTL_SUCCESS)
410 break;
411 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
412 break;
413 return_code = _rmnetctl_set_codes(response.return_code, error_code);
414 } while(0);
415 return return_code;
416}
417
418int rmnet_get_network_device_associated(rmnetctl_hndl_t *hndl,
419 const char *dev_name,
420 int *register_status,
421 uint16_t *error_code) {
422 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700423 size_t str_len = 0;
424 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600425 do {
426 if ((!hndl) || (!register_status) || (!error_code) ||
427 _rmnetctl_check_dev_name(dev_name)) {
428 return_code = RMNETCTL_INVALID_ARG;
429 break;
430 }
431
432 request.message_type = RMNET_NETLINK_GET_NETWORK_DEVICE_ASSOCIATED;
433
434 request.arg_length = RMNET_MAX_STR_LEN;
435 str_len = strlcpy((char *)(request.data), dev_name, RMNET_MAX_STR_LEN);
436 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
437 break;
438
439 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
440 != RMNETCTL_SUCCESS)
441 break;
442
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600443 if (_rmnetctl_check_data(response.crd, error_code)
444 != RMNETCTL_SUCCESS) {
445 if (_rmnetctl_check_code(response.crd, error_code)
446 == RMNETCTL_SUCCESS)
447 return_code = _rmnetctl_set_codes(response.return_code,
448 error_code);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600449 break;
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600450 }
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600451
452 *register_status = response.return_code;
453 return_code = RMNETCTL_SUCCESS;
454 } while(0);
455 return return_code;
456}
457
458int rmnet_set_link_egress_data_format(rmnetctl_hndl_t *hndl,
459 uint32_t egress_flags,
460 uint16_t agg_size,
461 uint16_t agg_count,
462 const char *dev_name,
463 uint16_t *error_code) {
464 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700465 size_t str_len = 0;
466 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600467 do {
Harout Hedeshian77825572014-02-17 10:47:14 +0200468 if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name) ||
469 ((~EGRESS_FLAGS_MASK) & egress_flags)) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600470 return_code = RMNETCTL_INVALID_ARG;
471 break;
472 }
473
474 request.message_type = RMNET_NETLINK_SET_LINK_EGRESS_DATA_FORMAT;
475
476 request.arg_length = RMNET_MAX_STR_LEN +
477 sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t);
478 str_len = strlcpy((char *)(request.data_format.dev),
479 dev_name,
480 RMNET_MAX_STR_LEN);
481 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
482 break;
483
484 request.data_format.flags = egress_flags;
485 request.data_format.agg_size = agg_size;
486 request.data_format.agg_count = agg_count;
487
488 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
489 != RMNETCTL_SUCCESS)
490 break;
491
492 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
493 break;
494
495 return_code = _rmnetctl_set_codes(response.return_code, error_code);
496 } while(0);
497 return return_code;
498}
499
500int rmnet_get_link_egress_data_format(rmnetctl_hndl_t *hndl,
501 const char *dev_name,
502 uint32_t *egress_flags,
503 uint16_t *agg_size,
504 uint16_t *agg_count,
505 uint16_t *error_code) {
506 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700507 size_t str_len = 0;
508 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600509 do {
510 if ((!hndl) || (!egress_flags) || (!agg_size) || (!agg_count) ||
511 (!error_code) || _rmnetctl_check_dev_name(dev_name)) {
512 return_code = RMNETCTL_INVALID_ARG;
513 break;
514 }
515 request.message_type = RMNET_NETLINK_GET_LINK_EGRESS_DATA_FORMAT;
516
517 request.arg_length = RMNET_MAX_STR_LEN;
518 str_len = strlcpy((char *)(request.data_format.dev),
519 dev_name,
520 RMNET_MAX_STR_LEN);
521 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
522 break;
523
524 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
525 != RMNETCTL_SUCCESS)
526 break;
527
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600528 if (_rmnetctl_check_data(response.crd, error_code)
529 != RMNETCTL_SUCCESS) {
530 if (_rmnetctl_check_code(response.crd, error_code)
531 == RMNETCTL_SUCCESS)
532 return_code = _rmnetctl_set_codes(response.return_code,
533 error_code);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600534 break;
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600535 }
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600536
537 *egress_flags = response.data_format.flags;
538 *agg_size = response.data_format.agg_size;
539 *agg_count = response.data_format.agg_count;
540 return_code = RMNETCTL_SUCCESS;
541 } while(0);
542 return return_code;
543}
544
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700545int rmnet_set_link_ingress_data_format_tailspace(rmnetctl_hndl_t *hndl,
546 uint32_t ingress_flags,
547 uint8_t tail_spacing,
548 const char *dev_name,
549 uint16_t *error_code) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600550 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700551 size_t str_len = 0;
552 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600553 do {
Harout Hedeshian77825572014-02-17 10:47:14 +0200554 if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name) ||
555 ((~INGRESS_FLAGS_MASK) & ingress_flags)) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600556 return_code = RMNETCTL_INVALID_ARG;
557 break;
558 }
559
560 request.message_type = RMNET_NETLINK_SET_LINK_INGRESS_DATA_FORMAT;
561
562 request.arg_length = RMNET_MAX_STR_LEN +
563 sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t);
564 str_len = strlcpy((char *)(request.data_format.dev),
565 dev_name,
566 RMNET_MAX_STR_LEN);
567 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
568 break;
569 request.data_format.flags = ingress_flags;
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700570 request.data_format.tail_spacing = tail_spacing;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600571
572 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
573 != RMNETCTL_SUCCESS)
574 break;
575
576 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
577 break;
578
579 return_code = _rmnetctl_set_codes(response.return_code, error_code);
580 } while(0);
581 return return_code;
582}
583
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700584int rmnet_get_link_ingress_data_format_tailspace(rmnetctl_hndl_t *hndl,
585 const char *dev_name,
586 uint32_t *ingress_flags,
587 uint8_t *tail_spacing,
588 uint16_t *error_code) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600589 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700590 size_t str_len = 0;
591 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600592 do {
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700593 if ((!hndl) || (!error_code) ||
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600594 _rmnetctl_check_dev_name(dev_name)) {
595 return_code = RMNETCTL_INVALID_ARG;
596 break;
597 }
598
599 request.message_type = RMNET_NETLINK_GET_LINK_INGRESS_DATA_FORMAT;
600
601 request.arg_length = RMNET_MAX_STR_LEN;
602 str_len = strlcpy((char *)(request.data_format.dev),
603 dev_name,
604 RMNET_MAX_STR_LEN);
605 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
606 break;
607
608 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
609 != RMNETCTL_SUCCESS)
610 break;
611
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600612 if (_rmnetctl_check_data(response.crd, error_code)
613 != RMNETCTL_SUCCESS) {
614 if (_rmnetctl_check_code(response.crd, error_code)
615 == RMNETCTL_SUCCESS)
616 return_code = _rmnetctl_set_codes(response.return_code,
617 error_code);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600618 break;
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600619 }
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600620
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700621 if (ingress_flags)
622 *ingress_flags = response.data_format.flags;
623
624 if (tail_spacing)
625 *tail_spacing = response.data_format.tail_spacing;
626
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600627 return_code = RMNETCTL_SUCCESS;
628 } while(0);
629 return return_code;
630}
631
632int rmnet_set_logical_ep_config(rmnetctl_hndl_t *hndl,
633 int32_t ep_id,
634 uint8_t operating_mode,
635 const char *dev_name,
636 const char *next_dev,
637 uint16_t *error_code) {
638 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700639 size_t str_len = 0;
640 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600641 do {
642 if ((!hndl) || ((ep_id < -1) || (ep_id > 31)) || (!error_code) ||
643 _rmnetctl_check_dev_name(dev_name) ||
Harout Hedeshian77825572014-02-17 10:47:14 +0200644 _rmnetctl_check_dev_name(next_dev) ||
645 operating_mode >= RMNET_EPMODE_LENGTH) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600646 return_code = RMNETCTL_INVALID_ARG;
647 break;
648 }
649
650 request.message_type = RMNET_NETLINK_SET_LOGICAL_EP_CONFIG;
651
652 request.arg_length = RMNET_MAX_STR_LEN +
653 RMNET_MAX_STR_LEN + sizeof(int32_t) + sizeof(uint8_t);
654 str_len = strlcpy((char *)(request.local_ep_config.dev),
655 dev_name,
656 RMNET_MAX_STR_LEN);
657 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
658 break;
659
660 str_len = strlcpy((char *)(request.local_ep_config.next_dev),
661 next_dev,
662 RMNET_MAX_STR_LEN);
663 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
664 break;
665 request.local_ep_config.ep_id = ep_id;
666 request.local_ep_config.operating_mode = operating_mode;
667
668 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
669 != RMNETCTL_SUCCESS)
670 break;
671 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
672 break;
673
674 return_code = _rmnetctl_set_codes(response.return_code, error_code);
675 } while(0);
676 return return_code;
677}
678
Harout Hedeshiana9731652014-01-06 18:00:23 +0200679int rmnet_unset_logical_ep_config(rmnetctl_hndl_t *hndl,
680 int32_t ep_id,
681 const char *dev_name,
682 uint16_t *error_code) {
683 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700684 size_t str_len = 0;
685 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshiana9731652014-01-06 18:00:23 +0200686 do {
687
688 if ((!hndl) || ((ep_id < -1) || (ep_id > 31)) || (!error_code) ||
689 _rmnetctl_check_dev_name(dev_name)) {
690 return_code = RMNETCTL_INVALID_ARG;
691 break;
692 }
693
694 request.message_type = RMNET_NETLINK_UNSET_LOGICAL_EP_CONFIG;
695
696 request.arg_length = RMNET_MAX_STR_LEN + sizeof(int32_t);
697 str_len = strlcpy((char *)(request.local_ep_config.dev),
698 dev_name,
699 RMNET_MAX_STR_LEN);
700
701 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
702 break;
703
704 request.local_ep_config.ep_id = ep_id;
705
706 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
707 != RMNETCTL_SUCCESS)
708 break;
709 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
710 break;
711
712 return_code = _rmnetctl_set_codes(response.return_code, error_code);
713 } while(0);
714
715 return return_code;
716}
717
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600718int rmnet_get_logical_ep_config(rmnetctl_hndl_t *hndl,
719 int32_t ep_id,
720 const char *dev_name,
721 uint8_t *operating_mode,
722 char **next_dev,
Harout Hedeshian77825572014-02-17 10:47:14 +0200723 uint32_t next_dev_len,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600724 uint16_t *error_code) {
725 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700726 size_t str_len = 0;
727 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600728 do {
729 if ((!hndl) || (!operating_mode) || (!error_code) || ((ep_id < -1) ||
Harout Hedeshian77825572014-02-17 10:47:14 +0200730 (ep_id > 31)) || _rmnetctl_check_dev_name(dev_name) || (!next_dev)
731 || (0 == next_dev_len)) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600732 return_code = RMNETCTL_INVALID_ARG;
733 break;
734 }
735
736 request.message_type = RMNET_NETLINK_GET_LOGICAL_EP_CONFIG;
737
738 request.arg_length = RMNET_MAX_STR_LEN + sizeof(int32_t);
739 str_len = strlcpy((char *)(request.local_ep_config.dev),
740 dev_name,
741 RMNET_MAX_STR_LEN);
742 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
743 break;
744
745 request.local_ep_config.ep_id = ep_id;
746
747 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
748 != RMNETCTL_SUCCESS)
749 break;
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600750
751 if (_rmnetctl_check_data(response.crd, error_code)
752 != RMNETCTL_SUCCESS) {
753 if (_rmnetctl_check_code(response.crd, error_code)
754 == RMNETCTL_SUCCESS)
755 return_code = _rmnetctl_set_codes(response.return_code,
756 error_code);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600757 break;
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600758 }
Harout Hedeshian77825572014-02-17 10:47:14 +0200759
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600760 str_len = strlcpy(*next_dev,
761 (char *)(response.local_ep_config.next_dev),
Harout Hedeshian77825572014-02-17 10:47:14 +0200762 min(RMNET_MAX_STR_LEN, next_dev_len));
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600763 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
764 break;
765
766 *operating_mode = response.local_ep_config.operating_mode;
767 return_code = RMNETCTL_SUCCESS;
768 } while(0);
769 return return_code;
770}
771
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600772int rmnet_new_vnd_prefix(rmnetctl_hndl_t *hndl,
773 uint32_t id,
774 uint16_t *error_code,
775 uint8_t new_vnd,
776 const char *prefix)
777{
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600778 struct rmnet_nl_msg_s request, response;
779 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700780 size_t str_len = 0;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600781 do {
782 if ((!hndl) || (!error_code) ||
783 ((new_vnd != RMNETCTL_NEW_VND) && (new_vnd != RMNETCTL_FREE_VND))) {
784 return_code = RMNETCTL_INVALID_ARG;
785 break;
786 }
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600787
788 memset(request.vnd.vnd_name, 0, RMNET_MAX_STR_LEN);
789 if (new_vnd == RMNETCTL_NEW_VND) {
790 if (prefix) {
791 request.message_type =RMNET_NETLINK_NEW_VND_WITH_PREFIX;
792 str_len = strlcpy((char *)request.vnd.vnd_name,
793 prefix, RMNET_MAX_STR_LEN);
794 if (_rmnetctl_check_len(str_len, error_code)
795 != RMNETCTL_SUCCESS)
796 break;
797 } else {
798 request.message_type = RMNET_NETLINK_NEW_VND;
799 }
800 } else {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600801 request.message_type = RMNET_NETLINK_FREE_VND;
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600802 }
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600803
804 request.arg_length = sizeof(uint32_t);
805 request.vnd.id = id;
806
807 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
808 != RMNETCTL_SUCCESS)
809 break;
810 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
811 break;
812
813 return_code = _rmnetctl_set_codes(response.return_code, error_code);
814 } while(0);
815 return return_code;
816}
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600817
818int rmnet_new_vnd(rmnetctl_hndl_t *hndl,
819 uint32_t id,
820 uint16_t *error_code,
821 uint8_t new_vnd)
822{
823 return rmnet_new_vnd_prefix(hndl, id, error_code, new_vnd, 0);
824}
825
826int rmnet_get_vnd_name(rmnetctl_hndl_t *hndl,
827 uint32_t id,
828 uint16_t *error_code,
829 char *buf,
830 uint32_t buflen)
831{
832 struct rmnet_nl_msg_s request, response;
833 uint32_t str_len;
834 int return_code = RMNETCTL_LIB_ERR;
835 do {
Harout Hedeshian77825572014-02-17 10:47:14 +0200836 if ((!hndl) || (!error_code) || (!buf) || (0 == buflen)) {
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600837 return_code = RMNETCTL_INVALID_ARG;
838 break;
839 }
840
841 request.message_type = RMNET_NETLINK_GET_VND_NAME;
842 request.arg_length = sizeof(uint32_t);
843 request.vnd.id = id;
844
845
846 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
847 != RMNETCTL_SUCCESS)
848 break;
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600849
850 if (_rmnetctl_check_data(response.crd, error_code)
851 != RMNETCTL_SUCCESS) {
852 if (_rmnetctl_check_code(response.crd, error_code)
853 == RMNETCTL_SUCCESS)
854 return_code = _rmnetctl_set_codes(response.return_code,
855 error_code);
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600856 break;
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600857 }
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600858
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700859 str_len = (uint32_t)strlcpy(buf,
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600860 (char *)(response.vnd.vnd_name),
861 buflen);
862 if (str_len >= buflen) {
863 *error_code = RMNETCTL_API_ERR_STRING_TRUNCATION;
864 break;
865 }
866
867 return_code = RMNETCTL_SUCCESS;
868 } while (0);
869 return return_code;
870}
871
Harout Hedeshian97a1e982013-11-08 09:28:53 -0700872int rmnet_add_del_vnd_tc_flow(rmnetctl_hndl_t *hndl,
873 uint32_t id,
874 uint32_t map_flow_id,
875 uint32_t tc_flow_id,
876 uint8_t set_flow,
877 uint16_t *error_code) {
878 struct rmnet_nl_msg_s request, response;
879 int return_code = RMNETCTL_LIB_ERR;
880 do {
Harout Hedeshian77825572014-02-17 10:47:14 +0200881 if ((!hndl) || (!error_code) || ((set_flow != RMNETCTL_ADD_FLOW) &&
882 (set_flow != RMNETCTL_DEL_FLOW))) {
Harout Hedeshian97a1e982013-11-08 09:28:53 -0700883 return_code = RMNETCTL_INVALID_ARG;
884 break;
885 }
886 if (set_flow == RMNETCTL_ADD_FLOW)
887 request.message_type = RMNET_NETLINK_ADD_VND_TC_FLOW;
888 else
889 request.message_type = RMNET_NETLINK_DEL_VND_TC_FLOW;
890
891 request.arg_length = (sizeof(uint32_t))*3;
892 request.flow_control.id = id;
893 request.flow_control.map_flow_id = map_flow_id;
894 request.flow_control.tc_flow_id = tc_flow_id;
895
896 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
897 != RMNETCTL_SUCCESS)
898 break;
899 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
900 break;
901 return_code = _rmnetctl_set_codes(response.return_code, error_code);
902 } while(0);
903 return return_code;
904}
905