blob: 8ad1874bd93006372bf2aa36220c3a3b823c8e4a [file] [log] [blame]
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -06001/******************************************************************************
2
3 L I B R M N E T C T L . C
4
Sean Tranchetti51133f52019-02-12 12:54:34 -07005Copyright (c) 2013-2015, 2017-2019 The Linux Foundation. All rights reserved.
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -06006
7Redistribution and use in source and binary forms, with or without
8modification, are permitted provided that the following conditions are
9met:
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above
13 copyright notice, this list of conditions and the following
14 disclaimer in the documentation and/or other materials provided
15 with the distribution.
16 * Neither the name of The Linux Foundation nor the names of its
17 contributors may be used to endorse or promote products derived
18 from this software without specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32******************************************************************************/
33
34/*!
35* @file librmnetctl.c
Subash Abhinov Kasiviswanathancf715082015-04-14 13:51:59 -060036* @brief rmnet control API's implementation file
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -060037*/
38
39/*===========================================================================
40 INCLUDE FILES
41===========================================================================*/
42
43#include <sys/socket.h>
44#include <stdint.h>
45#include <linux/netlink.h>
46#include <string.h>
47#include <stdio.h>
48#include <unistd.h>
49#include <stdlib.h>
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -070050#include <errno.h>
51#include <linux/rtnetlink.h>
52#include <linux/gen_stats.h>
53#include <net/if.h>
54#include <asm/types.h>
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -060055#include <linux/rmnet_data.h>
56#include "librmnetctl_hndl.h"
57#include "librmnetctl.h"
58
Harout Hedeshian04d69732013-10-02 09:29:11 -060059#ifdef USE_GLIB
60#include <glib.h>
61#define strlcpy g_strlcpy
62#endif
63
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -060064#define RMNETCTL_SOCK_FLAG 0
65#define ROOT_USER_ID 0
66#define MIN_VALID_PROCESS_ID 0
67#define MIN_VALID_SOCKET_FD 0
68#define KERNEL_PROCESS_ID 0
69#define UNICAST 0
70#define MAX_BUF_SIZE sizeof(struct nlmsghdr) + sizeof(struct rmnet_nl_msg_s)
Harout Hedeshian77825572014-02-17 10:47:14 +020071#define INGRESS_FLAGS_MASK (RMNET_INGRESS_FIX_ETHERNET | \
72 RMNET_INGRESS_FORMAT_MAP | \
73 RMNET_INGRESS_FORMAT_DEAGGREGATION | \
74 RMNET_INGRESS_FORMAT_DEMUXING | \
Sivan Reinsteinc22a0d82014-07-13 16:58:21 +030075 RMNET_INGRESS_FORMAT_MAP_COMMANDS | \
Subash Abhinov Kasiviswanathan21e5e442015-09-03 20:07:53 -060076 RMNET_INGRESS_FORMAT_MAP_CKSUMV3 | \
77 RMNET_INGRESS_FORMAT_MAP_CKSUMV4)
Harout Hedeshian77825572014-02-17 10:47:14 +020078#define EGRESS_FLAGS_MASK (RMNET_EGRESS_FORMAT__RESERVED__ | \
79 RMNET_EGRESS_FORMAT_MAP | \
80 RMNET_EGRESS_FORMAT_AGGREGATION | \
Sivan Reinsteina3c57172014-09-10 14:11:58 +030081 RMNET_EGRESS_FORMAT_MUXING | \
Subash Abhinov Kasiviswanathan21e5e442015-09-03 20:07:53 -060082 RMNET_EGRESS_FORMAT_MAP_CKSUMV3 | \
83 RMNET_EGRESS_FORMAT_MAP_CKSUMV4)
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -060084
Harout Hedeshian77825572014-02-17 10:47:14 +020085#define min(a, b) (((a) < (b)) ? (a) : (b))
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -070086#define NLMSG_TAIL(nmsg) \
87 ((struct rtattr *) (((char *)(nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
88
Subash Abhinov Kasiviswanathanc26ed592018-06-15 15:38:27 -070089#define NLMSG_DATA_SIZE 500
90
91#define CHECK_MEMSCPY(x) ({if (x < 0 ){return RMNETCTL_LIB_ERR;}})
92
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -070093struct nlmsg {
94 struct nlmsghdr nl_addr;
95 struct ifinfomsg ifmsg;
Subash Abhinov Kasiviswanathanc26ed592018-06-15 15:38:27 -070096 char data[NLMSG_DATA_SIZE];
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -070097};
98
Sean Tranchetti6cac2892019-04-19 11:04:57 -060099struct rmnetctl_uplink_params {
100 uint16_t byte_count;
Subash Abhinov Kasiviswanathana0c4bfb2019-08-14 11:26:52 -0600101 uint8_t packet_count;
102 uint8_t features;
Sean Tranchetti6cac2892019-04-19 11:04:57 -0600103 uint32_t time_limit;
104};
105
Sean Tranchetti037065c2019-04-19 11:04:43 -0600106/* IFLA Attributes for the RT RmNet driver */
107enum {
108 RMNETCTL_IFLA_UNSPEC,
109 RMNETCTL_IFLA_MUX_ID,
110 RMNETCTL_IFLA_FLAGS,
111 RMNETCTL_IFLA_DFC_QOS,
Sean Tranchetti6cac2892019-04-19 11:04:57 -0600112 RMNETCTL_IFLA_UPLINK_PARAMS,
Sean Tranchetti037065c2019-04-19 11:04:43 -0600113 __RMNETCTL_IFLA_MAX,
114};
115
Sean Tranchetti4fb72942019-02-12 15:36:30 -0700116/* Flow message types sent to DFC driver */
117enum {
118 /* Activate flow */
119 RMNET_FLOW_MSG_ACTIVATE = 1,
120 /* Delete flow */
121 RMNET_FLOW_MSG_DEACTIVATE = 2,
122 /* Legacy flow control */
123 RMNET_FLOW_MSG_CONTROL = 3,
124 /* Flow up */
125 RMNET_FLOW_MSG_UP = 4,
126 /* Flow down */
127 RMNET_FLOW_MSG_DOWN = 5,
Sean Tranchettif74a76a2018-12-18 15:28:08 -0700128 /* Change ACK scaling */
129 RMNET_FLOW_MSG_QMI_SCALE = 6,
130 /* Change powersave workqueue polling freq */
131 RMNET_FLOW_MSG_WDA_FREQ = 7,
Sean Tranchetti4fb72942019-02-12 15:36:30 -0700132};
133
Subash Abhinov Kasiviswanathandb2b6da2019-10-17 17:10:49 -0700134/* 0 reserved, 1-15 for data, 16-30 for acks */
135#define RMNETCTL_NUM_TX_QUEUES 31
Subash Abhinov Kasiviswanathancf3f8902018-08-30 14:23:08 -0600136
137/* This needs to be hardcoded here because some legacy linux systems
138 * do not have this definition
139 */
140#define RMNET_IFLA_NUM_TX_QUEUES 31
141
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600142/*===========================================================================
143 LOCAL FUNCTION DEFINITIONS
144===========================================================================*/
Subash Abhinov Kasiviswanathanc26ed592018-06-15 15:38:27 -0700145/* Helper functions
146 * @brief helper function to implement a secure memcpy
147 * @details take source and destination buffer size into
148 * considerations before copying
149 * @param dst destination buffer
150 * @param dst_size size of destination buffer
151 * @param src source buffer
152 * @param src_size size of source buffer
153 * @return size of the smallest of two buffer
154 */
155
156static inline size_t memscpy(void *dst, size_t dst_size, const void *src,
157 size_t src_size) {
158 size_t min_size = dst_size < src_size ? dst_size : src_size;
159 memcpy(dst, src, min_size);
160 return min_size;
161}
162
163/*
164* @brief helper function to implement a secure memcpy
165 * for a concatenating buffer where offset is kept
166 * track of
167 * @details take source and destination buffer size into
168 * considerations before copying
169 * @param dst destination buffer
170 * @param dst_size pointer used to decrement
171 * @param src source buffer
172 * @param src_size size of source buffer
173 * @return size of the remaining buffer
174 */
175
176
177static inline int memscpy_repeat(void* dst, size_t *dst_size,
178 const void* src, size_t src_size)
179{
180 if( !dst_size || *dst_size <= src_size || !dst || !src)
181 return RMNETCTL_LIB_ERR;
182 else {
183 *dst_size -= memscpy(dst, *dst_size, src, src_size);
184 }
185 return *dst_size;
186}
187
188
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600189/*!
190* @brief Synchronous method to send and receive messages to and from the kernel
191* using netlink sockets
192* @details Increments the transaction id for each message sent to the kernel.
193* Sends the netlink message to the kernel and receives the response from the
194* kernel.
195* @param *hndl RmNet handle for this transaction
196* @param request Message to be sent to the kernel
197* @param response Message received from the kernel
198* @return RMNETCTL_API_SUCCESS if successfully able to send and receive message
199* from the kernel
200* @return RMNETCTL_API_ERR_HNDL_INVALID if RmNet handle for the transaction was
201* NULL
202* @return RMNETCTL_API_ERR_REQUEST_NULL not enough memory to create buffer for
203* sending the message
204* @return RMNETCTL_API_ERR_MESSAGE_SEND if could not send the message to kernel
205* @return RMNETCTL_API_ERR_MESSAGE_RECEIVE if could not receive message from the
206* kernel
207* @return RMNETCTL_API_ERR_MESSAGE_TYPE if the request and response type do not
208* match
209*/
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700210static uint16_t rmnetctl_transact(rmnetctl_hndl_t *hndl,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600211 struct rmnet_nl_msg_s *request,
212 struct rmnet_nl_msg_s *response) {
213 uint8_t *request_buf, *response_buf;
214 struct nlmsghdr *nlmsghdr_val;
215 struct rmnet_nl_msg_s *rmnet_nl_msg_s_val;
Subash Abhinov Kasiviswanathanc26ed592018-06-15 15:38:27 -0700216 ssize_t bytes_read = -1, buffsize = MAX_BUF_SIZE - sizeof(struct nlmsghdr);
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700217 uint16_t return_code = RMNETCTL_API_ERR_HNDL_INVALID;
218 struct sockaddr_nl* __attribute__((__may_alias__)) saddr_ptr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600219 request_buf = NULL;
220 response_buf = NULL;
221 nlmsghdr_val = NULL;
222 rmnet_nl_msg_s_val = NULL;
223 do {
224 if (!hndl){
225 break;
226 }
227 if (!request){
228 return_code = RMNETCTL_API_ERR_REQUEST_NULL;
229 break;
230 }
231 if (!response){
232 return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
233 break;
234 }
235 request_buf = (uint8_t *)malloc(MAX_BUF_SIZE * sizeof(uint8_t));
236 if (!request_buf){
237 return_code = RMNETCTL_API_ERR_REQUEST_NULL;
238 break;
239 }
240
241 response_buf = (uint8_t *)malloc(MAX_BUF_SIZE * sizeof(uint8_t));
242 if (!response_buf) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600243 return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
244 break;
245 }
246
247 nlmsghdr_val = (struct nlmsghdr *)request_buf;
248 rmnet_nl_msg_s_val = (struct rmnet_nl_msg_s *)NLMSG_DATA(request_buf);
249
250 memset(request_buf, 0, MAX_BUF_SIZE*sizeof(uint8_t));
251 memset(response_buf, 0, MAX_BUF_SIZE*sizeof(uint8_t));
252
253 nlmsghdr_val->nlmsg_seq = hndl->transaction_id;
254 nlmsghdr_val->nlmsg_pid = hndl->pid;
255 nlmsghdr_val->nlmsg_len = MAX_BUF_SIZE;
256
Subash Abhinov Kasiviswanathanc26ed592018-06-15 15:38:27 -0700257 memscpy((void *)NLMSG_DATA(request_buf), buffsize, request,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600258 sizeof(struct rmnet_nl_msg_s));
259
260 rmnet_nl_msg_s_val->crd = RMNET_NETLINK_MSG_COMMAND;
261 hndl->transaction_id++;
262
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700263 saddr_ptr = &hndl->dest_addr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600264 socklen_t addrlen = sizeof(struct sockaddr_nl);
265 if (sendto(hndl->netlink_fd,
266 request_buf,
267 MAX_BUF_SIZE,
268 RMNETCTL_SOCK_FLAG,
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700269 (struct sockaddr*)saddr_ptr,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600270 sizeof(struct sockaddr_nl)) < 0) {
271 return_code = RMNETCTL_API_ERR_MESSAGE_SEND;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600272 break;
273 }
274
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700275 saddr_ptr = &hndl->src_addr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600276 bytes_read = recvfrom(hndl->netlink_fd,
277 response_buf,
278 MAX_BUF_SIZE,
279 RMNETCTL_SOCK_FLAG,
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700280 (struct sockaddr*)saddr_ptr,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600281 &addrlen);
282 if (bytes_read < 0) {
283 return_code = RMNETCTL_API_ERR_MESSAGE_RECEIVE;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600284 break;
285 }
Subash Abhinov Kasiviswanathanc26ed592018-06-15 15:38:27 -0700286 buffsize = MAX_BUF_SIZE - sizeof(struct nlmsghdr);
287 memscpy(response, buffsize, (void *)NLMSG_DATA(response_buf),
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600288 sizeof(struct rmnet_nl_msg_s));
289 if (sizeof(*response) < sizeof(struct rmnet_nl_msg_s)) {
290 return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600291 break;
292 }
293
294 if (request->message_type != response->message_type) {
295 return_code = RMNETCTL_API_ERR_MESSAGE_TYPE;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600296 break;
297 }
298 return_code = RMNETCTL_SUCCESS;
299 } while(0);
Harout Hedeshian77825572014-02-17 10:47:14 +0200300 free(request_buf);
301 free(response_buf);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600302 return return_code;
303}
304
305/*!
306* @brief Static function to check the dev name
307* @details Checks if the name is not NULL and if the name is less than the
308* RMNET_MAX_STR_LEN
309* @param dev_name Name of the device
310* @return RMNETCTL_SUCCESS if successful
311* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
312*/
313static inline int _rmnetctl_check_dev_name(const char *dev_name) {
314 int return_code = RMNETCTL_INVALID_ARG;
315 do {
316 if (!dev_name)
317 break;
318 if (strlen(dev_name) >= RMNET_MAX_STR_LEN)
319 break;
320 return_code = RMNETCTL_SUCCESS;
321 } while(0);
322 return return_code;
323}
324
325/*!
326* @brief Static function to check the string length after a copy
327* @details Checks if the string length is not lesser than zero and lesser than
328* RMNET_MAX_STR_LEN
329* @param str_len length of the string after a copy
330* @param error_code Status code of this operation
331* @return RMNETCTL_SUCCESS if successful
332* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
333*/
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700334static inline int _rmnetctl_check_len(size_t str_len, uint16_t *error_code) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600335 int return_code = RMNETCTL_LIB_ERR;
336 do {
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700337 if (str_len > RMNET_MAX_STR_LEN) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600338 *error_code = RMNETCTL_API_ERR_STRING_TRUNCATION;
339 break;
340 }
341 return_code = RMNETCTL_SUCCESS;
342 } while(0);
343 return return_code;
344}
345
346/*!
347* @brief Static function to check the response type
348* @details Checks if the response type of this message was return code
349* @param crd The crd field passed
350* @param error_code Status code of this operation
351* @return RMNETCTL_SUCCESS if successful
352* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
353*/
354static inline int _rmnetctl_check_code(int crd, uint16_t *error_code) {
355 int return_code = RMNETCTL_LIB_ERR;
356 do {
357 if (crd != RMNET_NETLINK_MSG_RETURNCODE) {
358 *error_code = RMNETCTL_API_ERR_RETURN_TYPE;
359 break;
360 }
361 return_code = RMNETCTL_SUCCESS;
362 } while(0);
363 return return_code;
364}
365
366/*!
367* @brief Static function to check the response type
368* @details Checks if the response type of this message was data
369* @param crd The crd field passed
370* @param error_code Status code of this operation
371* @return RMNETCTL_SUCCESS if successful
372* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
373*/
374static inline int _rmnetctl_check_data(int crd, uint16_t *error_code) {
375 int return_code = RMNETCTL_LIB_ERR;
376 do {
377 if (crd != RMNET_NETLINK_MSG_RETURNDATA) {
378 *error_code = RMNETCTL_API_ERR_RETURN_TYPE;
379 break;
380 }
381 return_code = RMNETCTL_SUCCESS;
382 } while(0);
383 return return_code;
384}
385
386/*!
387* @brief Static function to set the return value
388* @details Checks if the error_code from the transaction is zero for a return
389* code type message and sets the message type as RMNETCTL_SUCCESS
390* @param crd The crd field passed
391* @param error_code Status code of this operation
392* @return RMNETCTL_SUCCESS if successful
393* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
394* Check error_code
395*/
396static inline int _rmnetctl_set_codes(int error_val, uint16_t *error_code) {
397 int return_code = RMNETCTL_KERNEL_ERR;
Harout Hedeshian77825572014-02-17 10:47:14 +0200398 if (error_val == RMNET_CONFIG_OK)
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600399 return_code = RMNETCTL_SUCCESS;
Harout Hedeshian77825572014-02-17 10:47:14 +0200400 else
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700401 *error_code = (uint16_t)error_val + RMNETCTL_KERNEL_FIRST_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600402 return return_code;
403}
404
405/*===========================================================================
406 EXPOSED API
407===========================================================================*/
408
409int rmnetctl_init(rmnetctl_hndl_t **hndl, uint16_t *error_code)
410{
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700411 pid_t pid = 0;
412 int netlink_fd = -1, return_code = RMNETCTL_LIB_ERR;
413 struct sockaddr_nl* __attribute__((__may_alias__)) saddr_ptr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600414 do {
415 if ((!hndl) || (!error_code)){
416 return_code = RMNETCTL_INVALID_ARG;
417 break;
418 }
419
420 *hndl = (rmnetctl_hndl_t *)malloc(sizeof(rmnetctl_hndl_t));
421 if (!*hndl) {
422 *error_code = RMNETCTL_API_ERR_HNDL_INVALID;
423 break;
424 }
425
426 memset(*hndl, 0, sizeof(rmnetctl_hndl_t));
427
428 pid = getpid();
429 if (pid < MIN_VALID_PROCESS_ID) {
430 free(*hndl);
431 *error_code = RMNETCTL_INIT_ERR_PROCESS_ID;
432 break;
433 }
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700434 (*hndl)->pid = (uint32_t)pid;
Conner Huff1ecd2d82018-04-20 11:12:35 -0700435 netlink_fd = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, RMNET_NETLINK_PROTO);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600436 if (netlink_fd < MIN_VALID_SOCKET_FD) {
437 free(*hndl);
438 *error_code = RMNETCTL_INIT_ERR_NETLINK_FD;
439 break;
440 }
441
442 (*hndl)->netlink_fd = netlink_fd;
443
444 memset(&(*hndl)->src_addr, 0, sizeof(struct sockaddr_nl));
445
446 (*hndl)->src_addr.nl_family = AF_NETLINK;
447 (*hndl)->src_addr.nl_pid = (*hndl)->pid;
448
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700449 saddr_ptr = &(*hndl)->src_addr;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600450 if (bind((*hndl)->netlink_fd,
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700451 (struct sockaddr*)saddr_ptr,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600452 sizeof(struct sockaddr_nl)) < 0) {
453 close((*hndl)->netlink_fd);
454 free(*hndl);
455 *error_code = RMNETCTL_INIT_ERR_BIND;
456 break;
457 }
458
459 memset(&(*hndl)->dest_addr, 0, sizeof(struct sockaddr_nl));
460
461 (*hndl)->dest_addr.nl_family = AF_NETLINK;
462 (*hndl)->dest_addr.nl_pid = KERNEL_PROCESS_ID;
463 (*hndl)->dest_addr.nl_groups = UNICAST;
464
465 return_code = RMNETCTL_SUCCESS;
466 } while(0);
467 return return_code;
468}
469
470void rmnetctl_cleanup(rmnetctl_hndl_t *hndl)
471{
472 if (!hndl)
473 return;
474 close(hndl->netlink_fd);
475 free(hndl);
476}
477
478int rmnet_associate_network_device(rmnetctl_hndl_t *hndl,
479 const char *dev_name,
480 uint16_t *error_code,
481 uint8_t assoc_dev)
482{
483 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700484 size_t str_len = 0;
485 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600486 do {
487 if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name) ||
488 ((assoc_dev != RMNETCTL_DEVICE_ASSOCIATE) &&
489 (assoc_dev != RMNETCTL_DEVICE_UNASSOCIATE))) {
490 return_code = RMNETCTL_INVALID_ARG;
491 break;
492 }
493
494 if (assoc_dev == RMNETCTL_DEVICE_ASSOCIATE)
495 request.message_type = RMNET_NETLINK_ASSOCIATE_NETWORK_DEVICE;
496 else
497 request.message_type = RMNET_NETLINK_UNASSOCIATE_NETWORK_DEVICE;
498
499 request.arg_length = RMNET_MAX_STR_LEN;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700500 str_len = strlcpy((char *)(request.data), dev_name, (size_t)RMNET_MAX_STR_LEN);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600501 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
502 break;
503
504 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
505 != RMNETCTL_SUCCESS)
506 break;
507 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
508 break;
509 return_code = _rmnetctl_set_codes(response.return_code, error_code);
510 } while(0);
511 return return_code;
512}
513
514int rmnet_get_network_device_associated(rmnetctl_hndl_t *hndl,
515 const char *dev_name,
516 int *register_status,
517 uint16_t *error_code) {
518 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700519 size_t str_len = 0;
520 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600521 do {
522 if ((!hndl) || (!register_status) || (!error_code) ||
523 _rmnetctl_check_dev_name(dev_name)) {
524 return_code = RMNETCTL_INVALID_ARG;
525 break;
526 }
527
528 request.message_type = RMNET_NETLINK_GET_NETWORK_DEVICE_ASSOCIATED;
529
530 request.arg_length = RMNET_MAX_STR_LEN;
531 str_len = strlcpy((char *)(request.data), dev_name, RMNET_MAX_STR_LEN);
532 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
533 break;
534
535 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
536 != RMNETCTL_SUCCESS)
537 break;
538
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600539 if (_rmnetctl_check_data(response.crd, error_code)
540 != RMNETCTL_SUCCESS) {
541 if (_rmnetctl_check_code(response.crd, error_code)
542 == RMNETCTL_SUCCESS)
543 return_code = _rmnetctl_set_codes(response.return_code,
544 error_code);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600545 break;
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600546 }
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600547
548 *register_status = response.return_code;
549 return_code = RMNETCTL_SUCCESS;
550 } while(0);
551 return return_code;
552}
553
554int rmnet_set_link_egress_data_format(rmnetctl_hndl_t *hndl,
555 uint32_t egress_flags,
556 uint16_t agg_size,
557 uint16_t agg_count,
558 const char *dev_name,
559 uint16_t *error_code) {
560 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700561 size_t str_len = 0;
562 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600563 do {
Harout Hedeshian77825572014-02-17 10:47:14 +0200564 if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name) ||
565 ((~EGRESS_FLAGS_MASK) & egress_flags)) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600566 return_code = RMNETCTL_INVALID_ARG;
567 break;
568 }
569
570 request.message_type = RMNET_NETLINK_SET_LINK_EGRESS_DATA_FORMAT;
571
572 request.arg_length = RMNET_MAX_STR_LEN +
573 sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t);
574 str_len = strlcpy((char *)(request.data_format.dev),
575 dev_name,
576 RMNET_MAX_STR_LEN);
577 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
578 break;
579
580 request.data_format.flags = egress_flags;
581 request.data_format.agg_size = agg_size;
582 request.data_format.agg_count = agg_count;
583
584 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
585 != RMNETCTL_SUCCESS)
586 break;
587
588 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
589 break;
590
591 return_code = _rmnetctl_set_codes(response.return_code, error_code);
592 } while(0);
593 return return_code;
594}
595
596int rmnet_get_link_egress_data_format(rmnetctl_hndl_t *hndl,
597 const char *dev_name,
598 uint32_t *egress_flags,
599 uint16_t *agg_size,
600 uint16_t *agg_count,
601 uint16_t *error_code) {
602 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700603 size_t str_len = 0;
604 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600605 do {
606 if ((!hndl) || (!egress_flags) || (!agg_size) || (!agg_count) ||
607 (!error_code) || _rmnetctl_check_dev_name(dev_name)) {
608 return_code = RMNETCTL_INVALID_ARG;
609 break;
610 }
611 request.message_type = RMNET_NETLINK_GET_LINK_EGRESS_DATA_FORMAT;
612
613 request.arg_length = RMNET_MAX_STR_LEN;
614 str_len = strlcpy((char *)(request.data_format.dev),
615 dev_name,
616 RMNET_MAX_STR_LEN);
617 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
618 break;
619
620 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
621 != RMNETCTL_SUCCESS)
622 break;
623
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600624 if (_rmnetctl_check_data(response.crd, error_code)
625 != RMNETCTL_SUCCESS) {
626 if (_rmnetctl_check_code(response.crd, error_code)
627 == RMNETCTL_SUCCESS)
628 return_code = _rmnetctl_set_codes(response.return_code,
629 error_code);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600630 break;
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600631 }
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600632
633 *egress_flags = response.data_format.flags;
634 *agg_size = response.data_format.agg_size;
635 *agg_count = response.data_format.agg_count;
636 return_code = RMNETCTL_SUCCESS;
637 } while(0);
638 return return_code;
639}
640
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700641int rmnet_set_link_ingress_data_format_tailspace(rmnetctl_hndl_t *hndl,
642 uint32_t ingress_flags,
643 uint8_t tail_spacing,
644 const char *dev_name,
645 uint16_t *error_code) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600646 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700647 size_t str_len = 0;
648 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600649 do {
Harout Hedeshian77825572014-02-17 10:47:14 +0200650 if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name) ||
651 ((~INGRESS_FLAGS_MASK) & ingress_flags)) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600652 return_code = RMNETCTL_INVALID_ARG;
653 break;
654 }
655
656 request.message_type = RMNET_NETLINK_SET_LINK_INGRESS_DATA_FORMAT;
657
658 request.arg_length = RMNET_MAX_STR_LEN +
659 sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t);
660 str_len = strlcpy((char *)(request.data_format.dev),
661 dev_name,
662 RMNET_MAX_STR_LEN);
663 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
664 break;
665 request.data_format.flags = ingress_flags;
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700666 request.data_format.tail_spacing = tail_spacing;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600667
668 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
669 != RMNETCTL_SUCCESS)
670 break;
671
672 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
673 break;
674
675 return_code = _rmnetctl_set_codes(response.return_code, error_code);
676 } while(0);
677 return return_code;
678}
679
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700680int rmnet_get_link_ingress_data_format_tailspace(rmnetctl_hndl_t *hndl,
681 const char *dev_name,
682 uint32_t *ingress_flags,
683 uint8_t *tail_spacing,
684 uint16_t *error_code) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600685 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700686 size_t str_len = 0;
687 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600688 do {
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700689 if ((!hndl) || (!error_code) ||
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600690 _rmnetctl_check_dev_name(dev_name)) {
691 return_code = RMNETCTL_INVALID_ARG;
692 break;
693 }
694
695 request.message_type = RMNET_NETLINK_GET_LINK_INGRESS_DATA_FORMAT;
696
697 request.arg_length = RMNET_MAX_STR_LEN;
698 str_len = strlcpy((char *)(request.data_format.dev),
699 dev_name,
700 RMNET_MAX_STR_LEN);
701 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
702 break;
703
704 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
705 != RMNETCTL_SUCCESS)
706 break;
707
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600708 if (_rmnetctl_check_data(response.crd, error_code)
709 != RMNETCTL_SUCCESS) {
710 if (_rmnetctl_check_code(response.crd, error_code)
711 == RMNETCTL_SUCCESS)
712 return_code = _rmnetctl_set_codes(response.return_code,
713 error_code);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600714 break;
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600715 }
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600716
Subash Abhinov Kasiviswanathan22fa3882014-01-16 12:55:45 -0700717 if (ingress_flags)
718 *ingress_flags = response.data_format.flags;
719
720 if (tail_spacing)
721 *tail_spacing = response.data_format.tail_spacing;
722
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600723 return_code = RMNETCTL_SUCCESS;
724 } while(0);
725 return return_code;
726}
727
728int rmnet_set_logical_ep_config(rmnetctl_hndl_t *hndl,
729 int32_t ep_id,
730 uint8_t operating_mode,
731 const char *dev_name,
732 const char *next_dev,
733 uint16_t *error_code) {
734 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700735 size_t str_len = 0;
736 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600737 do {
738 if ((!hndl) || ((ep_id < -1) || (ep_id > 31)) || (!error_code) ||
739 _rmnetctl_check_dev_name(dev_name) ||
Harout Hedeshian77825572014-02-17 10:47:14 +0200740 _rmnetctl_check_dev_name(next_dev) ||
741 operating_mode >= RMNET_EPMODE_LENGTH) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600742 return_code = RMNETCTL_INVALID_ARG;
743 break;
744 }
745
746 request.message_type = RMNET_NETLINK_SET_LOGICAL_EP_CONFIG;
747
748 request.arg_length = RMNET_MAX_STR_LEN +
749 RMNET_MAX_STR_LEN + sizeof(int32_t) + sizeof(uint8_t);
750 str_len = strlcpy((char *)(request.local_ep_config.dev),
751 dev_name,
752 RMNET_MAX_STR_LEN);
753 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
754 break;
755
756 str_len = strlcpy((char *)(request.local_ep_config.next_dev),
757 next_dev,
758 RMNET_MAX_STR_LEN);
759 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
760 break;
761 request.local_ep_config.ep_id = ep_id;
762 request.local_ep_config.operating_mode = operating_mode;
763
764 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
765 != RMNETCTL_SUCCESS)
766 break;
767 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
768 break;
769
770 return_code = _rmnetctl_set_codes(response.return_code, error_code);
771 } while(0);
772 return return_code;
773}
774
Harout Hedeshiana9731652014-01-06 18:00:23 +0200775int rmnet_unset_logical_ep_config(rmnetctl_hndl_t *hndl,
776 int32_t ep_id,
777 const char *dev_name,
778 uint16_t *error_code) {
779 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700780 size_t str_len = 0;
781 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshiana9731652014-01-06 18:00:23 +0200782 do {
783
784 if ((!hndl) || ((ep_id < -1) || (ep_id > 31)) || (!error_code) ||
785 _rmnetctl_check_dev_name(dev_name)) {
786 return_code = RMNETCTL_INVALID_ARG;
787 break;
788 }
789
790 request.message_type = RMNET_NETLINK_UNSET_LOGICAL_EP_CONFIG;
791
792 request.arg_length = RMNET_MAX_STR_LEN + sizeof(int32_t);
793 str_len = strlcpy((char *)(request.local_ep_config.dev),
794 dev_name,
795 RMNET_MAX_STR_LEN);
796
797 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
798 break;
799
800 request.local_ep_config.ep_id = ep_id;
801
802 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
803 != RMNETCTL_SUCCESS)
804 break;
805 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
806 break;
807
808 return_code = _rmnetctl_set_codes(response.return_code, error_code);
809 } while(0);
810
811 return return_code;
812}
813
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600814int rmnet_get_logical_ep_config(rmnetctl_hndl_t *hndl,
815 int32_t ep_id,
816 const char *dev_name,
817 uint8_t *operating_mode,
818 char **next_dev,
Harout Hedeshian77825572014-02-17 10:47:14 +0200819 uint32_t next_dev_len,
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600820 uint16_t *error_code) {
821 struct rmnet_nl_msg_s request, response;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700822 size_t str_len = 0;
823 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600824 do {
825 if ((!hndl) || (!operating_mode) || (!error_code) || ((ep_id < -1) ||
Harout Hedeshian77825572014-02-17 10:47:14 +0200826 (ep_id > 31)) || _rmnetctl_check_dev_name(dev_name) || (!next_dev)
827 || (0 == next_dev_len)) {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600828 return_code = RMNETCTL_INVALID_ARG;
829 break;
830 }
831
832 request.message_type = RMNET_NETLINK_GET_LOGICAL_EP_CONFIG;
833
834 request.arg_length = RMNET_MAX_STR_LEN + sizeof(int32_t);
835 str_len = strlcpy((char *)(request.local_ep_config.dev),
836 dev_name,
837 RMNET_MAX_STR_LEN);
838 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
839 break;
840
841 request.local_ep_config.ep_id = ep_id;
842
843 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
844 != RMNETCTL_SUCCESS)
845 break;
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600846
847 if (_rmnetctl_check_data(response.crd, error_code)
848 != RMNETCTL_SUCCESS) {
849 if (_rmnetctl_check_code(response.crd, error_code)
850 == RMNETCTL_SUCCESS)
851 return_code = _rmnetctl_set_codes(response.return_code,
852 error_code);
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600853 break;
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600854 }
Harout Hedeshian77825572014-02-17 10:47:14 +0200855
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600856 str_len = strlcpy(*next_dev,
857 (char *)(response.local_ep_config.next_dev),
Harout Hedeshian77825572014-02-17 10:47:14 +0200858 min(RMNET_MAX_STR_LEN, next_dev_len));
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600859 if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
860 break;
861
862 *operating_mode = response.local_ep_config.operating_mode;
863 return_code = RMNETCTL_SUCCESS;
864 } while(0);
865 return return_code;
866}
867
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600868int rmnet_new_vnd_prefix(rmnetctl_hndl_t *hndl,
869 uint32_t id,
870 uint16_t *error_code,
871 uint8_t new_vnd,
872 const char *prefix)
873{
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600874 struct rmnet_nl_msg_s request, response;
875 int return_code = RMNETCTL_LIB_ERR;
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700876 size_t str_len = 0;
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600877 do {
878 if ((!hndl) || (!error_code) ||
879 ((new_vnd != RMNETCTL_NEW_VND) && (new_vnd != RMNETCTL_FREE_VND))) {
880 return_code = RMNETCTL_INVALID_ARG;
881 break;
882 }
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600883
884 memset(request.vnd.vnd_name, 0, RMNET_MAX_STR_LEN);
885 if (new_vnd == RMNETCTL_NEW_VND) {
886 if (prefix) {
887 request.message_type =RMNET_NETLINK_NEW_VND_WITH_PREFIX;
888 str_len = strlcpy((char *)request.vnd.vnd_name,
889 prefix, RMNET_MAX_STR_LEN);
890 if (_rmnetctl_check_len(str_len, error_code)
891 != RMNETCTL_SUCCESS)
892 break;
893 } else {
894 request.message_type = RMNET_NETLINK_NEW_VND;
895 }
896 } else {
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600897 request.message_type = RMNET_NETLINK_FREE_VND;
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600898 }
Harout Hedeshianb2fc5b12013-09-03 13:49:00 -0600899
900 request.arg_length = sizeof(uint32_t);
901 request.vnd.id = id;
902
903 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
904 != RMNETCTL_SUCCESS)
905 break;
906 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
907 break;
908
909 return_code = _rmnetctl_set_codes(response.return_code, error_code);
910 } while(0);
911 return return_code;
912}
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600913
Subash Abhinov Kasiviswanathandba447c2017-02-23 17:58:09 -0700914int rmnet_new_vnd_name(rmnetctl_hndl_t *hndl,
915 uint32_t id,
916 uint16_t *error_code,
917 const char *prefix)
918{
919 struct rmnet_nl_msg_s request, response;
920 int return_code = RMNETCTL_LIB_ERR;
921 size_t str_len = 0;
922 do {
923 if ((!hndl) || (!error_code)) {
924 return_code = RMNETCTL_INVALID_ARG;
925 break;
926 }
927
928 memset(request.vnd.vnd_name, 0, RMNET_MAX_STR_LEN);
929 if (prefix) {
930 request.message_type =RMNET_NETLINK_NEW_VND_WITH_NAME;
931 str_len = strlcpy((char *)request.vnd.vnd_name,
932 prefix, RMNET_MAX_STR_LEN);
933 if (_rmnetctl_check_len(str_len, error_code)
934 != RMNETCTL_SUCCESS)
935 break;
936 } else {
937 request.message_type = RMNET_NETLINK_NEW_VND;
938 }
939
940 request.arg_length = sizeof(uint32_t);
941 request.vnd.id = id;
942
943 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
944 != RMNETCTL_SUCCESS)
945 break;
946 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
947 break;
948
949 return_code = _rmnetctl_set_codes(response.return_code, error_code);
950 } while(0);
951 return return_code;
952}
953
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600954int rmnet_new_vnd(rmnetctl_hndl_t *hndl,
955 uint32_t id,
956 uint16_t *error_code,
957 uint8_t new_vnd)
958{
959 return rmnet_new_vnd_prefix(hndl, id, error_code, new_vnd, 0);
960}
961
962int rmnet_get_vnd_name(rmnetctl_hndl_t *hndl,
963 uint32_t id,
964 uint16_t *error_code,
965 char *buf,
966 uint32_t buflen)
967{
968 struct rmnet_nl_msg_s request, response;
969 uint32_t str_len;
970 int return_code = RMNETCTL_LIB_ERR;
971 do {
Harout Hedeshian77825572014-02-17 10:47:14 +0200972 if ((!hndl) || (!error_code) || (!buf) || (0 == buflen)) {
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600973 return_code = RMNETCTL_INVALID_ARG;
974 break;
975 }
976
977 request.message_type = RMNET_NETLINK_GET_VND_NAME;
978 request.arg_length = sizeof(uint32_t);
979 request.vnd.id = id;
980
981
982 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
983 != RMNETCTL_SUCCESS)
984 break;
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600985
986 if (_rmnetctl_check_data(response.crd, error_code)
987 != RMNETCTL_SUCCESS) {
988 if (_rmnetctl_check_code(response.crd, error_code)
989 == RMNETCTL_SUCCESS)
990 return_code = _rmnetctl_set_codes(response.return_code,
991 error_code);
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600992 break;
Subash Abhinov Kasiviswanathand42712d2015-04-14 13:44:02 -0600993 }
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600994
Harout Hedeshian0bf0a172014-02-19 23:52:05 -0700995 str_len = (uint32_t)strlcpy(buf,
Harout Hedeshian89a91e22013-10-09 08:59:47 -0600996 (char *)(response.vnd.vnd_name),
997 buflen);
998 if (str_len >= buflen) {
999 *error_code = RMNETCTL_API_ERR_STRING_TRUNCATION;
1000 break;
1001 }
1002
1003 return_code = RMNETCTL_SUCCESS;
1004 } while (0);
1005 return return_code;
1006}
1007
Harout Hedeshian97a1e982013-11-08 09:28:53 -07001008int rmnet_add_del_vnd_tc_flow(rmnetctl_hndl_t *hndl,
1009 uint32_t id,
1010 uint32_t map_flow_id,
1011 uint32_t tc_flow_id,
1012 uint8_t set_flow,
1013 uint16_t *error_code) {
1014 struct rmnet_nl_msg_s request, response;
1015 int return_code = RMNETCTL_LIB_ERR;
1016 do {
Harout Hedeshian77825572014-02-17 10:47:14 +02001017 if ((!hndl) || (!error_code) || ((set_flow != RMNETCTL_ADD_FLOW) &&
1018 (set_flow != RMNETCTL_DEL_FLOW))) {
Harout Hedeshian97a1e982013-11-08 09:28:53 -07001019 return_code = RMNETCTL_INVALID_ARG;
1020 break;
1021 }
1022 if (set_flow == RMNETCTL_ADD_FLOW)
1023 request.message_type = RMNET_NETLINK_ADD_VND_TC_FLOW;
1024 else
1025 request.message_type = RMNET_NETLINK_DEL_VND_TC_FLOW;
1026
1027 request.arg_length = (sizeof(uint32_t))*3;
1028 request.flow_control.id = id;
1029 request.flow_control.map_flow_id = map_flow_id;
1030 request.flow_control.tc_flow_id = tc_flow_id;
1031
1032 if ((*error_code = rmnetctl_transact(hndl, &request, &response))
1033 != RMNETCTL_SUCCESS)
1034 break;
1035 if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
1036 break;
1037 return_code = _rmnetctl_set_codes(response.return_code, error_code);
1038 } while(0);
1039 return return_code;
1040}
1041
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001042/*
1043 * NEW DRIVER API
1044 */
Sean Tranchetti51133f52019-02-12 12:54:34 -07001045
1046 /* @brief Add a Routing Attribute to a Netlink message
1047 * @param *req The Netlink message we're adding to
1048 * @param *reqsize The remaining space within the Netlink message
1049 * @param type The type of the RTA to add
1050 * @param len The length of the RTA data to add
1051 * @param *data A pointer to the RTA data to add
1052 * @return RMNETCTL_LIB_ERR if there is not enough space to add the RTA
1053 * @return RMNETCTL_SUCCESS if we added the RTA successfully
1054 */
1055static int rta_put(struct nlmsg *req, size_t *reqsize, int type, int len,
1056 void *data)
1057{
1058 struct rtattr *attr = NLMSG_TAIL(&req->nl_addr);
1059
1060 attr->rta_type = type;
1061 attr->rta_len = RTA_LENGTH(len);
1062 CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attr), reqsize, data, len));
1063 req->nl_addr.nlmsg_len = NLMSG_ALIGN(req->nl_addr.nlmsg_len) +
1064 RTA_ALIGN(attr->rta_len);
1065
1066 return RMNETCTL_SUCCESS;
1067}
Sean Tranchetti6e3d5232019-02-12 13:46:42 -07001068
1069/* @brief Add an RTA to the Netlink message with a u16 data
1070 * @param *req The Netlink message
1071 * @param *reqsize The remainins space within the Netlink message
1072 * @param type The type of the RTA to add
1073 * @param data The data of the RTA
1074 * @rteturn RMNETCTL_LIB_ERR if there is not enough space to add the RTA
1075 * @return RMNETCTL_SUCCESS if we added the RTA successfully
1076 */
1077static int rta_put_u16(struct nlmsg *req, size_t *reqsize, int type,
1078 uint16_t data)
1079{
1080 return rta_put(req, reqsize, type, sizeof(data), &data);
1081}
1082
1083/* @brief Add an RTA to the Netlink message with a u32 data
1084 * @param *req The Netlink message
1085 * @param *reqsize The remainins space within the Netlink message
1086 * @param type The type of the RTA to add
1087 * @param data The data of the RTA
1088 * @rteturn RMNETCTL_LIB_ERR if there is not enough space to add the RTA
1089 * @return RMNETCTL_SUCCESS if we added the RTA successfully
1090 */
1091static int rta_put_u32(struct nlmsg *req, size_t *reqsize, int type,
1092 uint32_t data)
1093{
1094 return rta_put(req, reqsize, type, sizeof(data), &data);
1095}
1096
1097/* @brief Add an RTA to the Netlink message with string data
1098 * @param *req The Netlink message
1099 * @param *reqsize The remainins space within the Netlink message
1100 * @param type The type of the RTA to add
1101 * @param *data The data of the RTA
1102 * @rteturn RMNETCTL_LIB_ERR if there is not enough space to add the RTA
1103 * @return RMNETCTL_SUCCESS if we added the RTA successfully
1104 */
1105static int rta_put_string(struct nlmsg *req, size_t *reqsize, int type,
1106 char *data)
1107{
1108 return rta_put(req, reqsize, type, strlen(data) + 1, data);
1109}
1110
1111/* @brief Start a nested RTA within the Netlink message
1112 * @param *req The Netlink message
1113 * @param *reqsize The remainins space within the Netlink message
1114 * @param type The type of the RTA to add
1115 * @param **start A pointer where we store the start of the ensted attribute
1116 * @rteturn RMNETCTL_LIB_ERR if there is not enough space to add the RTA
1117 * @return RMNETCTL_SUCCESS if we added the RTA successfully
1118 */
1119static int rta_nested_start(struct nlmsg *req, size_t *reqsize, int type,
1120 struct rtattr **start)
1121{
1122 *start = NLMSG_TAIL(&req->nl_addr);
1123 return rta_put(req, reqsize, type, 0, NULL);
1124}
1125
1126/* @brief End a nested RTA previously started with rta_nested_start
1127 * @param *req The Netlink message
1128 * @param *start The start of the nested RTA, as provided by rta_nested_start
1129 */
1130static void rta_nested_end(struct nlmsg *req, struct rtattr *start)
1131{
1132 start->rta_len = (char *)NLMSG_TAIL(&req->nl_addr) - (char *)start;
1133}
1134
Sean Tranchetti1a2abef2019-01-03 14:33:16 -07001135static void rta_parse(struct rtattr **tb, int maxtype, struct rtattr *head,
1136 int len)
1137{
1138 struct rtattr *rta;
1139
1140 memset(tb, 0, sizeof(struct rtattr *) * maxtype);
1141 for (rta = head; RTA_OK(rta, len);
1142 rta = RTA_NEXT(rta, len)) {
1143 __u16 type = rta->rta_type & NLA_TYPE_MASK;
1144
Subash Abhinov Kasiviswanathan0fb7abe2020-06-03 15:05:44 -07001145 if (type > 0 && type < maxtype)
Sean Tranchetti1a2abef2019-01-03 14:33:16 -07001146 tb[type] = rta;
1147 }
1148}
1149
1150static struct rtattr *rta_find(struct rtattr *rta, int attrlen, uint16_t type)
1151{
1152 for (; RTA_OK(rta, attrlen); rta = RTA_NEXT(rta, attrlen)) {
1153 if (rta->rta_type == (type & NLA_TYPE_MASK))
1154 return rta;
1155 }
1156
1157 return NULL;
1158}
1159
Sean Tranchetti37a08ec2019-02-12 15:22:50 -07001160/* @brief Fill a Netlink messages with the necessary common RTAs for creating a
1161 * RTM_NEWLINK message for creating or changing rmnet devices.
1162 * @param *req The netlink message
1163 * @param *reqsize The remaining space within the Netlink message
1164 * @param devindex The ifindex of the physical device
1165 * @param *vndname The name of the rmnet device
1166 * @param index The MUX ID of the rmnet device
1167 * @param flagconfig The dataformat flags for the rmnet device
1168 * @return RMNETCTL_LIB_ERR if there is not enough space to add all RTAs
1169 * @return RMNETCTL_SUCCESS if everything was added successfully
1170 */
1171static int rmnet_fill_newlink_msg(struct nlmsg *req, size_t *reqsize,
1172 unsigned int devindex, char *vndname,
1173 uint8_t index, uint32_t flagconfig)
1174{
1175 struct rtattr *linkinfo, *datainfo;
1176 struct ifla_vlan_flags flags;
1177 int rc;
1178
1179 /* Set up link attr with devindex as data */
1180 rc = rta_put_u32(req, reqsize, IFLA_LINK, devindex);
1181 if (rc != RMNETCTL_SUCCESS)
1182 return rc;
1183
1184 rc = rta_put_string(req, reqsize, IFLA_IFNAME, vndname);
1185 if (rc != RMNETCTL_SUCCESS)
1186 return rc;
1187
1188 /* Set up info kind RMNET that has linkinfo and type */
1189 rc = rta_nested_start(req, reqsize, IFLA_LINKINFO, &linkinfo);
1190 if (rc != RMNETCTL_SUCCESS)
1191 return rc;
1192
1193 rc = rta_put_string(req, reqsize, IFLA_INFO_KIND, "rmnet");
1194 if (rc != RMNETCTL_SUCCESS)
1195 return rc;
1196
1197 rc = rta_nested_start(req, reqsize, IFLA_INFO_DATA, &datainfo);
1198 if (rc != RMNETCTL_SUCCESS)
1199 return rc;
1200
Sean Tranchetti037065c2019-04-19 11:04:43 -06001201 rc = rta_put_u16(req, reqsize, RMNETCTL_IFLA_MUX_ID, index);
Sean Tranchetti37a08ec2019-02-12 15:22:50 -07001202 if (rc != RMNETCTL_SUCCESS)
1203 return rc;
1204
1205 if (flagconfig != 0) {
1206 flags.mask = flagconfig;
1207 flags.flags = flagconfig;
1208
Sean Tranchetti037065c2019-04-19 11:04:43 -06001209 rc = rta_put(req, reqsize, RMNETCTL_IFLA_FLAGS, sizeof(flags),
Sean Tranchetti37a08ec2019-02-12 15:22:50 -07001210 &flags);
1211 if (rc != RMNETCTL_SUCCESS)
1212 return rc;
1213 }
1214
1215 rta_nested_end(req, datainfo);
1216 rta_nested_end(req, linkinfo);
1217
1218 return RMNETCTL_SUCCESS;
1219}
1220
Sean Tranchettid9d69eb2019-02-12 14:30:49 -07001221/* @brief Add all necessary RTA elements to a Netlink message suitable for
1222 * sending to the DFC driver
1223 * @param *req The Netlink message
1224 * @param *reqsize The remaining space in the Netlink message
1225 * @param devindex The ifindex of the real physical device
1226 * @param *vndname The name of the VND we're modifying
1227 * @param *flowinfo The parameters sent to the DFC driver
1228 * @return RMENTCTL_LIB_ERR if there is not enough space to add the RTAs
1229 * @return RMNETCTL_SUCCESS if everything was added successfully
1230 */
1231static int rmnet_fill_flow_msg(struct nlmsg *req, size_t *reqsize,
1232 unsigned int devindex, char *vndname,
1233 struct tcmsg *flowinfo)
1234{
1235 struct rtattr *linkinfo, *datainfo;
1236 int rc;
1237
1238 /* Set up link attr with devindex as data */
1239 rc = rta_put_u32(req, reqsize, IFLA_LINK, devindex);
1240 if (rc != RMNETCTL_SUCCESS)
1241 return rc;
1242
1243 rc = rta_put_string(req, reqsize, IFLA_IFNAME, vndname);
1244 if (rc != RMNETCTL_SUCCESS)
1245 return rc;
1246
1247 /* Set up IFLA info kind RMNET that has linkinfo and type */
1248 rc = rta_nested_start(req, reqsize, IFLA_LINKINFO, &linkinfo);
1249 if (rc != RMNETCTL_SUCCESS)
1250 return rc;
1251
1252 rc = rta_put_string(req, reqsize, IFLA_INFO_KIND, "rmnet");
1253 if (rc != RMNETCTL_SUCCESS)
1254 return rc;
1255
1256 rc = rta_nested_start(req, reqsize, IFLA_INFO_DATA, &datainfo);
1257 if (rc != RMNETCTL_SUCCESS)
1258 return rc;
1259
Sean Tranchetti037065c2019-04-19 11:04:43 -06001260 rc = rta_put(req, reqsize, RMNETCTL_IFLA_DFC_QOS, sizeof(*flowinfo),
Sean Tranchettid9d69eb2019-02-12 14:30:49 -07001261 flowinfo);
1262 if (rc != RMNETCTL_SUCCESS)
1263 return rc;
1264
1265 rta_nested_end(req, datainfo);
1266 rta_nested_end(req, linkinfo);
1267
1268 return RMNETCTL_SUCCESS;
1269}
1270
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001271/* @brief Synchronous method to receive messages to and from the kernel
1272 * using netlink sockets
1273 * @details Receives the ack response from the kernel.
1274 * @param *hndl RmNet handle for this transaction
1275 * @param *error_code Error code if transaction fails
1276 * @return RMNETCTL_API_SUCCESS if successfully able to send and receive message
1277 * from the kernel
1278 * @return RMNETCTL_API_ERR_HNDL_INVALID if RmNet handle for the transaction was
1279 * NULL
1280 * @return RMNETCTL_API_ERR_MESSAGE_RECEIVE if could not receive message from
1281 * the kernel
1282 * @return RMNETCTL_API_ERR_MESSAGE_TYPE if the response type does not
1283 * match
1284 */
1285static int rmnet_get_ack(rmnetctl_hndl_t *hndl, uint16_t *error_code)
1286{
1287 struct nlack {
1288 struct nlmsghdr ackheader;
1289 struct nlmsgerr ackdata;
1290 char data[256];
1291
1292 } ack;
1293 int i;
1294
1295 if (!hndl || !error_code)
1296 return RMNETCTL_INVALID_ARG;
1297
1298 if ((i = recv(hndl->netlink_fd, &ack, sizeof(ack), 0)) < 0) {
1299 *error_code = errno;
1300 return RMNETCTL_API_ERR_MESSAGE_RECEIVE;
1301 }
1302
1303 /*Ack should always be NLMSG_ERROR type*/
1304 if (ack.ackheader.nlmsg_type == NLMSG_ERROR) {
1305 if (ack.ackdata.error == 0) {
1306 *error_code = RMNETCTL_API_SUCCESS;
1307 return RMNETCTL_SUCCESS;
1308 } else {
1309 *error_code = -ack.ackdata.error;
1310 return RMNETCTL_KERNEL_ERR;
1311 }
1312 }
1313
1314 *error_code = RMNETCTL_API_ERR_RETURN_TYPE;
1315 return RMNETCTL_API_FIRST_ERR;
1316}
1317
1318/*
1319 * EXPOSED NEW DRIVER API
1320 */
1321int rtrmnet_ctl_init(rmnetctl_hndl_t **hndl, uint16_t *error_code)
1322{
1323 struct sockaddr_nl __attribute__((__may_alias__)) *saddr_ptr;
1324 int netlink_fd = -1;
1325 pid_t pid = 0;
1326
1327 if (!hndl || !error_code)
1328 return RMNETCTL_INVALID_ARG;
1329
1330 *hndl = (rmnetctl_hndl_t *)malloc(sizeof(rmnetctl_hndl_t));
1331 if (!*hndl) {
1332 *error_code = RMNETCTL_API_ERR_HNDL_INVALID;
1333 return RMNETCTL_LIB_ERR;
1334 }
1335
1336 memset(*hndl, 0, sizeof(rmnetctl_hndl_t));
1337
1338 pid = getpid();
1339 if (pid < MIN_VALID_PROCESS_ID) {
1340 free(*hndl);
1341 *error_code = RMNETCTL_INIT_ERR_PROCESS_ID;
1342 return RMNETCTL_LIB_ERR;
1343 }
1344 (*hndl)->pid = KERNEL_PROCESS_ID;
Conner Huff1ecd2d82018-04-20 11:12:35 -07001345 netlink_fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001346 if (netlink_fd < MIN_VALID_SOCKET_FD) {
1347 free(*hndl);
1348 *error_code = RMNETCTL_INIT_ERR_NETLINK_FD;
1349 return RMNETCTL_LIB_ERR;
1350 }
1351
1352 (*hndl)->netlink_fd = netlink_fd;
1353
1354 memset(&(*hndl)->src_addr, 0, sizeof(struct sockaddr_nl));
1355
1356 (*hndl)->src_addr.nl_family = AF_NETLINK;
1357 (*hndl)->src_addr.nl_pid = (*hndl)->pid;
1358
1359 saddr_ptr = &(*hndl)->src_addr;
1360 if (bind((*hndl)->netlink_fd,
1361 (struct sockaddr *)saddr_ptr,
1362 sizeof(struct sockaddr_nl)) < 0) {
1363 close((*hndl)->netlink_fd);
1364 free(*hndl);
1365 *error_code = RMNETCTL_INIT_ERR_BIND;
1366 return RMNETCTL_LIB_ERR;
1367 }
1368
1369 memset(&(*hndl)->dest_addr, 0, sizeof(struct sockaddr_nl));
1370
1371 (*hndl)->dest_addr.nl_family = AF_NETLINK;
1372 (*hndl)->dest_addr.nl_pid = KERNEL_PROCESS_ID;
1373 (*hndl)->dest_addr.nl_groups = UNICAST;
1374
1375 return RMNETCTL_SUCCESS;
1376}
1377
1378int rtrmnet_ctl_deinit(rmnetctl_hndl_t *hndl)
1379{
1380 if (!hndl)
1381 return RMNETCTL_SUCCESS;
1382
1383 close(hndl->netlink_fd);
1384 free(hndl);
1385
1386 return RMNETCTL_SUCCESS;
1387}
1388
1389int rtrmnet_ctl_newvnd(rmnetctl_hndl_t *hndl, char *devname, char *vndname,
1390 uint16_t *error_code, uint8_t index,
1391 uint32_t flagconfig)
1392{
Sean Tranchetti6e3d5232019-02-12 13:46:42 -07001393 unsigned int devindex = 0;
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001394 struct nlmsg req;
Subash Abhinov Kasiviswanathanc26ed592018-06-15 15:38:27 -07001395 size_t reqsize;
Sean Tranchetti51133f52019-02-12 12:54:34 -07001396 int rc;
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001397
Subash Abhinov Kasiviswanathanc26ed592018-06-15 15:38:27 -07001398 if (!hndl || !devname || !vndname || !error_code ||
1399 _rmnetctl_check_dev_name(vndname) || _rmnetctl_check_dev_name(devname))
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001400 return RMNETCTL_INVALID_ARG;
1401
1402 memset(&req, 0, sizeof(req));
Sean Tranchetti51133f52019-02-12 12:54:34 -07001403 reqsize = NLMSG_DATA_SIZE - sizeof(struct rtattr);
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001404 req.nl_addr.nlmsg_type = RTM_NEWLINK;
1405 req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
1406 req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL |
1407 NLM_F_ACK;
1408 req.nl_addr.nlmsg_seq = hndl->transaction_id;
1409 hndl->transaction_id++;
1410
1411 /* Get index of devname*/
1412 devindex = if_nametoindex(devname);
Sean Tranchetti10650922018-08-16 11:42:59 -06001413 if (devindex == 0) {
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001414 *error_code = errno;
1415 return RMNETCTL_KERNEL_ERR;
1416 }
1417
Sean Tranchetti51133f52019-02-12 12:54:34 -07001418 *error_code = RMNETCTL_API_ERR_RTA_FAILURE;
Sean Tranchetti6e3d5232019-02-12 13:46:42 -07001419 rc = rta_put_u32(&req, &reqsize, RMNET_IFLA_NUM_TX_QUEUES,
1420 RMNETCTL_NUM_TX_QUEUES);
Sean Tranchetti51133f52019-02-12 12:54:34 -07001421 if (rc != RMNETCTL_SUCCESS)
1422 return rc;
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001423
Sean Tranchetti37a08ec2019-02-12 15:22:50 -07001424 rc = rmnet_fill_newlink_msg(&req, &reqsize, devindex, vndname, index,
1425 flagconfig);
Sean Tranchetti51133f52019-02-12 12:54:34 -07001426 if (rc != RMNETCTL_SUCCESS)
1427 return rc;
Subash Abhinov Kasiviswanathancf3f8902018-08-30 14:23:08 -06001428
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001429 if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
1430 *error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
1431 return RMNETCTL_LIB_ERR;
1432 }
1433
1434 return rmnet_get_ack(hndl, error_code);
1435}
1436
1437int rtrmnet_ctl_delvnd(rmnetctl_hndl_t *hndl, char *vndname,
1438 uint16_t *error_code)
1439{
Sean Tranchetti10650922018-08-16 11:42:59 -06001440 unsigned int devindex = 0;
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001441 struct nlmsg req;
1442
1443 if (!hndl || !vndname || !error_code)
1444 return RMNETCTL_INVALID_ARG;
1445
1446 memset(&req, 0, sizeof(req));
1447 req.nl_addr.nlmsg_type = RTM_DELLINK;
1448 req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
1449 req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1450 req.nl_addr.nlmsg_seq = hndl->transaction_id;
1451 hndl->transaction_id++;
1452
1453 /* Get index of vndname*/
1454 devindex = if_nametoindex(vndname);
Sean Tranchetti10650922018-08-16 11:42:59 -06001455 if (devindex == 0) {
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001456 *error_code = errno;
1457 return RMNETCTL_KERNEL_ERR;
1458 }
1459
1460 /* Setup index attribute */
1461 req.ifmsg.ifi_index = devindex;
1462 if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
1463 *error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
1464 return RMNETCTL_LIB_ERR;
1465 }
1466
1467 return rmnet_get_ack(hndl, error_code);
1468}
1469
1470
1471int rtrmnet_ctl_changevnd(rmnetctl_hndl_t *hndl, char *devname, char *vndname,
1472 uint16_t *error_code, uint8_t index,
1473 uint32_t flagconfig)
1474{
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001475 struct nlmsg req;
Sean Tranchetti51133f52019-02-12 12:54:34 -07001476 unsigned int devindex = 0;
Subash Abhinov Kasiviswanathanc26ed592018-06-15 15:38:27 -07001477 size_t reqsize;
Sean Tranchetti51133f52019-02-12 12:54:34 -07001478 int rc;
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001479
1480 memset(&req, 0, sizeof(req));
1481
Subash Abhinov Kasiviswanathanc26ed592018-06-15 15:38:27 -07001482 if (!hndl || !devname || !vndname || !error_code ||
1483 _rmnetctl_check_dev_name(vndname) || _rmnetctl_check_dev_name(devname))
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001484 return RMNETCTL_INVALID_ARG;
1485
Sean Tranchetti51133f52019-02-12 12:54:34 -07001486 reqsize = NLMSG_DATA_SIZE - sizeof(struct rtattr);
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001487 req.nl_addr.nlmsg_type = RTM_NEWLINK;
1488 req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
1489 req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1490 req.nl_addr.nlmsg_seq = hndl->transaction_id;
1491 hndl->transaction_id++;
1492
1493 /* Get index of devname*/
1494 devindex = if_nametoindex(devname);
Sean Tranchetti10650922018-08-16 11:42:59 -06001495 if (devindex == 0) {
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001496 *error_code = errno;
1497 return RMNETCTL_KERNEL_ERR;
1498 }
1499
Sean Tranchetti37a08ec2019-02-12 15:22:50 -07001500 rc = rmnet_fill_newlink_msg(&req, &reqsize, devindex, vndname, index,
1501 flagconfig);
1502 if (rc != RMNETCTL_SUCCESS) {
1503 *error_code = RMNETCTL_API_ERR_RTA_FAILURE;
Sean Tranchetti51133f52019-02-12 12:54:34 -07001504 return rc;
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001505 }
1506
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001507 if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
1508 *error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
1509 return RMNETCTL_LIB_ERR;
1510 }
1511
1512 return rmnet_get_ack(hndl, error_code);
1513}
1514
Sean Tranchetti1a2abef2019-01-03 14:33:16 -07001515int rtrmnet_ctl_getvnd(rmnetctl_hndl_t *hndl, char *vndname,
1516 uint16_t *error_code, uint16_t *mux_id,
Subash Abhinov Kasiviswanathana0c4bfb2019-08-14 11:26:52 -06001517 uint32_t *flagconfig, uint8_t *agg_count,
1518 uint16_t *agg_size, uint32_t *agg_time,
1519 uint8_t *features)
Sean Tranchetti1a2abef2019-01-03 14:33:16 -07001520{
1521 struct nlmsg req;
1522 struct nlmsghdr *resp;
1523 struct rtattr *attrs, *linkinfo, *datainfo;
Sean Tranchetti037065c2019-04-19 11:04:43 -06001524 struct rtattr *tb[__RMNETCTL_IFLA_MAX];
Sean Tranchetti1a2abef2019-01-03 14:33:16 -07001525 unsigned int devindex = 0;
1526 int resp_len;
1527
1528 memset(&req, 0, sizeof(req));
1529
1530 if (!hndl || !vndname || !error_code || !(mux_id || flagconfig) ||
1531 _rmnetctl_check_dev_name(vndname))
1532 return RMNETCTL_INVALID_ARG;
1533
1534 req.nl_addr.nlmsg_type = RTM_GETLINK;
1535 req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
1536 req.nl_addr.nlmsg_flags = NLM_F_REQUEST;
1537 req.nl_addr.nlmsg_seq = hndl->transaction_id;
1538 hndl->transaction_id++;
1539
1540 /* Get index of vndname */
1541 devindex = if_nametoindex(vndname);
1542 if (devindex == 0) {
1543 *error_code = errno;
1544 return RMNETCTL_KERNEL_ERR;
1545 }
1546
1547 req.ifmsg.ifi_index = devindex;
1548 if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
1549 *error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
1550 return RMNETCTL_LIB_ERR;
1551 }
1552
1553 resp_len = recv(hndl->netlink_fd, NULL, 0, MSG_PEEK | MSG_TRUNC);
1554 if (resp_len < 0) {
1555 *error_code = errno;
1556 return RMNETCTL_API_ERR_MESSAGE_RECEIVE;
1557 }
1558
1559 resp = malloc((size_t)resp_len);
1560 if (!resp) {
1561 *error_code = errno;
1562 return RMNETCTL_LIB_ERR;
1563 }
1564
1565 resp_len = recv(hndl->netlink_fd, (char *)resp, (size_t)resp_len, 0);
1566 if (resp_len < 0) {
1567 *error_code = errno;
1568 free(resp);
1569 return RMNETCTL_API_ERR_MESSAGE_RECEIVE;
1570 }
1571
1572 /* Parse out the RT attributes */
1573 attrs = (struct rtattr *)((char *)NLMSG_DATA(resp) +
1574 NLMSG_ALIGN(sizeof(req.ifmsg)));
1575 linkinfo = rta_find(attrs, NLMSG_PAYLOAD(resp, sizeof(req.ifmsg)),
1576 IFLA_LINKINFO);
1577 if (!linkinfo) {
1578 free(resp);
1579 *error_code = RMNETCTL_API_ERR_RTA_FAILURE;
1580 return RMNETCTL_KERNEL_ERR;
1581 }
1582
1583 datainfo = rta_find(RTA_DATA(linkinfo), RTA_PAYLOAD(linkinfo),
1584 IFLA_INFO_DATA);
1585 if (!datainfo) {
1586 free(resp);
1587 *error_code = RMNETCTL_API_ERR_RTA_FAILURE;
1588 return RMNETCTL_KERNEL_ERR;
1589 }
1590
1591 /* Parse all the rmnet-specific information from the kernel */
Sean Tranchetti037065c2019-04-19 11:04:43 -06001592 rta_parse(tb, __RMNETCTL_IFLA_MAX, RTA_DATA(datainfo),
Sean Tranchetti1a2abef2019-01-03 14:33:16 -07001593 RTA_PAYLOAD(datainfo));
Sean Tranchetti037065c2019-04-19 11:04:43 -06001594 if (tb[RMNETCTL_IFLA_MUX_ID] && mux_id)
1595 *mux_id = *((uint16_t *)RTA_DATA(tb[RMNETCTL_IFLA_MUX_ID]));
1596 if (tb[RMNETCTL_IFLA_FLAGS] && flagconfig) {
Sean Tranchetti1a2abef2019-01-03 14:33:16 -07001597 struct ifla_vlan_flags *flags;
1598
1599 flags = (struct ifla_vlan_flags *)
Sean Tranchetti037065c2019-04-19 11:04:43 -06001600 RTA_DATA(tb[RMNETCTL_IFLA_FLAGS]);
Sean Tranchetti1a2abef2019-01-03 14:33:16 -07001601 *flagconfig = flags->flags;
1602 }
Sean Tranchetti406fd812019-04-22 16:45:19 -06001603 if (tb[RMNETCTL_IFLA_UPLINK_PARAMS]) {
1604 struct rmnetctl_uplink_params *ul_agg;
1605
1606 ul_agg = (struct rmnetctl_uplink_params *)
1607 RTA_DATA(tb[RMNETCTL_IFLA_UPLINK_PARAMS]);
Subash Abhinov Kasiviswanathana0c4bfb2019-08-14 11:26:52 -06001608
Sean Tranchetti406fd812019-04-22 16:45:19 -06001609 if (agg_size)
1610 *agg_size = ul_agg->byte_count;
Subash Abhinov Kasiviswanathana0c4bfb2019-08-14 11:26:52 -06001611
1612 if (agg_count)
1613 *agg_count = ul_agg->packet_count;
1614
1615 if (features)
1616 *features = ul_agg->features;
1617
Sean Tranchetti406fd812019-04-22 16:45:19 -06001618 if (agg_time)
1619 *agg_time = ul_agg->time_limit;
1620 }
Sean Tranchetti1a2abef2019-01-03 14:33:16 -07001621
1622 free(resp);
1623 return RMNETCTL_API_SUCCESS;
1624}
1625
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001626int rtrmnet_ctl_bridgevnd(rmnetctl_hndl_t *hndl, char *devname, char *vndname,
1627 uint16_t *error_code)
1628{
Sean Tranchetti10650922018-08-16 11:42:59 -06001629 unsigned int devindex = 0, vndindex = 0;
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001630 struct nlmsg req;
Subash Abhinov Kasiviswanathanc26ed592018-06-15 15:38:27 -07001631 size_t reqsize;
Sean Tranchetti51133f52019-02-12 12:54:34 -07001632 int rc;
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001633
Subash Abhinov Kasiviswanathanc26ed592018-06-15 15:38:27 -07001634 if (!hndl || !vndname || !devname || !error_code || _rmnetctl_check_dev_name(vndname))
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001635 return RMNETCTL_INVALID_ARG;
1636
1637 memset(&req, 0, sizeof(req));
Sean Tranchetti51133f52019-02-12 12:54:34 -07001638 reqsize = NLMSG_DATA_SIZE - sizeof(struct rtattr);
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001639 req.nl_addr.nlmsg_type = RTM_NEWLINK;
1640 req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
1641 req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1642 req.nl_addr.nlmsg_seq = hndl->transaction_id;
1643 hndl->transaction_id++;
1644
1645 /* Get index of vndname*/
1646 devindex = if_nametoindex(devname);
Sean Tranchetti10650922018-08-16 11:42:59 -06001647 if (devindex == 0) {
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001648 *error_code = errno;
1649 return RMNETCTL_KERNEL_ERR;
1650 }
1651
1652 vndindex = if_nametoindex(vndname);
Sean Tranchetti10650922018-08-16 11:42:59 -06001653 if (vndindex == 0) {
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001654 *error_code = errno;
1655 return RMNETCTL_KERNEL_ERR;
1656 }
1657
1658 /* Setup index attribute */
1659 req.ifmsg.ifi_index = devindex;
Sean Tranchetti6e3d5232019-02-12 13:46:42 -07001660 rc = rta_put_u32(&req, &reqsize, IFLA_MASTER, vndindex);
Sean Tranchetti51133f52019-02-12 12:54:34 -07001661 if (rc != RMNETCTL_SUCCESS) {
1662 *error_code = RMNETCTL_API_ERR_RTA_FAILURE;
1663 return rc;
1664 }
Subash Abhinov Kasiviswanathan5b903dd2017-12-20 19:11:40 -07001665
1666 if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
1667 *error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
1668 return RMNETCTL_LIB_ERR;
1669 }
1670
1671 return rmnet_get_ack(hndl, error_code);
1672}
Conner Huffd0f3eca2018-05-18 11:37:46 -07001673
Sean Tranchetti6cac2892019-04-19 11:04:57 -06001674int rtrmnet_set_uplink_aggregation_params(rmnetctl_hndl_t *hndl,
1675 char *devname,
1676 char *vndname,
1677 uint8_t packet_count,
1678 uint16_t byte_count,
1679 uint32_t time_limit,
Subash Abhinov Kasiviswanathana0c4bfb2019-08-14 11:26:52 -06001680 uint8_t features,
Sean Tranchetti6cac2892019-04-19 11:04:57 -06001681 uint16_t *error_code)
1682{
1683 struct nlmsg req;
1684 struct rmnetctl_uplink_params uplink_params;
1685 struct rtattr *linkinfo, *datainfo;
1686 unsigned int devindex = 0;
1687 size_t reqsize;
1688 int rc;
1689
1690 memset(&req, 0, sizeof(req));
1691 memset(&uplink_params, 0, sizeof(uplink_params));
1692
1693 if (!hndl || !devname || !error_code ||_rmnetctl_check_dev_name(devname) ||
1694 _rmnetctl_check_dev_name(vndname))
1695 return RMNETCTL_INVALID_ARG;
1696
1697 reqsize = NLMSG_DATA_SIZE - sizeof(struct rtattr);
1698 req.nl_addr.nlmsg_type = RTM_NEWLINK;
1699 req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
1700 req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1701 req.nl_addr.nlmsg_seq = hndl->transaction_id;
1702 hndl->transaction_id++;
1703
1704 /* Get index of devname*/
1705 devindex = if_nametoindex(devname);
1706 if (devindex == 0) {
1707 *error_code = errno;
1708 return RMNETCTL_KERNEL_ERR;
1709 }
1710
1711 /* Set up link attr with devindex as data */
1712 rc = rta_put_u32(&req, &reqsize, IFLA_LINK, devindex);
1713 if (rc != RMNETCTL_SUCCESS) {
1714 *error_code = RMNETCTL_API_ERR_RTA_FAILURE;
1715 return rc;
1716 }
1717
1718 rc = rta_put_string(&req, &reqsize, IFLA_IFNAME, vndname);
1719 if (rc != RMNETCTL_SUCCESS) {
1720 *error_code = RMNETCTL_API_ERR_RTA_FAILURE;
1721 return rc;
1722 }
1723
1724 /* Set up IFLA info kind RMNET that has linkinfo and type */
1725 rc = rta_nested_start(&req, &reqsize, IFLA_LINKINFO, &linkinfo);
1726 if (rc != RMNETCTL_SUCCESS) {
1727 *error_code = RMNETCTL_API_ERR_RTA_FAILURE;
1728 return rc;
1729 }
1730
1731 rc = rta_put_string(&req, &reqsize, IFLA_INFO_KIND, "rmnet");
1732 if (rc != RMNETCTL_SUCCESS) {
1733 *error_code = RMNETCTL_API_ERR_RTA_FAILURE;
1734 return rc;
1735 }
1736
1737 rc = rta_nested_start(&req, &reqsize, IFLA_INFO_DATA, &datainfo);
1738 if (rc != RMNETCTL_SUCCESS) {
1739 *error_code = RMNETCTL_API_ERR_RTA_FAILURE;
1740 return rc;
1741 }
1742
1743 uplink_params.byte_count = byte_count;
1744 uplink_params.packet_count = packet_count;
Subash Abhinov Kasiviswanathana0c4bfb2019-08-14 11:26:52 -06001745 uplink_params.features = features;
Sean Tranchetti6cac2892019-04-19 11:04:57 -06001746 uplink_params.time_limit = time_limit;
1747 rc = rta_put(&req, &reqsize, RMNETCTL_IFLA_UPLINK_PARAMS,
1748 sizeof(uplink_params), &uplink_params);
1749 if (rc != RMNETCTL_SUCCESS) {
1750 *error_code = RMNETCTL_API_ERR_RTA_FAILURE;
1751 return rc;
1752 }
1753
1754 rta_nested_end(&req, datainfo);
1755 rta_nested_end(&req, linkinfo);
1756
1757 if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
1758 *error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
1759 return RMNETCTL_LIB_ERR;
1760 }
1761
1762 return rmnet_get_ack(hndl, error_code);
1763
1764}
Conner Huffd0f3eca2018-05-18 11:37:46 -07001765
1766int rtrmnet_activate_flow(rmnetctl_hndl_t *hndl,
1767 char *devname,
1768 char *vndname,
1769 uint8_t bearer_id,
1770 uint32_t flow_id,
1771 int ip_type,
1772 uint32_t tcm_handle,
1773 uint16_t *error_code)
1774{
Conner Huffd0f3eca2018-05-18 11:37:46 -07001775 struct tcmsg flowinfo;
Conner Huffd0f3eca2018-05-18 11:37:46 -07001776 struct nlmsg req;
Sean Tranchetti10650922018-08-16 11:42:59 -06001777 unsigned int devindex = 0;
Subash Abhinov Kasiviswanathanc26ed592018-06-15 15:38:27 -07001778 size_t reqsize =0;
Sean Tranchetti51133f52019-02-12 12:54:34 -07001779 int rc;
Conner Huffd0f3eca2018-05-18 11:37:46 -07001780
1781 memset(&req, 0, sizeof(req));
1782 memset(&flowinfo, 0, sizeof(flowinfo));
1783
1784
Subash Abhinov Kasiviswanathanc26ed592018-06-15 15:38:27 -07001785 if (!hndl || !devname || !error_code ||_rmnetctl_check_dev_name(devname) ||
1786 _rmnetctl_check_dev_name(vndname))
Conner Huffd0f3eca2018-05-18 11:37:46 -07001787 return RMNETCTL_INVALID_ARG;
1788
Sean Tranchetti51133f52019-02-12 12:54:34 -07001789 reqsize = NLMSG_DATA_SIZE - sizeof(struct rtattr);
Conner Huffd0f3eca2018-05-18 11:37:46 -07001790 req.nl_addr.nlmsg_type = RTM_NEWLINK;
1791 req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
1792 req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1793 req.nl_addr.nlmsg_seq = hndl->transaction_id;
1794 hndl->transaction_id++;
1795
1796 /* Get index of devname*/
1797 devindex = if_nametoindex(devname);
Sean Tranchetti10650922018-08-16 11:42:59 -06001798 if (devindex == 0) {
Conner Huffd0f3eca2018-05-18 11:37:46 -07001799 *error_code = errno;
1800 return RMNETCTL_KERNEL_ERR;
1801 }
1802
Conner Huffd0f3eca2018-05-18 11:37:46 -07001803 flowinfo.tcm_handle = tcm_handle;
Sean Tranchetti4fb72942019-02-12 15:36:30 -07001804 flowinfo.tcm_family = RMNET_FLOW_MSG_ACTIVATE;
Conner Huffd0f3eca2018-05-18 11:37:46 -07001805 flowinfo.tcm__pad1 = bearer_id;
1806 flowinfo.tcm_ifindex = ip_type;
1807 flowinfo.tcm_parent = flow_id;
1808
Sean Tranchettid9d69eb2019-02-12 14:30:49 -07001809 rc = rmnet_fill_flow_msg(&req, &reqsize, devindex, vndname, &flowinfo);
1810 if (rc != RMNETCTL_SUCCESS) {
1811 *error_code = RMNETCTL_API_ERR_RTA_FAILURE;
Sean Tranchetti51133f52019-02-12 12:54:34 -07001812 return rc;
Sean Tranchettid9d69eb2019-02-12 14:30:49 -07001813 }
Conner Huffd0f3eca2018-05-18 11:37:46 -07001814
1815 if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
1816 *error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
1817 return RMNETCTL_LIB_ERR;
1818 }
1819
1820 return rmnet_get_ack(hndl, error_code);
1821}
1822
1823
1824int rtrmnet_delete_flow(rmnetctl_hndl_t *hndl,
1825 char *devname,
1826 char *vndname,
1827 uint8_t bearer_id,
1828 uint32_t flow_id,
1829 int ip_type,
1830 uint16_t *error_code)
1831{
Conner Huffd0f3eca2018-05-18 11:37:46 -07001832 struct tcmsg flowinfo;
Conner Huffd0f3eca2018-05-18 11:37:46 -07001833 struct nlmsg req;
Sean Tranchetti10650922018-08-16 11:42:59 -06001834 unsigned int devindex = 0;
Subash Abhinov Kasiviswanathanc26ed592018-06-15 15:38:27 -07001835 size_t reqsize;
Sean Tranchetti51133f52019-02-12 12:54:34 -07001836 int rc;
Conner Huffd0f3eca2018-05-18 11:37:46 -07001837
1838 memset(&req, 0, sizeof(req));
1839 memset(&flowinfo, 0, sizeof(flowinfo));
1840
Subash Abhinov Kasiviswanathanc26ed592018-06-15 15:38:27 -07001841 if (!hndl || !devname || !error_code ||_rmnetctl_check_dev_name(devname) ||
1842 _rmnetctl_check_dev_name(vndname))
Conner Huffd0f3eca2018-05-18 11:37:46 -07001843 return RMNETCTL_INVALID_ARG;
1844
Subash Abhinov Kasiviswanathanc26ed592018-06-15 15:38:27 -07001845 reqsize = NLMSG_DATA_SIZE - sizeof(struct rtattr);
Conner Huffd0f3eca2018-05-18 11:37:46 -07001846 req.nl_addr.nlmsg_type = RTM_NEWLINK;
1847 req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
1848 req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1849 req.nl_addr.nlmsg_seq = hndl->transaction_id;
1850 hndl->transaction_id++;
1851
1852 /* Get index of devname*/
1853 devindex = if_nametoindex(devname);
Sean Tranchetti10650922018-08-16 11:42:59 -06001854 if (devindex == 0) {
Conner Huffd0f3eca2018-05-18 11:37:46 -07001855 *error_code = errno;
1856 return RMNETCTL_KERNEL_ERR;
1857 }
1858
Sean Tranchetti4fb72942019-02-12 15:36:30 -07001859 flowinfo.tcm_family = RMNET_FLOW_MSG_DEACTIVATE;
Sean Tranchetti51133f52019-02-12 12:54:34 -07001860 flowinfo.tcm_ifindex = ip_type;
1861 flowinfo.tcm__pad1 = bearer_id;
1862 flowinfo.tcm_parent = flow_id;
Conner Huffd0f3eca2018-05-18 11:37:46 -07001863
Sean Tranchettid9d69eb2019-02-12 14:30:49 -07001864 rc = rmnet_fill_flow_msg(&req, &reqsize, devindex, vndname, &flowinfo);
1865 if (rc != RMNETCTL_SUCCESS) {
1866 *error_code = RMNETCTL_API_ERR_RTA_FAILURE;
Sean Tranchetti51133f52019-02-12 12:54:34 -07001867 return rc;
Sean Tranchettid9d69eb2019-02-12 14:30:49 -07001868 }
Subash Abhinov Kasiviswanathanc26ed592018-06-15 15:38:27 -07001869
Sean Tranchetti51133f52019-02-12 12:54:34 -07001870 if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
1871 *error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
1872 return RMNETCTL_LIB_ERR;
1873 }
Conner Huffd0f3eca2018-05-18 11:37:46 -07001874
Sean Tranchetti51133f52019-02-12 12:54:34 -07001875 return rmnet_get_ack(hndl, error_code);
1876}
Conner Huffd0f3eca2018-05-18 11:37:46 -07001877
Sean Tranchetti51133f52019-02-12 12:54:34 -07001878int rtrmnet_control_flow(rmnetctl_hndl_t *hndl,
1879 char *devname,
1880 char *vndname,
1881 uint8_t bearer_id,
1882 uint16_t sequence,
1883 uint32_t grantsize,
1884 uint8_t ack,
1885 uint16_t *error_code)
1886{
Sean Tranchetti51133f52019-02-12 12:54:34 -07001887 struct tcmsg flowinfo;
Sean Tranchetti51133f52019-02-12 12:54:34 -07001888 struct nlmsg req;
1889 unsigned int devindex = 0;
1890 size_t reqsize;
1891 int rc;
1892
1893 memset(&req, 0, sizeof(req));
1894 memset(&flowinfo, 0, sizeof(flowinfo));
1895
1896 if (!hndl || !devname || !error_code ||_rmnetctl_check_dev_name(devname) ||
1897 _rmnetctl_check_dev_name(vndname))
1898 return RMNETCTL_INVALID_ARG;
1899
1900 reqsize = NLMSG_DATA_SIZE - sizeof(struct rtattr);
1901 req.nl_addr.nlmsg_type = RTM_NEWLINK;
1902 req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
1903 req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1904 req.nl_addr.nlmsg_seq = hndl->transaction_id;
1905 hndl->transaction_id++;
1906
1907 /* Get index of devname*/
1908 devindex = if_nametoindex(devname);
1909 if (devindex == 0) {
1910 *error_code = errno;
1911 return RMNETCTL_KERNEL_ERR;
1912 }
1913
Sean Tranchetti4fb72942019-02-12 15:36:30 -07001914 flowinfo.tcm_family = RMNET_FLOW_MSG_CONTROL;
Sean Tranchetti51133f52019-02-12 12:54:34 -07001915 flowinfo.tcm__pad1 = bearer_id;
1916 flowinfo.tcm__pad2 = sequence;
1917 flowinfo.tcm_parent = ack;
1918 flowinfo.tcm_info = grantsize;
1919
Sean Tranchettid9d69eb2019-02-12 14:30:49 -07001920 rc = rmnet_fill_flow_msg(&req, &reqsize, devindex, vndname, &flowinfo);
1921 if (rc != RMNETCTL_SUCCESS) {
1922 *error_code = RMNETCTL_API_ERR_RTA_FAILURE;
Sean Tranchetti51133f52019-02-12 12:54:34 -07001923 return rc;
Sean Tranchettid9d69eb2019-02-12 14:30:49 -07001924 }
Sean Tranchetti51133f52019-02-12 12:54:34 -07001925
1926 if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
1927 *error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
1928 return RMNETCTL_LIB_ERR;
1929 }
1930
1931 return rmnet_get_ack(hndl, error_code);
1932}
1933
1934
1935int rtrmnet_flow_state_up(rmnetctl_hndl_t *hndl,
1936 char *devname,
1937 char *vndname,
1938 uint32_t instance,
1939 uint32_t ep_type,
1940 uint32_t ifaceid,
1941 int flags,
1942 uint16_t *error_code)
1943{
Sean Tranchetti51133f52019-02-12 12:54:34 -07001944 struct tcmsg flowinfo;
Sean Tranchetti51133f52019-02-12 12:54:34 -07001945 struct nlmsg req;
1946 unsigned int devindex = 0;
1947 size_t reqsize;
1948 int rc;
1949
1950 memset(&req, 0, sizeof(req));
1951 memset(&flowinfo, 0, sizeof(flowinfo));
1952
1953 if (!hndl || !devname || !error_code ||_rmnetctl_check_dev_name(devname) ||
1954 _rmnetctl_check_dev_name(vndname))
1955 return RMNETCTL_INVALID_ARG;
1956
1957 reqsize = NLMSG_DATA_SIZE - sizeof(struct rtattr);
1958 req.nl_addr.nlmsg_type = RTM_NEWLINK;
1959 req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
1960 req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1961 req.nl_addr.nlmsg_seq = hndl->transaction_id;
1962 hndl->transaction_id++;
1963
1964 /* Get index of devname*/
1965 devindex = if_nametoindex(devname);
1966 if (devindex == 0) {
1967 *error_code = errno;
1968 return RMNETCTL_KERNEL_ERR;
1969 }
1970
Sean Tranchetti51133f52019-02-12 12:54:34 -07001971 flowinfo.tcm_handle = instance;
Sean Tranchetti4fb72942019-02-12 15:36:30 -07001972 flowinfo.tcm_family = RMNET_FLOW_MSG_UP;
Sean Tranchetti51133f52019-02-12 12:54:34 -07001973 flowinfo.tcm_ifindex = flags;
1974 flowinfo.tcm_parent = ifaceid;
1975 flowinfo.tcm_info = ep_type;
1976
Sean Tranchettid9d69eb2019-02-12 14:30:49 -07001977 rc = rmnet_fill_flow_msg(&req, &reqsize, devindex, vndname, &flowinfo);
1978 if (rc != RMNETCTL_SUCCESS) {
1979 *error_code = RMNETCTL_API_ERR_RTA_FAILURE;
Sean Tranchetti51133f52019-02-12 12:54:34 -07001980 return rc;
Sean Tranchettid9d69eb2019-02-12 14:30:49 -07001981 }
Sean Tranchetti51133f52019-02-12 12:54:34 -07001982
1983 if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
1984 *error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
1985 return RMNETCTL_LIB_ERR;
1986 }
1987
1988 return rmnet_get_ack(hndl, error_code);
1989}
1990
1991
1992int rtrmnet_flow_state_down(rmnetctl_hndl_t *hndl,
1993 char *devname,
1994 char *vndname,
1995 uint32_t instance,
1996 uint16_t *error_code)
1997{
Sean Tranchetti51133f52019-02-12 12:54:34 -07001998 struct tcmsg flowinfo;
Sean Tranchetti51133f52019-02-12 12:54:34 -07001999 struct nlmsg req;
2000 unsigned int devindex = 0;
2001 size_t reqsize;
2002 int rc;
2003
2004 memset(&req, 0, sizeof(req));
2005 memset(&flowinfo, 0, sizeof(flowinfo));
2006
2007 if (!hndl || !devname || !error_code ||_rmnetctl_check_dev_name(devname) ||
2008 _rmnetctl_check_dev_name(vndname))
2009 return RMNETCTL_INVALID_ARG;
2010
2011 reqsize = NLMSG_DATA_SIZE - sizeof(struct rtattr);
2012 req.nl_addr.nlmsg_type = RTM_NEWLINK;
2013 req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
2014 req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
2015 req.nl_addr.nlmsg_seq = hndl->transaction_id;
2016 hndl->transaction_id++;
2017
2018 /* Get index of devname*/
2019 devindex = if_nametoindex(devname);
2020 if (devindex == 0) {
2021 *error_code = errno;
2022 return RMNETCTL_KERNEL_ERR;
2023 }
2024
Conner Huffd0f3eca2018-05-18 11:37:46 -07002025 flowinfo.tcm_handle = instance;
Sean Tranchetti4fb72942019-02-12 15:36:30 -07002026 flowinfo.tcm_family = RMNET_FLOW_MSG_DOWN;
Conner Huffd0f3eca2018-05-18 11:37:46 -07002027
Sean Tranchettid9d69eb2019-02-12 14:30:49 -07002028 rc = rmnet_fill_flow_msg(&req, &reqsize, devindex, vndname, &flowinfo);
2029 if (rc != RMNETCTL_SUCCESS) {
2030 *error_code = RMNETCTL_API_ERR_RTA_FAILURE;
Sean Tranchetti51133f52019-02-12 12:54:34 -07002031 return rc;
Sean Tranchettid9d69eb2019-02-12 14:30:49 -07002032 }
Conner Huffd0f3eca2018-05-18 11:37:46 -07002033
2034 if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
2035 *error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
2036 return RMNETCTL_LIB_ERR;
2037 }
2038
2039 return rmnet_get_ack(hndl, error_code);
2040}
Sean Tranchettif74a76a2018-12-18 15:28:08 -07002041
2042int rtrmnet_set_qmi_scale(rmnetctl_hndl_t *hndl,
2043 char *devname,
2044 char *vndname,
2045 uint32_t scale,
2046 uint16_t *error_code)
2047{
2048 struct tcmsg flowinfo;
2049 struct nlmsg req;
2050 unsigned int devindex = 0;
2051 size_t reqsize;
2052 int rc;
2053
2054 memset(&req, 0, sizeof(req));
2055 memset(&flowinfo, 0, sizeof(flowinfo));
2056
2057 if (!hndl || !devname || !error_code ||_rmnetctl_check_dev_name(devname) ||
2058 _rmnetctl_check_dev_name(vndname) || !scale)
2059 return RMNETCTL_INVALID_ARG;
2060
2061 reqsize = NLMSG_DATA_SIZE - sizeof(struct rtattr);
2062 req.nl_addr.nlmsg_type = RTM_NEWLINK;
2063 req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
2064 req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
2065 req.nl_addr.nlmsg_seq = hndl->transaction_id;
2066 hndl->transaction_id++;
2067
2068 /* Get index of devname*/
2069 devindex = if_nametoindex(devname);
2070 if (devindex == 0) {
2071 *error_code = errno;
2072 return RMNETCTL_KERNEL_ERR;
2073 }
2074
2075 flowinfo.tcm_ifindex = scale;
2076 flowinfo.tcm_family = RMNET_FLOW_MSG_QMI_SCALE;
2077
2078 rc = rmnet_fill_flow_msg(&req, &reqsize, devindex, vndname, &flowinfo);
2079 if (rc != RMNETCTL_SUCCESS) {
2080 *error_code = RMNETCTL_API_ERR_RTA_FAILURE;
2081 return rc;
2082 }
2083
2084 if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
2085 *error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
2086 return RMNETCTL_LIB_ERR;
2087 }
2088
2089 return rmnet_get_ack(hndl, error_code);
2090}
2091
2092int rtrmnet_set_wda_freq(rmnetctl_hndl_t *hndl,
2093 char *devname,
2094 char *vndname,
2095 uint32_t freq,
2096 uint16_t *error_code)
2097{
2098 struct tcmsg flowinfo;
2099 struct nlmsg req;
2100 unsigned int devindex = 0;
2101 size_t reqsize;
2102 int rc;
2103
2104 memset(&req, 0, sizeof(req));
2105 memset(&flowinfo, 0, sizeof(flowinfo));
2106
2107 if (!hndl || !devname || !error_code ||_rmnetctl_check_dev_name(devname) ||
2108 _rmnetctl_check_dev_name(vndname))
2109 return RMNETCTL_INVALID_ARG;
2110
2111 reqsize = NLMSG_DATA_SIZE - sizeof(struct rtattr);
2112 req.nl_addr.nlmsg_type = RTM_NEWLINK;
2113 req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
2114 req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
2115 req.nl_addr.nlmsg_seq = hndl->transaction_id;
2116 hndl->transaction_id++;
2117
2118 /* Get index of devname*/
2119 devindex = if_nametoindex(devname);
2120 if (devindex == 0) {
2121 *error_code = errno;
2122 return RMNETCTL_KERNEL_ERR;
2123 }
2124
2125 flowinfo.tcm_ifindex = freq;
2126 flowinfo.tcm_family = RMNET_FLOW_MSG_WDA_FREQ;
2127
2128 rc = rmnet_fill_flow_msg(&req, &reqsize, devindex, vndname, &flowinfo);
2129 if (rc != RMNETCTL_SUCCESS) {
2130 *error_code = RMNETCTL_API_ERR_RTA_FAILURE;
2131 return rc;
2132 }
2133
2134 if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
2135 *error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
2136 return RMNETCTL_LIB_ERR;
2137 }
2138
2139 return rmnet_get_ack(hndl, error_code);
2140}