-
-
Notifications
You must be signed in to change notification settings - Fork 597
LocalIP: consider preferred source address when retrieving default route #1883
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
f285ccc
03b537b
0594c9f
c57e903
bf5a55c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -50,7 +50,7 @@ get_rt_address(struct rt_msghdr *rtm, int desired) | |||||
| return NULL; | ||||||
| } | ||||||
|
|
||||||
| bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex) | ||||||
| bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex, uint32_t* preferredSourceAddr) | ||||||
| { | ||||||
| #if defined(__OpenBSD__) || defined(__DragonFly__) | ||||||
| int mib[6] = {CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_FLAGS, RTF_GATEWAY}; | ||||||
|
|
@@ -80,6 +80,12 @@ bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex) | |||||
| memcpy(iface, sdl->sdl_data, sdl->sdl_nlen); | ||||||
| iface[sdl->sdl_nlen] = '\0'; | ||||||
| *ifIndex = sdl->sdl_index; | ||||||
|
|
||||||
| // Get the preferred source address | ||||||
| struct sockaddr_in* src = (struct sockaddr_in*)get_rt_address(rtm, RTA_IFA); | ||||||
| if (preferredSourceAddr && src && src->sin_family == AF_INET) | ||||||
| *preferredSourceAddr = src->sin_addr; | ||||||
|
||||||
| *preferredSourceAddr = src->sin_addr; | |
| *preferredSourceAddr = src->sin_addr.s_addr; |
Copilot uses AI. Check for mistakes.
Outdated
Copilot
AI
Aug 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type mismatch: sin_addr is of type struct in_addr, but preferredSourceAddr expects uint32_t. Should use src->sin_addr.s_addr instead.
| *preferredSourceAddr = src->sin_addr; | |
| *preferredSourceAddr = src->sin_addr.s_addr; |
Copilot uses AI. Check for mistakes.
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,27 +1,182 @@ | ||||||||||||||
| #include "netif.h" | ||||||||||||||
| #include "common/io/io.h" | ||||||||||||||
|
|
||||||||||||||
| #include <arpa/inet.h> | ||||||||||||||
| #include <linux/rtnetlink.h> | ||||||||||||||
| #include <net/if.h> | ||||||||||||||
| #include <stdio.h> | ||||||||||||||
|
|
||||||||||||||
| #define FF_STR_INDIR(x) #x | ||||||||||||||
| #define FF_STR(x) FF_STR_INDIR(x) | ||||||||||||||
|
|
||||||||||||||
| static bool getDefaultRouteIPv4(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex) | ||||||||||||||
| struct req_t { | ||||||||||||||
| struct nlmsghdr nlh; | ||||||||||||||
| struct rtmsg rtm; | ||||||||||||||
| struct rtattr rta; | ||||||||||||||
| uint32_t table; | ||||||||||||||
| }; | ||||||||||||||
|
|
||||||||||||||
| struct Route4Entry { | ||||||||||||||
| uint32_t dest; | ||||||||||||||
| uint32_t gateway; | ||||||||||||||
| uint32_t src; | ||||||||||||||
| uint8_t prefix_length; | ||||||||||||||
| uint32_t metric; | ||||||||||||||
| uint32_t ifindex; | ||||||||||||||
| }; | ||||||||||||||
|
|
||||||||||||||
| static bool getDefaultRouteIPv4(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex, uint32_t* preferredSourceAddr) | ||||||||||||||
| { | ||||||||||||||
| FILE* FF_AUTO_CLOSE_FILE netRoute = fopen("/proc/net/route", "r"); | ||||||||||||||
| if (!netRoute) return false; | ||||||||||||||
| int sock_fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE); | ||||||||||||||
| if (sock_fd < 0) | ||||||||||||||
| return false; | ||||||||||||||
|
|
||||||||||||||
| // skip first line | ||||||||||||||
| FF_UNUSED(fscanf(netRoute, "%*[^\n]\n")); | ||||||||||||||
| // Bind socket | ||||||||||||||
| struct sockaddr_nl addr; | ||||||||||||||
| memset(&addr, 0, sizeof(addr)); | ||||||||||||||
| addr.nl_family = AF_NETLINK; | ||||||||||||||
| addr.nl_pid = 0; // Let kernel assign PID | ||||||||||||||
| addr.nl_groups = 0; | ||||||||||||||
|
|
||||||||||||||
| unsigned long long destination; //, gateway, flags, refCount, use, metric, mask, mtu, ... | ||||||||||||||
| while (fscanf(netRoute, "%" FF_STR(IF_NAMESIZE) "s%llx%*[^\n]", iface, &destination) == 2) | ||||||||||||||
| { | ||||||||||||||
| if (destination != 0) continue; | ||||||||||||||
| *ifIndex = if_nametoindex(iface); | ||||||||||||||
| if (bind(sock_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { | ||||||||||||||
| close(sock_fd); | ||||||||||||||
| return false; | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| struct req_t req; | ||||||||||||||
| memset(&req, 0, sizeof(req)); | ||||||||||||||
|
|
||||||||||||||
| // Netlink message header | ||||||||||||||
| req.nlh.nlmsg_len = sizeof(req); | ||||||||||||||
| req.nlh.nlmsg_type = RTM_GETROUTE; | ||||||||||||||
| req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; | ||||||||||||||
| req.nlh.nlmsg_seq = 0; | ||||||||||||||
| req.nlh.nlmsg_pid = 0; | ||||||||||||||
|
|
||||||||||||||
| // Route message | ||||||||||||||
| req.rtm.rtm_family = AF_INET; | ||||||||||||||
| req.rtm.rtm_dst_len = 0; | ||||||||||||||
| req.rtm.rtm_src_len = 0; | ||||||||||||||
| req.rtm.rtm_tos = 0; | ||||||||||||||
| req.rtm.rtm_table = RT_TABLE_UNSPEC; | ||||||||||||||
| req.rtm.rtm_protocol = RTPROT_UNSPEC; | ||||||||||||||
| req.rtm.rtm_scope = RT_SCOPE_UNIVERSE; | ||||||||||||||
| req.rtm.rtm_type = RTN_UNSPEC; | ||||||||||||||
| req.rtm.rtm_flags = 0; | ||||||||||||||
|
|
||||||||||||||
| // Route attribute for main table | ||||||||||||||
| req.rta.rta_len = RTA_LENGTH(sizeof(uint32_t)); | ||||||||||||||
| req.rta.rta_type = RTA_TABLE; | ||||||||||||||
| req.table = RT_TABLE_MAIN; | ||||||||||||||
|
|
||||||||||||||
| struct sockaddr_nl dest_addr; | ||||||||||||||
| memset(&dest_addr, 0, sizeof(dest_addr)); | ||||||||||||||
| dest_addr.nl_family = AF_NETLINK; | ||||||||||||||
| dest_addr.nl_pid = 0; | ||||||||||||||
| dest_addr.nl_groups = 0; | ||||||||||||||
|
|
||||||||||||||
| ssize_t sent = sendto(sock_fd, &req, sizeof(req), 0, | ||||||||||||||
| (struct sockaddr*)&dest_addr, sizeof(dest_addr)); | ||||||||||||||
|
|
||||||||||||||
| if (sent != sizeof(req)) { | ||||||||||||||
| close(sock_fd); | ||||||||||||||
| return false; | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| struct sockaddr_nl src_addr; | ||||||||||||||
| socklen_t src_addr_len = sizeof(src_addr); | ||||||||||||||
| struct iovec iov = {NULL, 0}; | ||||||||||||||
| struct msghdr msg; | ||||||||||||||
|
|
||||||||||||||
| memset(&msg, 0, sizeof(msg)); | ||||||||||||||
| msg.msg_name = &src_addr; | ||||||||||||||
| msg.msg_namelen = sizeof(src_addr); | ||||||||||||||
| msg.msg_iov = &iov; | ||||||||||||||
| msg.msg_iovlen = 1; | ||||||||||||||
|
|
||||||||||||||
| ssize_t peek_size = recvmsg(sock_fd, &msg, MSG_PEEK | MSG_TRUNC); | ||||||||||||||
| if (peek_size < 0) { | ||||||||||||||
| close(sock_fd); | ||||||||||||||
| return false; | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| uint8_t *buffer = malloc((size_t)peek_size); | ||||||||||||||
|
||||||||||||||
| uint8_t *buffer = malloc((size_t)peek_size); | |
| uint8_t *buffer = malloc((size_t)peek_size); | |
| if (buffer == NULL) { | |
| // malloc failed, clean up and return error | |
| return false; | |
| } |
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't check malloc errors. But We prefer FF_AUTO_FREE instead of free(buffer) manually
jannispl marked this conversation as resolved.
Show resolved
Hide resolved
jannispl marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Outdated
Copilot
AI
Aug 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The buffer is freed unconditionally, but if malloc failed at line 102, this will attempt to free a NULL pointer or uninitialized memory.
| free(buffer); | |
| if (buffer) { | |
| free(buffer); | |
| } |
Copilot uses AI. Check for mistakes.
Uh oh!
There was an error while loading. Please reload this page.