blob: 73c0aa1da65d874652e45ce12d0c60555a550cb6 [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
Harout Hedeshiana9731652014-01-06 18:00:23 +02005Copyright (c) 2013-2014, 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
36* @brief rmnet control API's implentations file
37*/
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 | \
71 RMNET_INGRESS_FORMAT_MAP_CKSUMV3)
Harout Hedeshian77825572014-02-17 10:47:14 +020072#define EGRESS_FLAGS_MASK (RMNET_EGRESS_FORMAT__RESERVED__ | \
73 RMNET_EGRESS_FORMAT_MAP | \
74 RMNET_EGRESS_FORMAT_AGGREGATION | \
75 RMNET_EGRESS_FORMAT_MUXING)
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -060076
Harout Hedeshian77825572014-02-17 10:47:14 +020077#define min(a, b) (((a) < (b)) ? (a) : (b))
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -060078/*===========================================================================
79 LOCAL FUNCTION DEFINITIONS
80===========================================================================*/
81/*!
82* @brief Synchronous method to send and receive messages to and from the kernel
83* using netlink sockets
84* @details Increments the transaction id for each message sent to the kernel.
85* Sends the netlink message to the kernel and receives the response from the
86* kernel.
87* @param *hndl RmNet handle for this transaction
88* @param request Message to be sent to the kernel
89* @param response Message received from the kernel
90* @return RMNETCTL_API_SUCCESS if successfully able to send and receive message
91* from the kernel
92* @return RMNETCTL_API_ERR_HNDL_INVALID if RmNet handle for the transaction was
93* NULL
94* @return RMNETCTL_API_ERR_REQUEST_NULL not enough memory to create buffer for
95* sending the message
96* @return RMNETCTL_API_ERR_MESSAGE_SEND if could not send the message to kernel
97* @return RMNETCTL_API_ERR_MESSAGE_RECEIVE if could not receive message from the
98* kernel
99* @return RMNETCTL_API_ERR_MESSAGE_TYPE if the request and response type do not
100* match
101*/
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700102static uint16_t rmnetctl_transact(rmnetctl_hndl_t *hndl,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600103 struct rmnet_nl_msg_s *request,
104 struct rmnet_nl_msg_s *response) {
105 uint8_t *request_buf, *response_buf;
106 struct nlmsghdr *nlmsghdr_val;
107 struct rmnet_nl_msg_s *rmnet_nl_msg_s_val;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700108 ssize_t bytes_read = -1;
109 uint16_t return_code = RMNETCTL_API_ERR_HNDL_INVALID;
110 struct sockaddr_nl* __attribute__((__may_alias__)) saddr_ptr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600111 request_buf = NULL;
112 response_buf = NULL;
113 nlmsghdr_val = NULL;
114 rmnet_nl_msg_s_val = NULL;
115 do {
116 if (!hndl){
117 break;
118 }
119 if (!request){
120 return_code = RMNETCTL_API_ERR_REQUEST_NULL;
121 break;
122 }
123 if (!response){
124 return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
125 break;
126 }
127 request_buf = (uint8_t *)malloc(MAX_BUF_SIZE * sizeof(uint8_t));
128 if (!request_buf){
129 return_code = RMNETCTL_API_ERR_REQUEST_NULL;
130 break;
131 }
132
133 response_buf = (uint8_t *)malloc(MAX_BUF_SIZE * sizeof(uint8_t));
134 if (!response_buf) {
135 free(request_buf);
136 return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
137 break;
138 }
139
140 nlmsghdr_val = (struct nlmsghdr *)request_buf;
141 rmnet_nl_msg_s_val = (struct rmnet_nl_msg_s *)NLMSG_DATA(request_buf);
142
143 memset(request_buf, 0, MAX_BUF_SIZE*sizeof(uint8_t));
144 memset(response_buf, 0, MAX_BUF_SIZE*sizeof(uint8_t));
145
146 nlmsghdr_val->nlmsg_seq = hndl->transaction_id;
147 nlmsghdr_val->nlmsg_pid = hndl->pid;
148 nlmsghdr_val->nlmsg_len = MAX_BUF_SIZE;
149
150 memcpy((void *)NLMSG_DATA(request_buf), request,
151 sizeof(struct rmnet_nl_msg_s));
152
153 rmnet_nl_msg_s_val->crd = RMNET_NETLINK_MSG_COMMAND;
154 hndl->transaction_id++;
155
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700156 saddr_ptr = &hndl->dest_addr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600157 socklen_t addrlen = sizeof(struct sockaddr_nl);
158 if (sendto(hndl->netlink_fd,
159 request_buf,
160 MAX_BUF_SIZE,
161 RMNETCTL_SOCK_FLAG,
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700162 (struct sockaddr*)saddr_ptr,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600163 sizeof(struct sockaddr_nl)) < 0) {
164 return_code = RMNETCTL_API_ERR_MESSAGE_SEND;
165 free(request_buf);
166 free(response_buf);
167 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;
179 free(request_buf);
180 free(response_buf);
181 break;
182 }
183
184 memcpy(response, (void *)NLMSG_DATA(response_buf),
185 sizeof(struct rmnet_nl_msg_s));
186 if (sizeof(*response) < sizeof(struct rmnet_nl_msg_s)) {
187 return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
188 free(request_buf);
189 free(response_buf);
190 break;
191 }
192
193 if (request->message_type != response->message_type) {
194 return_code = RMNETCTL_API_ERR_MESSAGE_TYPE;
195 free(request_buf);
196 free(response_buf);
197 break;
198 }
199 return_code = RMNETCTL_SUCCESS;
200 } while(0);
Harout Hedeshian77825572014-02-17 10:47:14 +0200201 free(request_buf);
202 free(response_buf);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600203 return return_code;
204}
205
206/*!
207* @brief Static function to check the dev name
208* @details Checks if the name is not NULL and if the name is less than the
209* RMNET_MAX_STR_LEN
210* @param dev_name Name of the device
211* @return RMNETCTL_SUCCESS if successful
212* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
213*/
214static inline int _rmnetctl_check_dev_name(const char *dev_name) {
215 int return_code = RMNETCTL_INVALID_ARG;
216 do {
217 if (!dev_name)
218 break;
219 if (strlen(dev_name) >= RMNET_MAX_STR_LEN)
220 break;
221 return_code = RMNETCTL_SUCCESS;
222 } while(0);
223 return return_code;
224}
225
226/*!
227* @brief Static function to check the string length after a copy
228* @details Checks if the string length is not lesser than zero and lesser than
229* RMNET_MAX_STR_LEN
230* @param str_len length of the string after a copy
231* @param error_code Status code of this operation
232* @return RMNETCTL_SUCCESS if successful
233* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
234*/
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700235static inline int _rmnetctl_check_len(size_t str_len, uint16_t *error_code) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600236 int return_code = RMNETCTL_LIB_ERR;
237 do {
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700238 if (str_len > RMNET_MAX_STR_LEN) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600239 *error_code = RMNETCTL_API_ERR_STRING_TRUNCATION;
240 break;
241 }
242 return_code = RMNETCTL_SUCCESS;
243 } while(0);
244 return return_code;
245}
246
247/*!
248* @brief Static function to check the response type
249* @details Checks if the response type of this message was return code
250* @param crd The crd field passed
251* @param error_code Status code of this operation
252* @return RMNETCTL_SUCCESS if successful
253* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
254*/
255static inline int _rmnetctl_check_code(int crd, uint16_t *error_code) {
256 int return_code = RMNETCTL_LIB_ERR;
257 do {
258 if (crd != RMNET_NETLINK_MSG_RETURNCODE) {
259 *error_code = RMNETCTL_API_ERR_RETURN_TYPE;
260 break;
261 }
262 return_code = RMNETCTL_SUCCESS;
263 } while(0);
264 return return_code;
265}
266
267/*!
268* @brief Static function to check the response type
269* @details Checks if the response type of this message was data
270* @param crd The crd field passed
271* @param error_code Status code of this operation
272* @return RMNETCTL_SUCCESS if successful
273* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
274*/
275static inline int _rmnetctl_check_data(int crd, uint16_t *error_code) {
276 int return_code = RMNETCTL_LIB_ERR;
277 do {
278 if (crd != RMNET_NETLINK_MSG_RETURNDATA) {
279 *error_code = RMNETCTL_API_ERR_RETURN_TYPE;
280 break;
281 }
282 return_code = RMNETCTL_SUCCESS;
283 } while(0);
284 return return_code;
285}
286
287/*!
288* @brief Static function to set the return value
289* @details Checks if the error_code from the transaction is zero for a return
290* code type message and sets the message type as RMNETCTL_SUCCESS
291* @param crd The crd field passed
292* @param error_code Status code of this operation
293* @return RMNETCTL_SUCCESS if successful
294* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
295* Check error_code
296*/
297static inline int _rmnetctl_set_codes(int error_val, uint16_t *error_code) {
298 int return_code = RMNETCTL_KERNEL_ERR;
Harout Hedeshian77825572014-02-17 10:47:14 +0200299 if (error_val == RMNET_CONFIG_OK)
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600300 return_code = RMNETCTL_SUCCESS;
Harout Hedeshian77825572014-02-17 10:47:14 +0200301 else
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700302 *error_code = (uint16_t)error_val + RMNETCTL_KERNEL_FIRST_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600303 return return_code;
304}
305
306/*===========================================================================
307 EXPOSED API
308===========================================================================*/
309
310int rmnetctl_init(rmnetctl_hndl_t **hndl, uint16_t *error_code)
311{
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700312 pid_t pid = 0;
313 int netlink_fd = -1, return_code = RMNETCTL_LIB_ERR;
314 struct sockaddr_nl* __attribute__((__may_alias__)) saddr_ptr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600315 do {
316 if ((!hndl) || (!error_code)){
317 return_code = RMNETCTL_INVALID_ARG;
318 break;
319 }
320
321 *hndl = (rmnetctl_hndl_t *)malloc(sizeof(rmnetctl_hndl_t));
322 if (!*hndl) {
323 *error_code = RMNETCTL_API_ERR_HNDL_INVALID;
324 break;
325 }
326
327 memset(*hndl, 0, sizeof(rmnetctl_hndl_t));
328
329 pid = getpid();
330 if (pid < MIN_VALID_PROCESS_ID) {
331 free(*hndl);
332 *error_code = RMNETCTL_INIT_ERR_PROCESS_ID;
333 break;
334 }
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700335 (*hndl)->pid = (uint32_t)pid;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600336 netlink_fd = socket(PF_NETLINK, SOCK_RAW, RMNET_NETLINK_PROTO);
337 if (netlink_fd < MIN_VALID_SOCKET_FD) {
338 free(*hndl);
339 *error_code = RMNETCTL_INIT_ERR_NETLINK_FD;
340 break;
341 }
342
343 (*hndl)->netlink_fd = netlink_fd;
344
345 memset(&(*hndl)->src_addr, 0, sizeof(struct sockaddr_nl));
346
347 (*hndl)->src_addr.nl_family = AF_NETLINK;
348 (*hndl)->src_addr.nl_pid = (*hndl)->pid;
349
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700350 saddr_ptr = &(*hndl)->src_addr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600351 if (bind((*hndl)->netlink_fd,
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700352 (struct sockaddr*)saddr_ptr,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600353 sizeof(struct sockaddr_nl)) < 0) {
354 close((*hndl)->netlink_fd);
355 free(*hndl);
356 *error_code = RMNETCTL_INIT_ERR_BIND;
357 break;
358 }
359
360 memset(&(*hndl)->dest_addr, 0, sizeof(struct sockaddr_nl));
361
362 (*hndl)->dest_addr.nl_family = AF_NETLINK;
363 (*hndl)->dest_addr.nl_pid = KERNEL_PROCESS_ID;
364 (*hndl)->dest_addr.nl_groups = UNICAST;
365
366 return_code = RMNETCTL_SUCCESS;
367 } while(0);
368 return return_code;
369}
370
371void rmnetctl_cleanup(rmnetctl_hndl_t *hndl)
372{
373 if (!hndl)
374 return;
375 close(hndl->netlink_fd);
376 free(hndl);
377}
378
379int rmnet_associate_network_device(rmnetctl_hndl_t *hndl,
380 const char *dev_name,
381 uint16_t *error_code,
382 uint8_t assoc_dev)
383{
384 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700385 size_t str_len = 0;
386 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600387 do {
388 if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name) ||
389 ((assoc_dev != RMNETCTL_DEVICE_ASSOCIATE) &&
390 (assoc_dev != RMNETCTL_DEVICE_UNASSOCIATE))) {
391 return_code = RMNETCTL_INVALID_ARG;
392 break;
393 }
394
395 if (assoc_dev == RMNETCTL_DEVICE_ASSOCIATE)
396 request.message_type = RMNET_NETLINK_ASSOCIATE_NETWORK_DEVICE;
397 else
398 request.message_type = RMNET_NETLINK_UNASSOCIATE_NETWORK_DEVICE;
399
400 request.arg_length = RMNET_MAX_STR_LEN;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700401 str_len = strlcpy((char *)(request.data), dev_name, (size_t)RMNET_MAX_STR_LEN);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600402 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
403 break;
404
405 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
406 != RMNETCTL_SUCCESS)
407 break;
408 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
409 break;
410 return_code = _rmnetctl_set_codes(response.return_code, error_code);
411 } while(0);
412 return return_code;
413}
414
415int rmnet_get_network_device_associated(rmnetctl_hndl_t *hndl,
416 const char *dev_name,
417 int *register_status,
418 uint16_t *error_code) {
419 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700420 size_t str_len = 0;
421 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600422 do {
423 if ((!hndl) || (!register_status) || (!error_code) ||
424 _rmnetctl_check_dev_name(dev_name)) {
425 return_code = RMNETCTL_INVALID_ARG;
426 break;
427 }
428
429 request.message_type = RMNET_NETLINK_GET_NETWORK_DEVICE_ASSOCIATED;
430
431 request.arg_length = RMNET_MAX_STR_LEN;
432 str_len = strlcpy((char *)(request.data), dev_name, RMNET_MAX_STR_LEN);
433 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
434 break;
435
436 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
437 != RMNETCTL_SUCCESS)
438 break;
439
440 if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
441 break;
442
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
519 if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
520 break;
521
522 *egress_flags = response.data_format.flags;
523 *agg_size = response.data_format.agg_size;
524 *agg_count = response.data_format.agg_count;
525 return_code = RMNETCTL_SUCCESS;
526 } while(0);
527 return return_code;
528}
529
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700530int rmnet_set_link_ingress_data_format_tailspace(rmnetctl_hndl_t *hndl,
531 uint32_t ingress_flags,
532 uint8_t tail_spacing,
533 const char *dev_name,
534 uint16_t *error_code) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600535 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700536 size_t str_len = 0;
537 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600538 do {
Harout Hedeshian77825572014-02-17 10:47:14 +0200539 if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name) ||
540 ((~INGRESS_FLAGS_MASK) & ingress_flags)) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600541 return_code = RMNETCTL_INVALID_ARG;
542 break;
543 }
544
545 request.message_type = RMNET_NETLINK_SET_LINK_INGRESS_DATA_FORMAT;
546
547 request.arg_length = RMNET_MAX_STR_LEN +
548 sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t);
549 str_len = strlcpy((char *)(request.data_format.dev),
550 dev_name,
551 RMNET_MAX_STR_LEN);
552 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
553 break;
554 request.data_format.flags = ingress_flags;
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700555 request.data_format.tail_spacing = tail_spacing;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600556
557 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
558 != RMNETCTL_SUCCESS)
559 break;
560
561 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
562 break;
563
564 return_code = _rmnetctl_set_codes(response.return_code, error_code);
565 } while(0);
566 return return_code;
567}
568
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700569int rmnet_get_link_ingress_data_format_tailspace(rmnetctl_hndl_t *hndl,
570 const char *dev_name,
571 uint32_t *ingress_flags,
572 uint8_t *tail_spacing,
573 uint16_t *error_code) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600574 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700575 size_t str_len = 0;
576 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600577 do {
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700578 if ((!hndl) || (!error_code) ||
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600579 _rmnetctl_check_dev_name(dev_name)) {
580 return_code = RMNETCTL_INVALID_ARG;
581 break;
582 }
583
584 request.message_type = RMNET_NETLINK_GET_LINK_INGRESS_DATA_FORMAT;
585
586 request.arg_length = RMNET_MAX_STR_LEN;
587 str_len = strlcpy((char *)(request.data_format.dev),
588 dev_name,
589 RMNET_MAX_STR_LEN);
590 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
591 break;
592
593 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
594 != RMNETCTL_SUCCESS)
595 break;
596
597 if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
598 break;
599
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700600 if (ingress_flags)
601 *ingress_flags = response.data_format.flags;
602
603 if (tail_spacing)
604 *tail_spacing = response.data_format.tail_spacing;
605
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600606 return_code = RMNETCTL_SUCCESS;
607 } while(0);
608 return return_code;
609}
610
611int rmnet_set_logical_ep_config(rmnetctl_hndl_t *hndl,
612 int32_t ep_id,
613 uint8_t operating_mode,
614 const char *dev_name,
615 const char *next_dev,
616 uint16_t *error_code) {
617 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700618 size_t str_len = 0;
619 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600620 do {
621 if ((!hndl) || ((ep_id < -1) || (ep_id > 31)) || (!error_code) ||
622 _rmnetctl_check_dev_name(dev_name) ||
Harout Hedeshian77825572014-02-17 10:47:14 +0200623 _rmnetctl_check_dev_name(next_dev) ||
624 operating_mode >= RMNET_EPMODE_LENGTH) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600625 return_code = RMNETCTL_INVALID_ARG;
626 break;
627 }
628
629 request.message_type = RMNET_NETLINK_SET_LOGICAL_EP_CONFIG;
630
631 request.arg_length = RMNET_MAX_STR_LEN +
632 RMNET_MAX_STR_LEN + sizeof(int32_t) + sizeof(uint8_t);
633 str_len = strlcpy((char *)(request.local_ep_config.dev),
634 dev_name,
635 RMNET_MAX_STR_LEN);
636 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
637 break;
638
639 str_len = strlcpy((char *)(request.local_ep_config.next_dev),
640 next_dev,
641 RMNET_MAX_STR_LEN);
642 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
643 break;
644 request.local_ep_config.ep_id = ep_id;
645 request.local_ep_config.operating_mode = operating_mode;
646
647 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
648 != RMNETCTL_SUCCESS)
649 break;
650 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
651 break;
652
653 return_code = _rmnetctl_set_codes(response.return_code, error_code);
654 } while(0);
655 return return_code;
656}
657
Harout Hedeshiana9731652014-01-06 18:00:23 +0200658int rmnet_unset_logical_ep_config(rmnetctl_hndl_t *hndl,
659 int32_t ep_id,
660 const char *dev_name,
661 uint16_t *error_code) {
662 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700663 size_t str_len = 0;
664 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshiana9731652014-01-06 18:00:23 +0200665 do {
666
667 if ((!hndl) || ((ep_id < -1) || (ep_id > 31)) || (!error_code) ||
668 _rmnetctl_check_dev_name(dev_name)) {
669 return_code = RMNETCTL_INVALID_ARG;
670 break;
671 }
672
673 request.message_type = RMNET_NETLINK_UNSET_LOGICAL_EP_CONFIG;
674
675 request.arg_length = RMNET_MAX_STR_LEN + sizeof(int32_t);
676 str_len = strlcpy((char *)(request.local_ep_config.dev),
677 dev_name,
678 RMNET_MAX_STR_LEN);
679
680 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
681 break;
682
683 request.local_ep_config.ep_id = ep_id;
684
685 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
686 != RMNETCTL_SUCCESS)
687 break;
688 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
689 break;
690
691 return_code = _rmnetctl_set_codes(response.return_code, error_code);
692 } while(0);
693
694 return return_code;
695}
696
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600697int rmnet_get_logical_ep_config(rmnetctl_hndl_t *hndl,
698 int32_t ep_id,
699 const char *dev_name,
700 uint8_t *operating_mode,
701 char **next_dev,
Harout Hedeshian77825572014-02-17 10:47:14 +0200702 uint32_t next_dev_len,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600703 uint16_t *error_code) {
704 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700705 size_t str_len = 0;
706 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600707 do {
708 if ((!hndl) || (!operating_mode) || (!error_code) || ((ep_id < -1) ||
Harout Hedeshian77825572014-02-17 10:47:14 +0200709 (ep_id > 31)) || _rmnetctl_check_dev_name(dev_name) || (!next_dev)
710 || (0 == next_dev_len)) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600711 return_code = RMNETCTL_INVALID_ARG;
712 break;
713 }
714
715 request.message_type = RMNET_NETLINK_GET_LOGICAL_EP_CONFIG;
716
717 request.arg_length = RMNET_MAX_STR_LEN + sizeof(int32_t);
718 str_len = strlcpy((char *)(request.local_ep_config.dev),
719 dev_name,
720 RMNET_MAX_STR_LEN);
721 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
722 break;
723
724 request.local_ep_config.ep_id = ep_id;
725
726 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
727 != RMNETCTL_SUCCESS)
728 break;
729 if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
730 break;
Harout Hedeshian77825572014-02-17 10:47:14 +0200731
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600732 str_len = strlcpy(*next_dev,
733 (char *)(response.local_ep_config.next_dev),
Harout Hedeshian77825572014-02-17 10:47:14 +0200734 min(RMNET_MAX_STR_LEN, next_dev_len));
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600735 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
736 break;
737
738 *operating_mode = response.local_ep_config.operating_mode;
739 return_code = RMNETCTL_SUCCESS;
740 } while(0);
741 return return_code;
742}
743
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600744int rmnet_new_vnd_prefix(rmnetctl_hndl_t *hndl,
745 uint32_t id,
746 uint16_t *error_code,
747 uint8_t new_vnd,
748 const char *prefix)
749{
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600750 struct rmnet_nl_msg_s request, response;
751 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700752 size_t str_len = 0;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600753 do {
754 if ((!hndl) || (!error_code) ||
755 ((new_vnd != RMNETCTL_NEW_VND) && (new_vnd != RMNETCTL_FREE_VND))) {
756 return_code = RMNETCTL_INVALID_ARG;
757 break;
758 }
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600759
760 memset(request.vnd.vnd_name, 0, RMNET_MAX_STR_LEN);
761 if (new_vnd == RMNETCTL_NEW_VND) {
762 if (prefix) {
763 request.message_type =RMNET_NETLINK_NEW_VND_WITH_PREFIX;
764 str_len = strlcpy((char *)request.vnd.vnd_name,
765 prefix, RMNET_MAX_STR_LEN);
766 if (_rmnetctl_check_len(str_len, error_code)
767 != RMNETCTL_SUCCESS)
768 break;
769 } else {
770 request.message_type = RMNET_NETLINK_NEW_VND;
771 }
772 } else {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600773 request.message_type = RMNET_NETLINK_FREE_VND;
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600774 }
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600775
776 request.arg_length = sizeof(uint32_t);
777 request.vnd.id = id;
778
779 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
780 != RMNETCTL_SUCCESS)
781 break;
782 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
783 break;
784
785 return_code = _rmnetctl_set_codes(response.return_code, error_code);
786 } while(0);
787 return return_code;
788}
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600789
790int rmnet_new_vnd(rmnetctl_hndl_t *hndl,
791 uint32_t id,
792 uint16_t *error_code,
793 uint8_t new_vnd)
794{
795 return rmnet_new_vnd_prefix(hndl, id, error_code, new_vnd, 0);
796}
797
798int rmnet_get_vnd_name(rmnetctl_hndl_t *hndl,
799 uint32_t id,
800 uint16_t *error_code,
801 char *buf,
802 uint32_t buflen)
803{
804 struct rmnet_nl_msg_s request, response;
805 uint32_t str_len;
806 int return_code = RMNETCTL_LIB_ERR;
807 do {
Harout Hedeshian77825572014-02-17 10:47:14 +0200808 if ((!hndl) || (!error_code) || (!buf) || (0 == buflen)) {
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600809 return_code = RMNETCTL_INVALID_ARG;
810 break;
811 }
812
813 request.message_type = RMNET_NETLINK_GET_VND_NAME;
814 request.arg_length = sizeof(uint32_t);
815 request.vnd.id = id;
816
817
818 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
819 != RMNETCTL_SUCCESS)
820 break;
821 if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
822 break;
823
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700824 str_len = (uint32_t)strlcpy(buf,
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600825 (char *)(response.vnd.vnd_name),
826 buflen);
827 if (str_len >= buflen) {
828 *error_code = RMNETCTL_API_ERR_STRING_TRUNCATION;
829 break;
830 }
831
832 return_code = RMNETCTL_SUCCESS;
833 } while (0);
834 return return_code;
835}
836
Harout Hedeshian97a1e982013-11-08 09:28:53 -0700837int rmnet_add_del_vnd_tc_flow(rmnetctl_hndl_t *hndl,
838 uint32_t id,
839 uint32_t map_flow_id,
840 uint32_t tc_flow_id,
841 uint8_t set_flow,
842 uint16_t *error_code) {
843 struct rmnet_nl_msg_s request, response;
844 int return_code = RMNETCTL_LIB_ERR;
845 do {
Harout Hedeshian77825572014-02-17 10:47:14 +0200846 if ((!hndl) || (!error_code) || ((set_flow != RMNETCTL_ADD_FLOW) &&
847 (set_flow != RMNETCTL_DEL_FLOW))) {
Harout Hedeshian97a1e982013-11-08 09:28:53 -0700848 return_code = RMNETCTL_INVALID_ARG;
849 break;
850 }
851 if (set_flow == RMNETCTL_ADD_FLOW)
852 request.message_type = RMNET_NETLINK_ADD_VND_TC_FLOW;
853 else
854 request.message_type = RMNET_NETLINK_DEL_VND_TC_FLOW;
855
856 request.arg_length = (sizeof(uint32_t))*3;
857 request.flow_control.id = id;
858 request.flow_control.map_flow_id = map_flow_id;
859 request.flow_control.tc_flow_id = tc_flow_id;
860
861 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
862 != RMNETCTL_SUCCESS)
863 break;
864 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
865 break;
866 return_code = _rmnetctl_set_codes(response.return_code, error_code);
867 } while(0);
868 return return_code;
869}
870