1 /*
2 * Copyright (c) 2025 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 "softbus_htp_socket.h"
17
18 #include <ctype.h>
19 #include <securec.h>
20
21 #include "anonymizer.h"
22 #include "conn_log.h"
23 #include "softbus_conn_common.h"
24 #include "softbus_socket.h"
25 #include "softbus_tcp_socket.h"
26 #include "wifi_direct_defines_struct.h"
27
28 #define IPPROTO_HTP 201
29 #define HTP_ADDR_TYPE_MAC 0
30 #define HTP_ADDR_TYPE_IPV4 1
31 #define HTP_ADDR_TYPE_IPV6 2
32
MacToHtpAddr(const char * mac,SoftBusSockAddrHtp * addr,uint16_t port)33 static int32_t MacToHtpAddr(const char *mac, SoftBusSockAddrHtp *addr, uint16_t port)
34 {
35 if (mac == NULL || addr == NULL) {
36 CONN_LOGE(CONN_COMMON, "invalid param, mac or addr is nullptr");
37 return SOFTBUS_INVALID_PARAM;
38 }
39 if (sscanf_s(mac, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", &addr->mac.addr[0], &addr->mac.addr[1],
40 &addr->mac.addr[2], &addr->mac.addr[3], &addr->mac.addr[4], &addr->mac.addr[5]) != MAC_ADDR_ARRAY_SIZE) {
41 return SOFTBUS_TRANS_SCAN_MAC_NUMBER_FAILED;
42 }
43 addr->sa_family = SOFTBUS_AF_INET;
44 addr->type = HTP_ADDR_TYPE_MAC;
45 addr->port = SoftBusHtoNs(port);
46 return SOFTBUS_OK;
47 }
48
HtpConnect(int32_t fd,const char * mac,uint16_t port)49 static int32_t HtpConnect(int32_t fd, const char *mac, uint16_t port)
50 {
51 SoftBusSockAddrHtp htpAddr;
52 int32_t ret = MacToHtpAddr(mac, &htpAddr, port);
53 if (ret != SOFTBUS_OK) {
54 CONN_LOGE(CONN_COMMON, "convert mac to htp address fail, ret=%{public}d", ret);
55 return ret;
56 }
57 return SOFTBUS_TEMP_FAILURE_RETRY(
58 SoftBusSocketConnect(fd, (SoftBusSockAddr *)&htpAddr, sizeof(SoftBusSockAddrHtp)));
59 }
60
BindLocalMac(int32_t fd,const char * mac,uint16_t port)61 static int32_t BindLocalMac(int32_t fd, const char *mac, uint16_t port)
62 {
63 SoftBusSockAddrHtp htpAddr;
64 int32_t ret = MacToHtpAddr(mac, &htpAddr, port);
65 if (ret != SOFTBUS_OK) {
66 CONN_LOGE(CONN_COMMON, "convert mac to htp address fail, ret=%{public}d", ret);
67 return ret;
68 }
69 return SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketBind(fd, (SoftBusSockAddr *)&htpAddr, sizeof(SoftBusSockAddrHtp)));
70 }
71
GetHtpSockPort(int32_t fd)72 static int32_t GetHtpSockPort(int32_t fd)
73 {
74 SoftBusSockAddr addr;
75 int32_t rc = SoftBusSocketGetLocalName(fd, &addr);
76 if (rc != SOFTBUS_ADAPTER_OK) {
77 CONN_LOGE(CONN_COMMON, "get mintp sock port fail. rc=%{public}d, fd=%{public}d", rc, fd);
78 return rc;
79 }
80 if (addr.saFamily == SOFTBUS_AF_INET6) {
81 return SoftBusNtoHs(((SoftBusSockAddrIn6 *)&addr)->sin6Port);
82 }
83 return SoftBusNtoHs(((SoftBusSockAddrIn *)&addr)->sinPort);
84 }
85
OpenHtpClientSocket(const ConnectOption * option,const char * myIp,bool isNonBlock)86 static int32_t OpenHtpClientSocket(const ConnectOption *option, const char *myIp, bool isNonBlock)
87 {
88 (void)myIp;
89 CONN_CHECK_AND_RETURN_RET_LOGE(
90 option != NULL, SOFTBUS_INVALID_PARAM, CONN_COMMON, "invalid param, option is null.");
91 CONN_CHECK_AND_RETURN_RET_LOGE(option->type == CONNECT_HML, SOFTBUS_INVALID_PARAM, CONN_COMMON,
92 "invalid param, unsupported connect type, type=%{public}d.", option->type);
93 CONN_CHECK_AND_RETURN_RET_LOGE(
94 option->socketOption.port > 0, SOFTBUS_INVALID_PARAM, CONN_COMMON, "invalid param, port is invalid.");
95 CONN_CHECK_AND_RETURN_RET_LOGE(
96 option->socketOption.addr[0] != '\0', SOFTBUS_INVALID_PARAM, CONN_COMMON, "invalid param, addr is invalid.");
97
98 char animizedMac[MAC_MAX_LEN] = { 0 };
99 ConvertAnonymizeIpAddress(
100 animizedMac, MAC_MAX_LEN, option->socketOption.remoteMac, strlen(option->socketOption.remoteMac));
101 CONN_LOGI(CONN_COMMON, "open htp client socket, server mac=%{public}s, server port=%{public}d.",
102 AnonymizeWrapper(animizedMac), option->socketOption.port);
103
104 int32_t domain = GetDomainByAddr(option->socketOption.addr);
105 int32_t fd = -1;
106 int32_t ret = SoftBusSocketCreate(domain, SOFTBUS_SOCK_DGRAM, IPPROTO_HTP, &fd);
107 if (ret != SOFTBUS_OK) {
108 CONN_LOGE(CONN_COMMON, "create htp socket fail. serverMac=%{public}s, serverPort=%{public}d, ret=%{public}d",
109 AnonymizeWrapper(animizedMac), option->socketOption.port, ret);
110 return ret;
111 }
112 if (isNonBlock && ConnToggleNonBlockMode(fd, true) != SOFTBUS_OK) {
113 CONN_LOGE(CONN_COMMON, "set nonblock mode fail. serverMac=%{public}s, serverPort=%{public}d",
114 AnonymizeWrapper(animizedMac), option->socketOption.port);
115 ConnShutdownSocket(fd);
116 return SOFTBUS_SOCKET_ERR;
117 }
118 SetClientOption(fd);
119 ret = BindLocalMac(fd, option->socketOption.localMac, 0);
120 if (ret != SOFTBUS_OK) {
121 CONN_LOGE(CONN_COMMON, "bind client address fail. ret=%{public}d", ret);
122 ConnShutdownSocket(fd);
123 return ret;
124 }
125
126 ret = HtpConnect(fd, option->socketOption.remoteMac, option->socketOption.port);
127 if ((ret != SOFTBUS_ADAPTER_OK) && (ret != SOFTBUS_ADAPTER_SOCKET_EINPROGRESS) &&
128 (ret != SOFTBUS_ADAPTER_SOCKET_EAGAIN)) {
129 CONN_LOGE(CONN_COMMON, "connect htp fail. serverMac=%{public}s, serverPort=%{public}d, ret=%{public}d",
130 AnonymizeWrapper(animizedMac), option->socketOption.port, ret);
131 ConnShutdownSocket(fd);
132 return SOFTBUS_SOCKET_ERR;
133 }
134 CONN_LOGI(CONN_COMMON, "htp connect success, fd=%{public}d, serverMac=%{public}s, serverPort=%{public}d.", fd,
135 AnonymizeWrapper(animizedMac), option->socketOption.port);
136 return fd;
137 }
138
OpenHtpServerSocket(const LocalListenerInfo * option)139 static int32_t OpenHtpServerSocket(const LocalListenerInfo *option)
140 {
141 CONN_CHECK_AND_RETURN_RET_LOGE(
142 option != NULL, SOFTBUS_INVALID_PARAM, CONN_COMMON, "invalid param, option is null.");
143 CONN_CHECK_AND_RETURN_RET_LOGE(
144 option->type == CONNECT_HML, SOFTBUS_INVALID_PARAM, CONN_COMMON, "invalid connect type.");
145 CONN_CHECK_AND_RETURN_RET_LOGE(option->socketOption.port >= 0, SOFTBUS_INVALID_PARAM, CONN_COMMON, "invalid port.");
146
147 char animizedMac[MAC_MAX_LEN] = { 0 };
148 ConvertAnonymizeIpAddress(
149 animizedMac, MAC_MAX_LEN, option->socketOption.remoteMac, strlen(option->socketOption.remoteMac));
150 CONN_LOGI(CONN_COMMON, "open htp server socket, mac=%{public}s, port=%{public}d.", AnonymizeWrapper(animizedMac),
151 option->socketOption.port);
152
153 int32_t fd = -1;
154 int32_t domain = GetDomainByAddr(option->socketOption.addr);
155 int32_t ret = SoftBusSocketCreate(
156 domain, SOFTBUS_SOCK_DGRAM | SOFTBUS_SOCK_CLOEXEC | SOFTBUS_SOCK_NONBLOCK, IPPROTO_HTP, &fd);
157 if (ret != SOFTBUS_ADAPTER_OK) {
158 CONN_LOGE(CONN_COMMON, "create htp socket fail. ret=%{public}d", ret);
159 return ret;
160 }
161 SetServerOption(fd);
162 ret = BindLocalMac(fd, option->socketOption.localMac, 0);
163 if (ret != SOFTBUS_OK) {
164 CONN_LOGE(CONN_COMMON, "bind client address fail. ret=%{public}d", ret);
165 ConnShutdownSocket(fd);
166 return ret;
167 }
168 CONN_LOGI(CONN_COMMON, "open htp server socket success, fd=%{public}d.", fd);
169 return fd;
170 }
171
AcceptHtpClient(int32_t fd,ConnectOption * clientAddr,int32_t * cfd)172 static int32_t AcceptHtpClient(int32_t fd, ConnectOption *clientAddr, int32_t *cfd)
173 {
174 CONN_CHECK_AND_RETURN_RET_LOGW(
175 clientAddr != NULL, SOFTBUS_INVALID_PARAM, CONN_COMMON, "invalid param, clientAddr is null");
176 CONN_CHECK_AND_RETURN_RET_LOGW(cfd != NULL, SOFTBUS_INVALID_PARAM, CONN_COMMON, "invalid param, cfd is null");
177 SoftBusSockAddr addr;
178 (void)memset_s(&addr, sizeof(addr), 0, sizeof(addr));
179 int32_t ret = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketAccept(fd, &addr, cfd));
180 if (ret != SOFTBUS_OK) {
181 CONN_LOGE(CONN_COMMON, "htp accept fail. ret=%{public}d", ret);
182 return ret;
183 }
184 clientAddr->type = CONNECT_HML;
185 clientAddr->socketOption.port = ((SoftBusSockAddrHtp *)&addr)->port;
186 clientAddr->socketOption.protocol = LNN_PROTOCOL_HTP;
187 unsigned char *mac_addr = ((SoftBusSockAddrHtp *)&addr)->mac.addr;
188 ret = snprintf_s(clientAddr->socketOption.addr, sizeof(clientAddr->socketOption.addr), MAC_MAX_LEN,
189 "%02X:%02X:%02X:%02X:%02X:%02X", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
190 if (ret < 0 || ret >= MAC_MAX_LEN) {
191 CONN_LOGE(CONN_COMMON, "snprintf_s fail. ret=%{public}d", ret);
192 return SOFTBUS_STRCPY_ERR;
193 }
194 for (uint32_t i = 0; i < strlen(clientAddr->socketOption.addr); i++) {
195 if (isalpha(clientAddr->socketOption.addr[i])) {
196 clientAddr->socketOption.addr[i] = tolower(clientAddr->socketOption.addr[i]);
197 }
198 }
199 return SOFTBUS_OK;
200 }
201
GetHtpProtocol(void)202 const SocketInterface *GetHtpProtocol(void)
203 {
204 static SocketInterface HtpSocketIntf = {
205 .name = "HTP",
206 .type = LNN_PROTOCOL_HTP,
207 .GetSockPort = GetHtpSockPort,
208 .OpenServerSocket = OpenHtpServerSocket,
209 .OpenClientSocket = OpenHtpClientSocket,
210 .AcceptClient = AcceptHtpClient,
211 };
212 return &HtpSocketIntf;
213 }