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