Merge "rmnetcfg: Initial commit"
This commit is contained in:
committed by
Gerrit - the friendly Code Review server
commit
b970e57a7a
2
Android.mk
Normal file
2
Android.mk
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
include $(call all-subdir-makefiles)
|
||||||
|
|
||||||
2
rmnetctl/Android.mk
Normal file
2
rmnetctl/Android.mk
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
include $(call all-subdir-makefiles)
|
||||||
|
|
||||||
16
rmnetctl/cli/Android.mk
Normal file
16
rmnetctl/cli/Android.mk
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := rmnetcli.c
|
||||||
|
LOCAL_CFLAGS := -Wall -Werror
|
||||||
|
|
||||||
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../inc
|
||||||
|
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../src
|
||||||
|
LOCAL_C_INCLUDES += $(LOCAL_PATH)
|
||||||
|
|
||||||
|
LOCAL_MODULE := rmnetcli
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
|
||||||
|
LOCAL_SHARED_LIBRARIES := librmnetctl
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
352
rmnetctl/cli/rmnetcli.c
Normal file
352
rmnetctl/cli/rmnetcli.c
Normal file
@@ -0,0 +1,352 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
R M N E T C L I . C
|
||||||
|
|
||||||
|
Copyright (c) 2013, The Linux Foundation. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer in the documentation and/or other materials provided
|
||||||
|
with the distribution.
|
||||||
|
* Neither the name of The Linux Foundation nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||||
|
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
|
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||||
|
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
@file rmnetcli.c
|
||||||
|
@brief command line interface to expose rmnet control API's
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
File containing implementation of the command line interface to expose the
|
||||||
|
rmnet control configuration .
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/*===========================================================================
|
||||||
|
INCLUDE FILES
|
||||||
|
===========================================================================*/
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <linux/netlink.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "rmnetcli.h"
|
||||||
|
#include "librmnetctl.h"
|
||||||
|
|
||||||
|
#define RMNET_MAX_STR_LEN 16
|
||||||
|
|
||||||
|
#define _RMNETCLI_CHECKNULL(X) do { if (!X) { \
|
||||||
|
print_rmnet_api_status(RMNETCTL_INVALID_ARG, RMNETCTL_CFG_FAILURE_NO_COMMAND); \
|
||||||
|
rmnetctl_cleanup(handle); \
|
||||||
|
return RMNETCTL_INVALID_ARG; \
|
||||||
|
} } while (0);
|
||||||
|
#define _STRTOUI32(X) (uint32_t)strtoul(X, NULL, 0)
|
||||||
|
#define _STRTOUI16(X) (uint16_t)strtoul(X, NULL, 0)
|
||||||
|
#define _STRTOUI8(X) (uint8_t)strtoul(X, NULL, 0)
|
||||||
|
#define _STRTOI32(X) (int32_t)strtol(X, NULL, 0)
|
||||||
|
|
||||||
|
#define _5TABS "\n\t\t\t\t\t"
|
||||||
|
#define _2TABS "\n\t\t"
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Contains a list of error message from CLI
|
||||||
|
*/
|
||||||
|
char rmnetcfg_error_code_text
|
||||||
|
[RMNETCFG_TOTAL_ERR_MSGS][RMNETCTL_ERR_MSG_SIZE] = {
|
||||||
|
"Help option Specified",
|
||||||
|
"ERROR: No\\Invalid command was specified\n",
|
||||||
|
"ERROR: Could not allocate buffer for Egress device\n"
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Method to display the syntax for the commands
|
||||||
|
* @details Displays the syntax and usage for the commands
|
||||||
|
* @param void
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
static void rmnet_api_usage()
|
||||||
|
{
|
||||||
|
printf("RmNet API Usage:\n\n");
|
||||||
|
printf("rmnetcli help Displays this help\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("rmnetcli assocnetdev <dev_name> Registers the RmNet");
|
||||||
|
printf(_5TABS" data driver on a particular");
|
||||||
|
printf(_5TABS" device.dev_name cannot");
|
||||||
|
printf(_5TABS" be larger than 15");
|
||||||
|
printf(_5TABS" characters. Returns");
|
||||||
|
printf(_5TABS" the status code.\n\n");
|
||||||
|
printf("rmnetcli unassocnetdev <dev_name> Unregisters the");
|
||||||
|
printf(_5TABS" RmNet data driver on a particular");
|
||||||
|
printf(_5TABS" device. dev_name cannot");
|
||||||
|
printf(_5TABS" be larger than 15");
|
||||||
|
printf(_5TABS" characters. Returns");
|
||||||
|
printf(_5TABS" the status code.\n\n");
|
||||||
|
printf("rmnetcli getnetdevassoc <dev_name> Get if the RmNet");
|
||||||
|
printf(_5TABS" data driver is registered on");
|
||||||
|
printf(_5TABS" a particular device.");
|
||||||
|
printf(_5TABS" dev_name cannot be");
|
||||||
|
printf(_5TABS" larger than 15");
|
||||||
|
printf(_5TABS" characters. Returns 1");
|
||||||
|
printf(_5TABS" if is registered and");
|
||||||
|
printf(_5TABS" 0 if it is not");
|
||||||
|
printf(_5TABS" registered\n\n");
|
||||||
|
printf("rmnetcli setledf <egress_flags> Sets the egress data");
|
||||||
|
printf(_2TABS" <agg_size> format for a particular link.");
|
||||||
|
printf(_2TABS" <agg_count> dev_name cannot be larger");
|
||||||
|
printf(_2TABS" <dev_name> than 15 characters.");
|
||||||
|
printf(_5TABS" Returns the status code\n\n");
|
||||||
|
printf("rmnetcli getledf <dev_name> Gets the egress data");
|
||||||
|
printf(_5TABS" format for a particular link.");
|
||||||
|
printf(_5TABS" dev_name cannot be larger");
|
||||||
|
printf(_5TABS" than 15. Returns the 4");
|
||||||
|
printf(_5TABS" byte unsigned integer");
|
||||||
|
printf(_5TABS" egress_flags\n\n");
|
||||||
|
printf("rmnetcli setlidf <ingress_flags> Sets the ingress");
|
||||||
|
printf(_2TABS" <dev_name> data format for a particular");
|
||||||
|
printf(_5TABS" link. egress_flags is 4");
|
||||||
|
printf(_5TABS" byte unsigned integer.");
|
||||||
|
printf(_5TABS" dev_name cannot be");
|
||||||
|
printf(_5TABS" larger than 15.");
|
||||||
|
printf(_5TABS" characters. Returns");
|
||||||
|
printf(_5TABS" the status code\n\n");
|
||||||
|
printf("rmnetcli getlidf <dev_name> Gets the ingress");
|
||||||
|
printf(_5TABS" data format for a particular");
|
||||||
|
printf(_5TABS" link. dev_name cannot be");
|
||||||
|
printf(_5TABS" larger than 15. Returns");
|
||||||
|
printf(_5TABS" the 4 byte unsigned");
|
||||||
|
printf(_5TABS" integer ingress_flags\n\n");
|
||||||
|
printf("rmnetcli setlepc <logical_ep_id> Sets the logical");
|
||||||
|
printf(_2TABS" <rmnet_mode> endpoint configuration for");
|
||||||
|
printf(_2TABS" <dev_name> a particular link.");
|
||||||
|
printf(_2TABS" <egress_dev_name> logical_ep_id are 32bit");
|
||||||
|
printf(_5TABS" integers from -1 to 31.");
|
||||||
|
printf(_5TABS" rmnet_mode is a 1 byte");
|
||||||
|
printf(_5TABS" unsigned integer of");
|
||||||
|
printf(_5TABS" value none, vnd or");
|
||||||
|
printf(_5TABS" bridged. dev_name");
|
||||||
|
printf(_5TABS" and egress_dev_name");
|
||||||
|
printf(_5TABS" cannot be larger");
|
||||||
|
printf(_5TABS" than 15 tcharacters");
|
||||||
|
printf(_5TABS" Returns the status code\n\n");
|
||||||
|
printf("rmnetcli getlepc <logical_ep_id> Sets the logical");
|
||||||
|
printf(_2TABS" <dev_name> enpoint configuration for a");
|
||||||
|
printf(_5TABS" particular link.");
|
||||||
|
printf(_5TABS" logical_ep_id are 32bit");
|
||||||
|
printf(_5TABS" integers from -1 to 31.");
|
||||||
|
printf(_5TABS" Returns the rmnet_mode");
|
||||||
|
printf(_5TABS" and egress_dev_name.");
|
||||||
|
printf(_5TABS" rmnet_mode is a 1");
|
||||||
|
printf(_5TABS" byte unsigned integer");
|
||||||
|
printf(_5TABS" of value none, vnd or");
|
||||||
|
printf(_5TABS" bridged. dev_name and");
|
||||||
|
printf(_5TABS" egress_dev_name cannot be");
|
||||||
|
printf(_5TABS" larger than 15 ");
|
||||||
|
printf(_5TABS" characters. Returns the");
|
||||||
|
printf(_5TABS" status code\n\n");
|
||||||
|
printf("rmnetcli newvnd <dev_name> Creates a new");
|
||||||
|
printf(_5TABS" virtual network device node.");
|
||||||
|
printf(_5TABS" dev_name cannot be");
|
||||||
|
printf(_5TABS" larger than 15. Returns");
|
||||||
|
printf(_5TABS" the status code\n\n");
|
||||||
|
printf("rmnetcli freevnd <dev_name> Removes virtual");
|
||||||
|
printf(_5TABS" network device node. dev_name");
|
||||||
|
printf(_5TABS" cannot be larger than 15.");
|
||||||
|
printf(_5TABS" Returns the status code\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_rmnetctl_lib_errors(uint16_t error_number) {
|
||||||
|
if ((error_number > RMNETCTL_API_SUCCESS) &&
|
||||||
|
(error_number < RMNETCTL_API_ERR_ENUM_LENGTH)) {
|
||||||
|
printf("%s", rmnetctl_error_code_text[error_number]);
|
||||||
|
}
|
||||||
|
if ((error_number >= RMNETCFG_ERR_NUM_START) &&
|
||||||
|
(error_number < RMNETCFG_ERR_NUM_START + RMNETCFG_TOTAL_ERR_MSGS)) {
|
||||||
|
printf("%s", rmnetcfg_error_code_text
|
||||||
|
[error_number - RMNETCFG_ERR_NUM_START]);
|
||||||
|
if ((error_number == RMNETCTL_CFG_SUCCESS_HELP_COMMAND) ||
|
||||||
|
(error_number == RMNETCTL_CFG_FAILURE_NO_COMMAND))
|
||||||
|
rmnet_api_usage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Method to check the error numbers generated from API calls
|
||||||
|
* @details Displays the error messages based on each error code
|
||||||
|
* @param error_number Error number returned from the API and the CLI
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
static void print_rmnet_api_status(int return_code, uint16_t error_number)
|
||||||
|
{
|
||||||
|
if (return_code == RMNETCTL_SUCCESS)
|
||||||
|
printf("SUCCESS\n");
|
||||||
|
else if (return_code == RMNETCTL_LIB_ERR)
|
||||||
|
printf("LIBRARY ");
|
||||||
|
else if (return_code == RMNETCTL_KERNEL_ERR)
|
||||||
|
printf("KERNEL : Error code %u\n", error_number);
|
||||||
|
else if (return_code == RMNETCTL_INVALID_ARG)
|
||||||
|
printf("INVALID_ARG\n");
|
||||||
|
|
||||||
|
if (return_code == RMNETCTL_LIB_ERR) {
|
||||||
|
print_rmnetctl_lib_errors(error_number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Method to make the API calls
|
||||||
|
* @details Checks for each type of parameter and calls the appropriate
|
||||||
|
* function based on the number of parameters and paramter type
|
||||||
|
* @param argc Number of arguments which vary based on the commands
|
||||||
|
* @param argv Value of the arguments which vary based on the commands
|
||||||
|
* @return RMNETCTL_SUCCESS if successful. Relevant data might be printed
|
||||||
|
* based on the message type
|
||||||
|
* @return RMNETCTL_LIB_ERR if there was a library error. Error code will be
|
||||||
|
* printed
|
||||||
|
* @return RMNETCTL_KERNEL_ERR if there was a error in the kernel. Error code will be
|
||||||
|
* printed
|
||||||
|
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int rmnet_api_call(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct rmnetctl_hndl_s *handle = NULL;
|
||||||
|
uint16_t error_number = RMNETCTL_CFG_FAILURE_NO_COMMAND;
|
||||||
|
int return_code = RMNETCTL_LIB_ERR;
|
||||||
|
if ((!argc) || (!*argv)) {
|
||||||
|
print_rmnet_api_status(RMNETCTL_LIB_ERR,
|
||||||
|
RMNETCTL_CFG_FAILURE_NO_COMMAND);
|
||||||
|
return RMNETCTL_LIB_ERR;
|
||||||
|
}
|
||||||
|
if (!strcmp(*argv, "help")) {
|
||||||
|
print_rmnet_api_status(RMNETCTL_LIB_ERR,
|
||||||
|
RMNETCTL_CFG_SUCCESS_HELP_COMMAND);
|
||||||
|
return RMNETCTL_LIB_ERR;
|
||||||
|
}
|
||||||
|
return_code = rmnetctl_init(&handle, &error_number);
|
||||||
|
if (return_code!= RMNETCTL_SUCCESS) {
|
||||||
|
print_rmnet_api_status(return_code, error_number);
|
||||||
|
return RMNETCTL_LIB_ERR;
|
||||||
|
}
|
||||||
|
error_number = RMNETCTL_CFG_FAILURE_NO_COMMAND;
|
||||||
|
return_code = RMNETCTL_LIB_ERR;
|
||||||
|
if (!strcmp(*argv, "assocnetdev")) {
|
||||||
|
return_code = rmnet_associate_network_device(handle,
|
||||||
|
argv[1], &error_number, RMNETCTL_DEVICE_ASSOCIATE);
|
||||||
|
} else if (!strcmp(*argv, "unassocnetdev")) {
|
||||||
|
return_code = rmnet_associate_network_device(handle,
|
||||||
|
argv[1], &error_number, RMNETCTL_DEVICE_UNASSOCIATE);
|
||||||
|
} else if (!strcmp(*argv, "getnetdevassoc")) {
|
||||||
|
int register_status;
|
||||||
|
return_code = rmnet_get_network_device_associated(handle,
|
||||||
|
argv[1], ®ister_status, &error_number);
|
||||||
|
if (return_code == RMNETCTL_SUCCESS)
|
||||||
|
printf("register_status is %d\n", register_status);
|
||||||
|
} else if (!strcmp(*argv, "getledf")) {
|
||||||
|
uint32_t egress_flags;
|
||||||
|
uint16_t agg_size, agg_count;
|
||||||
|
return_code = rmnet_get_link_egress_data_format(handle,
|
||||||
|
argv[1], &egress_flags, &agg_size, &agg_count, &error_number);
|
||||||
|
if (return_code == RMNETCTL_SUCCESS) {
|
||||||
|
printf("egress_flags is %u\n", egress_flags);
|
||||||
|
printf("agg_size is %u\n", agg_size);
|
||||||
|
printf("agg_count is %u\n", agg_count);
|
||||||
|
}
|
||||||
|
} else if (!strcmp(*argv, "getlidf")) {
|
||||||
|
uint32_t ingress_flags;
|
||||||
|
return_code = rmnet_get_link_ingress_data_format(handle,
|
||||||
|
argv[1], &ingress_flags, &error_number);
|
||||||
|
if (return_code == RMNETCTL_SUCCESS) {
|
||||||
|
printf("ingress_flags is %u\n", ingress_flags);
|
||||||
|
}
|
||||||
|
} else if (!strcmp(*argv, "newvnd")) {
|
||||||
|
_RMNETCLI_CHECKNULL(argv[1]);
|
||||||
|
return_code = rmnet_new_vnd(handle,
|
||||||
|
_STRTOUI32(argv[1]), &error_number, RMNETCTL_NEW_VND);
|
||||||
|
} else if (!strcmp(*argv, "freevnd")) {
|
||||||
|
_RMNETCLI_CHECKNULL(argv[1]);
|
||||||
|
return_code = rmnet_new_vnd(handle,
|
||||||
|
_STRTOUI32(argv[1]), &error_number, RMNETCTL_FREE_VND);
|
||||||
|
} else if (!strcmp(*argv, "setlidf")) {
|
||||||
|
_RMNETCLI_CHECKNULL(argv[1]);
|
||||||
|
return_code = rmnet_set_link_ingress_data_format(handle,
|
||||||
|
_STRTOUI32(argv[1]), argv[2], &error_number);
|
||||||
|
} else if (!strcmp(*argv, "getlepc")) {
|
||||||
|
_RMNETCLI_CHECKNULL(argv[1]);
|
||||||
|
uint8_t rmnet_mode;
|
||||||
|
char *egress_dev_name;
|
||||||
|
egress_dev_name = NULL;
|
||||||
|
egress_dev_name = (char *)malloc(RMNET_MAX_STR_LEN
|
||||||
|
* sizeof(char));
|
||||||
|
if (!egress_dev_name) {
|
||||||
|
print_rmnet_api_status(RMNETCTL_LIB_ERR,
|
||||||
|
RMNETCTL_CFG_FAILURE_EGRESS_DEV_NAME_NULL);
|
||||||
|
return RMNETCTL_LIB_ERR;
|
||||||
|
}
|
||||||
|
return_code = rmnet_get_logical_ep_config(handle,
|
||||||
|
_STRTOI32(argv[1]), argv[2], &rmnet_mode,
|
||||||
|
&egress_dev_name, &error_number);
|
||||||
|
if (return_code == RMNETCTL_SUCCESS) {
|
||||||
|
printf("rmnet_mode is %u\n", rmnet_mode);
|
||||||
|
printf("egress_dev_name is %s\n", egress_dev_name);
|
||||||
|
}
|
||||||
|
} else if (!strcmp(*argv, "setledf")) {
|
||||||
|
_RMNETCLI_CHECKNULL(argv[1]);
|
||||||
|
_RMNETCLI_CHECKNULL(argv[2]);
|
||||||
|
_RMNETCLI_CHECKNULL(argv[3]);
|
||||||
|
return_code = rmnet_set_link_egress_data_format(handle,
|
||||||
|
_STRTOUI32(argv[1]), _STRTOUI16(argv[2]), _STRTOUI16(argv[3]),
|
||||||
|
argv[4], &error_number);
|
||||||
|
} else if (!strcmp(*argv, "setlepc")) {
|
||||||
|
_RMNETCLI_CHECKNULL(argv[1]);
|
||||||
|
_RMNETCLI_CHECKNULL(argv[2]);
|
||||||
|
return_code = rmnet_set_logical_ep_config(handle,
|
||||||
|
_STRTOI32(argv[1]), _STRTOUI8(argv[2]), argv[3], argv[4],
|
||||||
|
&error_number);
|
||||||
|
}
|
||||||
|
print_rmnet_api_status(return_code, error_number);
|
||||||
|
rmnetctl_cleanup(handle);
|
||||||
|
return return_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Method which serves as en entry point to the rmnetcli function
|
||||||
|
* @details Entry point for the RmNet Netlink API. This is the command line
|
||||||
|
* interface for the RmNet API
|
||||||
|
* @param argc Number of arguments which vary based on the commands
|
||||||
|
* @param argv Value of the arguments which vary based on the commands
|
||||||
|
* @return RMNETCTL_SUCCESS if successful. Relevant data might be printed
|
||||||
|
* based on the message type
|
||||||
|
* @return RMNETCTL_LIB_ERR if there was a library error. Error code will be
|
||||||
|
* printed
|
||||||
|
* @return RMNETCTL_KERNEL_ERR if there was a error in the kernel. Error code will be
|
||||||
|
* printed
|
||||||
|
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
|
||||||
|
*/
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
return rmnet_api_call(argc, argv);
|
||||||
|
}
|
||||||
61
rmnetctl/cli/rmnetcli.h
Normal file
61
rmnetctl/cli/rmnetcli.h
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
R M N E T C L I . H
|
||||||
|
|
||||||
|
Copyright (c) 2013, The Linux Foundation. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer in the documentation and/or other materials provided
|
||||||
|
with the distribution.
|
||||||
|
* Neither the name of The Linux Foundation nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||||
|
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
|
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||||
|
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
@file rmnetcli.h
|
||||||
|
@brief headers for the command line interface to expose rmnet control API's
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
Header file containing definition for the command line interface to expose
|
||||||
|
rmnet control API's
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef RMNETCLI_H
|
||||||
|
#define RMNETCLI_H
|
||||||
|
|
||||||
|
/* Print the help for the commands since the help flag was used. */
|
||||||
|
#define RMNETCTL_CFG_SUCCESS_HELP_COMMAND 100
|
||||||
|
/* No/invalid API call was specified. So return an error. */
|
||||||
|
#define RMNETCTL_CFG_FAILURE_NO_COMMAND 101
|
||||||
|
/* The buffer for egress device name was NULL */
|
||||||
|
#define RMNETCTL_CFG_FAILURE_EGRESS_DEV_NAME_NULL 102
|
||||||
|
|
||||||
|
/* This should always be the value of the starting element */
|
||||||
|
#define RMNETCFG_ERR_NUM_START 100
|
||||||
|
|
||||||
|
/* This should always be the total number of error message from CLI */
|
||||||
|
#define RMNETCFG_TOTAL_ERR_MSGS 3
|
||||||
|
|
||||||
|
#endif /* not defined RMNETCLI_H */
|
||||||
336
rmnetctl/inc/librmnetctl.h
Normal file
336
rmnetctl/inc/librmnetctl.h
Normal file
@@ -0,0 +1,336 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
L I B R M N E T C T L . H
|
||||||
|
|
||||||
|
Copyright (c) 2013, The Linux Foundation. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer in the documentation and/or other materials provided
|
||||||
|
with the distribution.
|
||||||
|
* Neither the name of The Linux Foundation nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||||
|
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
|
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||||
|
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @file librmnetctl.h
|
||||||
|
* @brief rmnet control API's header file
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBRMNETCTL_H
|
||||||
|
#define LIBRMNETCTL_H
|
||||||
|
|
||||||
|
/* RMNET API succeeded */
|
||||||
|
#define RMNETCTL_SUCCESS 0
|
||||||
|
/* RMNET API encountered an error while executing within the library. Check the
|
||||||
|
* error code in this case */
|
||||||
|
#define RMNETCTL_LIB_ERR 1
|
||||||
|
/* RMNET API encountered an error while executing in the kernel. Check the
|
||||||
|
* error code in this case */
|
||||||
|
#define RMNETCTL_KERNEL_ERR 2
|
||||||
|
/* RMNET API encountered an error because of invalid arguments*/
|
||||||
|
#define RMNETCTL_INVALID_ARG 3
|
||||||
|
|
||||||
|
/* Flag to associate a network device*/
|
||||||
|
#define RMNETCTL_DEVICE_ASSOCIATE 1
|
||||||
|
/* Flag to unassociate a network device*/
|
||||||
|
#define RMNETCTL_DEVICE_UNASSOCIATE 0
|
||||||
|
/* Flag to create a new virtual network device*/
|
||||||
|
#define RMNETCTL_NEW_VND 1
|
||||||
|
/* Flag to free a new virtual network device*/
|
||||||
|
#define RMNETCTL_FREE_VND 0
|
||||||
|
|
||||||
|
enum rmnetctl_error_codes_e {
|
||||||
|
/* API succeeded. This should always be the first element. */
|
||||||
|
RMNETCTL_API_SUCCESS,
|
||||||
|
/* API failed because not enough memory to create buffer to send
|
||||||
|
* message */
|
||||||
|
RMNETCTL_API_ERR_REQUEST_INVALID,
|
||||||
|
/* API failed because not enough memory to create buffer for the
|
||||||
|
* response message */
|
||||||
|
RMNETCTL_API_ERR_RESPONSE_INVALID,
|
||||||
|
/* API failed because could not send the message to kernel */
|
||||||
|
RMNETCTL_API_ERR_MESSAGE_SEND,
|
||||||
|
/* API failed because could not receive message from the kernel */
|
||||||
|
RMNETCTL_API_ERR_MESSAGE_RECEIVE,
|
||||||
|
/* Invalid process id. So return an error. */
|
||||||
|
RMNETCTL_INIT_ERR_PROCESS_ID,
|
||||||
|
/* Invalid socket descriptor id. So return an error. */
|
||||||
|
RMNETCTL_INIT_ERR_NETLINK_FD,
|
||||||
|
/* Could not bind the socket to the Netlink file descriptor */
|
||||||
|
RMNETCTL_INIT_ERR_BIND,
|
||||||
|
/* Invalid user id. Only root has access to this function. (NA) */
|
||||||
|
RMNETCTL_INIT_ERR_INVALID_USER,
|
||||||
|
/* API failed because the RmNet handle for the transaction was NULL */
|
||||||
|
RMNETCTL_API_ERR_HNDL_INVALID,
|
||||||
|
/* API failed because the request buffer for the transaction was NULL */
|
||||||
|
RMNETCTL_API_ERR_REQUEST_NULL,
|
||||||
|
/* API failed because the response buffer for the transaction was NULL*/
|
||||||
|
RMNETCTL_API_ERR_RESPONSE_NULL,
|
||||||
|
/* API failed because the request and response type do not match*/
|
||||||
|
RMNETCTL_API_ERR_MESSAGE_TYPE,
|
||||||
|
/* API failed because the return type is invalid */
|
||||||
|
RMNETCTL_API_ERR_RETURN_TYPE,
|
||||||
|
/* API failed because the string was truncated */
|
||||||
|
RMNETCTL_API_ERR_STRING_TRUNCATION,
|
||||||
|
/* This should always be the last element */
|
||||||
|
RMNETCTL_API_ERR_ENUM_LENGTH
|
||||||
|
};
|
||||||
|
|
||||||
|
#define RMNETCTL_ERR_MSG_SIZE 100
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Contains a list of error message from API
|
||||||
|
*/
|
||||||
|
char rmnetctl_error_code_text
|
||||||
|
[RMNETCTL_API_ERR_ENUM_LENGTH][RMNETCTL_ERR_MSG_SIZE] = {
|
||||||
|
"ERROR: API succeeded\n",
|
||||||
|
"ERROR: Unable to allocate the buffer to send message\n",
|
||||||
|
"ERROR: Unable to allocate the buffer to receive message\n",
|
||||||
|
"ERROR: Could not send the message to kernel\n",
|
||||||
|
"ERROR: Unable to receive message from the kernel\n",
|
||||||
|
"ERROR: Invalid process id\n",
|
||||||
|
"ERROR: Invalid socket descriptor id\n",
|
||||||
|
"ERROR: Could not bind to netlink socket\n",
|
||||||
|
"ERROR: Only root can access this API\n",
|
||||||
|
"ERROR: RmNet handle for the transaction was NULL\n",
|
||||||
|
"ERROR: Request buffer for the transaction was NULL\n",
|
||||||
|
"ERROR: Response buffer for the transaction was NULL\n",
|
||||||
|
"ERROR: Request and response type do not match\n",
|
||||||
|
"ERROR: Return type is invalid\n",
|
||||||
|
"ERROR: String was truncated\n"
|
||||||
|
};
|
||||||
|
|
||||||
|
/*===========================================================================
|
||||||
|
DEFINITIONS AND DECLARATIONS
|
||||||
|
===========================================================================*/
|
||||||
|
typedef struct rmnetctl_hndl_s rmnetctl_hndl_t;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Public API to initialize the RMNET control driver
|
||||||
|
* @details Allocates memory for the RmNet handle. Creates and binds to a and
|
||||||
|
* netlink socket if successful
|
||||||
|
* @param **rmnetctl_hndl_t_val RmNet handle to be initialized
|
||||||
|
* @return RMNETCTL_SUCCESS if successful
|
||||||
|
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
|
||||||
|
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
|
||||||
|
* Check error_code
|
||||||
|
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
|
||||||
|
*/
|
||||||
|
int rmnetctl_init(rmnetctl_hndl_t **hndl, uint16_t *error_code);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Public API to clean up the RmNeT control handle
|
||||||
|
* @details Close the socket and free the RmNet handle
|
||||||
|
* @param *rmnetctl_hndl_t_val RmNet handle to be initialized
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
void rmnetctl_cleanup(rmnetctl_hndl_t *hndl);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Public API to register/unregister a RMNET driver on a particular device
|
||||||
|
* @details Message type is RMNET_NETLINK_ASSOCIATE_NETWORK_DEVICE or
|
||||||
|
* RMNET_NETLINK_UNASSOCIATE_NETWORK_DEVICE based on the flag for assoc_dev
|
||||||
|
* @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message
|
||||||
|
* @param dev_name Device on which to register the RmNet driver
|
||||||
|
* @param error_code Status code of this operation
|
||||||
|
* @param assoc_dev registers the device if RMNETCTL_DEVICE_ASSOCIATE or
|
||||||
|
* unregisters the device if RMNETCTL_DEVICE_UNASSOCIATE
|
||||||
|
* @return RMNETCTL_SUCCESS if successful
|
||||||
|
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
|
||||||
|
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
|
||||||
|
* Check error_code
|
||||||
|
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
|
||||||
|
*/
|
||||||
|
int rmnet_associate_network_device(rmnetctl_hndl_t *hndl,
|
||||||
|
const char *dev_name,
|
||||||
|
uint16_t *error_code,
|
||||||
|
uint8_t assoc_dev);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Public API to get if a RMNET driver is registered on a particular
|
||||||
|
* device
|
||||||
|
* @details Message type is RMNET_NETLINK_GET_NETWORK_DEVICE_ASSOCIATED.
|
||||||
|
* @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message
|
||||||
|
* @param dev_name Device on which to check if the RmNet driver is registered
|
||||||
|
* @param register_status 1 if RmNet data driver is registered on a particular
|
||||||
|
* device, 0 if not
|
||||||
|
* @param error_code Status code of this operation
|
||||||
|
* @return RMNETCTL_SUCCESS if successful
|
||||||
|
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
|
||||||
|
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
|
||||||
|
* Check error_code
|
||||||
|
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
|
||||||
|
*/
|
||||||
|
int rmnet_get_network_device_associated(rmnetctl_hndl_t *hndl,
|
||||||
|
const char *dev_name,
|
||||||
|
int *register_status,
|
||||||
|
uint16_t *error_code);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Public API to set the egress data format for a particular link.
|
||||||
|
* @details Message type is RMNET_NETLINK_SET_LINK_EGRESS_DATA_FORMAT.
|
||||||
|
* @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message
|
||||||
|
* @param egress_flags Egress flags to be set on the device
|
||||||
|
* @param agg_size Max size of aggregated packets
|
||||||
|
* @param agg_count Number of packets to be aggregated
|
||||||
|
* @param dev_name Device on which to set the egress data format
|
||||||
|
* @param error_code Status code of this operation returned from the kernel
|
||||||
|
* @return RMNETCTL_SUCCESS if successful
|
||||||
|
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
|
||||||
|
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
|
||||||
|
* Check error_code
|
||||||
|
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
|
||||||
|
*/
|
||||||
|
int rmnet_set_link_egress_data_format(rmnetctl_hndl_t *hndl,
|
||||||
|
uint32_t egress_flags,
|
||||||
|
uint16_t agg_size,
|
||||||
|
uint16_t agg_count,
|
||||||
|
const char *dev_name,
|
||||||
|
uint16_t *error_code);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Public API to get the egress data format for a particular link.
|
||||||
|
* @details Message type is RMNET_NETLINK_GET_LINK_EGRESS_DATA_FORMAT.
|
||||||
|
* @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message
|
||||||
|
* @param dev_name Device on which to get the egress data format
|
||||||
|
* @param egress_flags Egress flags from the device
|
||||||
|
* @param agg_count Number of packets to be aggregated
|
||||||
|
* @param error_code Status code of this operation returned from the kernel
|
||||||
|
* @return RMNETCTL_SUCCESS if successful
|
||||||
|
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
|
||||||
|
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
|
||||||
|
* Check error_code
|
||||||
|
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
|
||||||
|
*/
|
||||||
|
int rmnet_get_link_egress_data_format(rmnetctl_hndl_t *hndl,
|
||||||
|
const char *dev_name,
|
||||||
|
uint32_t *egress_flags,
|
||||||
|
uint16_t *agg_size,
|
||||||
|
uint16_t *agg_count,
|
||||||
|
uint16_t *error_code);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Public API to set the ingress data format for a particular link.
|
||||||
|
* @details Message type is RMNET_NETLINK_SET_LINK_INGRESS_DATA_FORMAT.
|
||||||
|
* @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message
|
||||||
|
* @param ingress_flags Ingress flags from the device
|
||||||
|
* @param dev_name Device on which to set the ingress data format
|
||||||
|
* @param error_code Status code of this operation returned from the kernel
|
||||||
|
* @return RMNETCTL_SUCCESS if successful
|
||||||
|
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
|
||||||
|
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
|
||||||
|
* Check error_code
|
||||||
|
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
|
||||||
|
*/
|
||||||
|
int rmnet_set_link_ingress_data_format(rmnetctl_hndl_t *hndl,
|
||||||
|
uint32_t ingress_flags,
|
||||||
|
const char *dev_name,
|
||||||
|
uint16_t *error_code);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Public API to get the ingress data format for a particular link.
|
||||||
|
* @details Message type is RMNET_NETLINK_GET_LINK_INGRESS_DATA_FORMAT.
|
||||||
|
* @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message
|
||||||
|
* @param dev_name Device on which to get the ingress data format
|
||||||
|
* @param ingress_flags Ingress flags from the device
|
||||||
|
* @param error_code Status code of this operation returned from the kernel
|
||||||
|
* @return RMNETCTL_SUCCESS if successful
|
||||||
|
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
|
||||||
|
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
|
||||||
|
* Check error_code
|
||||||
|
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
|
||||||
|
*/
|
||||||
|
int rmnet_get_link_ingress_data_format(rmnetctl_hndl_t *hndl,
|
||||||
|
const char *dev_name,
|
||||||
|
uint32_t *ingress_flags,
|
||||||
|
uint16_t *error_code);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Public API to set the logical endpoint configuration for a
|
||||||
|
* particular link.
|
||||||
|
* @details Message type is RMNET_NETLINK_SET_LOGICAL_EP_CONFIG.
|
||||||
|
* @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message
|
||||||
|
* @param logical_ep_id Logical end point id on which the configuration is to be
|
||||||
|
* set
|
||||||
|
* @param rmnet_mode RmNet mode to be set on the device
|
||||||
|
* @param dev_name Device on which to set the logical end point configuration
|
||||||
|
* @param egress_dev_name Egress Device if operating in bridge mode
|
||||||
|
* @param error_code Status code of this operation returned from the kernel
|
||||||
|
* @return RMNETCTL_SUCCESS if successful
|
||||||
|
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
|
||||||
|
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
|
||||||
|
* Check error_code
|
||||||
|
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
|
||||||
|
*/
|
||||||
|
int rmnet_set_logical_ep_config(rmnetctl_hndl_t *hndl,
|
||||||
|
int32_t ep_id,
|
||||||
|
uint8_t operating_mode,
|
||||||
|
const char *dev_name,
|
||||||
|
const char *next_dev,
|
||||||
|
uint16_t *error_code);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Public API to get the logical endpoint configuration for a
|
||||||
|
* particular link.
|
||||||
|
* @details Message type is RMNET_NETLINK_GET_LOGICAL_EP_CONFIG.
|
||||||
|
* @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message
|
||||||
|
* @param logical_ep_id Logical end point id from which to get the configuration
|
||||||
|
* @param dev_name Device on which to get the logical end point configuration
|
||||||
|
* @param rmnet_mode RmNet mode from the device
|
||||||
|
* @param egress_dev_name Egress Device if operating in bridge mode
|
||||||
|
* @param error_code Status code of this operation returned from the kernel
|
||||||
|
* @return RMNETCTL_SUCCESS if successful
|
||||||
|
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
|
||||||
|
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
|
||||||
|
* Check error_code
|
||||||
|
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
|
||||||
|
*/
|
||||||
|
int rmnet_get_logical_ep_config(rmnetctl_hndl_t *hndl,
|
||||||
|
int32_t ep_id,
|
||||||
|
const char *dev_name,
|
||||||
|
uint8_t *operating_mode,
|
||||||
|
char **next_dev,
|
||||||
|
uint16_t *error_code);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Public API to create a new virtual device node
|
||||||
|
* @details Message type is RMNET_NETLINK_NEW_VND or
|
||||||
|
* RMNETCTL_FREE_VND based on the flag for new_vnd
|
||||||
|
* @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message
|
||||||
|
* @param node_number Node number to create the virtual network device node
|
||||||
|
* @param error_code Status code of this operation returned from the kernel
|
||||||
|
* @param new_vnd creates a new virtual network device if RMNETCTL_NEW_VND or
|
||||||
|
* frees the device if RMNETCTL_FREE_VND
|
||||||
|
* @return RMNETCTL_SUCCESS if successful
|
||||||
|
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
|
||||||
|
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
|
||||||
|
* Check error_code
|
||||||
|
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
|
||||||
|
*/
|
||||||
|
int rmnet_new_vnd(rmnetctl_hndl_t *hndl,
|
||||||
|
uint32_t id,
|
||||||
|
uint16_t *error_code,
|
||||||
|
uint8_t new_vnd);
|
||||||
|
|
||||||
|
#endif /* not defined LIBRMNETCTL_H */
|
||||||
|
|
||||||
65
rmnetctl/inc/librmnetctl_hndl.h
Normal file
65
rmnetctl/inc/librmnetctl_hndl.h
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
L I B R M N E T C T L _ H N D L. H
|
||||||
|
|
||||||
|
Copyright (c) 2013, The Linux Foundation. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer in the documentation and/or other materials provided
|
||||||
|
with the distribution.
|
||||||
|
* Neither the name of The Linux Foundation nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||||
|
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
|
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||||
|
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @file librmnetctl_hndl.h
|
||||||
|
* @brief rmnet control API's handle file
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBRMNETCTL_HNDL_H
|
||||||
|
#define LIBRMNETCTL_HNDL_H
|
||||||
|
|
||||||
|
/*===========================================================================
|
||||||
|
DEFINITIONS AND DECLARATIONS
|
||||||
|
===========================================================================*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Structure for RMNET control handles. A rmnet hndl contains the caller
|
||||||
|
* process id, the transaction id which is initialized to 0 for each new
|
||||||
|
* initialized handle and the netlink file descriptor for this handle.
|
||||||
|
* @var pid process id to be used for the netlink message
|
||||||
|
* @var transaction_id message number for debugging
|
||||||
|
* @var netlink_fd netlink file descriptor to be used
|
||||||
|
* @var src_addr source socket address properties for this message
|
||||||
|
* @var dest_addr destination socket address properties for this message
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct rmnetctl_hndl_s {
|
||||||
|
uint32_t pid;
|
||||||
|
uint32_t transaction_id;
|
||||||
|
uint32_t netlink_fd;
|
||||||
|
struct sockaddr_nl src_addr, dest_addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* not defined LIBRMNETCTL_HNDL_H */
|
||||||
|
|
||||||
20
rmnetctl/src/Android.mk
Normal file
20
rmnetctl/src/Android.mk
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_COPY_HEADERS_TO := dataservices/rmnetctl
|
||||||
|
LOCAL_COPY_HEADERS := ../inc/librmnetctl.h
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := librmnetctl.c
|
||||||
|
LOCAL_CFLAGS := -Wall -Werror
|
||||||
|
|
||||||
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../inc
|
||||||
|
LOCAL_C_INCLUDES += $(LOCAL_PATH)
|
||||||
|
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
|
||||||
|
LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL_MODULE := librmnetctl
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
LOCAL_PRELINK_MODULE := false
|
||||||
|
|
||||||
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
687
rmnetctl/src/librmnetctl.c
Normal file
687
rmnetctl/src/librmnetctl.c
Normal file
@@ -0,0 +1,687 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
L I B R M N E T C T L . C
|
||||||
|
|
||||||
|
Copyright (c) 2013, The Linux Foundation. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer in the documentation and/or other materials provided
|
||||||
|
with the distribution.
|
||||||
|
* Neither the name of The Linux Foundation nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||||
|
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
|
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||||
|
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @file librmnetctl.c
|
||||||
|
* @brief rmnet control API's implentations file
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*===========================================================================
|
||||||
|
INCLUDE FILES
|
||||||
|
===========================================================================*/
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <linux/netlink.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <linux/rmnet_data.h>
|
||||||
|
#include "librmnetctl_hndl.h"
|
||||||
|
#include "librmnetctl.h"
|
||||||
|
|
||||||
|
#define RMNETCTL_SOCK_FLAG 0
|
||||||
|
#define ROOT_USER_ID 0
|
||||||
|
#define MIN_VALID_PROCESS_ID 0
|
||||||
|
#define MIN_VALID_SOCKET_FD 0
|
||||||
|
#define KERNEL_PROCESS_ID 0
|
||||||
|
#define UNICAST 0
|
||||||
|
#define MAX_BUF_SIZE sizeof(struct nlmsghdr) + sizeof(struct rmnet_nl_msg_s)
|
||||||
|
|
||||||
|
/*===========================================================================
|
||||||
|
LOCAL FUNCTION DEFINITIONS
|
||||||
|
===========================================================================*/
|
||||||
|
/*!
|
||||||
|
* @brief Synchronous method to send and receive messages to and from the kernel
|
||||||
|
* using netlink sockets
|
||||||
|
* @details Increments the transaction id for each message sent to the kernel.
|
||||||
|
* Sends the netlink message to the kernel and receives the response from the
|
||||||
|
* kernel.
|
||||||
|
* @param *hndl RmNet handle for this transaction
|
||||||
|
* @param request Message to be sent to the kernel
|
||||||
|
* @param response Message received from the kernel
|
||||||
|
* @return RMNETCTL_API_SUCCESS if successfully able to send and receive message
|
||||||
|
* from the kernel
|
||||||
|
* @return RMNETCTL_API_ERR_HNDL_INVALID if RmNet handle for the transaction was
|
||||||
|
* NULL
|
||||||
|
* @return RMNETCTL_API_ERR_REQUEST_NULL not enough memory to create buffer for
|
||||||
|
* sending the message
|
||||||
|
* @return RMNETCTL_API_ERR_MESSAGE_SEND if could not send the message to kernel
|
||||||
|
* @return RMNETCTL_API_ERR_MESSAGE_RECEIVE if could not receive message from the
|
||||||
|
* kernel
|
||||||
|
* @return RMNETCTL_API_ERR_MESSAGE_TYPE if the request and response type do not
|
||||||
|
* match
|
||||||
|
*/
|
||||||
|
static int rmnetctl_transact(rmnetctl_hndl_t *hndl,
|
||||||
|
struct rmnet_nl_msg_s *request,
|
||||||
|
struct rmnet_nl_msg_s *response) {
|
||||||
|
uint8_t *request_buf, *response_buf;
|
||||||
|
struct nlmsghdr *nlmsghdr_val;
|
||||||
|
struct rmnet_nl_msg_s *rmnet_nl_msg_s_val;
|
||||||
|
int bytes_read = -1, return_code = RMNETCTL_API_ERR_HNDL_INVALID;
|
||||||
|
request_buf = NULL;
|
||||||
|
response_buf = NULL;
|
||||||
|
nlmsghdr_val = NULL;
|
||||||
|
rmnet_nl_msg_s_val = NULL;
|
||||||
|
do {
|
||||||
|
if (!hndl){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!request){
|
||||||
|
return_code = RMNETCTL_API_ERR_REQUEST_NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!response){
|
||||||
|
return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
request_buf = (uint8_t *)malloc(MAX_BUF_SIZE * sizeof(uint8_t));
|
||||||
|
if (!request_buf){
|
||||||
|
return_code = RMNETCTL_API_ERR_REQUEST_NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
response_buf = (uint8_t *)malloc(MAX_BUF_SIZE * sizeof(uint8_t));
|
||||||
|
if (!response_buf) {
|
||||||
|
free(request_buf);
|
||||||
|
return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
nlmsghdr_val = (struct nlmsghdr *)request_buf;
|
||||||
|
rmnet_nl_msg_s_val = (struct rmnet_nl_msg_s *)NLMSG_DATA(request_buf);
|
||||||
|
|
||||||
|
memset(request_buf, 0, MAX_BUF_SIZE*sizeof(uint8_t));
|
||||||
|
memset(response_buf, 0, MAX_BUF_SIZE*sizeof(uint8_t));
|
||||||
|
|
||||||
|
nlmsghdr_val->nlmsg_seq = hndl->transaction_id;
|
||||||
|
nlmsghdr_val->nlmsg_pid = hndl->pid;
|
||||||
|
nlmsghdr_val->nlmsg_len = MAX_BUF_SIZE;
|
||||||
|
|
||||||
|
memcpy((void *)NLMSG_DATA(request_buf), request,
|
||||||
|
sizeof(struct rmnet_nl_msg_s));
|
||||||
|
|
||||||
|
rmnet_nl_msg_s_val->crd = RMNET_NETLINK_MSG_COMMAND;
|
||||||
|
hndl->transaction_id++;
|
||||||
|
|
||||||
|
socklen_t addrlen = sizeof(struct sockaddr_nl);
|
||||||
|
if (sendto(hndl->netlink_fd,
|
||||||
|
request_buf,
|
||||||
|
MAX_BUF_SIZE,
|
||||||
|
RMNETCTL_SOCK_FLAG,
|
||||||
|
(struct sockaddr *) &hndl->dest_addr,
|
||||||
|
sizeof(struct sockaddr_nl)) < 0) {
|
||||||
|
return_code = RMNETCTL_API_ERR_MESSAGE_SEND;
|
||||||
|
free(request_buf);
|
||||||
|
free(response_buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_read = recvfrom(hndl->netlink_fd,
|
||||||
|
response_buf,
|
||||||
|
MAX_BUF_SIZE,
|
||||||
|
RMNETCTL_SOCK_FLAG,
|
||||||
|
(struct sockaddr *) &hndl->src_addr,
|
||||||
|
&addrlen);
|
||||||
|
if (bytes_read < 0) {
|
||||||
|
return_code = RMNETCTL_API_ERR_MESSAGE_RECEIVE;
|
||||||
|
free(request_buf);
|
||||||
|
free(response_buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(response, (void *)NLMSG_DATA(response_buf),
|
||||||
|
sizeof(struct rmnet_nl_msg_s));
|
||||||
|
if (sizeof(*response) < sizeof(struct rmnet_nl_msg_s)) {
|
||||||
|
return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
|
||||||
|
free(request_buf);
|
||||||
|
free(response_buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request->message_type != response->message_type) {
|
||||||
|
return_code = RMNETCTL_API_ERR_MESSAGE_TYPE;
|
||||||
|
free(request_buf);
|
||||||
|
free(response_buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return_code = RMNETCTL_SUCCESS;
|
||||||
|
} while(0);
|
||||||
|
return return_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Static function to check the dev name
|
||||||
|
* @details Checks if the name is not NULL and if the name is less than the
|
||||||
|
* RMNET_MAX_STR_LEN
|
||||||
|
* @param dev_name Name of the device
|
||||||
|
* @return RMNETCTL_SUCCESS if successful
|
||||||
|
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
|
||||||
|
*/
|
||||||
|
static inline int _rmnetctl_check_dev_name(const char *dev_name) {
|
||||||
|
int return_code = RMNETCTL_INVALID_ARG;
|
||||||
|
do {
|
||||||
|
if (!dev_name)
|
||||||
|
break;
|
||||||
|
if (strlen(dev_name) >= RMNET_MAX_STR_LEN)
|
||||||
|
break;
|
||||||
|
return_code = RMNETCTL_SUCCESS;
|
||||||
|
} while(0);
|
||||||
|
return return_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Static function to check the string length after a copy
|
||||||
|
* @details Checks if the string length is not lesser than zero and lesser than
|
||||||
|
* RMNET_MAX_STR_LEN
|
||||||
|
* @param str_len length of the string after a copy
|
||||||
|
* @param error_code Status code of this operation
|
||||||
|
* @return RMNETCTL_SUCCESS if successful
|
||||||
|
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
|
||||||
|
*/
|
||||||
|
static inline int _rmnetctl_check_len(int str_len, uint16_t *error_code) {
|
||||||
|
int return_code = RMNETCTL_LIB_ERR;
|
||||||
|
do {
|
||||||
|
if ((str_len < 0) || (str_len > RMNET_MAX_STR_LEN)) {
|
||||||
|
*error_code = RMNETCTL_API_ERR_STRING_TRUNCATION;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return_code = RMNETCTL_SUCCESS;
|
||||||
|
} while(0);
|
||||||
|
return return_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Static function to check the response type
|
||||||
|
* @details Checks if the response type of this message was return code
|
||||||
|
* @param crd The crd field passed
|
||||||
|
* @param error_code Status code of this operation
|
||||||
|
* @return RMNETCTL_SUCCESS if successful
|
||||||
|
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
|
||||||
|
*/
|
||||||
|
static inline int _rmnetctl_check_code(int crd, uint16_t *error_code) {
|
||||||
|
int return_code = RMNETCTL_LIB_ERR;
|
||||||
|
do {
|
||||||
|
if (crd != RMNET_NETLINK_MSG_RETURNCODE) {
|
||||||
|
*error_code = RMNETCTL_API_ERR_RETURN_TYPE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return_code = RMNETCTL_SUCCESS;
|
||||||
|
} while(0);
|
||||||
|
return return_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Static function to check the response type
|
||||||
|
* @details Checks if the response type of this message was data
|
||||||
|
* @param crd The crd field passed
|
||||||
|
* @param error_code Status code of this operation
|
||||||
|
* @return RMNETCTL_SUCCESS if successful
|
||||||
|
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
|
||||||
|
*/
|
||||||
|
static inline int _rmnetctl_check_data(int crd, uint16_t *error_code) {
|
||||||
|
int return_code = RMNETCTL_LIB_ERR;
|
||||||
|
do {
|
||||||
|
if (crd != RMNET_NETLINK_MSG_RETURNDATA) {
|
||||||
|
*error_code = RMNETCTL_API_ERR_RETURN_TYPE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return_code = RMNETCTL_SUCCESS;
|
||||||
|
} while(0);
|
||||||
|
return return_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Static function to set the return value
|
||||||
|
* @details Checks if the error_code from the transaction is zero for a return
|
||||||
|
* code type message and sets the message type as RMNETCTL_SUCCESS
|
||||||
|
* @param crd The crd field passed
|
||||||
|
* @param error_code Status code of this operation
|
||||||
|
* @return RMNETCTL_SUCCESS if successful
|
||||||
|
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
|
||||||
|
* Check error_code
|
||||||
|
*/
|
||||||
|
static inline int _rmnetctl_set_codes(int error_val, uint16_t *error_code) {
|
||||||
|
int return_code = RMNETCTL_KERNEL_ERR;
|
||||||
|
*error_code = error_val;
|
||||||
|
if (*error_code == RMNETCTL_SUCCESS)
|
||||||
|
return_code = RMNETCTL_SUCCESS;
|
||||||
|
return return_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================
|
||||||
|
EXPOSED API
|
||||||
|
===========================================================================*/
|
||||||
|
|
||||||
|
int rmnetctl_init(rmnetctl_hndl_t **hndl, uint16_t *error_code)
|
||||||
|
{
|
||||||
|
int pid = -1, netlink_fd = -1, return_code = RMNETCTL_LIB_ERR;
|
||||||
|
do {
|
||||||
|
if ((!hndl) || (!error_code)){
|
||||||
|
return_code = RMNETCTL_INVALID_ARG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*hndl = (rmnetctl_hndl_t *)malloc(sizeof(rmnetctl_hndl_t));
|
||||||
|
if (!*hndl) {
|
||||||
|
*error_code = RMNETCTL_API_ERR_HNDL_INVALID;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(*hndl, 0, sizeof(rmnetctl_hndl_t));
|
||||||
|
|
||||||
|
pid = getpid();
|
||||||
|
if (pid < MIN_VALID_PROCESS_ID) {
|
||||||
|
free(*hndl);
|
||||||
|
*error_code = RMNETCTL_INIT_ERR_PROCESS_ID;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(*hndl)->pid = pid;
|
||||||
|
netlink_fd = socket(PF_NETLINK, SOCK_RAW, RMNET_NETLINK_PROTO);
|
||||||
|
if (netlink_fd < MIN_VALID_SOCKET_FD) {
|
||||||
|
free(*hndl);
|
||||||
|
*error_code = RMNETCTL_INIT_ERR_NETLINK_FD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*hndl)->netlink_fd = netlink_fd;
|
||||||
|
|
||||||
|
memset(&(*hndl)->src_addr, 0, sizeof(struct sockaddr_nl));
|
||||||
|
|
||||||
|
(*hndl)->src_addr.nl_family = AF_NETLINK;
|
||||||
|
(*hndl)->src_addr.nl_pid = (*hndl)->pid;
|
||||||
|
|
||||||
|
if (bind((*hndl)->netlink_fd,
|
||||||
|
(struct sockaddr *)&(*hndl)->src_addr,
|
||||||
|
sizeof(struct sockaddr_nl)) < 0) {
|
||||||
|
close((*hndl)->netlink_fd);
|
||||||
|
free(*hndl);
|
||||||
|
*error_code = RMNETCTL_INIT_ERR_BIND;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&(*hndl)->dest_addr, 0, sizeof(struct sockaddr_nl));
|
||||||
|
|
||||||
|
(*hndl)->dest_addr.nl_family = AF_NETLINK;
|
||||||
|
(*hndl)->dest_addr.nl_pid = KERNEL_PROCESS_ID;
|
||||||
|
(*hndl)->dest_addr.nl_groups = UNICAST;
|
||||||
|
|
||||||
|
return_code = RMNETCTL_SUCCESS;
|
||||||
|
} while(0);
|
||||||
|
return return_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rmnetctl_cleanup(rmnetctl_hndl_t *hndl)
|
||||||
|
{
|
||||||
|
if (!hndl)
|
||||||
|
return;
|
||||||
|
close(hndl->netlink_fd);
|
||||||
|
free(hndl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rmnet_associate_network_device(rmnetctl_hndl_t *hndl,
|
||||||
|
const char *dev_name,
|
||||||
|
uint16_t *error_code,
|
||||||
|
uint8_t assoc_dev)
|
||||||
|
{
|
||||||
|
struct rmnet_nl_msg_s request, response;
|
||||||
|
int str_len = -1, return_code = RMNETCTL_LIB_ERR;
|
||||||
|
do {
|
||||||
|
if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name) ||
|
||||||
|
((assoc_dev != RMNETCTL_DEVICE_ASSOCIATE) &&
|
||||||
|
(assoc_dev != RMNETCTL_DEVICE_UNASSOCIATE))) {
|
||||||
|
return_code = RMNETCTL_INVALID_ARG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (assoc_dev == RMNETCTL_DEVICE_ASSOCIATE)
|
||||||
|
request.message_type = RMNET_NETLINK_ASSOCIATE_NETWORK_DEVICE;
|
||||||
|
else
|
||||||
|
request.message_type = RMNET_NETLINK_UNASSOCIATE_NETWORK_DEVICE;
|
||||||
|
|
||||||
|
request.arg_length = RMNET_MAX_STR_LEN;
|
||||||
|
str_len = strlcpy((char *)(request.data), dev_name, RMNET_MAX_STR_LEN);
|
||||||
|
if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ((*error_code = rmnetctl_transact(hndl, &request, &response))
|
||||||
|
!= RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
return_code = _rmnetctl_set_codes(response.return_code, error_code);
|
||||||
|
} while(0);
|
||||||
|
return return_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rmnet_get_network_device_associated(rmnetctl_hndl_t *hndl,
|
||||||
|
const char *dev_name,
|
||||||
|
int *register_status,
|
||||||
|
uint16_t *error_code) {
|
||||||
|
struct rmnet_nl_msg_s request, response;
|
||||||
|
int str_len = -1, return_code = RMNETCTL_LIB_ERR;
|
||||||
|
do {
|
||||||
|
if ((!hndl) || (!register_status) || (!error_code) ||
|
||||||
|
_rmnetctl_check_dev_name(dev_name)) {
|
||||||
|
return_code = RMNETCTL_INVALID_ARG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
request.message_type = RMNET_NETLINK_GET_NETWORK_DEVICE_ASSOCIATED;
|
||||||
|
|
||||||
|
request.arg_length = RMNET_MAX_STR_LEN;
|
||||||
|
str_len = strlcpy((char *)(request.data), dev_name, RMNET_MAX_STR_LEN);
|
||||||
|
if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ((*error_code = rmnetctl_transact(hndl, &request, &response))
|
||||||
|
!= RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
*register_status = response.return_code;
|
||||||
|
return_code = RMNETCTL_SUCCESS;
|
||||||
|
} while(0);
|
||||||
|
return return_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rmnet_set_link_egress_data_format(rmnetctl_hndl_t *hndl,
|
||||||
|
uint32_t egress_flags,
|
||||||
|
uint16_t agg_size,
|
||||||
|
uint16_t agg_count,
|
||||||
|
const char *dev_name,
|
||||||
|
uint16_t *error_code) {
|
||||||
|
struct rmnet_nl_msg_s request, response;
|
||||||
|
int str_len = -1, return_code = RMNETCTL_LIB_ERR;
|
||||||
|
do {
|
||||||
|
if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name)) {
|
||||||
|
return_code = RMNETCTL_INVALID_ARG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
request.message_type = RMNET_NETLINK_SET_LINK_EGRESS_DATA_FORMAT;
|
||||||
|
|
||||||
|
request.arg_length = RMNET_MAX_STR_LEN +
|
||||||
|
sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t);
|
||||||
|
str_len = strlcpy((char *)(request.data_format.dev),
|
||||||
|
dev_name,
|
||||||
|
RMNET_MAX_STR_LEN);
|
||||||
|
if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
request.data_format.flags = egress_flags;
|
||||||
|
request.data_format.agg_size = agg_size;
|
||||||
|
request.data_format.agg_count = agg_count;
|
||||||
|
|
||||||
|
if ((*error_code = rmnetctl_transact(hndl, &request, &response))
|
||||||
|
!= RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
return_code = _rmnetctl_set_codes(response.return_code, error_code);
|
||||||
|
} while(0);
|
||||||
|
return return_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rmnet_get_link_egress_data_format(rmnetctl_hndl_t *hndl,
|
||||||
|
const char *dev_name,
|
||||||
|
uint32_t *egress_flags,
|
||||||
|
uint16_t *agg_size,
|
||||||
|
uint16_t *agg_count,
|
||||||
|
uint16_t *error_code) {
|
||||||
|
struct rmnet_nl_msg_s request, response;
|
||||||
|
int str_len = -1, return_code = RMNETCTL_LIB_ERR;
|
||||||
|
do {
|
||||||
|
if ((!hndl) || (!egress_flags) || (!agg_size) || (!agg_count) ||
|
||||||
|
(!error_code) || _rmnetctl_check_dev_name(dev_name)) {
|
||||||
|
return_code = RMNETCTL_INVALID_ARG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
request.message_type = RMNET_NETLINK_GET_LINK_EGRESS_DATA_FORMAT;
|
||||||
|
|
||||||
|
request.arg_length = RMNET_MAX_STR_LEN;
|
||||||
|
str_len = strlcpy((char *)(request.data_format.dev),
|
||||||
|
dev_name,
|
||||||
|
RMNET_MAX_STR_LEN);
|
||||||
|
if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ((*error_code = rmnetctl_transact(hndl, &request, &response))
|
||||||
|
!= RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
*egress_flags = response.data_format.flags;
|
||||||
|
*agg_size = response.data_format.agg_size;
|
||||||
|
*agg_count = response.data_format.agg_count;
|
||||||
|
return_code = RMNETCTL_SUCCESS;
|
||||||
|
} while(0);
|
||||||
|
return return_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rmnet_set_link_ingress_data_format(rmnetctl_hndl_t *hndl,
|
||||||
|
uint32_t ingress_flags,
|
||||||
|
const char *dev_name,
|
||||||
|
uint16_t *error_code) {
|
||||||
|
struct rmnet_nl_msg_s request, response;
|
||||||
|
int str_len = -1, return_code = RMNETCTL_LIB_ERR;
|
||||||
|
do {
|
||||||
|
if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name)) {
|
||||||
|
return_code = RMNETCTL_INVALID_ARG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
request.message_type = RMNET_NETLINK_SET_LINK_INGRESS_DATA_FORMAT;
|
||||||
|
|
||||||
|
request.arg_length = RMNET_MAX_STR_LEN +
|
||||||
|
sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t);
|
||||||
|
str_len = strlcpy((char *)(request.data_format.dev),
|
||||||
|
dev_name,
|
||||||
|
RMNET_MAX_STR_LEN);
|
||||||
|
if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
request.data_format.flags = ingress_flags;
|
||||||
|
|
||||||
|
if ((*error_code = rmnetctl_transact(hndl, &request, &response))
|
||||||
|
!= RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
return_code = _rmnetctl_set_codes(response.return_code, error_code);
|
||||||
|
} while(0);
|
||||||
|
return return_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rmnet_get_link_ingress_data_format(rmnetctl_hndl_t *hndl,
|
||||||
|
const char *dev_name,
|
||||||
|
uint32_t *ingress_flags,
|
||||||
|
uint16_t *error_code) {
|
||||||
|
struct rmnet_nl_msg_s request, response;
|
||||||
|
int str_len = -1, return_code = RMNETCTL_LIB_ERR;
|
||||||
|
do {
|
||||||
|
if ((!hndl) || (!ingress_flags) || (!error_code) ||
|
||||||
|
_rmnetctl_check_dev_name(dev_name)) {
|
||||||
|
return_code = RMNETCTL_INVALID_ARG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
request.message_type = RMNET_NETLINK_GET_LINK_INGRESS_DATA_FORMAT;
|
||||||
|
|
||||||
|
request.arg_length = RMNET_MAX_STR_LEN;
|
||||||
|
str_len = strlcpy((char *)(request.data_format.dev),
|
||||||
|
dev_name,
|
||||||
|
RMNET_MAX_STR_LEN);
|
||||||
|
if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ((*error_code = rmnetctl_transact(hndl, &request, &response))
|
||||||
|
!= RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
*ingress_flags = response.data_format.flags;
|
||||||
|
return_code = RMNETCTL_SUCCESS;
|
||||||
|
} while(0);
|
||||||
|
return return_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rmnet_set_logical_ep_config(rmnetctl_hndl_t *hndl,
|
||||||
|
int32_t ep_id,
|
||||||
|
uint8_t operating_mode,
|
||||||
|
const char *dev_name,
|
||||||
|
const char *next_dev,
|
||||||
|
uint16_t *error_code) {
|
||||||
|
struct rmnet_nl_msg_s request, response;
|
||||||
|
int str_len = -1, return_code = RMNETCTL_LIB_ERR;
|
||||||
|
do {
|
||||||
|
if ((!hndl) || ((ep_id < -1) || (ep_id > 31)) || (!error_code) ||
|
||||||
|
_rmnetctl_check_dev_name(dev_name) ||
|
||||||
|
_rmnetctl_check_dev_name(next_dev)) {
|
||||||
|
return_code = RMNETCTL_INVALID_ARG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
request.message_type = RMNET_NETLINK_SET_LOGICAL_EP_CONFIG;
|
||||||
|
|
||||||
|
request.arg_length = RMNET_MAX_STR_LEN +
|
||||||
|
RMNET_MAX_STR_LEN + sizeof(int32_t) + sizeof(uint8_t);
|
||||||
|
str_len = strlcpy((char *)(request.local_ep_config.dev),
|
||||||
|
dev_name,
|
||||||
|
RMNET_MAX_STR_LEN);
|
||||||
|
if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
str_len = strlcpy((char *)(request.local_ep_config.next_dev),
|
||||||
|
next_dev,
|
||||||
|
RMNET_MAX_STR_LEN);
|
||||||
|
if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
request.local_ep_config.ep_id = ep_id;
|
||||||
|
request.local_ep_config.operating_mode = operating_mode;
|
||||||
|
|
||||||
|
if ((*error_code = rmnetctl_transact(hndl, &request, &response))
|
||||||
|
!= RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
return_code = _rmnetctl_set_codes(response.return_code, error_code);
|
||||||
|
} while(0);
|
||||||
|
return return_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rmnet_get_logical_ep_config(rmnetctl_hndl_t *hndl,
|
||||||
|
int32_t ep_id,
|
||||||
|
const char *dev_name,
|
||||||
|
uint8_t *operating_mode,
|
||||||
|
char **next_dev,
|
||||||
|
uint16_t *error_code) {
|
||||||
|
struct rmnet_nl_msg_s request, response;
|
||||||
|
int str_len = -1, return_code = RMNETCTL_LIB_ERR;
|
||||||
|
do {
|
||||||
|
if ((!hndl) || (!operating_mode) || (!error_code) || ((ep_id < -1) ||
|
||||||
|
(ep_id > 31)) || _rmnetctl_check_dev_name(dev_name) || (!next_dev)) {
|
||||||
|
return_code = RMNETCTL_INVALID_ARG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
request.message_type = RMNET_NETLINK_GET_LOGICAL_EP_CONFIG;
|
||||||
|
|
||||||
|
request.arg_length = RMNET_MAX_STR_LEN + sizeof(int32_t);
|
||||||
|
str_len = strlcpy((char *)(request.local_ep_config.dev),
|
||||||
|
dev_name,
|
||||||
|
RMNET_MAX_STR_LEN);
|
||||||
|
if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
request.local_ep_config.ep_id = ep_id;
|
||||||
|
|
||||||
|
if ((*error_code = rmnetctl_transact(hndl, &request, &response))
|
||||||
|
!= RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
if (_rmnetctl_check_data(response.crd, error_code) != RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
printf("%s\n", (char *)(response.local_ep_config.next_dev));
|
||||||
|
str_len = strlcpy(*next_dev,
|
||||||
|
(char *)(response.local_ep_config.next_dev),
|
||||||
|
RMNET_MAX_STR_LEN);
|
||||||
|
if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
*operating_mode = response.local_ep_config.operating_mode;
|
||||||
|
return_code = RMNETCTL_SUCCESS;
|
||||||
|
} while(0);
|
||||||
|
return return_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rmnet_new_vnd(rmnetctl_hndl_t *hndl,
|
||||||
|
uint32_t id,
|
||||||
|
uint16_t *error_code,
|
||||||
|
uint8_t new_vnd) {
|
||||||
|
struct rmnet_nl_msg_s request, response;
|
||||||
|
int return_code = RMNETCTL_LIB_ERR;
|
||||||
|
do {
|
||||||
|
if ((!hndl) || (!error_code) ||
|
||||||
|
((new_vnd != RMNETCTL_NEW_VND) && (new_vnd != RMNETCTL_FREE_VND))) {
|
||||||
|
return_code = RMNETCTL_INVALID_ARG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (new_vnd == RMNETCTL_NEW_VND)
|
||||||
|
request.message_type = RMNET_NETLINK_NEW_VND;
|
||||||
|
else
|
||||||
|
request.message_type = RMNET_NETLINK_FREE_VND;
|
||||||
|
|
||||||
|
request.arg_length = sizeof(uint32_t);
|
||||||
|
request.vnd.id = id;
|
||||||
|
|
||||||
|
if ((*error_code = rmnetctl_transact(hndl, &request, &response))
|
||||||
|
!= RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
return_code = _rmnetctl_set_codes(response.return_code, error_code);
|
||||||
|
} while(0);
|
||||||
|
return return_code;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user