blob: 95f0510a13dbd700a1f69178ba0138618970aee7 [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) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600138 return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
139 break;
140 }
141
142 nlmsghdr_val = (struct nlmsghdr *)request_buf;
143 rmnet_nl_msg_s_val = (struct rmnet_nl_msg_s *)NLMSG_DATA(request_buf);
144
145 memset(request_buf, 0, MAX_BUF_SIZE*sizeof(uint8_t));
146 memset(response_buf, 0, MAX_BUF_SIZE*sizeof(uint8_t));
147
148 nlmsghdr_val->nlmsg_seq = hndl->transaction_id;
149 nlmsghdr_val->nlmsg_pid = hndl->pid;
150 nlmsghdr_val->nlmsg_len = MAX_BUF_SIZE;
151
152 memcpy((void *)NLMSG_DATA(request_buf), request,
153 sizeof(struct rmnet_nl_msg_s));
154
155 rmnet_nl_msg_s_val->crd = RMNET_NETLINK_MSG_COMMAND;
156 hndl->transaction_id++;
157
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700158 saddr_ptr = &hndl->dest_addr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600159 socklen_t addrlen = sizeof(struct sockaddr_nl);
160 if (sendto(hndl->netlink_fd,
161 request_buf,
162 MAX_BUF_SIZE,
163 RMNETCTL_SOCK_FLAG,
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700164 (struct sockaddr*)saddr_ptr,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600165 sizeof(struct sockaddr_nl)) < 0) {
166 return_code = RMNETCTL_API_ERR_MESSAGE_SEND;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600167 break;
168 }
169
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700170 saddr_ptr = &hndl->src_addr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600171 bytes_read = recvfrom(hndl->netlink_fd,
172 response_buf,
173 MAX_BUF_SIZE,
174 RMNETCTL_SOCK_FLAG,
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700175 (struct sockaddr*)saddr_ptr,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600176 &addrlen);
177 if (bytes_read < 0) {
178 return_code = RMNETCTL_API_ERR_MESSAGE_RECEIVE;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600179 break;
180 }
181
182 memcpy(response, (void *)NLMSG_DATA(response_buf),
183 sizeof(struct rmnet_nl_msg_s));
184 if (sizeof(*response) < sizeof(struct rmnet_nl_msg_s)) {
185 return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600186 break;
187 }
188
189 if (request->message_type != response->message_type) {
190 return_code = RMNETCTL_API_ERR_MESSAGE_TYPE;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600191 break;
192 }
193 return_code = RMNETCTL_SUCCESS;
194 } while(0);
Harout Hedeshian77825572014-02-17 10:47:14 +0200195 free(request_buf);
196 free(response_buf);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600197 return return_code;
198}
199
200/*!
201* @brief Static function to check the dev name
202* @details Checks if the name is not NULL and if the name is less than the
203* RMNET_MAX_STR_LEN
204* @param dev_name Name of the device
205* @return RMNETCTL_SUCCESS if successful
206* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
207*/
208static inline int _rmnetctl_check_dev_name(const char *dev_name) {
209 int return_code = RMNETCTL_INVALID_ARG;
210 do {
211 if (!dev_name)
212 break;
213 if (strlen(dev_name) >= RMNET_MAX_STR_LEN)
214 break;
215 return_code = RMNETCTL_SUCCESS;
216 } while(0);
217 return return_code;
218}
219
220/*!
221* @brief Static function to check the string length after a copy
222* @details Checks if the string length is not lesser than zero and lesser than
223* RMNET_MAX_STR_LEN
224* @param str_len length of the string after a copy
225* @param error_code Status code of this operation
226* @return RMNETCTL_SUCCESS if successful
227* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
228*/
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700229static inline int _rmnetctl_check_len(size_t str_len, uint16_t *error_code) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600230 int return_code = RMNETCTL_LIB_ERR;
231 do {
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700232 if (str_len > RMNET_MAX_STR_LEN) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600233 *error_code = RMNETCTL_API_ERR_STRING_TRUNCATION;
234 break;
235 }
236 return_code = RMNETCTL_SUCCESS;
237 } while(0);
238 return return_code;
239}
240
241/*!
242* @brief Static function to check the response type
243* @details Checks if the response type of this message was return code
244* @param crd The crd field passed
245* @param error_code Status code of this operation
246* @return RMNETCTL_SUCCESS if successful
247* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
248*/
249static inline int _rmnetctl_check_code(int crd, uint16_t *error_code) {
250 int return_code = RMNETCTL_LIB_ERR;
251 do {
252 if (crd != RMNET_NETLINK_MSG_RETURNCODE) {
253 *error_code = RMNETCTL_API_ERR_RETURN_TYPE;
254 break;
255 }
256 return_code = RMNETCTL_SUCCESS;
257 } while(0);
258 return return_code;
259}
260
261/*!
262* @brief Static function to check the response type
263* @details Checks if the response type of this message was data
264* @param crd The crd field passed
265* @param error_code Status code of this operation
266* @return RMNETCTL_SUCCESS if successful
267* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
268*/
269static inline int _rmnetctl_check_data(int crd, uint16_t *error_code) {
270 int return_code = RMNETCTL_LIB_ERR;
271 do {
272 if (crd != RMNET_NETLINK_MSG_RETURNDATA) {
273 *error_code = RMNETCTL_API_ERR_RETURN_TYPE;
274 break;
275 }
276 return_code = RMNETCTL_SUCCESS;
277 } while(0);
278 return return_code;
279}
280
281/*!
282* @brief Static function to set the return value
283* @details Checks if the error_code from the transaction is zero for a return
284* code type message and sets the message type as RMNETCTL_SUCCESS
285* @param crd The crd field passed
286* @param error_code Status code of this operation
287* @return RMNETCTL_SUCCESS if successful
288* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
289* Check error_code
290*/
291static inline int _rmnetctl_set_codes(int error_val, uint16_t *error_code) {
292 int return_code = RMNETCTL_KERNEL_ERR;
Harout Hedeshian77825572014-02-17 10:47:14 +0200293 if (error_val == RMNET_CONFIG_OK)
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600294 return_code = RMNETCTL_SUCCESS;
Harout Hedeshian77825572014-02-17 10:47:14 +0200295 else
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700296 *error_code = (uint16_t)error_val + RMNETCTL_KERNEL_FIRST_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600297 return return_code;
298}
299
300/*===========================================================================
301 EXPOSED API
302===========================================================================*/
303
304int rmnetctl_init(rmnetctl_hndl_t **hndl, uint16_t *error_code)
305{
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700306 pid_t pid = 0;
307 int netlink_fd = -1, return_code = RMNETCTL_LIB_ERR;
308 struct sockaddr_nl* __attribute__((__may_alias__)) saddr_ptr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600309 do {
310 if ((!hndl) || (!error_code)){
311 return_code = RMNETCTL_INVALID_ARG;
312 break;
313 }
314
315 *hndl = (rmnetctl_hndl_t *)malloc(sizeof(rmnetctl_hndl_t));
316 if (!*hndl) {
317 *error_code = RMNETCTL_API_ERR_HNDL_INVALID;
318 break;
319 }
320
321 memset(*hndl, 0, sizeof(rmnetctl_hndl_t));
322
323 pid = getpid();
324 if (pid < MIN_VALID_PROCESS_ID) {
325 free(*hndl);
326 *error_code = RMNETCTL_INIT_ERR_PROCESS_ID;
327 break;
328 }
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700329 (*hndl)->pid = (uint32_t)pid;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600330 netlink_fd = socket(PF_NETLINK, SOCK_RAW, RMNET_NETLINK_PROTO);
331 if (netlink_fd < MIN_VALID_SOCKET_FD) {
332 free(*hndl);
333 *error_code = RMNETCTL_INIT_ERR_NETLINK_FD;
334 break;
335 }
336
337 (*hndl)->netlink_fd = netlink_fd;
338
339 memset(&(*hndl)->src_addr, 0, sizeof(struct sockaddr_nl));
340
341 (*hndl)->src_addr.nl_family = AF_NETLINK;
342 (*hndl)->src_addr.nl_pid = (*hndl)->pid;
343
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700344 saddr_ptr = &(*hndl)->src_addr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600345 if (bind((*hndl)->netlink_fd,
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700346 (struct sockaddr*)saddr_ptr,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600347 sizeof(struct sockaddr_nl)) < 0) {
348 close((*hndl)->netlink_fd);
349 free(*hndl);
350 *error_code = RMNETCTL_INIT_ERR_BIND;
351 break;
352 }
353
354 memset(&(*hndl)->dest_addr, 0, sizeof(struct sockaddr_nl));
355
356 (*hndl)->dest_addr.nl_family = AF_NETLINK;
357 (*hndl)->dest_addr.nl_pid = KERNEL_PROCESS_ID;
358 (*hndl)->dest_addr.nl_groups = UNICAST;
359
360 return_code = RMNETCTL_SUCCESS;
361 } while(0);
362 return return_code;
363}
364
365void rmnetctl_cleanup(rmnetctl_hndl_t *hndl)
366{
367 if (!hndl)
368 return;
369 close(hndl->netlink_fd);
370 free(hndl);
371}
372
373int rmnet_associate_network_device(rmnetctl_hndl_t *hndl,
374 const char *dev_name,
375 uint16_t *error_code,
376 uint8_t assoc_dev)
377{
378 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700379 size_t str_len = 0;
380 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600381 do {
382 if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name) ||
383 ((assoc_dev != RMNETCTL_DEVICE_ASSOCIATE) &&
384 (assoc_dev != RMNETCTL_DEVICE_UNASSOCIATE))) {
385 return_code = RMNETCTL_INVALID_ARG;
386 break;
387 }
388
389 if (assoc_dev == RMNETCTL_DEVICE_ASSOCIATE)
390 request.message_type = RMNET_NETLINK_ASSOCIATE_NETWORK_DEVICE;
391 else
392 request.message_type = RMNET_NETLINK_UNASSOCIATE_NETWORK_DEVICE;
393
394 request.arg_length = RMNET_MAX_STR_LEN;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700395 str_len = strlcpy((char *)(request.data), dev_name, (size_t)RMNET_MAX_STR_LEN);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600396 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
397 break;
398
399 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
400 != RMNETCTL_SUCCESS)
401 break;
402 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
403 break;
404 return_code = _rmnetctl_set_codes(response.return_code, error_code);
405 } while(0);
406 return return_code;
407}
408
409int rmnet_get_network_device_associated(rmnetctl_hndl_t *hndl,
410 const char *dev_name,
411 int *register_status,
412 uint16_t *error_code) {
413 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700414 size_t str_len = 0;
415 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600416 do {
417 if ((!hndl) || (!register_status) || (!error_code) ||
418 _rmnetctl_check_dev_name(dev_name)) {
419 return_code = RMNETCTL_INVALID_ARG;
420 break;
421 }
422
423 request.message_type = RMNET_NETLINK_GET_NETWORK_DEVICE_ASSOCIATED;
424
425 request.arg_length = RMNET_MAX_STR_LEN;
426 str_len = strlcpy((char *)(request.data), dev_name, RMNET_MAX_STR_LEN);
427 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
428 break;
429
430 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
431 != RMNETCTL_SUCCESS)
432 break;
433
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600434 if (_rmnetctl_check_data(response.crd, error_code)
435 != RMNETCTL_SUCCESS) {
436 if (_rmnetctl_check_code(response.crd, error_code)
437 == RMNETCTL_SUCCESS)
438 return_code = _rmnetctl_set_codes(response.return_code,
439 error_code);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600440 break;
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600441 }
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600442
443 *register_status = response.return_code;
444 return_code = RMNETCTL_SUCCESS;
445 } while(0);
446 return return_code;
447}
448
449int rmnet_set_link_egress_data_format(rmnetctl_hndl_t *hndl,
450 uint32_t egress_flags,
451 uint16_t agg_size,
452 uint16_t agg_count,
453 const char *dev_name,
454 uint16_t *error_code) {
455 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700456 size_t str_len = 0;
457 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600458 do {
Harout Hedeshian77825572014-02-17 10:47:14 +0200459 if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name) ||
460 ((~EGRESS_FLAGS_MASK) & egress_flags)) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600461 return_code = RMNETCTL_INVALID_ARG;
462 break;
463 }
464
465 request.message_type = RMNET_NETLINK_SET_LINK_EGRESS_DATA_FORMAT;
466
467 request.arg_length = RMNET_MAX_STR_LEN +
468 sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t);
469 str_len = strlcpy((char *)(request.data_format.dev),
470 dev_name,
471 RMNET_MAX_STR_LEN);
472 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
473 break;
474
475 request.data_format.flags = egress_flags;
476 request.data_format.agg_size = agg_size;
477 request.data_format.agg_count = agg_count;
478
479 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
480 != RMNETCTL_SUCCESS)
481 break;
482
483 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
484 break;
485
486 return_code = _rmnetctl_set_codes(response.return_code, error_code);
487 } while(0);
488 return return_code;
489}
490
491int rmnet_get_link_egress_data_format(rmnetctl_hndl_t *hndl,
492 const char *dev_name,
493 uint32_t *egress_flags,
494 uint16_t *agg_size,
495 uint16_t *agg_count,
496 uint16_t *error_code) {
497 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700498 size_t str_len = 0;
499 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600500 do {
501 if ((!hndl) || (!egress_flags) || (!agg_size) || (!agg_count) ||
502 (!error_code) || _rmnetctl_check_dev_name(dev_name)) {
503 return_code = RMNETCTL_INVALID_ARG;
504 break;
505 }
506 request.message_type = RMNET_NETLINK_GET_LINK_EGRESS_DATA_FORMAT;
507
508 request.arg_length = RMNET_MAX_STR_LEN;
509 str_len = strlcpy((char *)(request.data_format.dev),
510 dev_name,
511 RMNET_MAX_STR_LEN);
512 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
513 break;
514
515 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
516 != RMNETCTL_SUCCESS)
517 break;
518
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600519 if (_rmnetctl_check_data(response.crd, error_code)
520 != RMNETCTL_SUCCESS) {
521 if (_rmnetctl_check_code(response.crd, error_code)
522 == RMNETCTL_SUCCESS)
523 return_code = _rmnetctl_set_codes(response.return_code,
524 error_code);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600525 break;
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600526 }
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600527
528 *egress_flags = response.data_format.flags;
529 *agg_size = response.data_format.agg_size;
530 *agg_count = response.data_format.agg_count;
531 return_code = RMNETCTL_SUCCESS;
532 } while(0);
533 return return_code;
534}
535
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700536int rmnet_set_link_ingress_data_format_tailspace(rmnetctl_hndl_t *hndl,
537 uint32_t ingress_flags,
538 uint8_t tail_spacing,
539 const char *dev_name,
540 uint16_t *error_code) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600541 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700542 size_t str_len = 0;
543 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600544 do {
Harout Hedeshian77825572014-02-17 10:47:14 +0200545 if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name) ||
546 ((~INGRESS_FLAGS_MASK) & ingress_flags)) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600547 return_code = RMNETCTL_INVALID_ARG;
548 break;
549 }
550
551 request.message_type = RMNET_NETLINK_SET_LINK_INGRESS_DATA_FORMAT;
552
553 request.arg_length = RMNET_MAX_STR_LEN +
554 sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t);
555 str_len = strlcpy((char *)(request.data_format.dev),
556 dev_name,
557 RMNET_MAX_STR_LEN);
558 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
559 break;
560 request.data_format.flags = ingress_flags;
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700561 request.data_format.tail_spacing = tail_spacing;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600562
563 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
564 != RMNETCTL_SUCCESS)
565 break;
566
567 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
568 break;
569
570 return_code = _rmnetctl_set_codes(response.return_code, error_code);
571 } while(0);
572 return return_code;
573}
574
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700575int rmnet_get_link_ingress_data_format_tailspace(rmnetctl_hndl_t *hndl,
576 const char *dev_name,
577 uint32_t *ingress_flags,
578 uint8_t *tail_spacing,
579 uint16_t *error_code) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600580 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700581 size_t str_len = 0;
582 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600583 do {
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700584 if ((!hndl) || (!error_code) ||
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600585 _rmnetctl_check_dev_name(dev_name)) {
586 return_code = RMNETCTL_INVALID_ARG;
587 break;
588 }
589
590 request.message_type = RMNET_NETLINK_GET_LINK_INGRESS_DATA_FORMAT;
591
592 request.arg_length = RMNET_MAX_STR_LEN;
593 str_len = strlcpy((char *)(request.data_format.dev),
594 dev_name,
595 RMNET_MAX_STR_LEN);
596 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
597 break;
598
599 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
600 != RMNETCTL_SUCCESS)
601 break;
602
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600603 if (_rmnetctl_check_data(response.crd, error_code)
604 != RMNETCTL_SUCCESS) {
605 if (_rmnetctl_check_code(response.crd, error_code)
606 == RMNETCTL_SUCCESS)
607 return_code = _rmnetctl_set_codes(response.return_code,
608 error_code);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600609 break;
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600610 }
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600611
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700612 if (ingress_flags)
613 *ingress_flags = response.data_format.flags;
614
615 if (tail_spacing)
616 *tail_spacing = response.data_format.tail_spacing;
617
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600618 return_code = RMNETCTL_SUCCESS;
619 } while(0);
620 return return_code;
621}
622
623int rmnet_set_logical_ep_config(rmnetctl_hndl_t *hndl,
624 int32_t ep_id,
625 uint8_t operating_mode,
626 const char *dev_name,
627 const char *next_dev,
628 uint16_t *error_code) {
629 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700630 size_t str_len = 0;
631 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600632 do {
633 if ((!hndl) || ((ep_id < -1) || (ep_id > 31)) || (!error_code) ||
634 _rmnetctl_check_dev_name(dev_name) ||
Harout Hedeshian77825572014-02-17 10:47:14 +0200635 _rmnetctl_check_dev_name(next_dev) ||
636 operating_mode >= RMNET_EPMODE_LENGTH) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600637 return_code = RMNETCTL_INVALID_ARG;
638 break;
639 }
640
641 request.message_type = RMNET_NETLINK_SET_LOGICAL_EP_CONFIG;
642
643 request.arg_length = RMNET_MAX_STR_LEN +
644 RMNET_MAX_STR_LEN + sizeof(int32_t) + sizeof(uint8_t);
645 str_len = strlcpy((char *)(request.local_ep_config.dev),
646 dev_name,
647 RMNET_MAX_STR_LEN);
648 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
649 break;
650
651 str_len = strlcpy((char *)(request.local_ep_config.next_dev),
652 next_dev,
653 RMNET_MAX_STR_LEN);
654 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
655 break;
656 request.local_ep_config.ep_id = ep_id;
657 request.local_ep_config.operating_mode = operating_mode;
658
659 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
660 != RMNETCTL_SUCCESS)
661 break;
662 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
663 break;
664
665 return_code = _rmnetctl_set_codes(response.return_code, error_code);
666 } while(0);
667 return return_code;
668}
669
Harout Hedeshiana9731652014-01-06 18:00:23 +0200670int rmnet_unset_logical_ep_config(rmnetctl_hndl_t *hndl,
671 int32_t ep_id,
672 const char *dev_name,
673 uint16_t *error_code) {
674 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700675 size_t str_len = 0;
676 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshiana9731652014-01-06 18:00:23 +0200677 do {
678
679 if ((!hndl) || ((ep_id < -1) || (ep_id > 31)) || (!error_code) ||
680 _rmnetctl_check_dev_name(dev_name)) {
681 return_code = RMNETCTL_INVALID_ARG;
682 break;
683 }
684
685 request.message_type = RMNET_NETLINK_UNSET_LOGICAL_EP_CONFIG;
686
687 request.arg_length = RMNET_MAX_STR_LEN + sizeof(int32_t);
688 str_len = strlcpy((char *)(request.local_ep_config.dev),
689 dev_name,
690 RMNET_MAX_STR_LEN);
691
692 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
693 break;
694
695 request.local_ep_config.ep_id = ep_id;
696
697 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
698 != RMNETCTL_SUCCESS)
699 break;
700 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
701 break;
702
703 return_code = _rmnetctl_set_codes(response.return_code, error_code);
704 } while(0);
705
706 return return_code;
707}
708
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600709int rmnet_get_logical_ep_config(rmnetctl_hndl_t *hndl,
710 int32_t ep_id,
711 const char *dev_name,
712 uint8_t *operating_mode,
713 char **next_dev,
Harout Hedeshian77825572014-02-17 10:47:14 +0200714 uint32_t next_dev_len,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600715 uint16_t *error_code) {
716 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700717 size_t str_len = 0;
718 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600719 do {
720 if ((!hndl) || (!operating_mode) || (!error_code) || ((ep_id < -1) ||
Harout Hedeshian77825572014-02-17 10:47:14 +0200721 (ep_id > 31)) || _rmnetctl_check_dev_name(dev_name) || (!next_dev)
722 || (0 == next_dev_len)) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600723 return_code = RMNETCTL_INVALID_ARG;
724 break;
725 }
726
727 request.message_type = RMNET_NETLINK_GET_LOGICAL_EP_CONFIG;
728
729 request.arg_length = RMNET_MAX_STR_LEN + sizeof(int32_t);
730 str_len = strlcpy((char *)(request.local_ep_config.dev),
731 dev_name,
732 RMNET_MAX_STR_LEN);
733 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
734 break;
735
736 request.local_ep_config.ep_id = ep_id;
737
738 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
739 != RMNETCTL_SUCCESS)
740 break;
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600741
742 if (_rmnetctl_check_data(response.crd, error_code)
743 != RMNETCTL_SUCCESS) {
744 if (_rmnetctl_check_code(response.crd, error_code)
745 == RMNETCTL_SUCCESS)
746 return_code = _rmnetctl_set_codes(response.return_code,
747 error_code);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600748 break;
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600749 }
Harout Hedeshian77825572014-02-17 10:47:14 +0200750
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600751 str_len = strlcpy(*next_dev,
752 (char *)(response.local_ep_config.next_dev),
Harout Hedeshian77825572014-02-17 10:47:14 +0200753 min(RMNET_MAX_STR_LEN, next_dev_len));
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600754 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
755 break;
756
757 *operating_mode = response.local_ep_config.operating_mode;
758 return_code = RMNETCTL_SUCCESS;
759 } while(0);
760 return return_code;
761}
762
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600763int rmnet_new_vnd_prefix(rmnetctl_hndl_t *hndl,
764 uint32_t id,
765 uint16_t *error_code,
766 uint8_t new_vnd,
767 const char *prefix)
768{
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600769 struct rmnet_nl_msg_s request, response;
770 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700771 size_t str_len = 0;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600772 do {
773 if ((!hndl) || (!error_code) ||
774 ((new_vnd != RMNETCTL_NEW_VND) && (new_vnd != RMNETCTL_FREE_VND))) {
775 return_code = RMNETCTL_INVALID_ARG;
776 break;
777 }
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600778
779 memset(request.vnd.vnd_name, 0, RMNET_MAX_STR_LEN);
780 if (new_vnd == RMNETCTL_NEW_VND) {
781 if (prefix) {
782 request.message_type =RMNET_NETLINK_NEW_VND_WITH_PREFIX;
783 str_len = strlcpy((char *)request.vnd.vnd_name,
784 prefix, RMNET_MAX_STR_LEN);
785 if (_rmnetctl_check_len(str_len, error_code)
786 != RMNETCTL_SUCCESS)
787 break;
788 } else {
789 request.message_type = RMNET_NETLINK_NEW_VND;
790 }
791 } else {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600792 request.message_type = RMNET_NETLINK_FREE_VND;
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600793 }
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600794
795 request.arg_length = sizeof(uint32_t);
796 request.vnd.id = id;
797
798 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
799 != RMNETCTL_SUCCESS)
800 break;
801 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
802 break;
803
804 return_code = _rmnetctl_set_codes(response.return_code, error_code);
805 } while(0);
806 return return_code;
807}
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600808
809int rmnet_new_vnd(rmnetctl_hndl_t *hndl,
810 uint32_t id,
811 uint16_t *error_code,
812 uint8_t new_vnd)
813{
814 return rmnet_new_vnd_prefix(hndl, id, error_code, new_vnd, 0);
815}
816
817int rmnet_get_vnd_name(rmnetctl_hndl_t *hndl,
818 uint32_t id,
819 uint16_t *error_code,
820 char *buf,
821 uint32_t buflen)
822{
823 struct rmnet_nl_msg_s request, response;
824 uint32_t str_len;
825 int return_code = RMNETCTL_LIB_ERR;
826 do {
Harout Hedeshian77825572014-02-17 10:47:14 +0200827 if ((!hndl) || (!error_code) || (!buf) || (0 == buflen)) {
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600828 return_code = RMNETCTL_INVALID_ARG;
829 break;
830 }
831
832 request.message_type = RMNET_NETLINK_GET_VND_NAME;
833 request.arg_length = sizeof(uint32_t);
834 request.vnd.id = id;
835
836
837 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
838 != RMNETCTL_SUCCESS)
839 break;
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600840
841 if (_rmnetctl_check_data(response.crd, error_code)
842 != RMNETCTL_SUCCESS) {
843 if (_rmnetctl_check_code(response.crd, error_code)
844 == RMNETCTL_SUCCESS)
845 return_code = _rmnetctl_set_codes(response.return_code,
846 error_code);
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600847 break;
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600848 }
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600849
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700850 str_len = (uint32_t)strlcpy(buf,
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600851 (char *)(response.vnd.vnd_name),
852 buflen);
853 if (str_len >= buflen) {
854 *error_code = RMNETCTL_API_ERR_STRING_TRUNCATION;
855 break;
856 }
857
858 return_code = RMNETCTL_SUCCESS;
859 } while (0);
860 return return_code;
861}
862
Harout Hedeshian97a1e982013-11-08 09:28:53 -0700863int rmnet_add_del_vnd_tc_flow(rmnetctl_hndl_t *hndl,
864 uint32_t id,
865 uint32_t map_flow_id,
866 uint32_t tc_flow_id,
867 uint8_t set_flow,
868 uint16_t *error_code) {
869 struct rmnet_nl_msg_s request, response;
870 int return_code = RMNETCTL_LIB_ERR;
871 do {
Harout Hedeshian77825572014-02-17 10:47:14 +0200872 if ((!hndl) || (!error_code) || ((set_flow != RMNETCTL_ADD_FLOW) &&
873 (set_flow != RMNETCTL_DEL_FLOW))) {
Harout Hedeshian97a1e982013-11-08 09:28:53 -0700874 return_code = RMNETCTL_INVALID_ARG;
875 break;
876 }
877 if (set_flow == RMNETCTL_ADD_FLOW)
878 request.message_type = RMNET_NETLINK_ADD_VND_TC_FLOW;
879 else
880 request.message_type = RMNET_NETLINK_DEL_VND_TC_FLOW;
881
882 request.arg_length = (sizeof(uint32_t))*3;
883 request.flow_control.id = id;
884 request.flow_control.map_flow_id = map_flow_id;
885 request.flow_control.tc_flow_id = tc_flow_id;
886
887 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
888 != RMNETCTL_SUCCESS)
889 break;
890 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
891 break;
892 return_code = _rmnetctl_set_codes(response.return_code, error_code);
893 } while(0);
894 return return_code;
895}
896