重现步骤
getsockname是否也需要在内核通过自定义dev来获取啊?
static int _eXosip_default_gateway_ipv4(char* destination, char* address, int size)
{
socklen_t len;
int sock_rt, on = 1;
struct sockaddr_in iface_out;
struct sockaddr_in remote;
int type;
printf("\n------ [DEBUG] Start _eXosip_default_gateway_ipv4 ------\n");
printf("[DEBUG] Input: destination=%s, address=%p, size=%d\n", destination ? destination : "NULL", address, size);
// Step 1: 初始化目标地址结构体
memset(&remote, 0, sizeof(struct sockaddr_in));
remote.sin_family = AF_INET;
remote.sin_addr.s_addr = inet_addr(destination);
remote.sin_port = htons(11111);
printf("[DEBUG] Remote address set: family=AF_INET, addr=%s, port=11111\n", inet_ntoa(remote.sin_addr));
// Step 2: 创建 UDP 套接字
memset(&iface_out, 0, sizeof(iface_out));
type = SOCK_DGRAM;
#if defined(SOCK_CLOEXEC)
type = SOCK_CLOEXEC | SOCK_DGRAM;
#endif
sock_rt = socket(AF_INET, type, 0);
printf("[DEBUG] socket() called: AF_INET, type=%d, protocol=0\n", type);
if (sock_rt == -1) {
printf("[ERROR] socket() failed! errno=%d (%s)\n", errno, strerror(errno));
snprintf(address, size, "127.0.0.1");
return OSIP_NO_NETWORK;
}
printf("[DEBUG] socket() returned fd=%d\n", sock_rt);
// Step 3: 设置 SO_BROADCAST 选项
if (setsockopt(sock_rt, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) == -1) {
printf("[ERROR] setsockopt(SO_BROADCAST) failed! errno=%d (%s)\n", errno, strerror(errno));
_eXosip_closesocket(sock_rt);
snprintf(address, size, "127.0.0.1");
return OSIP_NO_NETWORK;
}
printf("[DEBUG] setsockopt(SO_BROADCAST) success\n");
// Step 4: 连接目标地址(模拟路由选择)
printf("[DEBUG] Attempting connect() to %s:11111...\n", inet_ntoa(remote.sin_addr));
if (connect(sock_rt, (struct sockaddr*)&remote, sizeof(struct sockaddr_in)) == -1) {
printf("[ERROR] connect() failed! errno=%d (%s)\n", errno, strerror(errno));
_eXosip_closesocket(sock_rt);
snprintf(address, size, "127.0.0.1");
return OSIP_NO_NETWORK;
}
printf("[DEBUG] connect() success (UDP pseudo-connection established)\n");
// Step 5: 获取本地绑定地址(出口 IP)
len = sizeof(iface_out);
printf("[DEBUG] Calling getsockname()...\n");
if (getsockname(sock_rt, (struct sockaddr*)&iface_out, &len) == -1) {
printf("[ERROR] getsockname() failed! errno=%d (%s)\n", errno, strerror(errno));
_eXosip_closesocket(sock_rt);
snprintf(address, size, "127.0.0.1");
return OSIP_NO_NETWORK;
}
printf("[DEBUG] getsockname() returned: family=%d, addr=%s, port=%d\n", iface_out.sin_family,
inet_ntoa(iface_out.sin_addr), ntohs(iface_out.sin_port));
// iface_out.sin_addr.
// Step 6: 关闭套接字
_eXosip_closesocket(sock_rt);
printf("[DEBUG] Socket closed (fd=%d)\n", sock_rt);
// Step 7: 验证获取的 IP 是否有效
if (iface_out.sin_addr.s_addr == 0) {
printf("[WARN] getsockname() returned 0.0.0.0! No valid route to destination?\n");
snprintf(address, size, "127.0.0.1");
return OSIP_NO_NETWORK;
}
// Step 8: 返回结果
printf("[DEBUG] Final local interface IP: %s\n", inet_ntoa(iface_out.sin_addr));
osip_strncpy(address, inet_ntoa(iface_out.sin_addr), size - 1);
printf("------ [DEBUG] End _eXosip_default_gateway_ipv4 (SUCCESS) ------\n\n");
return OSIP_SUCCESS;
}
期待结果和实际结果
软硬件版本信息
错误日志
------ [DEBUG] Start _eXosip_default_gateway_ipv4 ------
[DEBUG] Input: destination=217.12.3.11, address=0x100a5cb20, size=128
[DEBUG] Remote address set: family=AF_INET, addr=217.12.3.11, port=11111
[DEBUG] socket() called: AF_INET, type=524290, protocol=0
[DEBUG] socket() returned fd=27
[DEBUG] setsockopt(SO_BROADCAST) success
[DEBUG] Attempting connect() to 217.12.3.11:11111...
[DEBUG] connect() success (UDP pseudo-connection established)
[DEBUG] Calling getsockname()...
[DEBUG] getsockname() returned: family=2, addr=0.0.0.0, port=49158
[DEBUG] Socket closed (fd=113246210)
[WARN] getsockname() returned 0.0.0.0! No valid route to destination?
[E/sal.skt] not find network interface device by protocol family(16).
[E/sal.skt] SAL socket protocol family input failed, return error -3.
尝试解决过程
补充材料