• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }