1 /*
2 * Copyright (c) 2022 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 #include "lnn_physical_subnet_manager.h"
16
17 #include <stddef.h>
18 #include <string.h>
19
20 #include "lnn_network_manager.h"
21 #include "softbus_adapter_thread.h"
22 #include "softbus_def.h"
23 #include "softbus_errcode.h"
24 #include "softbus_log.h"
25
26 #define MAX_SUPPORTED_PHYSICAL_SUBNET 6
27
28 static SoftBusMutex g_physicalSubnetsLock;
29 static LnnPhysicalSubnet *g_physicalSubnets[MAX_SUPPORTED_PHYSICAL_SUBNET];
30
31 #define CALL_WITH_LOCK(RET, LOCK, ACTION) \
32 do { \
33 ret = SoftBusMutexLock(LOCK); \
34 if (ret != SOFTBUS_OK) { \
35 HILOG_ERROR(SOFTBUS_HILOG_ID, "%s:lock mutex failed", __func__); \
36 break; \
37 } \
38 (RET) = (ACTION); \
39 SoftBusMutexUnlock(LOCK); \
40 } while (false)
41
42 #define CALL_VOID_FUNC_WITH_LOCK(LOCK, ACTION) \
43 do { \
44 if (SoftBusMutexLock(LOCK) != 0) { \
45 HILOG_ERROR(SOFTBUS_HILOG_ID, "%s:lock mutex failed", __func__); \
46 break; \
47 } \
48 (ACTION); \
49 SoftBusMutexUnlock(LOCK); \
50 } while (false)
51
LnnInitPhysicalSubnetManager(void)52 NO_SANITIZE("cfi") int32_t LnnInitPhysicalSubnetManager(void)
53 {
54 return SoftBusMutexInit(&g_physicalSubnetsLock, NULL);
55 }
56
ClearSubnetManager(void)57 static void ClearSubnetManager(void)
58 {
59 for (uint8_t i = 0; i < MAX_SUPPORTED_PHYSICAL_SUBNET; i++) {
60 if (g_physicalSubnets[i] != NULL) {
61 if (g_physicalSubnets[i]->destroy != NULL) {
62 g_physicalSubnets[i]->destroy(g_physicalSubnets[i]);
63 }
64 g_physicalSubnets[i] = NULL;
65 }
66 }
67 }
68
LnnDeinitPhysicalSubnetManager(void)69 NO_SANITIZE("cfi") void LnnDeinitPhysicalSubnetManager(void)
70 {
71 CALL_VOID_FUNC_WITH_LOCK(&g_physicalSubnetsLock, ClearSubnetManager());
72 if (SoftBusMutexDestroy(&g_physicalSubnetsLock) != SOFTBUS_OK) {
73 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "%s: destroy mutex failed!", __func__);
74 }
75 }
76
DoRegistSubnet(LnnPhysicalSubnet * subnet)77 static int32_t DoRegistSubnet(LnnPhysicalSubnet *subnet)
78 {
79 for (uint8_t i = 0; i < MAX_SUPPORTED_PHYSICAL_SUBNET; i++) {
80 if (g_physicalSubnets[i] != NULL) {
81 continue;
82 }
83 g_physicalSubnets[i] = subnet;
84 if (g_physicalSubnets[i]->onNetifStatusChanged != NULL) {
85 g_physicalSubnets[i]->onNetifStatusChanged(g_physicalSubnets[i], NULL);
86 }
87 return SOFTBUS_OK;
88 }
89 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "%s: subnet list is full", __func__);
90 return SOFTBUS_ERR;
91 }
92
LnnRegistPhysicalSubnet(LnnPhysicalSubnet * subnet)93 NO_SANITIZE("cfi") int32_t LnnRegistPhysicalSubnet(LnnPhysicalSubnet *subnet)
94 {
95 if (subnet == NULL || subnet->protocol == NULL) {
96 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "%s: protocol of subnet is required!", __func__);
97 return SOFTBUS_ERR;
98 }
99 int32_t ret = SOFTBUS_OK;
100 CALL_WITH_LOCK(ret, &g_physicalSubnetsLock, DoRegistSubnet(subnet));
101 return ret;
102 }
103
DoUnregistSubnetByType(ProtocolType type)104 static int32_t DoUnregistSubnetByType(ProtocolType type)
105 {
106 for (uint8_t i = 0; i < MAX_SUPPORTED_PHYSICAL_SUBNET; i++) {
107 if (g_physicalSubnets[i] != NULL && g_physicalSubnets[i]->protocol->id == type) {
108 if (g_physicalSubnets[i]->destroy != NULL) {
109 g_physicalSubnets[i]->destroy(g_physicalSubnets[i]);
110 }
111 g_physicalSubnets[i] = NULL;
112 }
113 }
114 return SOFTBUS_OK;
115 }
116
LnnUnregistPhysicalSubnetByType(ProtocolType type)117 NO_SANITIZE("cfi") int32_t LnnUnregistPhysicalSubnetByType(ProtocolType type)
118 {
119 int32_t ret = SOFTBUS_OK;
120 CALL_WITH_LOCK(ret, &g_physicalSubnetsLock, DoUnregistSubnetByType(type));
121 return ret;
122 }
123
DoNotifyStatusChange(const char * ifName,ProtocolType protocolType,void * status)124 void DoNotifyStatusChange(const char *ifName, ProtocolType protocolType, void *status)
125 {
126 for (uint16_t i = 0; i < MAX_SUPPORTED_PHYSICAL_SUBNET; i++) {
127 if (g_physicalSubnets[i] == NULL || g_physicalSubnets[i]->protocol->id != protocolType) {
128 continue;
129 }
130
131 if (strcmp(g_physicalSubnets[i]->ifName, LNN_PHYSICAL_SUBNET_ALL_NETIF) != 0 &&
132 strcmp(g_physicalSubnets[i]->ifName, ifName) != 0) {
133 continue;
134 }
135
136 if (g_physicalSubnets[i]->onNetifStatusChanged != NULL) {
137 g_physicalSubnets[i]->onNetifStatusChanged(g_physicalSubnets[i], status);
138 }
139 }
140 }
141
LnnNotifyPhysicalSubnetStatusChanged(const char * ifName,ProtocolType protocolType,void * status)142 void LnnNotifyPhysicalSubnetStatusChanged(const char *ifName, ProtocolType protocolType, void *status)
143 {
144 CALL_VOID_FUNC_WITH_LOCK(&g_physicalSubnetsLock, DoNotifyStatusChange(ifName, protocolType, status));
145 }
146
EnableResetingSubnetByType(ProtocolType protocolType)147 NO_SANITIZE("cfi") static void EnableResetingSubnetByType(ProtocolType protocolType)
148 {
149 for (uint16_t i = 0; i < MAX_SUPPORTED_PHYSICAL_SUBNET; i++) {
150 if (g_physicalSubnets[i] == NULL || g_physicalSubnets[i]->protocol->id != protocolType) {
151 continue;
152 }
153 if (g_physicalSubnets[i]->onSoftbusNetworkDisconnected != NULL) {
154 g_physicalSubnets[i]->onSoftbusNetworkDisconnected(g_physicalSubnets[i]);
155 }
156 }
157 }
158
LnnNotifyAllTypeOffline(ConnectionAddrType type)159 NO_SANITIZE("cfi") void LnnNotifyAllTypeOffline(ConnectionAddrType type)
160 {
161 if (type == CONNECTION_ADDR_ETH || type == CONNECTION_ADDR_WLAN || type == CONNECTION_ADDR_MAX) {
162 CALL_VOID_FUNC_WITH_LOCK(&g_physicalSubnetsLock, EnableResetingSubnetByType(LNN_PROTOCOL_IP));
163 }
164 }
165
DoVisitSubnet(LnnVisitPhysicalSubnetCallback callback,void * data)166 static bool DoVisitSubnet(LnnVisitPhysicalSubnetCallback callback, void *data)
167 {
168 VisitNextChoice result = CHOICE_VISIT_NEXT;
169 for (uint16_t i = 0; i < MAX_SUPPORTED_PHYSICAL_SUBNET; i++) {
170 if (g_physicalSubnets[i] == NULL) {
171 continue;
172 }
173 result = callback(g_physicalSubnets[i], data);
174 if (result == CHOICE_FINISH_VISITING) {
175 return false;
176 }
177 }
178 return true;
179 }
180
LnnVisitPhysicalSubnet(LnnVisitPhysicalSubnetCallback callback,void * data)181 NO_SANITIZE("cfi") bool LnnVisitPhysicalSubnet(LnnVisitPhysicalSubnetCallback callback, void *data)
182 {
183 bool ret = false;
184 CALL_WITH_LOCK(ret, &g_physicalSubnetsLock, DoVisitSubnet(callback, data));
185 return ret;
186 }
187