blob: efd5d2065e1e2966cbd0f336146d5b46824c56f3 [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*/
101static int rmnetctl_transact(rmnetctl_hndl_t *hndl,
102 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;
107 int bytes_read = -1, return_code = RMNETCTL_API_ERR_HNDL_INVALID;
108 request_buf = NULL;
109 response_buf = NULL;
110 nlmsghdr_val = NULL;
111 rmnet_nl_msg_s_val = NULL;
112 do {
113 if (!hndl){
114 break;
115 }
116 if (!request){
117 return_code = RMNETCTL_API_ERR_REQUEST_NULL;
118 break;
119 }
120 if (!response){
121 return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
122 break;
123 }
124 request_buf = (uint8_t *)malloc(MAX_BUF_SIZE * sizeof(uint8_t));
125 if (!request_buf){
126 return_code = RMNETCTL_API_ERR_REQUEST_NULL;
127 break;
128 }
129
130 response_buf = (uint8_t *)malloc(MAX_BUF_SIZE * sizeof(uint8_t));
131 if (!response_buf) {
132 free(request_buf);
133 return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
134 break;
135 }
136
137 nlmsghdr_val = (struct nlmsghdr *)request_buf;
138 rmnet_nl_msg_s_val = (struct rmnet_nl_msg_s *)NLMSG_DATA(request_buf);
139
140 memset(request_buf, 0, MAX_BUF_SIZE*sizeof(uint8_t));
141 memset(response_buf, 0, MAX_BUF_SIZE*sizeof(uint8_t));
142
143 nlmsghdr_val->nlmsg_seq = hndl->transaction_id;
144 nlmsghdr_val->nlmsg_pid = hndl->pid;
145 nlmsghdr_val->nlmsg_len = MAX_BUF_SIZE;
146
147 memcpy((void *)NLMSG_DATA(request_buf), request,
148 sizeof(struct rmnet_nl_msg_s));
149
150 rmnet_nl_msg_s_val->crd = RMNET_NETLINK_MSG_COMMAND;
151 hndl->transaction_id++;
152
153 socklen_t addrlen = sizeof(struct sockaddr_nl);
154 if (sendto(hndl->netlink_fd,
155 request_buf,
156 MAX_BUF_SIZE,
157 RMNETCTL_SOCK_FLAG,
158 (struct sockaddr *) &hndl->dest_addr,
159 sizeof(struct sockaddr_nl)) < 0) {
160 return_code = RMNETCTL_API_ERR_MESSAGE_SEND;
161 free(request_buf);
162 free(response_buf);
163 break;
164 }
165
166 bytes_read = recvfrom(hndl->netlink_fd,
167 response_buf,
168 MAX_BUF_SIZE,
169 RMNETCTL_SOCK_FLAG,
170 (struct sockaddr *) &hndl->src_addr,
171 &addrlen);
172 if (bytes_read < 0) {
173 return_code = RMNETCTL_API_ERR_MESSAGE_RECEIVE;
174 free(request_buf);
175 free(response_buf);
176 break;
177 }
178
179 memcpy(response, (void *)NLMSG_DATA(response_buf),
180 sizeof(struct rmnet_nl_msg_s));
181 if (sizeof(*response) < sizeof(struct rmnet_nl_msg_s)) {
182 return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
183 free(request_buf);
184 free(response_buf);
185 break;
186 }
187
188 if (request->message_type != response->message_type) {
189 return_code = RMNETCTL_API_ERR_MESSAGE_TYPE;
190 free(request_buf);
191 free(response_buf);
192 break;
193 }
194 return_code = RMNETCTL_SUCCESS;
195 } while(0);
Harout Hedeshian77825572014-02-17 10:47:14 +0200196 free(request_buf);
197 free(response_buf);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600198 return return_code;
199}
200
201/*!
202* @brief Static function to check the dev name
203* @details Checks if the name is not NULL and if the name is less than the
204* RMNET_MAX_STR_LEN
205* @param dev_name Name of the device
206* @return RMNETCTL_SUCCESS if successful
207* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
208*/
209static inline int _rmnetctl_check_dev_name(const char *dev_name) {
210 int return_code = RMNETCTL_INVALID_ARG;
211 do {
212 if (!dev_name)
213 break;
214 if (strlen(dev_name) >= RMNET_MAX_STR_LEN)
215 break;
216 return_code = RMNETCTL_SUCCESS;
217 } while(0);
218 return return_code;
219}
220
221/*!
222* @brief Static function to check the string length after a copy
223* @details Checks if the string length is not lesser than zero and lesser than
224* RMNET_MAX_STR_LEN
225* @param str_len length of the string after a copy
226* @param error_code Status code of this operation
227* @return RMNETCTL_SUCCESS if successful
228* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
229*/
230static inline int _rmnetctl_check_len(int str_len, uint16_t *error_code) {
231 int return_code = RMNETCTL_LIB_ERR;
232 do {
233 if ((str_len < 0) || (str_len > RMNET_MAX_STR_LEN)) {
234 *error_code = RMNETCTL_API_ERR_STRING_TRUNCATION;
235 break;
236 }
237 return_code = RMNETCTL_SUCCESS;
238 } while(0);
239 return return_code;
240}
241
242/*!
243* @brief Static function to check the response type
244* @details Checks if the response type of this message was return code
245* @param crd The crd field passed
246* @param error_code Status code of this operation
247* @return RMNETCTL_SUCCESS if successful
248* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
249*/
250static inline int _rmnetctl_check_code(int crd, uint16_t *error_code) {
251 int return_code = RMNETCTL_LIB_ERR;
252 do {
253 if (crd != RMNET_NETLINK_MSG_RETURNCODE) {
254 *error_code = RMNETCTL_API_ERR_RETURN_TYPE;
255 break;
256 }
257 return_code = RMNETCTL_SUCCESS;
258 } while(0);
259 return return_code;
260}
261
262/*!
263* @brief Static function to check the response type
264* @details Checks if the response type of this message was data
265* @param crd The crd field passed
266* @param error_code Status code of this operation
267* @return RMNETCTL_SUCCESS if successful
268* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
269*/
270static inline int _rmnetctl_check_data(int crd, uint16_t *error_code) {
271 int return_code = RMNETCTL_LIB_ERR;
272 do {
273 if (crd != RMNET_NETLINK_MSG_RETURNDATA) {
274 *error_code = RMNETCTL_API_ERR_RETURN_TYPE;
275 break;
276 }
277 return_code = RMNETCTL_SUCCESS;
278 } while(0);
279 return return_code;
280}
281
282/*!
283* @brief Static function to set the return value
284* @details Checks if the error_code from the transaction is zero for a return
285* code type message and sets the message type as RMNETCTL_SUCCESS
286* @param crd The crd field passed
287* @param error_code Status code of this operation
288* @return RMNETCTL_SUCCESS if successful
289* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
290* Check error_code
291*/
292static inline int _rmnetctl_set_codes(int error_val, uint16_t *error_code) {
293 int return_code = RMNETCTL_KERNEL_ERR;
Harout Hedeshian77825572014-02-17 10:47:14 +0200294 if (error_val == RMNET_CONFIG_OK)
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600295 return_code = RMNETCTL_SUCCESS;
Harout Hedeshian77825572014-02-17 10:47:14 +0200296 else
297 *error_code = error_val + RMNETCTL_KERNEL_FIRST_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600298 return return_code;
299}
300
301/*===========================================================================
302 EXPOSED API
303===========================================================================*/
304
305int rmnetctl_init(rmnetctl_hndl_t **hndl, uint16_t *error_code)
306{
307 int pid = -1, netlink_fd = -1, return_code = RMNETCTL_LIB_ERR;
308 do {
309 if ((!hndl) || (!error_code)){
310 return_code = RMNETCTL_INVALID_ARG;
311 break;
312 }
313
314 *hndl = (rmnetctl_hndl_t *)malloc(sizeof(rmnetctl_hndl_t));
315 if (!*hndl) {
316 *error_code = RMNETCTL_API_ERR_HNDL_INVALID;
317 break;
318 }
319
320 memset(*hndl, 0, sizeof(rmnetctl_hndl_t));
321
322 pid = getpid();
323 if (pid < MIN_VALID_PROCESS_ID) {
324 free(*hndl);
325 *error_code = RMNETCTL_INIT_ERR_PROCESS_ID;
326 break;
327 }
328 (*hndl)->pid = pid;
329 netlink_fd = socket(PF_NETLINK, SOCK_RAW, RMNET_NETLINK_PROTO);
330 if (netlink_fd < MIN_VALID_SOCKET_FD) {
331 free(*hndl);
332 *error_code = RMNETCTL_INIT_ERR_NETLINK_FD;
333 break;
334 }
335
336 (*hndl)->netlink_fd = netlink_fd;
337
338 memset(&(*hndl)->src_addr, 0, sizeof(struct sockaddr_nl));
339
340 (*hndl)->src_addr.nl_family = AF_NETLINK;
341 (*hndl)->src_addr.nl_pid = (*hndl)->pid;
342
343 if (bind((*hndl)->netlink_fd,
344 (struct sockaddr *)&(*hndl)->src_addr,
345 sizeof(struct sockaddr_nl)) < 0) {
346 close((*hndl)->netlink_fd);
347 free(*hndl);
348 *error_code = RMNETCTL_INIT_ERR_BIND;
349 break;
350 }
351
352 memset(&(*hndl)->dest_addr, 0, sizeof(struct sockaddr_nl));
353
354 (*hndl)->dest_addr.nl_family = AF_NETLINK;
355 (*hndl)->dest_addr.nl_pid = KERNEL_PROCESS_ID;
356 (*hndl)->dest_addr.nl_groups = UNICAST;
357
358 return_code = RMNETCTL_SUCCESS;
359 } while(0);
360 return return_code;
361}
362
363void rmnetctl_cleanup(rmnetctl_hndl_t *hndl)
364{
365 if (!hndl)
366 return;
367 close(hndl->netlink_fd);
368 free(hndl);
369}
370
371int rmnet_associate_network_device(rmnetctl_hndl_t *hndl,
372 const char *dev_name,
373 uint16_t *error_code,
374 uint8_t assoc_dev)
375{
376 struct rmnet_nl_msg_s request, response;
377 int str_len = -1, return_code = RMNETCTL_LIB_ERR;
378 do {
379 if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name) ||
380 ((assoc_dev != RMNETCTL_DEVICE_ASSOCIATE) &&
381 (assoc_dev != RMNETCTL_DEVICE_UNASSOCIATE))) {
382 return_code = RMNETCTL_INVALID_ARG;
383 break;
384 }
385
386 if (assoc_dev == RMNETCTL_DEVICE_ASSOCIATE)
387 request.message_type = RMNET_NETLINK_ASSOCIATE_NETWORK_DEVICE;
388 else
389 request.message_type = RMNET_NETLINK_UNASSOCIATE_NETWORK_DEVICE;
390
391 request.arg_length = RMNET_MAX_STR_LEN;
392 str_len = strlcpy((char *)(request.data), dev_name, RMNET_MAX_STR_LEN);
393 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
394 break;
395
396 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
397 != RMNETCTL_SUCCESS)
398 break;
399 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
400 break;
401 return_code = _rmnetctl_set_codes(response.return_code, error_code);
402 } while(0);
403 return return_code;
404}
405
406int rmnet_get_network_device_associated(rmnetctl_hndl_t *hndl,
407 const char *dev_name,
408 int *register_status,
409 uint16_t *error_code) {
410 struct rmnet_nl_msg_s request, response;
411 int str_len = -1, return_code = RMNETCTL_LIB_ERR;
412 do {
413 if ((!hndl) || (!register_status) || (!error_code) ||
414 _rmnetctl_check_dev_name(dev_name)) {
415 return_code = RMNETCTL_INVALID_ARG;
416 break;
417 }
418
419 request.message_type = RMNET_NETLINK_GET_NETWORK_DEVICE_ASSOCIATED;
420
421 request.arg_length = RMNET_MAX_STR_LEN;
422 str_len = strlcpy((char *)(request.data), dev_name, RMNET_MAX_STR_LEN);
423 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
424 break;
425
426 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
427 != RMNETCTL_SUCCESS)
428 break;
429
430 if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
431 break;
432
433 *register_status = response.return_code;
434 return_code = RMNETCTL_SUCCESS;
435 } while(0);
436 return return_code;
437}
438
439int rmnet_set_link_egress_data_format(rmnetctl_hndl_t *hndl,
440 uint32_t egress_flags,
441 uint16_t agg_size,
442 uint16_t agg_count,
443 const char *dev_name,
444 uint16_t *error_code) {
445 struct rmnet_nl_msg_s request, response;
446 int str_len = -1, return_code = RMNETCTL_LIB_ERR;
447 do {
Harout Hedeshian77825572014-02-17 10:47:14 +0200448 if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name) ||
449 ((~EGRESS_FLAGS_MASK) & egress_flags)) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600450 return_code = RMNETCTL_INVALID_ARG;
451 break;
452 }
453
454 request.message_type = RMNET_NETLINK_SET_LINK_EGRESS_DATA_FORMAT;
455
456 request.arg_length = RMNET_MAX_STR_LEN +
457 sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t);
458 str_len = strlcpy((char *)(request.data_format.dev),
459 dev_name,
460 RMNET_MAX_STR_LEN);
461 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
462 break;
463
464 request.data_format.flags = egress_flags;
465 request.data_format.agg_size = agg_size;
466 request.data_format.agg_count = agg_count;
467
468 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
469 != RMNETCTL_SUCCESS)
470 break;
471
472 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
473 break;
474
475 return_code = _rmnetctl_set_codes(response.return_code, error_code);
476 } while(0);
477 return return_code;
478}
479
480int rmnet_get_link_egress_data_format(rmnetctl_hndl_t *hndl,
481 const char *dev_name,
482 uint32_t *egress_flags,
483 uint16_t *agg_size,
484 uint16_t *agg_count,
485 uint16_t *error_code) {
486 struct rmnet_nl_msg_s request, response;
487 int str_len = -1, return_code = RMNETCTL_LIB_ERR;
488 do {
489 if ((!hndl) || (!egress_flags) || (!agg_size) || (!agg_count) ||
490 (!error_code) || _rmnetctl_check_dev_name(dev_name)) {
491 return_code = RMNETCTL_INVALID_ARG;
492 break;
493 }
494 request.message_type = RMNET_NETLINK_GET_LINK_EGRESS_DATA_FORMAT;
495
496 request.arg_length = RMNET_MAX_STR_LEN;
497 str_len = strlcpy((char *)(request.data_format.dev),
498 dev_name,
499 RMNET_MAX_STR_LEN);
500 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
501 break;
502
503 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
504 != RMNETCTL_SUCCESS)
505 break;
506
507 if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
508 break;
509
510 *egress_flags = response.data_format.flags;
511 *agg_size = response.data_format.agg_size;
512 *agg_count = response.data_format.agg_count;
513 return_code = RMNETCTL_SUCCESS;
514 } while(0);
515 return return_code;
516}
517
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700518int rmnet_set_link_ingress_data_format_tailspace(rmnetctl_hndl_t *hndl,
519 uint32_t ingress_flags,
520 uint8_t tail_spacing,
521 const char *dev_name,
522 uint16_t *error_code) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600523 struct rmnet_nl_msg_s request, response;
524 int str_len = -1, return_code = RMNETCTL_LIB_ERR;
525 do {
Harout Hedeshian77825572014-02-17 10:47:14 +0200526 if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name) ||
527 ((~INGRESS_FLAGS_MASK) & ingress_flags)) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600528 return_code = RMNETCTL_INVALID_ARG;
529 break;
530 }
531
532 request.message_type = RMNET_NETLINK_SET_LINK_INGRESS_DATA_FORMAT;
533
534 request.arg_length = RMNET_MAX_STR_LEN +
535 sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t);
536 str_len = strlcpy((char *)(request.data_format.dev),
537 dev_name,
538 RMNET_MAX_STR_LEN);
539 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
540 break;
541 request.data_format.flags = ingress_flags;
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700542 request.data_format.tail_spacing = tail_spacing;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600543
544 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
545 != RMNETCTL_SUCCESS)
546 break;
547
548 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
549 break;
550
551 return_code = _rmnetctl_set_codes(response.return_code, error_code);
552 } while(0);
553 return return_code;
554}
555
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700556int rmnet_get_link_ingress_data_format_tailspace(rmnetctl_hndl_t *hndl,
557 const char *dev_name,
558 uint32_t *ingress_flags,
559 uint8_t *tail_spacing,
560 uint16_t *error_code) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600561 struct rmnet_nl_msg_s request, response;
562 int str_len = -1, return_code = RMNETCTL_LIB_ERR;
563 do {
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700564 if ((!hndl) || (!error_code) ||
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600565 _rmnetctl_check_dev_name(dev_name)) {
566 return_code = RMNETCTL_INVALID_ARG;
567 break;
568 }
569
570 request.message_type = RMNET_NETLINK_GET_LINK_INGRESS_DATA_FORMAT;
571
572 request.arg_length = RMNET_MAX_STR_LEN;
573 str_len = strlcpy((char *)(request.data_format.dev),
574 dev_name,
575 RMNET_MAX_STR_LEN);
576 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
577 break;
578
579 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
580 != RMNETCTL_SUCCESS)
581 break;
582
583 if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
584 break;
585
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700586 if (ingress_flags)
587 *ingress_flags = response.data_format.flags;
588
589 if (tail_spacing)
590 *tail_spacing = response.data_format.tail_spacing;
591
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600592 return_code = RMNETCTL_SUCCESS;
593 } while(0);
594 return return_code;
595}
596
597int rmnet_set_logical_ep_config(rmnetctl_hndl_t *hndl,
598 int32_t ep_id,
599 uint8_t operating_mode,
600 const char *dev_name,
601 const char *next_dev,
602 uint16_t *error_code) {
603 struct rmnet_nl_msg_s request, response;
604 int str_len = -1, return_code = RMNETCTL_LIB_ERR;
605 do {
606 if ((!hndl) || ((ep_id < -1) || (ep_id > 31)) || (!error_code) ||
607 _rmnetctl_check_dev_name(dev_name) ||
Harout Hedeshian77825572014-02-17 10:47:14 +0200608 _rmnetctl_check_dev_name(next_dev) ||
609 operating_mode >= RMNET_EPMODE_LENGTH) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600610 return_code = RMNETCTL_INVALID_ARG;
611 break;
612 }
613
614 request.message_type = RMNET_NETLINK_SET_LOGICAL_EP_CONFIG;
615
616 request.arg_length = RMNET_MAX_STR_LEN +
617 RMNET_MAX_STR_LEN + sizeof(int32_t) + sizeof(uint8_t);
618 str_len = strlcpy((char *)(request.local_ep_config.dev),
619 dev_name,
620 RMNET_MAX_STR_LEN);
621 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
622 break;
623
624 str_len = strlcpy((char *)(request.local_ep_config.next_dev),
625 next_dev,
626 RMNET_MAX_STR_LEN);
627 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
628 break;
629 request.local_ep_config.ep_id = ep_id;
630 request.local_ep_config.operating_mode = operating_mode;
631
632 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
633 != RMNETCTL_SUCCESS)
634 break;
635 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
636 break;
637
638 return_code = _rmnetctl_set_codes(response.return_code, error_code);
639 } while(0);
640 return return_code;
641}
642
Harout Hedeshiana9731652014-01-06 18:00:23 +0200643int rmnet_unset_logical_ep_config(rmnetctl_hndl_t *hndl,
644 int32_t ep_id,
645 const char *dev_name,
646 uint16_t *error_code) {
647 struct rmnet_nl_msg_s request, response;
648 int str_len = -1, return_code = RMNETCTL_LIB_ERR;
649 do {
650
651 if ((!hndl) || ((ep_id < -1) || (ep_id > 31)) || (!error_code) ||
652 _rmnetctl_check_dev_name(dev_name)) {
653 return_code = RMNETCTL_INVALID_ARG;
654 break;
655 }
656
657 request.message_type = RMNET_NETLINK_UNSET_LOGICAL_EP_CONFIG;
658
659 request.arg_length = RMNET_MAX_STR_LEN + sizeof(int32_t);
660 str_len = strlcpy((char *)(request.local_ep_config.dev),
661 dev_name,
662 RMNET_MAX_STR_LEN);
663
664 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
665 break;
666
667 request.local_ep_config.ep_id = ep_id;
668
669 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
670 != RMNETCTL_SUCCESS)
671 break;
672 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
673 break;
674
675 return_code = _rmnetctl_set_codes(response.return_code, error_code);
676 } while(0);
677
678 return return_code;
679}
680
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600681int rmnet_get_logical_ep_config(rmnetctl_hndl_t *hndl,
682 int32_t ep_id,
683 const char *dev_name,
684 uint8_t *operating_mode,
685 char **next_dev,
Harout Hedeshian77825572014-02-17 10:47:14 +0200686 uint32_t next_dev_len,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600687 uint16_t *error_code) {
688 struct rmnet_nl_msg_s request, response;
689 int str_len = -1, return_code = RMNETCTL_LIB_ERR;
690 do {
691 if ((!hndl) || (!operating_mode) || (!error_code) || ((ep_id < -1) ||
Harout Hedeshian77825572014-02-17 10:47:14 +0200692 (ep_id > 31)) || _rmnetctl_check_dev_name(dev_name) || (!next_dev)
693 || (0 == next_dev_len)) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600694 return_code = RMNETCTL_INVALID_ARG;
695 break;
696 }
697
698 request.message_type = RMNET_NETLINK_GET_LOGICAL_EP_CONFIG;
699
700 request.arg_length = RMNET_MAX_STR_LEN + sizeof(int32_t);
701 str_len = strlcpy((char *)(request.local_ep_config.dev),
702 dev_name,
703 RMNET_MAX_STR_LEN);
704 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
705 break;
706
707 request.local_ep_config.ep_id = ep_id;
708
709 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
710 != RMNETCTL_SUCCESS)
711 break;
712 if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
713 break;
Harout Hedeshian77825572014-02-17 10:47:14 +0200714
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600715 str_len = strlcpy(*next_dev,
716 (char *)(response.local_ep_config.next_dev),
Harout Hedeshian77825572014-02-17 10:47:14 +0200717 min(RMNET_MAX_STR_LEN, next_dev_len));
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600718 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
719 break;
720
721 *operating_mode = response.local_ep_config.operating_mode;
722 return_code = RMNETCTL_SUCCESS;
723 } while(0);
724 return return_code;
725}
726
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600727int rmnet_new_vnd_prefix(rmnetctl_hndl_t *hndl,
728 uint32_t id,
729 uint16_t *error_code,
730 uint8_t new_vnd,
731 const char *prefix)
732{
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600733 struct rmnet_nl_msg_s request, response;
734 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600735 int str_len = -1;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600736 do {
737 if ((!hndl) || (!error_code) ||
738 ((new_vnd != RMNETCTL_NEW_VND) && (new_vnd != RMNETCTL_FREE_VND))) {
739 return_code = RMNETCTL_INVALID_ARG;
740 break;
741 }
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600742
743 memset(request.vnd.vnd_name, 0, RMNET_MAX_STR_LEN);
744 if (new_vnd == RMNETCTL_NEW_VND) {
745 if (prefix) {
746 request.message_type =RMNET_NETLINK_NEW_VND_WITH_PREFIX;
747 str_len = strlcpy((char *)request.vnd.vnd_name,
748 prefix, RMNET_MAX_STR_LEN);
749 if (_rmnetctl_check_len(str_len, error_code)
750 != RMNETCTL_SUCCESS)
751 break;
752 } else {
753 request.message_type = RMNET_NETLINK_NEW_VND;
754 }
755 } else {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600756 request.message_type = RMNET_NETLINK_FREE_VND;
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600757 }
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600758
759 request.arg_length = sizeof(uint32_t);
760 request.vnd.id = id;
761
762 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
763 != RMNETCTL_SUCCESS)
764 break;
765 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
766 break;
767
768 return_code = _rmnetctl_set_codes(response.return_code, error_code);
769 } while(0);
770 return return_code;
771}
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600772
773int rmnet_new_vnd(rmnetctl_hndl_t *hndl,
774 uint32_t id,
775 uint16_t *error_code,
776 uint8_t new_vnd)
777{
778 return rmnet_new_vnd_prefix(hndl, id, error_code, new_vnd, 0);
779}
780
781int rmnet_get_vnd_name(rmnetctl_hndl_t *hndl,
782 uint32_t id,
783 uint16_t *error_code,
784 char *buf,
785 uint32_t buflen)
786{
787 struct rmnet_nl_msg_s request, response;
788 uint32_t str_len;
789 int return_code = RMNETCTL_LIB_ERR;
790 do {
Harout Hedeshian77825572014-02-17 10:47:14 +0200791 if ((!hndl) || (!error_code) || (!buf) || (0 == buflen)) {
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600792 return_code = RMNETCTL_INVALID_ARG;
793 break;
794 }
795
796 request.message_type = RMNET_NETLINK_GET_VND_NAME;
797 request.arg_length = sizeof(uint32_t);
798 request.vnd.id = id;
799
800
801 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
802 != RMNETCTL_SUCCESS)
803 break;
804 if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
805 break;
806
807 str_len = strlcpy(buf,
808 (char *)(response.vnd.vnd_name),
809 buflen);
810 if (str_len >= buflen) {
811 *error_code = RMNETCTL_API_ERR_STRING_TRUNCATION;
812 break;
813 }
814
815 return_code = RMNETCTL_SUCCESS;
816 } while (0);
817 return return_code;
818}
819
Harout Hedeshian97a1e982013-11-08 09:28:53 -0700820int rmnet_add_del_vnd_tc_flow(rmnetctl_hndl_t *hndl,
821 uint32_t id,
822 uint32_t map_flow_id,
823 uint32_t tc_flow_id,
824 uint8_t set_flow,
825 uint16_t *error_code) {
826 struct rmnet_nl_msg_s request, response;
827 int return_code = RMNETCTL_LIB_ERR;
828 do {
Harout Hedeshian77825572014-02-17 10:47:14 +0200829 if ((!hndl) || (!error_code) || ((set_flow != RMNETCTL_ADD_FLOW) &&
830 (set_flow != RMNETCTL_DEL_FLOW))) {
Harout Hedeshian97a1e982013-11-08 09:28:53 -0700831 return_code = RMNETCTL_INVALID_ARG;
832 break;
833 }
834 if (set_flow == RMNETCTL_ADD_FLOW)
835 request.message_type = RMNET_NETLINK_ADD_VND_TC_FLOW;
836 else
837 request.message_type = RMNET_NETLINK_DEL_VND_TC_FLOW;
838
839 request.arg_length = (sizeof(uint32_t))*3;
840 request.flow_control.id = id;
841 request.flow_control.map_flow_id = map_flow_id;
842 request.flow_control.tc_flow_id = tc_flow_id;
843
844 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
845 != RMNETCTL_SUCCESS)
846 break;
847 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
848 break;
849 return_code = _rmnetctl_set_codes(response.return_code, error_code);
850 } while(0);
851 return return_code;
852}
853