blob: 91d7711c07ffad46e2741746a161b2fb5ad5a764 [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
5Copyright (c) 2013, The Linux Foundation. All rights reserved.
6
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
54#define RMNETCTL_SOCK_FLAG 0
55#define ROOT_USER_ID 0
56#define MIN_VALID_PROCESS_ID 0
57#define MIN_VALID_SOCKET_FD 0
58#define KERNEL_PROCESS_ID 0
59#define UNICAST 0
60#define MAX_BUF_SIZE sizeof(struct nlmsghdr) + sizeof(struct rmnet_nl_msg_s)
61
62/*===========================================================================
63 LOCAL FUNCTION DEFINITIONS
64===========================================================================*/
65/*!
66* @brief Synchronous method to send and receive messages to and from the kernel
67* using netlink sockets
68* @details Increments the transaction id for each message sent to the kernel.
69* Sends the netlink message to the kernel and receives the response from the
70* kernel.
71* @param *hndl RmNet handle for this transaction
72* @param request Message to be sent to the kernel
73* @param response Message received from the kernel
74* @return RMNETCTL_API_SUCCESS if successfully able to send and receive message
75* from the kernel
76* @return RMNETCTL_API_ERR_HNDL_INVALID if RmNet handle for the transaction was
77* NULL
78* @return RMNETCTL_API_ERR_REQUEST_NULL not enough memory to create buffer for
79* sending the message
80* @return RMNETCTL_API_ERR_MESSAGE_SEND if could not send the message to kernel
81* @return RMNETCTL_API_ERR_MESSAGE_RECEIVE if could not receive message from the
82* kernel
83* @return RMNETCTL_API_ERR_MESSAGE_TYPE if the request and response type do not
84* match
85*/
86static int rmnetctl_transact(rmnetctl_hndl_t *hndl,
87 struct rmnet_nl_msg_s *request,
88 struct rmnet_nl_msg_s *response) {
89 uint8_t *request_buf, *response_buf;
90 struct nlmsghdr *nlmsghdr_val;
91 struct rmnet_nl_msg_s *rmnet_nl_msg_s_val;
92 int bytes_read = -1, return_code = RMNETCTL_API_ERR_HNDL_INVALID;
93 request_buf = NULL;
94 response_buf = NULL;
95 nlmsghdr_val = NULL;
96 rmnet_nl_msg_s_val = NULL;
97 do {
98 if (!hndl){
99 break;
100 }
101 if (!request){
102 return_code = RMNETCTL_API_ERR_REQUEST_NULL;
103 break;
104 }
105 if (!response){
106 return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
107 break;
108 }
109 request_buf = (uint8_t *)malloc(MAX_BUF_SIZE * sizeof(uint8_t));
110 if (!request_buf){
111 return_code = RMNETCTL_API_ERR_REQUEST_NULL;
112 break;
113 }
114
115 response_buf = (uint8_t *)malloc(MAX_BUF_SIZE * sizeof(uint8_t));
116 if (!response_buf) {
117 free(request_buf);
118 return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
119 break;
120 }
121
122 nlmsghdr_val = (struct nlmsghdr *)request_buf;
123 rmnet_nl_msg_s_val = (struct rmnet_nl_msg_s *)NLMSG_DATA(request_buf);
124
125 memset(request_buf, 0, MAX_BUF_SIZE*sizeof(uint8_t));
126 memset(response_buf, 0, MAX_BUF_SIZE*sizeof(uint8_t));
127
128 nlmsghdr_val->nlmsg_seq = hndl->transaction_id;
129 nlmsghdr_val->nlmsg_pid = hndl->pid;
130 nlmsghdr_val->nlmsg_len = MAX_BUF_SIZE;
131
132 memcpy((void *)NLMSG_DATA(request_buf), request,
133 sizeof(struct rmnet_nl_msg_s));
134
135 rmnet_nl_msg_s_val->crd = RMNET_NETLINK_MSG_COMMAND;
136 hndl->transaction_id++;
137
138 socklen_t addrlen = sizeof(struct sockaddr_nl);
139 if (sendto(hndl->netlink_fd,
140 request_buf,
141 MAX_BUF_SIZE,
142 RMNETCTL_SOCK_FLAG,
143 (struct sockaddr *) &hndl->dest_addr,
144 sizeof(struct sockaddr_nl)) < 0) {
145 return_code = RMNETCTL_API_ERR_MESSAGE_SEND;
146 free(request_buf);
147 free(response_buf);
148 break;
149 }
150
151 bytes_read = recvfrom(hndl->netlink_fd,
152 response_buf,
153 MAX_BUF_SIZE,
154 RMNETCTL_SOCK_FLAG,
155 (struct sockaddr *) &hndl->src_addr,
156 &addrlen);
157 if (bytes_read < 0) {
158 return_code = RMNETCTL_API_ERR_MESSAGE_RECEIVE;
159 free(request_buf);
160 free(response_buf);
161 break;
162 }
163
164 memcpy(response, (void *)NLMSG_DATA(response_buf),
165 sizeof(struct rmnet_nl_msg_s));
166 if (sizeof(*response) < sizeof(struct rmnet_nl_msg_s)) {
167 return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
168 free(request_buf);
169 free(response_buf);
170 break;
171 }
172
173 if (request->message_type != response->message_type) {
174 return_code = RMNETCTL_API_ERR_MESSAGE_TYPE;
175 free(request_buf);
176 free(response_buf);
177 break;
178 }
179 return_code = RMNETCTL_SUCCESS;
180 } while(0);
181 return return_code;
182}
183
184/*!
185* @brief Static function to check the dev name
186* @details Checks if the name is not NULL and if the name is less than the
187* RMNET_MAX_STR_LEN
188* @param dev_name Name of the device
189* @return RMNETCTL_SUCCESS if successful
190* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
191*/
192static inline int _rmnetctl_check_dev_name(const char *dev_name) {
193 int return_code = RMNETCTL_INVALID_ARG;
194 do {
195 if (!dev_name)
196 break;
197 if (strlen(dev_name) >= RMNET_MAX_STR_LEN)
198 break;
199 return_code = RMNETCTL_SUCCESS;
200 } while(0);
201 return return_code;
202}
203
204/*!
205* @brief Static function to check the string length after a copy
206* @details Checks if the string length is not lesser than zero and lesser than
207* RMNET_MAX_STR_LEN
208* @param str_len length of the string after a copy
209* @param error_code Status code of this operation
210* @return RMNETCTL_SUCCESS if successful
211* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
212*/
213static inline int _rmnetctl_check_len(int str_len, uint16_t *error_code) {
214 int return_code = RMNETCTL_LIB_ERR;
215 do {
216 if ((str_len < 0) || (str_len > RMNET_MAX_STR_LEN)) {
217 *error_code = RMNETCTL_API_ERR_STRING_TRUNCATION;
218 break;
219 }
220 return_code = RMNETCTL_SUCCESS;
221 } while(0);
222 return return_code;
223}
224
225/*!
226* @brief Static function to check the response type
227* @details Checks if the response type of this message was return code
228* @param crd The crd field passed
229* @param error_code Status code of this operation
230* @return RMNETCTL_SUCCESS if successful
231* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
232*/
233static inline int _rmnetctl_check_code(int crd, uint16_t *error_code) {
234 int return_code = RMNETCTL_LIB_ERR;
235 do {
236 if (crd != RMNET_NETLINK_MSG_RETURNCODE) {
237 *error_code = RMNETCTL_API_ERR_RETURN_TYPE;
238 break;
239 }
240 return_code = RMNETCTL_SUCCESS;
241 } while(0);
242 return return_code;
243}
244
245/*!
246* @brief Static function to check the response type
247* @details Checks if the response type of this message was data
248* @param crd The crd field passed
249* @param error_code Status code of this operation
250* @return RMNETCTL_SUCCESS if successful
251* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
252*/
253static inline int _rmnetctl_check_data(int crd, uint16_t *error_code) {
254 int return_code = RMNETCTL_LIB_ERR;
255 do {
256 if (crd != RMNET_NETLINK_MSG_RETURNDATA) {
257 *error_code = RMNETCTL_API_ERR_RETURN_TYPE;
258 break;
259 }
260 return_code = RMNETCTL_SUCCESS;
261 } while(0);
262 return return_code;
263}
264
265/*!
266* @brief Static function to set the return value
267* @details Checks if the error_code from the transaction is zero for a return
268* code type message and sets the message type as RMNETCTL_SUCCESS
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_KERNEL_ERR if there was an error in the kernel.
273* Check error_code
274*/
275static inline int _rmnetctl_set_codes(int error_val, uint16_t *error_code) {
276 int return_code = RMNETCTL_KERNEL_ERR;
277 *error_code = error_val;
278 if (*error_code == RMNETCTL_SUCCESS)
279 return_code = RMNETCTL_SUCCESS;
280 return return_code;
281}
282
283/*===========================================================================
284 EXPOSED API
285===========================================================================*/
286
287int rmnetctl_init(rmnetctl_hndl_t **hndl, uint16_t *error_code)
288{
289 int pid = -1, netlink_fd = -1, return_code = RMNETCTL_LIB_ERR;
290 do {
291 if ((!hndl) || (!error_code)){
292 return_code = RMNETCTL_INVALID_ARG;
293 break;
294 }
295
296 *hndl = (rmnetctl_hndl_t *)malloc(sizeof(rmnetctl_hndl_t));
297 if (!*hndl) {
298 *error_code = RMNETCTL_API_ERR_HNDL_INVALID;
299 break;
300 }
301
302 memset(*hndl, 0, sizeof(rmnetctl_hndl_t));
303
304 pid = getpid();
305 if (pid < MIN_VALID_PROCESS_ID) {
306 free(*hndl);
307 *error_code = RMNETCTL_INIT_ERR_PROCESS_ID;
308 break;
309 }
310 (*hndl)->pid = pid;
311 netlink_fd = socket(PF_NETLINK, SOCK_RAW, RMNET_NETLINK_PROTO);
312 if (netlink_fd < MIN_VALID_SOCKET_FD) {
313 free(*hndl);
314 *error_code = RMNETCTL_INIT_ERR_NETLINK_FD;
315 break;
316 }
317
318 (*hndl)->netlink_fd = netlink_fd;
319
320 memset(&(*hndl)->src_addr, 0, sizeof(struct sockaddr_nl));
321
322 (*hndl)->src_addr.nl_family = AF_NETLINK;
323 (*hndl)->src_addr.nl_pid = (*hndl)->pid;
324
325 if (bind((*hndl)->netlink_fd,
326 (struct sockaddr *)&(*hndl)->src_addr,
327 sizeof(struct sockaddr_nl)) < 0) {
328 close((*hndl)->netlink_fd);
329 free(*hndl);
330 *error_code = RMNETCTL_INIT_ERR_BIND;
331 break;
332 }
333
334 memset(&(*hndl)->dest_addr, 0, sizeof(struct sockaddr_nl));
335
336 (*hndl)->dest_addr.nl_family = AF_NETLINK;
337 (*hndl)->dest_addr.nl_pid = KERNEL_PROCESS_ID;
338 (*hndl)->dest_addr.nl_groups = UNICAST;
339
340 return_code = RMNETCTL_SUCCESS;
341 } while(0);
342 return return_code;
343}
344
345void rmnetctl_cleanup(rmnetctl_hndl_t *hndl)
346{
347 if (!hndl)
348 return;
349 close(hndl->netlink_fd);
350 free(hndl);
351}
352
353int rmnet_associate_network_device(rmnetctl_hndl_t *hndl,
354 const char *dev_name,
355 uint16_t *error_code,
356 uint8_t assoc_dev)
357{
358 struct rmnet_nl_msg_s request, response;
359 int str_len = -1, return_code = RMNETCTL_LIB_ERR;
360 do {
361 if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name) ||
362 ((assoc_dev != RMNETCTL_DEVICE_ASSOCIATE) &&
363 (assoc_dev != RMNETCTL_DEVICE_UNASSOCIATE))) {
364 return_code = RMNETCTL_INVALID_ARG;
365 break;
366 }
367
368 if (assoc_dev == RMNETCTL_DEVICE_ASSOCIATE)
369 request.message_type = RMNET_NETLINK_ASSOCIATE_NETWORK_DEVICE;
370 else
371 request.message_type = RMNET_NETLINK_UNASSOCIATE_NETWORK_DEVICE;
372
373 request.arg_length = RMNET_MAX_STR_LEN;
374 str_len = strlcpy((char *)(request.data), dev_name, RMNET_MAX_STR_LEN);
375 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
376 break;
377
378 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
379 != RMNETCTL_SUCCESS)
380 break;
381 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
382 break;
383 return_code = _rmnetctl_set_codes(response.return_code, error_code);
384 } while(0);
385 return return_code;
386}
387
388int rmnet_get_network_device_associated(rmnetctl_hndl_t *hndl,
389 const char *dev_name,
390 int *register_status,
391 uint16_t *error_code) {
392 struct rmnet_nl_msg_s request, response;
393 int str_len = -1, return_code = RMNETCTL_LIB_ERR;
394 do {
395 if ((!hndl) || (!register_status) || (!error_code) ||
396 _rmnetctl_check_dev_name(dev_name)) {
397 return_code = RMNETCTL_INVALID_ARG;
398 break;
399 }
400
401 request.message_type = RMNET_NETLINK_GET_NETWORK_DEVICE_ASSOCIATED;
402
403 request.arg_length = RMNET_MAX_STR_LEN;
404 str_len = strlcpy((char *)(request.data), dev_name, RMNET_MAX_STR_LEN);
405 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
406 break;
407
408 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
409 != RMNETCTL_SUCCESS)
410 break;
411
412 if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
413 break;
414
415 *register_status = response.return_code;
416 return_code = RMNETCTL_SUCCESS;
417 } while(0);
418 return return_code;
419}
420
421int rmnet_set_link_egress_data_format(rmnetctl_hndl_t *hndl,
422 uint32_t egress_flags,
423 uint16_t agg_size,
424 uint16_t agg_count,
425 const char *dev_name,
426 uint16_t *error_code) {
427 struct rmnet_nl_msg_s request, response;
428 int str_len = -1, return_code = RMNETCTL_LIB_ERR;
429 do {
430 if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name)) {
431 return_code = RMNETCTL_INVALID_ARG;
432 break;
433 }
434
435 request.message_type = RMNET_NETLINK_SET_LINK_EGRESS_DATA_FORMAT;
436
437 request.arg_length = RMNET_MAX_STR_LEN +
438 sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t);
439 str_len = strlcpy((char *)(request.data_format.dev),
440 dev_name,
441 RMNET_MAX_STR_LEN);
442 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
443 break;
444
445 request.data_format.flags = egress_flags;
446 request.data_format.agg_size = agg_size;
447 request.data_format.agg_count = agg_count;
448
449 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
450 != RMNETCTL_SUCCESS)
451 break;
452
453 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
454 break;
455
456 return_code = _rmnetctl_set_codes(response.return_code, error_code);
457 } while(0);
458 return return_code;
459}
460
461int rmnet_get_link_egress_data_format(rmnetctl_hndl_t *hndl,
462 const char *dev_name,
463 uint32_t *egress_flags,
464 uint16_t *agg_size,
465 uint16_t *agg_count,
466 uint16_t *error_code) {
467 struct rmnet_nl_msg_s request, response;
468 int str_len = -1, return_code = RMNETCTL_LIB_ERR;
469 do {
470 if ((!hndl) || (!egress_flags) || (!agg_size) || (!agg_count) ||
471 (!error_code) || _rmnetctl_check_dev_name(dev_name)) {
472 return_code = RMNETCTL_INVALID_ARG;
473 break;
474 }
475 request.message_type = RMNET_NETLINK_GET_LINK_EGRESS_DATA_FORMAT;
476
477 request.arg_length = RMNET_MAX_STR_LEN;
478 str_len = strlcpy((char *)(request.data_format.dev),
479 dev_name,
480 RMNET_MAX_STR_LEN);
481 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
482 break;
483
484 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
485 != RMNETCTL_SUCCESS)
486 break;
487
488 if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
489 break;
490
491 *egress_flags = response.data_format.flags;
492 *agg_size = response.data_format.agg_size;
493 *agg_count = response.data_format.agg_count;
494 return_code = RMNETCTL_SUCCESS;
495 } while(0);
496 return return_code;
497}
498
499int rmnet_set_link_ingress_data_format(rmnetctl_hndl_t *hndl,
500 uint32_t ingress_flags,
501 const char *dev_name,
502 uint16_t *error_code) {
503 struct rmnet_nl_msg_s request, response;
504 int str_len = -1, return_code = RMNETCTL_LIB_ERR;
505 do {
506 if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name)) {
507 return_code = RMNETCTL_INVALID_ARG;
508 break;
509 }
510
511 request.message_type = RMNET_NETLINK_SET_LINK_INGRESS_DATA_FORMAT;
512
513 request.arg_length = RMNET_MAX_STR_LEN +
514 sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t);
515 str_len = strlcpy((char *)(request.data_format.dev),
516 dev_name,
517 RMNET_MAX_STR_LEN);
518 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
519 break;
520 request.data_format.flags = ingress_flags;
521
522 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
523 != RMNETCTL_SUCCESS)
524 break;
525
526 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
527 break;
528
529 return_code = _rmnetctl_set_codes(response.return_code, error_code);
530 } while(0);
531 return return_code;
532}
533
534int rmnet_get_link_ingress_data_format(rmnetctl_hndl_t *hndl,
535 const char *dev_name,
536 uint32_t *ingress_flags,
537 uint16_t *error_code) {
538 struct rmnet_nl_msg_s request, response;
539 int str_len = -1, return_code = RMNETCTL_LIB_ERR;
540 do {
541 if ((!hndl) || (!ingress_flags) || (!error_code) ||
542 _rmnetctl_check_dev_name(dev_name)) {
543 return_code = RMNETCTL_INVALID_ARG;
544 break;
545 }
546
547 request.message_type = RMNET_NETLINK_GET_LINK_INGRESS_DATA_FORMAT;
548
549 request.arg_length = RMNET_MAX_STR_LEN;
550 str_len = strlcpy((char *)(request.data_format.dev),
551 dev_name,
552 RMNET_MAX_STR_LEN);
553 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
554 break;
555
556 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
557 != RMNETCTL_SUCCESS)
558 break;
559
560 if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
561 break;
562
563 *ingress_flags = response.data_format.flags;
564 return_code = RMNETCTL_SUCCESS;
565 } while(0);
566 return return_code;
567}
568
569int rmnet_set_logical_ep_config(rmnetctl_hndl_t *hndl,
570 int32_t ep_id,
571 uint8_t operating_mode,
572 const char *dev_name,
573 const char *next_dev,
574 uint16_t *error_code) {
575 struct rmnet_nl_msg_s request, response;
576 int str_len = -1, return_code = RMNETCTL_LIB_ERR;
577 do {
578 if ((!hndl) || ((ep_id < -1) || (ep_id > 31)) || (!error_code) ||
579 _rmnetctl_check_dev_name(dev_name) ||
580 _rmnetctl_check_dev_name(next_dev)) {
581 return_code = RMNETCTL_INVALID_ARG;
582 break;
583 }
584
585 request.message_type = RMNET_NETLINK_SET_LOGICAL_EP_CONFIG;
586
587 request.arg_length = RMNET_MAX_STR_LEN +
588 RMNET_MAX_STR_LEN + sizeof(int32_t) + sizeof(uint8_t);
589 str_len = strlcpy((char *)(request.local_ep_config.dev),
590 dev_name,
591 RMNET_MAX_STR_LEN);
592 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
593 break;
594
595 str_len = strlcpy((char *)(request.local_ep_config.next_dev),
596 next_dev,
597 RMNET_MAX_STR_LEN);
598 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
599 break;
600 request.local_ep_config.ep_id = ep_id;
601 request.local_ep_config.operating_mode = operating_mode;
602
603 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
604 != RMNETCTL_SUCCESS)
605 break;
606 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
607 break;
608
609 return_code = _rmnetctl_set_codes(response.return_code, error_code);
610 } while(0);
611 return return_code;
612}
613
614int rmnet_get_logical_ep_config(rmnetctl_hndl_t *hndl,
615 int32_t ep_id,
616 const char *dev_name,
617 uint8_t *operating_mode,
618 char **next_dev,
619 uint16_t *error_code) {
620 struct rmnet_nl_msg_s request, response;
621 int str_len = -1, return_code = RMNETCTL_LIB_ERR;
622 do {
623 if ((!hndl) || (!operating_mode) || (!error_code) || ((ep_id < -1) ||
624 (ep_id > 31)) || _rmnetctl_check_dev_name(dev_name) || (!next_dev)) {
625 return_code = RMNETCTL_INVALID_ARG;
626 break;
627 }
628
629 request.message_type = RMNET_NETLINK_GET_LOGICAL_EP_CONFIG;
630
631 request.arg_length = RMNET_MAX_STR_LEN + sizeof(int32_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 request.local_ep_config.ep_id = ep_id;
639
640 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
641 != RMNETCTL_SUCCESS)
642 break;
643 if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
644 break;
645 printf("%s\n", (char *)(response.local_ep_config.next_dev));
646 str_len = strlcpy(*next_dev,
647 (char *)(response.local_ep_config.next_dev),
648 RMNET_MAX_STR_LEN);
649 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
650 break;
651
652 *operating_mode = response.local_ep_config.operating_mode;
653 return_code = RMNETCTL_SUCCESS;
654 } while(0);
655 return return_code;
656}
657
658int rmnet_new_vnd(rmnetctl_hndl_t *hndl,
659 uint32_t id,
660 uint16_t *error_code,
661 uint8_t new_vnd) {
662 struct rmnet_nl_msg_s request, response;
663 int return_code = RMNETCTL_LIB_ERR;
664 do {
665 if ((!hndl) || (!error_code) ||
666 ((new_vnd != RMNETCTL_NEW_VND) && (new_vnd != RMNETCTL_FREE_VND))) {
667 return_code = RMNETCTL_INVALID_ARG;
668 break;
669 }
670 if (new_vnd == RMNETCTL_NEW_VND)
671 request.message_type = RMNET_NETLINK_NEW_VND;
672 else
673 request.message_type = RMNET_NETLINK_FREE_VND;
674
675 request.arg_length = sizeof(uint32_t);
676 request.vnd.id = id;
677
678 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
679 != RMNETCTL_SUCCESS)
680 break;
681 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
682 break;
683
684 return_code = _rmnetctl_set_codes(response.return_code, error_code);
685 } while(0);
686 return return_code;
687}