1 /****************************************************************************** 2 3 L I B R M N E T C T L . H 4 5 Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. 6 7 Redistribution and use in source and binary forms, with or without 8 modification, are permitted provided that the following conditions are 9 met: 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 20 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 21 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 24 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 27 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 28 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 29 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 30 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 32 ******************************************************************************/ 33 34 /*! 35 * @file librmnetctl.h 36 * @brief rmnet control API's header file 37 */ 38 39 #ifndef LIBRMNETCTL_H 40 #define LIBRMNETCTL_H 41 42 /* RMNET API succeeded */ 43 #define RMNETCTL_SUCCESS 0 44 /* RMNET API encountered an error while executing within the library. Check the 45 * error code in this case */ 46 #define RMNETCTL_LIB_ERR 1 47 /* RMNET API encountered an error while executing in the kernel. Check the 48 * error code in this case */ 49 #define RMNETCTL_KERNEL_ERR 2 50 /* RMNET API encountered an error because of invalid arguments*/ 51 #define RMNETCTL_INVALID_ARG 3 52 53 /* Flag to associate a network device*/ 54 #define RMNETCTL_DEVICE_ASSOCIATE 1 55 /* Flag to unassociate a network device*/ 56 #define RMNETCTL_DEVICE_UNASSOCIATE 0 57 /* Flag to create a new virtual network device*/ 58 #define RMNETCTL_NEW_VND 1 59 /* Flag to free a new virtual network device*/ 60 #define RMNETCTL_FREE_VND 0 61 /* Flag to add a new flow*/ 62 #define RMNETCTL_ADD_FLOW 1 63 /* Flag to delete an existing flow*/ 64 #define RMNETCTL_DEL_FLOW 0 65 66 enum rmnetctl_error_codes_e { 67 /* API succeeded. This should always be the first element. */ 68 RMNETCTL_API_SUCCESS, 69 70 RMNETCTL_API_FIRST_ERR, 71 /* API failed because not enough memory to create buffer to send 72 * message */ 73 RMNETCTL_API_ERR_REQUEST_INVALID = RMNETCTL_API_FIRST_ERR, 74 /* API failed because not enough memory to create buffer for the 75 * response message */ 76 RMNETCTL_API_ERR_RESPONSE_INVALID, 77 /* API failed because could not send the message to kernel */ 78 RMNETCTL_API_ERR_MESSAGE_SEND, 79 /* API failed because could not receive message from the kernel */ 80 RMNETCTL_API_ERR_MESSAGE_RECEIVE, 81 82 RMNETCTL_INIT_FIRST_ERR, 83 /* Invalid process id. So return an error. */ 84 RMNETCTL_INIT_ERR_PROCESS_ID = RMNETCTL_INIT_FIRST_ERR, 85 /* Invalid socket descriptor id. So return an error. */ 86 RMNETCTL_INIT_ERR_NETLINK_FD, 87 /* Could not bind the socket to the Netlink file descriptor */ 88 RMNETCTL_INIT_ERR_BIND, 89 /* Invalid user id. Only root has access to this function. (NA) */ 90 RMNETCTL_INIT_ERR_INVALID_USER, 91 92 RMNETCTL_API_SECOND_ERR, 93 /* API failed because the RmNet handle for the transaction was NULL */ 94 RMNETCTL_API_ERR_HNDL_INVALID = RMNETCTL_API_SECOND_ERR, 95 /* API failed because the request buffer for the transaction was NULL */ 96 RMNETCTL_API_ERR_REQUEST_NULL, 97 /* API failed because the response buffer for the transaction was NULL*/ 98 RMNETCTL_API_ERR_RESPONSE_NULL, 99 /* API failed because the request and response type do not match*/ 100 RMNETCTL_API_ERR_MESSAGE_TYPE, 101 /* API failed because the return type is invalid */ 102 RMNETCTL_API_ERR_RETURN_TYPE, 103 /* API failed because the string was truncated */ 104 RMNETCTL_API_ERR_STRING_TRUNCATION, 105 106 /* These error are 1-to-1 with rmnet_data config errors in rmnet_data.h 107 for each conversion. 108 please keep the enums synced. 109 */ 110 RMNETCTL_KERNEL_FIRST_ERR, 111 /* No error */ 112 RMNETCTL_KERNEL_ERROR_NO_ERR = RMNETCTL_KERNEL_FIRST_ERR, 113 /* Invalid / unsupported message */ 114 RMNETCTL_KERNEL_ERR_UNKNOWN_MESSAGE, 115 /* Internal problem in the kernel modeule */ 116 RMNETCTL_KERNEL_ERR_INTERNAL, 117 /* Kernel is temporarely out of memory */ 118 RMNETCTL_KERNEL_ERR_OUT_OF_MEM, 119 /* Device already exists / Still in use */ 120 RMETNCTL_KERNEL_ERR_DEVICE_IN_USE, 121 /* Invalid request / Unsupported scenario */ 122 RMNETCTL_KERNEL_ERR_INVALID_REQUEST, 123 /* Device doesn't exist */ 124 RMNETCTL_KERNEL_ERR_NO_SUCH_DEVICE, 125 /* One or more of the arguments is invalid */ 126 RMNETCTL_KERNEL_ERR_BAD_ARGS, 127 /* Egress device is invalid */ 128 RMNETCTL_KERNEL_ERR_BAD_EGRESS_DEVICE, 129 /* TC handle is full */ 130 RMNETCTL_KERNEL_ERR_TC_HANDLE_FULL, 131 132 /* This should always be the last element */ 133 RMNETCTL_API_ERR_ENUM_LENGTH 134 }; 135 136 #define RMNETCTL_ERR_MSG_SIZE 100 137 138 /*! 139 * @brief Contains a list of error message from API 140 */ 141 char rmnetctl_error_code_text 142 [RMNETCTL_API_ERR_ENUM_LENGTH][RMNETCTL_ERR_MSG_SIZE] = { 143 "ERROR: API succeeded\n", 144 "ERROR: Unable to allocate the buffer to send message\n", 145 "ERROR: Unable to allocate the buffer to receive message\n", 146 "ERROR: Could not send the message to kernel\n", 147 "ERROR: Unable to receive message from the kernel\n", 148 "ERROR: Invalid process id\n", 149 "ERROR: Invalid socket descriptor id\n", 150 "ERROR: Could not bind to netlink socket\n", 151 "ERROR: Only root can access this API\n", 152 "ERROR: RmNet handle for the transaction was NULL\n", 153 "ERROR: Request buffer for the transaction was NULL\n", 154 "ERROR: Response buffer for the transaction was NULL\n", 155 "ERROR: Request and response type do not match\n", 156 "ERROR: Return type is invalid\n", 157 "ERROR: String was truncated\n", 158 /* Kernel errors */ 159 "ERROR: Kernel call succeeded\n", 160 "ERROR: Invalid / Unsupported directive\n", 161 "ERROR: Internal problem in the kernel module\n", 162 "ERROR: The kernel is temporarely out of memory\n", 163 "ERROR: Device already exists / Still in use\n", 164 "ERROR: Invalid request / Unsupported scenario\n", 165 "ERROR: Device doesn't exist\n", 166 "ERROR: One or more of the arguments is invalid\n", 167 "ERROR: Egress device is invalid\n", 168 "ERROR: TC handle is full\n" 169 }; 170 171 /*=========================================================================== 172 DEFINITIONS AND DECLARATIONS 173 ===========================================================================*/ 174 typedef struct rmnetctl_hndl_s rmnetctl_hndl_t; 175 176 /*! 177 * @brief Public API to initialize the RMNET control driver 178 * @details Allocates memory for the RmNet handle. Creates and binds to a and 179 * netlink socket if successful 180 * @param **rmnetctl_hndl_t_val RmNet handle to be initialized 181 * @return RMNETCTL_SUCCESS if successful 182 * @return RMNETCTL_LIB_ERR if there was a library error. Check error_code 183 * @return RMNETCTL_KERNEL_ERR if there was an error in the kernel. 184 * Check error_code 185 * @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API 186 */ 187 int rmnetctl_init(rmnetctl_hndl_t **hndl, uint16_t *error_code); 188 189 /*! 190 * @brief Public API to clean up the RmNeT control handle 191 * @details Close the socket and free the RmNet handle 192 * @param *rmnetctl_hndl_t_val RmNet handle to be initialized 193 * @return void 194 */ 195 void rmnetctl_cleanup(rmnetctl_hndl_t *hndl); 196 197 /*! 198 * @brief Public API to register/unregister a RMNET driver on a particular device 199 * @details Message type is RMNET_NETLINK_ASSOCIATE_NETWORK_DEVICE or 200 * RMNET_NETLINK_UNASSOCIATE_NETWORK_DEVICE based on the flag for assoc_dev 201 * @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message 202 * @param dev_name Device on which to register the RmNet driver 203 * @param error_code Status code of this operation 204 * @param assoc_dev registers the device if RMNETCTL_DEVICE_ASSOCIATE or 205 * unregisters the device if RMNETCTL_DEVICE_UNASSOCIATE 206 * @return RMNETCTL_SUCCESS if successful 207 * @return RMNETCTL_LIB_ERR if there was a library error. Check error_code 208 * @return RMNETCTL_KERNEL_ERR if there was an error in the kernel. 209 * Check error_code 210 * @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API 211 */ 212 int rmnet_associate_network_device(rmnetctl_hndl_t *hndl, 213 const char *dev_name, 214 uint16_t *error_code, 215 uint8_t assoc_dev); 216 217 /*! 218 * @brief Public API to get if a RMNET driver is registered on a particular 219 * device 220 * @details Message type is RMNET_NETLINK_GET_NETWORK_DEVICE_ASSOCIATED. 221 * @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message 222 * @param dev_name Device on which to check if the RmNet driver is registered 223 * @param register_status 1 if RmNet data driver is registered on a particular 224 * device, 0 if not 225 * @param error_code Status code of this operation 226 * @return RMNETCTL_SUCCESS if successful 227 * @return RMNETCTL_LIB_ERR if there was a library error. Check error_code 228 * @return RMNETCTL_KERNEL_ERR if there was an error in the kernel. 229 * Check error_code 230 * @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API 231 */ 232 int rmnet_get_network_device_associated(rmnetctl_hndl_t *hndl, 233 const char *dev_name, 234 int *register_status, 235 uint16_t *error_code); 236 237 /*! 238 * @brief Public API to set the egress data format for a particular link. 239 * @details Message type is RMNET_NETLINK_SET_LINK_EGRESS_DATA_FORMAT. 240 * @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message 241 * @param egress_flags Egress flags to be set on the device 242 * @param agg_size Max size of aggregated packets 243 * @param agg_count Number of packets to be aggregated 244 * @param dev_name Device on which to set the egress data format 245 * @param error_code Status code of this operation returned from the kernel 246 * @return RMNETCTL_SUCCESS if successful 247 * @return RMNETCTL_LIB_ERR if there was a library error. Check error_code 248 * @return RMNETCTL_KERNEL_ERR if there was an error in the kernel. 249 * Check error_code 250 * @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API 251 */ 252 int rmnet_set_link_egress_data_format(rmnetctl_hndl_t *hndl, 253 uint32_t egress_flags, 254 uint16_t agg_size, 255 uint16_t agg_count, 256 const char *dev_name, 257 uint16_t *error_code); 258 259 /*! 260 * @brief Public API to get the egress data format for a particular link. 261 * @details Message type is RMNET_NETLINK_GET_LINK_EGRESS_DATA_FORMAT. 262 * @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message 263 * @param dev_name Device on which to get the egress data format 264 * @param egress_flags Egress flags from the device 265 * @param agg_count Number of packets to be aggregated 266 * @param error_code Status code of this operation returned from the kernel 267 * @return RMNETCTL_SUCCESS if successful 268 * @return RMNETCTL_LIB_ERR if there was a library error. Check error_code 269 * @return RMNETCTL_KERNEL_ERR if there was an error in the kernel. 270 * Check error_code 271 * @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API 272 */ 273 int rmnet_get_link_egress_data_format(rmnetctl_hndl_t *hndl, 274 const char *dev_name, 275 uint32_t *egress_flags, 276 uint16_t *agg_size, 277 uint16_t *agg_count, 278 uint16_t *error_code); 279 280 /*! 281 * @brief Public API to set the ingress data format for a particular link. 282 * @details Message type is RMNET_NETLINK_SET_LINK_INGRESS_DATA_FORMAT. 283 * @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message 284 * @param ingress_flags Ingress flags from the device 285 * @param tail_spacing Tail spacing needed for the packet 286 * @param dev_name Device on which to set the ingress data format 287 * @param error_code Status code of this operation returned from the kernel 288 * @return RMNETCTL_SUCCESS if successful 289 * @return RMNETCTL_LIB_ERR if there was a library error. Check error_code 290 * @return RMNETCTL_KERNEL_ERR if there was an error in the kernel. 291 * Check error_code 292 * @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API 293 */ 294 int rmnet_set_link_ingress_data_format_tailspace(rmnetctl_hndl_t *hndl, 295 uint32_t ingress_flags, 296 uint8_t tail_spacing, 297 const char *dev_name, 298 uint16_t *error_code); 299 300 /*! 301 * @brief Public API to get the ingress data format for a particular link. 302 * @details Message type is RMNET_NETLINK_GET_LINK_INGRESS_DATA_FORMAT. 303 * @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message 304 * @param dev_name Device on which to get the ingress data format 305 * @param ingress_flags Ingress flags from the device 306 * @param tail_spacing Tail spacing needed for the packet 307 * @param error_code Status code of this operation returned from the kernel 308 * @return RMNETCTL_SUCCESS if successful 309 * @return RMNETCTL_LIB_ERR if there was a library error. Check error_code 310 * @return RMNETCTL_KERNEL_ERR if there was an error in the kernel. 311 * Check error_code 312 * @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API 313 */ 314 int rmnet_get_link_ingress_data_format_tailspace(rmnetctl_hndl_t *hndl, 315 const char *dev_name, 316 uint32_t *ingress_flags, 317 uint8_t *tail_spacing, 318 uint16_t *error_code); 319 320 inline int rmnet_set_link_ingress_data_format(rmnetctl_hndl_t *hndl, 321 uint32_t ingress_flags, 322 const char *dev_name, 323 uint16_t *error_code) 324 { 325 return rmnet_set_link_ingress_data_format_tailspace(hndl, 326 ingress_flags, 327 0, 328 dev_name, 329 error_code); 330 } 331 332 inline int rmnet_get_link_ingress_data_format(rmnetctl_hndl_t *hndl, 333 const char *dev_name, 334 uint32_t *ingress_flags, 335 uint16_t *error_code) 336 { 337 return rmnet_get_link_ingress_data_format_tailspace(hndl, 338 dev_name, 339 ingress_flags, 340 0, 341 error_code); 342 } 343 344 /*! 345 * @brief Public API to set the logical endpoint configuration for a 346 * particular link. 347 * @details Message type is RMNET_NETLINK_SET_LOGICAL_EP_CONFIG. 348 * @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message 349 * @param logical_ep_id Logical end point id on which the configuration is to be 350 * set 351 * @param rmnet_mode RmNet mode to be set on the device 352 * @param dev_name Device on which to set the logical end point configuration 353 * @param egress_dev_name Egress Device if operating in bridge mode 354 * @param error_code Status code of this operation returned from the kernel 355 * @return RMNETCTL_SUCCESS if successful 356 * @return RMNETCTL_LIB_ERR if there was a library error. Check error_code 357 * @return RMNETCTL_KERNEL_ERR if there was an error in the kernel. 358 * Check error_code 359 * @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API 360 */ 361 int rmnet_set_logical_ep_config(rmnetctl_hndl_t *hndl, 362 int32_t ep_id, 363 uint8_t operating_mode, 364 const char *dev_name, 365 const char *next_dev, 366 uint16_t *error_code); 367 368 /*! 369 * @brief Public API to un-set the logical endpoint configuration for a 370 * particular link. 371 * @details Message type is RMNET_NETLINK_UNSET_LOGICAL_EP_CONFIG. 372 * @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message 373 * @param logical_ep_id Logical end point id on which the configuration is to be 374 * un-set 375 * @param dev_name Device on which to un-set the logical end point configuration 376 * @param error_code Status code of this operation returned from the kernel 377 * @return RMNETCTL_SUCCESS if successful 378 * @return RMNETCTL_LIB_ERR if there was a library error. Check error_code 379 * @return RMNETCTL_KERNEL_ERR if there was an error in the kernel. 380 * Check error_code 381 * @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API 382 */ 383 int rmnet_unset_logical_ep_config(rmnetctl_hndl_t *hndl, 384 int32_t ep_id, 385 const char *dev_name, 386 uint16_t *error_code); 387 /*! 388 * @brief Public API to get the logical endpoint configuration for a 389 * particular link. 390 * @details Message type is RMNET_NETLINK_GET_LOGICAL_EP_CONFIG. 391 * @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message 392 * @param logical_ep_id Logical end point id from which to get the configuration 393 * @param dev_name Device on which to get the logical end point configuration 394 * @param rmnet_mode RmNet mode from the device 395 * @param next_dev Egress Device name 396 * @param next_dev_len Egress Device I/O string len 397 * @param error_code Status code of this operation returned from the kernel 398 * @return RMNETCTL_SUCCESS if successful 399 * @return RMNETCTL_LIB_ERR if there was a library error. Check error_code 400 * @return RMNETCTL_KERNEL_ERR if there was an error in the kernel. 401 * Check error_code 402 * @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API 403 */ 404 int rmnet_get_logical_ep_config(rmnetctl_hndl_t *hndl, 405 int32_t ep_id, 406 const char *dev_name, 407 uint8_t *operating_mode, 408 char **next_dev, 409 uint32_t next_dev_len, 410 uint16_t *error_code); 411 412 /*! 413 * @brief Public API to create a new virtual device node 414 * @details Message type is RMNET_NETLINK_NEW_VND or 415 * RMNETCTL_FREE_VND based on the flag for new_vnd 416 * @param hndl RmNet handle for the Netlink message 417 * @param id Node number to create the virtual network device node 418 * @param error_code Status code of this operation returned from the kernel 419 * @param new_vnd creates a new virtual network device if RMNETCTL_NEW_VND or 420 * frees the device if RMNETCTL_FREE_VND 421 * @return RMNETCTL_SUCCESS if successful 422 * @return RMNETCTL_LIB_ERR if there was a library error. Check error_code 423 * @return RMNETCTL_KERNEL_ERR if there was an error in the kernel. 424 * Check error_code 425 * @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API 426 */ 427 int rmnet_new_vnd(rmnetctl_hndl_t *hndl, 428 uint32_t id, 429 uint16_t *error_code, 430 uint8_t new_vnd); 431 432 /*! 433 * @brief Public API to create a new virtual device node with a custom prefix 434 * @details Message type is RMNET_NETLINK_NEW_VND or 435 * RMNETCTL_FREE_VND based on the flag for new_vnd 436 * @param hndl RmNet handle for the Netlink message 437 * @param id Node number to create the virtual network device node 438 * @param error_code Status code of this operation returned from the kernel 439 * @param new_vnd creates a new virtual network device if RMNETCTL_NEW_VND or 440 * frees the device if RMNETCTL_FREE_VND 441 * @param prefix Prefix to be used when naming the network interface 442 * @return RMNETCTL_SUCCESS if successful 443 * @return RMNETCTL_LIB_ERR if there was a library error. Check error_code 444 * @return RMNETCTL_KERNEL_ERR if there was an error in the kernel. 445 * Check error_code 446 * @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API 447 */ 448 int rmnet_new_vnd_prefix(rmnetctl_hndl_t *hndl, 449 uint32_t id, 450 uint16_t *error_code, 451 uint8_t new_vnd, 452 const char *prefix); 453 /*! 454 * @brief API to get the ASCII name of a virtual network device from its ID 455 * @param hndl RmNet handle for the Netlink message 456 * @param id Node number to create the virtual network device node 457 * @param error_code Status code of this operation returned from the kernel 458 * @param buf Buffer to store ASCII representation of device name 459 * @param buflen Length of the buffer 460 * @param prefix Prefix to be used when naming the network interface 461 * @return RMNETCTL_SUCCESS if successful 462 * @return RMNETCTL_LIB_ERR if there was a library error. Check error_code 463 * @return RMNETCTL_KERNEL_ERR if there was an error in the kernel. 464 * Check error_code 465 * @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API 466 */ 467 468 int rmnet_get_vnd_name(rmnetctl_hndl_t *hndl, 469 uint32_t id, 470 uint16_t *error_code, 471 char *buf, 472 uint32_t buflen); 473 474 /*! 475 * @brief Public API to set or clear a flow 476 * @details Message type is RMNET_NETLINK_ADD_VND_TC_FLOW or 477 * RMNET_NETLINK_DEL_VND_TC_FLOW based on the flag for set_flow 478 * @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message 479 * @param id Node number to set or clear the flow on the virtual network 480 * device node 481 * @param map_flow_id Flow handle of the modem 482 * @param tc_flow_id Software flow handle 483 * @param set_flow sets the flow if RMNET_NETLINK_SET_FLOW or 484 * clears the flow if RMNET_NETLINK_CLEAR_FLOW 485 * @return RMNETCTL_SUCCESS if successful 486 * @return RMNETCTL_LIB_ERR if there was a library error. Check error_code 487 * @return RMNETCTL_KERNEL_ERR if there was an error in the kernel. 488 * Check error_code 489 * @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API 490 */ 491 int rmnet_add_del_vnd_tc_flow(rmnetctl_hndl_t *hndl, 492 uint32_t id, 493 uint32_t map_flow_id, 494 uint32_t tc_flow_id, 495 uint8_t set_flow, 496 uint16_t *error_code); 497 498 #endif /* not defined LIBRMNETCTL_H */ 499 500