• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "lnn_linkwatch.h"
17 
18 #ifndef _GNU_SOURCE
19 #define _GNU_SOURCE
20 #endif
21 
22 #ifndef __MUSL__
23 #define __MUSL__
24 #endif
25 
26 #include <securec.h>
27 #include <time.h>
28 #include <unistd.h>
29 #include <linux/netlink.h>
30 #include <linux/rtnetlink.h>
31 
32 #include "softbus_adapter_errcode.h"
33 #include "softbus_adapter_socket.h"
34 #include "softbus_errcode.h"
35 #include "softbus_log.h"
36 
37 
38 #define NETLINK_BUF_LEN 1024
39 
AddAttr(struct nlmsghdr * nlMsgHdr,uint32_t maxLen,int32_t type,const uint8_t * data,uint32_t attrLen)40 static int32_t AddAttr(struct nlmsghdr *nlMsgHdr, uint32_t maxLen, int32_t type,
41     const uint8_t *data, uint32_t attrLen)
42 {
43     int32_t len = RTA_LENGTH(attrLen);
44     struct rtattr *rta = NULL;
45 
46     if (NLMSG_ALIGN(nlMsgHdr->nlmsg_len) + RTA_ALIGN(len) > maxLen) {
47         SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "AddAttr ERROR: message exceeded bound of %d\n", maxLen);
48         return SOFTBUS_ERR;
49     }
50     rta = ((struct rtattr *) (((uint8_t *) (nlMsgHdr)) + NLMSG_ALIGN((nlMsgHdr)->nlmsg_len)));
51     rta->rta_type = (uint16_t)type;
52     rta->rta_len = (uint16_t)len;
53     if (memcpy_s(RTA_DATA(rta), rta->rta_len, data, attrLen) != EOK) {
54         SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "AddAttr ERROR: memcpy attr failed");
55         return SOFTBUS_MEM_ERR;
56     }
57     nlMsgHdr->nlmsg_len = NLMSG_ALIGN(nlMsgHdr->nlmsg_len) + RTA_ALIGN(len);
58     return SOFTBUS_OK;
59 }
60 
ProcessNetlinkAnswer(struct nlmsghdr * answer,int32_t bufLen,uint32_t seq)61 static int32_t ProcessNetlinkAnswer(struct nlmsghdr *answer, int32_t bufLen, uint32_t seq)
62 {
63     struct nlmsghdr *hdr = NULL;
64     uint32_t len;
65     int32_t remain = bufLen;
66 
67     for (hdr = (struct nlmsghdr *)answer; remain >= (int32_t)sizeof(*hdr);) {
68         len = hdr->nlmsg_len;
69         if ((hdr->nlmsg_len - sizeof(*hdr)) < 0 || len > (uint32_t)remain) {
70             SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "malformed message: len=%d", len);
71             return SOFTBUS_ERR;
72         }
73         if (hdr->nlmsg_seq != seq) {
74             // skip that message
75             remain -= NLMSG_ALIGN(len);
76             hdr = (struct nlmsghdr *)((char *)hdr + NLMSG_ALIGN(len));
77             continue;
78         }
79         if (hdr->nlmsg_type == NLMSG_ERROR) {
80             SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "ERROR netlink msg");
81             return SOFTBUS_ERR;
82         }
83         return SOFTBUS_OK;
84     }
85     return SOFTBUS_ERR;
86 }
87 
RtNetlinkTalk(struct nlmsghdr * nlMsgHdr,struct nlmsghdr * answer,uint32_t maxlen)88 static int32_t RtNetlinkTalk(struct nlmsghdr *nlMsgHdr, struct nlmsghdr *answer, uint32_t maxlen)
89 {
90     int32_t status;
91     int32_t fd;
92 
93     int32_t ret  = SoftBusSocketCreate(SOFTBUS_AF_NETLINK, SOFTBUS_SOCK_RAW, NETLINK_ROUTE, &fd);
94     if (ret != SOFTBUS_ADAPTER_OK) {
95         SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "netlink_socket failed");
96         return SOFTBUS_ERR;
97     }
98 
99     status = SoftBusSocketSend(fd, nlMsgHdr, nlMsgHdr->nlmsg_len, 0);
100     if (status != (int32_t)(nlMsgHdr->nlmsg_len)) {
101         SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "Cannot talk to rtnetlink");
102         SoftBusSocketClose(fd);
103         return SOFTBUS_ERR;
104     }
105 
106     while (true) {
107         status = SoftBusSocketRecv(fd, answer, maxlen, 0);
108         if (status < 0) {
109             if (status == SOFTBUS_ADAPTER_SOCKET_EINTR || status == SOFTBUS_ADAPTER_SOCKET_EAGAIN) {
110                 continue;
111             }
112             SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "netlink receive error (%d)", status);
113             SoftBusSocketClose(fd);
114             return SOFTBUS_ERR;
115         }
116         if (status == 0) {
117             SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "EOF on netlink\n");
118             SoftBusSocketClose(fd);
119             return SOFTBUS_ERR;
120         }
121         SoftBusSocketClose(fd);
122         return ProcessNetlinkAnswer(answer, status, nlMsgHdr->nlmsg_seq);
123     }
124 }
125 
GetRtAttr(struct rtattr * rta,int32_t len,uint16_t type,uint8_t * value,uint32_t valueLen)126 static int32_t GetRtAttr(struct rtattr *rta, int32_t len, uint16_t type, uint8_t *value, uint32_t valueLen)
127 {
128     struct rtattr *attr = rta;
129     while (RTA_OK(attr, len)) {
130         if (attr->rta_type != type) {
131             attr = RTA_NEXT(attr, len);
132             continue;
133         }
134         if (memcpy_s(value, valueLen, RTA_DATA(attr), (uint32_t)RTA_PAYLOAD(attr)) != EOK) {
135             SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "get attr fail: %d, %d",
136                 valueLen, RTA_PAYLOAD(attr));
137             break;
138         }
139         return SOFTBUS_OK;
140     }
141     return SOFTBUS_ERR;
142 }
143 
LnnIsLinkReady(const char * iface)144 bool LnnIsLinkReady(const char *iface)
145 {
146     if (iface == NULL) {
147         return false;
148     }
149     struct ifinfomsg *info = NULL;
150     struct {
151         struct nlmsghdr hdr;
152         struct ifinfomsg info;
153         char buf[NETLINK_BUF_LEN];
154     } req = {
155         .hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
156         .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
157         .hdr.nlmsg_type = RTM_GETLINK,
158         .info.ifi_family = SOFTBUS_PF_UNSPEC,
159     };
160     struct {
161         struct nlmsghdr hdr;
162         char buf[NETLINK_BUF_LEN + NETLINK_BUF_LEN];
163     } answer;
164     int32_t infoDataLen, seq;
165     uint8_t carrier;
166 
167     seq = time(NULL);
168     if (seq < 0) {
169         seq = 0;
170     }
171     req.hdr.nlmsg_seq = ++seq;
172     (void)memset_s(&answer, sizeof(answer), 0, sizeof(answer));
173     if (AddAttr(&req.hdr, sizeof(req), IFLA_IFNAME, (const uint8_t *)iface, strlen(iface) + 1) != SOFTBUS_OK) {
174         return false;
175     }
176     if (RtNetlinkTalk(&req.hdr, &answer.hdr, sizeof(answer)) != SOFTBUS_OK) {
177         return false;
178     }
179     info = NLMSG_DATA(&answer.hdr);
180     infoDataLen = (int32_t)answer.hdr.nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));
181     if (GetRtAttr(IFLA_RTA(info), infoDataLen, IFLA_CARRIER, &carrier, sizeof(uint8_t)) != SOFTBUS_OK) {
182         return false;
183     }
184     SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_INFO, "carrier result: %d\n", carrier);
185     return carrier != 0;
186 }