Merge "Return errors to caller" into tizen_5.5
[platform/core/connectivity/stc-manager.git] / src / helper / helper-nl.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "helper-nl.h"
18
19 #include <unistd.h>
20 #include <linux/rtnetlink.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <errno.h>
24
25 #define NETLINK_SOCK_RETRY_COUNT 3
26
27 int __create_netlink(int protocol, uint32_t groups, int retry)
28 {
29         /**
30          * TODO it's one socket, in future make set of sockets
31          * unique for protocol and groups
32          */
33         int sock;
34
35         if (retry <= 0)
36                 return -EINVAL; //LCOV_EXCL_LINE
37
38         errno = 0;
39         sock = socket(PF_NETLINK, SOCK_RAW, protocol);
40         if (sock < 0) {
41                 STC_LOGE("failed to open socket errno [%d], retry [%d]",
42                                 errno, NETLINK_SOCK_RETRY_COUNT - retry); //LCOV_EXCL_LINE
43                 return __create_netlink(protocol, groups, --retry); //LCOV_EXCL_LINE
44         }
45
46         struct sockaddr_nl src_addr = { 0, };
47
48         src_addr.nl_family = AF_NETLINK;
49         src_addr.nl_groups = groups;
50
51         errno = 0;
52         if (bind(sock, (struct sockaddr *)&src_addr, sizeof(src_addr)) < 0) {
53                 STC_LOGE("failed to bind socket errno [%d], retry [%d]",
54                                 errno, NETLINK_SOCK_RETRY_COUNT - retry); //LCOV_EXCL_LINE
55                 close(sock); //LCOV_EXCL_LINE
56                 return __create_netlink(protocol, groups, --retry); //LCOV_EXCL_LINE
57         }
58
59         return sock;
60 }
61
62 /**
63  * create_netlink(): Create netlink socket and returns it.
64  * Returns: Created socket on success and -1 on failure.
65  */
66 API int create_netlink(int protocol, uint32_t groups)
67 {
68         return __create_netlink(protocol, groups, NETLINK_SOCK_RETRY_COUNT);
69 }
70
71 void fill_attribute_list(struct rtattr **atb, const int max_len,
72                          struct rtattr *rt_na, int rt_len)
73 {
74         int i = 0;
75         while (RTA_OK(rt_na, rt_len)) {
76                 if (rt_na->rta_type <= max_len)
77                         atb[rt_na->rta_type] = rt_na;
78
79                 rt_na = RTA_NEXT(rt_na, rt_len);
80                 ++i;
81                 if (i >= max_len)
82                         break;
83         }
84 }
85
86 /* read netlink message from socket
87  * return opaque pointer to genl structure
88  */
89 API int read_netlink(int sock, void *buf, size_t len)
90 {
91         ssize_t ret;
92         struct sockaddr_nl addr;
93         struct iovec iov = {
94                 .iov_base       = buf,
95                 .iov_len        = len,
96         };
97         struct msghdr msg = {
98                 .msg_name       = &addr,
99                 .msg_namelen    = sizeof(struct sockaddr_nl),
100                 .msg_iov        = &iov,
101                 .msg_iovlen     = 1,
102                 .msg_control    = NULL,
103                 .msg_controllen = 0,
104                 .msg_flags      = 0,
105         };
106         ret = recvmsg(sock, &msg, 0);
107         if (ret == -1)
108                 return ret; //LCOV_EXCL_LINE
109
110         if (msg.msg_flags & MSG_TRUNC) {
111                 errno = ENOSPC; //LCOV_EXCL_LINE
112                 return -1; //LCOV_EXCL_LINE
113         }
114
115         if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
116                 errno = EINVAL; //LCOV_EXCL_LINE
117                 return -1; //LCOV_EXCL_LINE
118         }
119
120         return ret;
121 }