blob: 893fa15abd95b5ed372b7c632bf5f63c7d1e9202 [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 | \
70 RMNET_INGRESS_FORMAT_MAP_COMMANDS)
71#define EGRESS_FLAGS_MASK (RMNET_EGRESS_FORMAT__RESERVED__ | \
72 RMNET_EGRESS_FORMAT_MAP | \
73 RMNET_EGRESS_FORMAT_AGGREGATION | \
74 RMNET_EGRESS_FORMAT_MUXING)
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -060075
Harout Hedeshian77825572014-02-17 10:47:14 +020076#define min(a, b) (((a) < (b)) ? (a) : (b))
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -060077/*===========================================================================
78 LOCAL FUNCTION DEFINITIONS
79===========================================================================*/
80/*!
81* @brief Synchronous method to send and receive messages to and from the kernel
82* using netlink sockets
83* @details Increments the transaction id for each message sent to the kernel.
84* Sends the netlink message to the kernel and receives the response from the
85* kernel.
86* @param *hndl RmNet handle for this transaction
87* @param request Message to be sent to the kernel
88* @param response Message received from the kernel
89* @return RMNETCTL_API_SUCCESS if successfully able to send and receive message
90* from the kernel
91* @return RMNETCTL_API_ERR_HNDL_INVALID if RmNet handle for the transaction was
92* NULL
93* @return RMNETCTL_API_ERR_REQUEST_NULL not enough memory to create buffer for
94* sending the message
95* @return RMNETCTL_API_ERR_MESSAGE_SEND if could not send the message to kernel
96* @return RMNETCTL_API_ERR_MESSAGE_RECEIVE if could not receive message from the
97* kernel
98* @return RMNETCTL_API_ERR_MESSAGE_TYPE if the request and response type do not
99* match
100*/
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700101static uint16_t rmnetctl_transact(rmnetctl_hndl_t *hndl,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600102 struct rmnet_nl_msg_s *request,
103 struct rmnet_nl_msg_s *response) {
104 uint8_t *request_buf, *response_buf;
105 struct nlmsghdr *nlmsghdr_val;
106 struct rmnet_nl_msg_s *rmnet_nl_msg_s_val;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700107 ssize_t bytes_read = -1;
108 uint16_t return_code = RMNETCTL_API_ERR_HNDL_INVALID;
109 struct sockaddr_nl* __attribute__((__may_alias__)) saddr_ptr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600110 request_buf = NULL;
111 response_buf = NULL;
112 nlmsghdr_val = NULL;
113 rmnet_nl_msg_s_val = NULL;
114 do {
115 if (!hndl){
116 break;
117 }
118 if (!request){
119 return_code = RMNETCTL_API_ERR_REQUEST_NULL;
120 break;
121 }
122 if (!response){
123 return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
124 break;
125 }
126 request_buf = (uint8_t *)malloc(MAX_BUF_SIZE * sizeof(uint8_t));
127 if (!request_buf){
128 return_code = RMNETCTL_API_ERR_REQUEST_NULL;
129 break;
130 }
131
132 response_buf = (uint8_t *)malloc(MAX_BUF_SIZE * sizeof(uint8_t));
133 if (!response_buf) {
134 free(request_buf);
135 return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
136 break;
137 }
138
139 nlmsghdr_val = (struct nlmsghdr *)request_buf;
140 rmnet_nl_msg_s_val = (struct rmnet_nl_msg_s *)NLMSG_DATA(request_buf);
141
142 memset(request_buf, 0, MAX_BUF_SIZE*sizeof(uint8_t));
143 memset(response_buf, 0, MAX_BUF_SIZE*sizeof(uint8_t));
144
145 nlmsghdr_val->nlmsg_seq = hndl->transaction_id;
146 nlmsghdr_val->nlmsg_pid = hndl->pid;
147 nlmsghdr_val->nlmsg_len = MAX_BUF_SIZE;
148
149 memcpy((void *)NLMSG_DATA(request_buf), request,
150 sizeof(struct rmnet_nl_msg_s));
151
152 rmnet_nl_msg_s_val->crd = RMNET_NETLINK_MSG_COMMAND;
153 hndl->transaction_id++;
154
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700155 saddr_ptr = &hndl->dest_addr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600156 socklen_t addrlen = sizeof(struct sockaddr_nl);
157 if (sendto(hndl->netlink_fd,
158 request_buf,
159 MAX_BUF_SIZE,
160 RMNETCTL_SOCK_FLAG,
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700161 (struct sockaddr*)saddr_ptr,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600162 sizeof(struct sockaddr_nl)) < 0) {
163 return_code = RMNETCTL_API_ERR_MESSAGE_SEND;
164 free(request_buf);
165 free(response_buf);
166 break;
167 }
168
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700169 saddr_ptr = &hndl->src_addr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600170 bytes_read = recvfrom(hndl->netlink_fd,
171 response_buf,
172 MAX_BUF_SIZE,
173 RMNETCTL_SOCK_FLAG,
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700174 (struct sockaddr*)saddr_ptr,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600175 &addrlen);
176 if (bytes_read < 0) {
177 return_code = RMNETCTL_API_ERR_MESSAGE_RECEIVE;
178 free(request_buf);
179 free(response_buf);
180 break;
181 }
182
183 memcpy(response, (void *)NLMSG_DATA(response_buf),
184 sizeof(struct rmnet_nl_msg_s));
185 if (sizeof(*response) < sizeof(struct rmnet_nl_msg_s)) {
186 return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
187 free(request_buf);
188 free(response_buf);
189 break;
190 }
191
192 if (request->message_type != response->message_type) {
193 return_code = RMNETCTL_API_ERR_MESSAGE_TYPE;
194 free(request_buf);
195 free(response_buf);
196 break;
197 }
198 return_code = RMNETCTL_SUCCESS;
199 } while(0);
Harout Hedeshian77825572014-02-17 10:47:14 +0200200 free(request_buf);
201 free(response_buf);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600202 return return_code;
203}
204
205/*!
206* @brief Static function to check the dev name
207* @details Checks if the name is not NULL and if the name is less than the
208* RMNET_MAX_STR_LEN
209* @param dev_name Name of the device
210* @return RMNETCTL_SUCCESS if successful
211* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
212*/
213static inline int _rmnetctl_check_dev_name(const char *dev_name) {
214 int return_code = RMNETCTL_INVALID_ARG;
215 do {
216 if (!dev_name)
217 break;
218 if (strlen(dev_name) >= RMNET_MAX_STR_LEN)
219 break;
220 return_code = RMNETCTL_SUCCESS;
221 } while(0);
222 return return_code;
223}
224
225/*!
226* @brief Static function to check the string length after a copy
227* @details Checks if the string length is not lesser than zero and lesser than
228* RMNET_MAX_STR_LEN
229* @param str_len length of the string after a copy
230* @param error_code Status code of this operation
231* @return RMNETCTL_SUCCESS if successful
232* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
233*/
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700234static inline int _rmnetctl_check_len(size_t str_len, uint16_t *error_code) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600235 int return_code = RMNETCTL_LIB_ERR;
236 do {
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700237 if (str_len > RMNET_MAX_STR_LEN) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600238 *error_code = RMNETCTL_API_ERR_STRING_TRUNCATION;
239 break;
240 }
241 return_code = RMNETCTL_SUCCESS;
242 } while(0);
243 return return_code;
244}
245
246/*!
247* @brief Static function to check the response type
248* @details Checks if the response type of this message was return code
249* @param crd The crd field passed
250* @param error_code Status code of this operation
251* @return RMNETCTL_SUCCESS if successful
252* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
253*/
254static inline int _rmnetctl_check_code(int crd, uint16_t *error_code) {
255 int return_code = RMNETCTL_LIB_ERR;
256 do {
257 if (crd != RMNET_NETLINK_MSG_RETURNCODE) {
258 *error_code = RMNETCTL_API_ERR_RETURN_TYPE;
259 break;
260 }
261 return_code = RMNETCTL_SUCCESS;
262 } while(0);
263 return return_code;
264}
265
266/*!
267* @brief Static function to check the response type
268* @details Checks if the response type of this message was data
269* @param crd The crd field passed
270* @param error_code Status code of this operation
271* @return RMNETCTL_SUCCESS if successful
272* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
273*/
274static inline int _rmnetctl_check_data(int crd, uint16_t *error_code) {
275 int return_code = RMNETCTL_LIB_ERR;
276 do {
277 if (crd != RMNET_NETLINK_MSG_RETURNDATA) {
278 *error_code = RMNETCTL_API_ERR_RETURN_TYPE;
279 break;
280 }
281 return_code = RMNETCTL_SUCCESS;
282 } while(0);
283 return return_code;
284}
285
286/*!
287* @brief Static function to set the return value
288* @details Checks if the error_code from the transaction is zero for a return
289* code type message and sets the message type as RMNETCTL_SUCCESS
290* @param crd The crd field passed
291* @param error_code Status code of this operation
292* @return RMNETCTL_SUCCESS if successful
293* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
294* Check error_code
295*/
296static inline int _rmnetctl_set_codes(int error_val, uint16_t *error_code) {
297 int return_code = RMNETCTL_KERNEL_ERR;
Harout Hedeshian77825572014-02-17 10:47:14 +0200298 if (error_val == RMNET_CONFIG_OK)
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600299 return_code = RMNETCTL_SUCCESS;
Harout Hedeshian77825572014-02-17 10:47:14 +0200300 else
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700301 *error_code = (uint16_t)error_val + RMNETCTL_KERNEL_FIRST_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600302 return return_code;
303}
304
305/*===========================================================================
306 EXPOSED API
307===========================================================================*/
308
309int rmnetctl_init(rmnetctl_hndl_t **hndl, uint16_t *error_code)
310{
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700311 pid_t pid = 0;
312 int netlink_fd = -1, return_code = RMNETCTL_LIB_ERR;
313 struct sockaddr_nl* __attribute__((__may_alias__)) saddr_ptr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600314 do {
315 if ((!hndl) || (!error_code)){
316 return_code = RMNETCTL_INVALID_ARG;
317 break;
318 }
319
320 *hndl = (rmnetctl_hndl_t *)malloc(sizeof(rmnetctl_hndl_t));
321 if (!*hndl) {
322 *error_code = RMNETCTL_API_ERR_HNDL_INVALID;
323 break;
324 }
325
326 memset(*hndl, 0, sizeof(rmnetctl_hndl_t));
327
328 pid = getpid();
329 if (pid < MIN_VALID_PROCESS_ID) {
330 free(*hndl);
331 *error_code = RMNETCTL_INIT_ERR_PROCESS_ID;
332 break;
333 }
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700334 (*hndl)->pid = (uint32_t)pid;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600335 netlink_fd = socket(PF_NETLINK, SOCK_RAW, RMNET_NETLINK_PROTO);
336 if (netlink_fd < MIN_VALID_SOCKET_FD) {
337 free(*hndl);
338 *error_code = RMNETCTL_INIT_ERR_NETLINK_FD;
339 break;
340 }
341
342 (*hndl)->netlink_fd = netlink_fd;
343
344 memset(&(*hndl)->src_addr, 0, sizeof(struct sockaddr_nl));
345
346 (*hndl)->src_addr.nl_family = AF_NETLINK;
347 (*hndl)->src_addr.nl_pid = (*hndl)->pid;
348
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700349 saddr_ptr = &(*hndl)->src_addr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600350 if (bind((*hndl)->netlink_fd,
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700351 (struct sockaddr*)saddr_ptr,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600352 sizeof(struct sockaddr_nl)) < 0) {
353 close((*hndl)->netlink_fd);
354 free(*hndl);
355 *error_code = RMNETCTL_INIT_ERR_BIND;
356 break;
357 }
358
359 memset(&(*hndl)->dest_addr, 0, sizeof(struct sockaddr_nl));
360
361 (*hndl)->dest_addr.nl_family = AF_NETLINK;
362 (*hndl)->dest_addr.nl_pid = KERNEL_PROCESS_ID;
363 (*hndl)->dest_addr.nl_groups = UNICAST;
364
365 return_code = RMNETCTL_SUCCESS;
366 } while(0);
367 return return_code;
368}
369
370void rmnetctl_cleanup(rmnetctl_hndl_t *hndl)
371{
372 if (!hndl)
373 return;
374 close(hndl->netlink_fd);
375 free(hndl);
376}
377
378int rmnet_associate_network_device(rmnetctl_hndl_t *hndl,
379 const char *dev_name,
380 uint16_t *error_code,
381 uint8_t assoc_dev)
382{
383 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700384 size_t str_len = 0;
385 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600386 do {
387 if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name) ||
388 ((assoc_dev != RMNETCTL_DEVICE_ASSOCIATE) &&
389 (assoc_dev != RMNETCTL_DEVICE_UNASSOCIATE))) {
390 return_code = RMNETCTL_INVALID_ARG;
391 break;
392 }
393
394 if (assoc_dev == RMNETCTL_DEVICE_ASSOCIATE)
395 request.message_type = RMNET_NETLINK_ASSOCIATE_NETWORK_DEVICE;
396 else
397 request.message_type = RMNET_NETLINK_UNASSOCIATE_NETWORK_DEVICE;
398
399 request.arg_length = RMNET_MAX_STR_LEN;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700400 str_len = strlcpy((char *)(request.data), dev_name, (size_t)RMNET_MAX_STR_LEN);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600401 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
402 break;
403
404 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
405 != RMNETCTL_SUCCESS)
406 break;
407 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
408 break;
409 return_code = _rmnetctl_set_codes(response.return_code, error_code);
410 } while(0);
411 return return_code;
412}
413
414int rmnet_get_network_device_associated(rmnetctl_hndl_t *hndl,
415 const char *dev_name,
416 int *register_status,
417 uint16_t *error_code) {
418 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700419 size_t str_len = 0;
420 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600421 do {
422 if ((!hndl) || (!register_status) || (!error_code) ||
423 _rmnetctl_check_dev_name(dev_name)) {
424 return_code = RMNETCTL_INVALID_ARG;
425 break;
426 }
427
428 request.message_type = RMNET_NETLINK_GET_NETWORK_DEVICE_ASSOCIATED;
429
430 request.arg_length = RMNET_MAX_STR_LEN;
431 str_len = strlcpy((char *)(request.data), dev_name, RMNET_MAX_STR_LEN);
432 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
433 break;
434
435 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
436 != RMNETCTL_SUCCESS)
437 break;
438
439 if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
440 break;
441
442 *register_status = response.return_code;
443 return_code = RMNETCTL_SUCCESS;
444 } while(0);
445 return return_code;
446}
447
448int rmnet_set_link_egress_data_format(rmnetctl_hndl_t *hndl,
449 uint32_t egress_flags,
450 uint16_t agg_size,
451 uint16_t agg_count,
452 const char *dev_name,
453 uint16_t *error_code) {
454 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700455 size_t str_len = 0;
456 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600457 do {
Harout Hedeshian77825572014-02-17 10:47:14 +0200458 if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name) ||
459 ((~EGRESS_FLAGS_MASK) & egress_flags)) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600460 return_code = RMNETCTL_INVALID_ARG;
461 break;
462 }
463
464 request.message_type = RMNET_NETLINK_SET_LINK_EGRESS_DATA_FORMAT;
465
466 request.arg_length = RMNET_MAX_STR_LEN +
467 sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t);
468 str_len = strlcpy((char *)(request.data_format.dev),
469 dev_name,
470 RMNET_MAX_STR_LEN);
471 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
472 break;
473
474 request.data_format.flags = egress_flags;
475 request.data_format.agg_size = agg_size;
476 request.data_format.agg_count = agg_count;
477
478 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
479 != RMNETCTL_SUCCESS)
480 break;
481
482 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
483 break;
484
485 return_code = _rmnetctl_set_codes(response.return_code, error_code);
486 } while(0);
487 return return_code;
488}
489
490int rmnet_get_link_egress_data_format(rmnetctl_hndl_t *hndl,
491 const char *dev_name,
492 uint32_t *egress_flags,
493 uint16_t *agg_size,
494 uint16_t *agg_count,
495 uint16_t *error_code) {
496 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700497 size_t str_len = 0;
498 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600499 do {
500 if ((!hndl) || (!egress_flags) || (!agg_size) || (!agg_count) ||
501 (!error_code) || _rmnetctl_check_dev_name(dev_name)) {
502 return_code = RMNETCTL_INVALID_ARG;
503 break;
504 }
505 request.message_type = RMNET_NETLINK_GET_LINK_EGRESS_DATA_FORMAT;
506
507 request.arg_length = RMNET_MAX_STR_LEN;
508 str_len = strlcpy((char *)(request.data_format.dev),
509 dev_name,
510 RMNET_MAX_STR_LEN);
511 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
512 break;
513
514 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
515 != RMNETCTL_SUCCESS)
516 break;
517
518 if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
519 break;
520
521 *egress_flags = response.data_format.flags;
522 *agg_size = response.data_format.agg_size;
523 *agg_count = response.data_format.agg_count;
524 return_code = RMNETCTL_SUCCESS;
525 } while(0);
526 return return_code;
527}
528
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700529int rmnet_set_link_ingress_data_format_tailspace(rmnetctl_hndl_t *hndl,
530 uint32_t ingress_flags,
531 uint8_t tail_spacing,
532 const char *dev_name,
533 uint16_t *error_code) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600534 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700535 size_t str_len = 0;
536 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600537 do {
Harout Hedeshian77825572014-02-17 10:47:14 +0200538 if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name) ||
539 ((~INGRESS_FLAGS_MASK) & ingress_flags)) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600540 return_code = RMNETCTL_INVALID_ARG;
541 break;
542 }
543
544 request.message_type = RMNET_NETLINK_SET_LINK_INGRESS_DATA_FORMAT;
545
546 request.arg_length = RMNET_MAX_STR_LEN +
547 sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t);
548 str_len = strlcpy((char *)(request.data_format.dev),
549 dev_name,
550 RMNET_MAX_STR_LEN);
551 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
552 break;
553 request.data_format.flags = ingress_flags;
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700554 request.data_format.tail_spacing = tail_spacing;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600555
556 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
557 != RMNETCTL_SUCCESS)
558 break;
559
560 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
561 break;
562
563 return_code = _rmnetctl_set_codes(response.return_code, error_code);
564 } while(0);
565 return return_code;
566}
567
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700568int rmnet_get_link_ingress_data_format_tailspace(rmnetctl_hndl_t *hndl,
569 const char *dev_name,
570 uint32_t *ingress_flags,
571 uint8_t *tail_spacing,
572 uint16_t *error_code) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600573 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700574 size_t str_len = 0;
575 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600576 do {
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700577 if ((!hndl) || (!error_code) ||
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600578 _rmnetctl_check_dev_name(dev_name)) {
579 return_code = RMNETCTL_INVALID_ARG;
580 break;
581 }
582
583 request.message_type = RMNET_NETLINK_GET_LINK_INGRESS_DATA_FORMAT;
584
585 request.arg_length = RMNET_MAX_STR_LEN;
586 str_len = strlcpy((char *)(request.data_format.dev),
587 dev_name,
588 RMNET_MAX_STR_LEN);
589 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
590 break;
591
592 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
593 != RMNETCTL_SUCCESS)
594 break;
595
596 if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
597 break;
598
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700599 if (ingress_flags)
600 *ingress_flags = response.data_format.flags;
601
602 if (tail_spacing)
603 *tail_spacing = response.data_format.tail_spacing;
604
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600605 return_code = RMNETCTL_SUCCESS;
606 } while(0);
607 return return_code;
608}
609
610int rmnet_set_logical_ep_config(rmnetctl_hndl_t *hndl,
611 int32_t ep_id,
612 uint8_t operating_mode,
613 const char *dev_name,
614 const char *next_dev,
615 uint16_t *error_code) {
616 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700617 size_t str_len = 0;
618 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600619 do {
620 if ((!hndl) || ((ep_id < -1) || (ep_id > 31)) || (!error_code) ||
621 _rmnetctl_check_dev_name(dev_name) ||
Harout Hedeshian77825572014-02-17 10:47:14 +0200622 _rmnetctl_check_dev_name(next_dev) ||
623 operating_mode >= RMNET_EPMODE_LENGTH) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600624 return_code = RMNETCTL_INVALID_ARG;
625 break;
626 }
627
628 request.message_type = RMNET_NETLINK_SET_LOGICAL_EP_CONFIG;
629
630 request.arg_length = RMNET_MAX_STR_LEN +
631 RMNET_MAX_STR_LEN + sizeof(int32_t) + sizeof(uint8_t);
632 str_len = strlcpy((char *)(request.local_ep_config.dev),
633 dev_name,
634 RMNET_MAX_STR_LEN);
635 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
636 break;
637
638 str_len = strlcpy((char *)(request.local_ep_config.next_dev),
639 next_dev,
640 RMNET_MAX_STR_LEN);
641 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
642 break;
643 request.local_ep_config.ep_id = ep_id;
644 request.local_ep_config.operating_mode = operating_mode;
645
646 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
647 != RMNETCTL_SUCCESS)
648 break;
649 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
650 break;
651
652 return_code = _rmnetctl_set_codes(response.return_code, error_code);
653 } while(0);
654 return return_code;
655}
656
Harout Hedeshiana9731652014-01-06 18:00:23 +0200657int rmnet_unset_logical_ep_config(rmnetctl_hndl_t *hndl,
658 int32_t ep_id,
659 const char *dev_name,
660 uint16_t *error_code) {
661 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700662 size_t str_len = 0;
663 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshiana9731652014-01-06 18:00:23 +0200664 do {
665
666 if ((!hndl) || ((ep_id < -1) || (ep_id > 31)) || (!error_code) ||
667 _rmnetctl_check_dev_name(dev_name)) {
668 return_code = RMNETCTL_INVALID_ARG;
669 break;
670 }
671
672 request.message_type = RMNET_NETLINK_UNSET_LOGICAL_EP_CONFIG;
673
674 request.arg_length = RMNET_MAX_STR_LEN + sizeof(int32_t);
675 str_len = strlcpy((char *)(request.local_ep_config.dev),
676 dev_name,
677 RMNET_MAX_STR_LEN);
678
679 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
680 break;
681
682 request.local_ep_config.ep_id = ep_id;
683
684 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
685 != RMNETCTL_SUCCESS)
686 break;
687 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
688 break;
689
690 return_code = _rmnetctl_set_codes(response.return_code, error_code);
691 } while(0);
692
693 return return_code;
694}
695
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600696int rmnet_get_logical_ep_config(rmnetctl_hndl_t *hndl,
697 int32_t ep_id,
698 const char *dev_name,
699 uint8_t *operating_mode,
700 char **next_dev,
Harout Hedeshian77825572014-02-17 10:47:14 +0200701 uint32_t next_dev_len,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600702 uint16_t *error_code) {
703 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700704 size_t str_len = 0;
705 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600706 do {
707 if ((!hndl) || (!operating_mode) || (!error_code) || ((ep_id < -1) ||
Harout Hedeshian77825572014-02-17 10:47:14 +0200708 (ep_id > 31)) || _rmnetctl_check_dev_name(dev_name) || (!next_dev)
709 || (0 == next_dev_len)) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600710 return_code = RMNETCTL_INVALID_ARG;
711 break;
712 }
713
714 request.message_type = RMNET_NETLINK_GET_LOGICAL_EP_CONFIG;
715
716 request.arg_length = RMNET_MAX_STR_LEN + sizeof(int32_t);
717 str_len = strlcpy((char *)(request.local_ep_config.dev),
718 dev_name,
719 RMNET_MAX_STR_LEN);
720 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
721 break;
722
723 request.local_ep_config.ep_id = ep_id;
724
725 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
726 != RMNETCTL_SUCCESS)
727 break;
728 if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
729 break;
Harout Hedeshian77825572014-02-17 10:47:14 +0200730
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600731 str_len = strlcpy(*next_dev,
732 (char *)(response.local_ep_config.next_dev),
Harout Hedeshian77825572014-02-17 10:47:14 +0200733 min(RMNET_MAX_STR_LEN, next_dev_len));
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600734 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
735 break;
736
737 *operating_mode = response.local_ep_config.operating_mode;
738 return_code = RMNETCTL_SUCCESS;
739 } while(0);
740 return return_code;
741}
742
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600743int rmnet_new_vnd_prefix(rmnetctl_hndl_t *hndl,
744 uint32_t id,
745 uint16_t *error_code,
746 uint8_t new_vnd,
747 const char *prefix)
748{
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600749 struct rmnet_nl_msg_s request, response;
750 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700751 size_t str_len = 0;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600752 do {
753 if ((!hndl) || (!error_code) ||
754 ((new_vnd != RMNETCTL_NEW_VND) && (new_vnd != RMNETCTL_FREE_VND))) {
755 return_code = RMNETCTL_INVALID_ARG;
756 break;
757 }
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600758
759 memset(request.vnd.vnd_name, 0, RMNET_MAX_STR_LEN);
760 if (new_vnd == RMNETCTL_NEW_VND) {
761 if (prefix) {
762 request.message_type =RMNET_NETLINK_NEW_VND_WITH_PREFIX;
763 str_len = strlcpy((char *)request.vnd.vnd_name,
764 prefix, RMNET_MAX_STR_LEN);
765 if (_rmnetctl_check_len(str_len, error_code)
766 != RMNETCTL_SUCCESS)
767 break;
768 } else {
769 request.message_type = RMNET_NETLINK_NEW_VND;
770 }
771 } else {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600772 request.message_type = RMNET_NETLINK_FREE_VND;
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600773 }
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600774
775 request.arg_length = sizeof(uint32_t);
776 request.vnd.id = id;
777
778 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
779 != RMNETCTL_SUCCESS)
780 break;
781 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
782 break;
783
784 return_code = _rmnetctl_set_codes(response.return_code, error_code);
785 } while(0);
786 return return_code;
787}
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600788
789int rmnet_new_vnd(rmnetctl_hndl_t *hndl,
790 uint32_t id,
791 uint16_t *error_code,
792 uint8_t new_vnd)
793{
794 return rmnet_new_vnd_prefix(hndl, id, error_code, new_vnd, 0);
795}
796
797int rmnet_get_vnd_name(rmnetctl_hndl_t *hndl,
798 uint32_t id,
799 uint16_t *error_code,
800 char *buf,
801 uint32_t buflen)
802{
803 struct rmnet_nl_msg_s request, response;
804 uint32_t str_len;
805 int return_code = RMNETCTL_LIB_ERR;
806 do {
Harout Hedeshian77825572014-02-17 10:47:14 +0200807 if ((!hndl) || (!error_code) || (!buf) || (0 == buflen)) {
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600808 return_code = RMNETCTL_INVALID_ARG;
809 break;
810 }
811
812 request.message_type = RMNET_NETLINK_GET_VND_NAME;
813 request.arg_length = sizeof(uint32_t);
814 request.vnd.id = id;
815
816
817 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
818 != RMNETCTL_SUCCESS)
819 break;
820 if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
821 break;
822
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700823 str_len = (uint32_t)strlcpy(buf,
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600824 (char *)(response.vnd.vnd_name),
825 buflen);
826 if (str_len >= buflen) {
827 *error_code = RMNETCTL_API_ERR_STRING_TRUNCATION;
828 break;
829 }
830
831 return_code = RMNETCTL_SUCCESS;
832 } while (0);
833 return return_code;
834}
835
Harout Hedeshian97a1e982013-11-08 09:28:53 -0700836int rmnet_add_del_vnd_tc_flow(rmnetctl_hndl_t *hndl,
837 uint32_t id,
838 uint32_t map_flow_id,
839 uint32_t tc_flow_id,
840 uint8_t set_flow,
841 uint16_t *error_code) {
842 struct rmnet_nl_msg_s request, response;
843 int return_code = RMNETCTL_LIB_ERR;
844 do {
Harout Hedeshian77825572014-02-17 10:47:14 +0200845 if ((!hndl) || (!error_code) || ((set_flow != RMNETCTL_ADD_FLOW) &&
846 (set_flow != RMNETCTL_DEL_FLOW))) {
Harout Hedeshian97a1e982013-11-08 09:28:53 -0700847 return_code = RMNETCTL_INVALID_ARG;
848 break;
849 }
850 if (set_flow == RMNETCTL_ADD_FLOW)
851 request.message_type = RMNET_NETLINK_ADD_VND_TC_FLOW;
852 else
853 request.message_type = RMNET_NETLINK_DEL_VND_TC_FLOW;
854
855 request.arg_length = (sizeof(uint32_t))*3;
856 request.flow_control.id = id;
857 request.flow_control.map_flow_id = map_flow_id;
858 request.flow_control.tc_flow_id = tc_flow_id;
859
860 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
861 != RMNETCTL_SUCCESS)
862 break;
863 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
864 break;
865 return_code = _rmnetctl_set_codes(response.return_code, error_code);
866 } while(0);
867 return return_code;
868}
869