implement auto gateway Ip auto detection (#25)
Reviewed-on: #25 implemented #19
This commit was merged in pull request #25.
This commit is contained in:
+86
-1
@@ -15,6 +15,7 @@
|
||||
#include <net/if.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/route.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
@@ -64,6 +65,54 @@ static int get_ip(const char *iface, char *out, size_t sz)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Find the IPv4 next hop used by the kernel's default route. Prefer the
|
||||
* configured LAN interface when more than one default route exists. */
|
||||
static int get_default_gateway(const char *preferred_iface,
|
||||
char *out, size_t sz)
|
||||
{
|
||||
FILE *f = fopen("/proc/net/route", "r");
|
||||
if (!f) return -1;
|
||||
|
||||
char line[256];
|
||||
char iface[IFNAMSIZ];
|
||||
unsigned long destination, gateway;
|
||||
unsigned int flags, metric;
|
||||
unsigned int best_metric = ~0U;
|
||||
unsigned long best_gateway = 0;
|
||||
int best_preferred = 0;
|
||||
|
||||
/* Skip the column headings. */
|
||||
if (!fgets(line, sizeof(line), f)) {
|
||||
fclose(f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
if (sscanf(line, "%15s %lx %lx %x %*u %*u %u %*lx",
|
||||
iface, &destination, &gateway, &flags,
|
||||
&metric) != 5)
|
||||
continue;
|
||||
if (destination != 0 || gateway == 0 ||
|
||||
!(flags & RTF_UP) || !(flags & RTF_GATEWAY))
|
||||
continue;
|
||||
|
||||
int preferred = preferred_iface && preferred_iface[0] &&
|
||||
!strcmp(iface, preferred_iface);
|
||||
if (!best_gateway || preferred > best_preferred ||
|
||||
(preferred == best_preferred && metric < best_metric)) {
|
||||
best_gateway = gateway;
|
||||
best_metric = metric;
|
||||
best_preferred = preferred;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
if (!best_gateway) return -1;
|
||||
|
||||
struct in_addr addr = { .s_addr = (in_addr_t)best_gateway };
|
||||
return inet_ntop(AF_INET, &addr, out, sz) ? 0 : -1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
for (int i = 1; i < argc-1; i++)
|
||||
@@ -105,9 +154,31 @@ int main(int argc, char *argv[])
|
||||
LOG("Initial device state: adopted=%d, authkey=%.8s...", state.adopted,
|
||||
state.authkey[0] ? state.authkey : "DEFAULT");
|
||||
|
||||
if (!state.adopted || !state.inform_url[0])
|
||||
/*
|
||||
* A configured controller is an explicit override, including after
|
||||
* adoption. With an empty setting, discover the initial controller from
|
||||
* the default-route gateway and then preserve controller-issued state.
|
||||
*/
|
||||
if (cfg.controller_ip[0]) {
|
||||
snprintf(state.inform_url, sizeof(state.inform_url),
|
||||
"http://%s:%d%s", cfg.controller_ip, INFORM_PORT, INFORM_PATH);
|
||||
LOG("Using configured controller override: %s", cfg.controller_ip);
|
||||
} else if (!state.adopted || !state.inform_url[0]) {
|
||||
char controller_ip[INET_ADDRSTRLEN] = {0};
|
||||
if (get_default_gateway(cfg.lan_if, controller_ip,
|
||||
sizeof(controller_ip)) == 0) {
|
||||
snprintf(state.inform_url, sizeof(state.inform_url),
|
||||
"http://%s:%d%s", controller_ip,
|
||||
INFORM_PORT, INFORM_PATH);
|
||||
LOG("Autodetected controller from default gateway: %s",
|
||||
controller_ip);
|
||||
} else {
|
||||
state.inform_url[0] = '\0';
|
||||
fprintf(stderr,
|
||||
"[openuf] No controller configured and no IPv4 default "
|
||||
"gateway found\n");
|
||||
}
|
||||
}
|
||||
state_save(&state);
|
||||
|
||||
printf("[openuf] Starting model=%-8s MAC=%s IP=%s\n",
|
||||
@@ -180,6 +251,20 @@ int main(int argc, char *argv[])
|
||||
last_inform = now;
|
||||
LOG("Sending inform");
|
||||
|
||||
/* The default route may appear after the service starts. */
|
||||
if (!cfg.controller_ip[0] && !state.inform_url[0]) {
|
||||
char controller_ip[INET_ADDRSTRLEN] = {0};
|
||||
if (get_default_gateway(cfg.lan_if, controller_ip,
|
||||
sizeof(controller_ip)) == 0) {
|
||||
snprintf(state.inform_url, sizeof(state.inform_url),
|
||||
"http://%s:%d%s", controller_ip,
|
||||
INFORM_PORT, INFORM_PATH);
|
||||
LOG("Autodetected controller after startup: %s",
|
||||
controller_ip);
|
||||
state_save(&state);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update IP each cycle */
|
||||
char new_ip[64] = {0};
|
||||
if (get_ip(cfg.lan_if, new_ip, sizeof(new_ip)) == 0 ||
|
||||
|
||||
Reference in New Issue
Block a user