/****************************************************************************** * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. * qtfs licensed under the Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. * You may obtain a copy of Mulan PSL v2 at: * http://license.coscl.org.cn/MulanPSL2 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR * PURPOSE. * See the Mulan PSL v2 for more details. * Author: Liqiang * Create: 2023-03-20 * Description: *******************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include "uds_module.h" #define LOG_OFF 1 #if LOG_OFF #define uds_log(info, ...) #define uds_err(info, ...) #else #define uds_log(info, ...) \ do { \ time_t t; \ struct tm p; \ time(&t); \ localtime_r(&t, &p); \ printf("[%d/%02d/%02d %02d:%02d:%02d][LOG:%s:%3d]"info"\n", \ p.tm_year + 1900, p.tm_mon+1, p.tm_mday, \ p.tm_hour, p.tm_min, p.tm_sec, __func__, __LINE__, ##__VA_ARGS__); \ } while (0); #define uds_err(info, ...) \ do { \ time_t t; \ struct tm p; \ time(&t); \ localtime_r(&t, &p); \ printf("[%d/%02d/%02d %02d:%02d:%02d][LOG:%s:%3d]"info"\n", \ p.tm_year + 1900, p.tm_mon+1, p.tm_mday, \ p.tm_hour, p.tm_min, p.tm_sec, __func__, __LINE__, ##__VA_ARGS__); \ } while (0); #endif static unsigned short uds_conn_get_sock_type(int sockfd) { unsigned short type; socklen_t len = 2; int ret = getsockopt(sockfd, SOL_SOCKET, SO_TYPE, &type, &len); if (ret < 0) { uds_err("get sock type failed, fd:%d", sockfd); return (unsigned short)-1; } uds_log("fd:%d type:%d", sockfd, type); return type; } static int uds_conn_whitelist_check(const char *path) { return 1; } int connect(int fd, const struct sockaddr *addrarg, socklen_t len) { int sock_fd; typeof(connect) *libcconnect = NULL; int libcret; const struct sockaddr_un *addr = (const struct sockaddr_un *)addrarg; if (libcconnect == NULL) { libcconnect = dlsym(((void *) - 1l), "connect"); if (libcconnect == NULL) { uds_err("can't find connect by dlsym."); return -1; } } libcret = (*libcconnect)(fd, addrarg, len); if (libcret == 0 || addr->sun_family != AF_UNIX) { // 如果本地connect成功,或者非UNIX DOMAIN SOCKET,都直接返回即可 return libcret; } if (strlen(addr->sun_path) >= (UDS_SUN_PATH_LEN - strlen(UDS_PROXY_SUFFIX))) { uds_err("sun_path:<%s> len:%d is too large to add suffex:<%s>, so can't connect to uds proxy.", addr->sun_path, strlen(addr->sun_path), UDS_PROXY_SUFFIX); return libcret; } uds_log("enter uds connect fd:%d sunpath:%s family:%d len:%d ", fd, addr->sun_path, addr->sun_family, len); // 本地未连接,且是uds链接 if (!uds_conn_whitelist_check(addr->sun_path)) { uds_err("path:%s not in white list", addr->sun_path); return libcret; } // 尝试远端链接 do { int ret; struct uds_proxy_remote_conn_req remoteconn; struct uds_proxy_remote_conn_rsp remotersp; struct sockaddr_un proxy = {.sun_family = AF_UNIX}; sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); if (sock_fd < 0) { uds_err("create socket failed"); return libcret; } strncpy(proxy.sun_path, UDS_BUILD_CONN_ADDR, sizeof(proxy.sun_path)); if ((*libcconnect)(sock_fd, (struct sockaddr *)&proxy, sizeof(struct sockaddr_un)) < 0) { uds_err("can't connect to uds proxy: %s", UDS_BUILD_CONN_ADDR); goto err_end; } // 这里type需要是第一个入参fd的type remoteconn.type = uds_conn_get_sock_type(fd); if (remoteconn.type == (unsigned short)-1) { remoteconn.type = SOCK_STREAM; } memset(remoteconn.sun_path, 0, sizeof(remoteconn.sun_path)); strncpy(remoteconn.sun_path, addr->sun_path, sizeof(remoteconn.sun_path)); ret = send(sock_fd, &remoteconn, sizeof(remoteconn), 0); if (ret <= 0) { uds_err("send remote connect request failed, ret:%d errno:%d", ret, errno); goto err_end; } ret = recv(sock_fd, &remotersp, sizeof(remotersp), MSG_WAITALL); if (ret <= 0) { uds_err("recv remote connect replay failed, ret:%d errno:%d", ret, errno); goto err_end; } if (remotersp.ret == 0) { goto err_end; } } while(0); close(sock_fd); struct sockaddr_un addr_proxy; int sun_len = strlen(addr->sun_path); memcpy(&addr_proxy, addr, sizeof(struct sockaddr_un)); memcpy(&addr_proxy.sun_path[sun_len], UDS_PROXY_SUFFIX, strlen(UDS_PROXY_SUFFIX)); addr_proxy.sun_path[sun_len + strlen(UDS_PROXY_SUFFIX)] = '\0'; return (*libcconnect)(fd, (const struct sockaddr *)&addr_proxy, sizeof(struct sockaddr_un)); err_end: close(sock_fd); return libcret; }