rpcd-mod-luci: handle lease files from all dnsmasq/odhcpd sections
Fixes: #911, #4303, #4308 Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
parent
1c482dde3d
commit
0c7a335230
1 changed files with 135 additions and 112 deletions
|
@ -315,9 +315,12 @@ duid2ea(const char *duid)
|
||||||
|
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
FILE *dnsmasq_file;
|
|
||||||
FILE *odhcpd_file;
|
|
||||||
time_t now;
|
time_t now;
|
||||||
|
size_t num, off;
|
||||||
|
struct {
|
||||||
|
FILE *fh;
|
||||||
|
bool odhcpd;
|
||||||
|
} *files;
|
||||||
} lease_state = { };
|
} lease_state = { };
|
||||||
|
|
||||||
struct lease_entry {
|
struct lease_entry {
|
||||||
|
@ -333,13 +336,41 @@ struct lease_entry {
|
||||||
} addr[10];
|
} addr[10];
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *
|
static bool
|
||||||
find_leasefile(struct uci_context *uci, const char *section)
|
add_leasefile(const char *path, bool is_odhcpd)
|
||||||
|
{
|
||||||
|
void *ptr;
|
||||||
|
FILE *fh;
|
||||||
|
|
||||||
|
fh = fopen(path, "r");
|
||||||
|
|
||||||
|
if (!fh)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ptr = realloc(lease_state.files, sizeof(*lease_state.files) * (lease_state.num + 1));
|
||||||
|
|
||||||
|
if (!ptr) {
|
||||||
|
fclose(fh);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
lease_state.files = ptr;
|
||||||
|
lease_state.files[lease_state.num].fh = fh;
|
||||||
|
lease_state.files[lease_state.num].odhcpd = is_odhcpd;
|
||||||
|
lease_state.num++;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
find_leasefiles(struct uci_context *uci, bool is_odhcpd)
|
||||||
{
|
{
|
||||||
struct uci_ptr ptr = { .package = "dhcp" };
|
struct uci_ptr ptr = { .package = "dhcp" };
|
||||||
struct uci_package *pkg = NULL;
|
struct uci_package *pkg = NULL;
|
||||||
struct uci_section *s;
|
struct uci_section *s;
|
||||||
struct uci_element *e;
|
struct uci_element *e;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
pkg = uci_lookup_package(uci, ptr.package);
|
pkg = uci_lookup_package(uci, ptr.package);
|
||||||
|
|
||||||
|
@ -353,7 +384,7 @@ find_leasefile(struct uci_context *uci, const char *section)
|
||||||
uci_foreach_element(&pkg->sections, e) {
|
uci_foreach_element(&pkg->sections, e) {
|
||||||
s = uci_to_section(e);
|
s = uci_to_section(e);
|
||||||
|
|
||||||
if (strcmp(s->type, section))
|
if (strcmp(s->type, is_odhcpd ? "odhcpd" : "dnsmasq"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ptr.flags = 0;
|
ptr.flags = 0;
|
||||||
|
@ -370,31 +401,30 @@ find_leasefile(struct uci_context *uci, const char *section)
|
||||||
if (ptr.o->type != UCI_TYPE_STRING)
|
if (ptr.o->type != UCI_TYPE_STRING)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
return ptr.o->v.string;
|
if (add_leasefile(ptr.o->v.string, is_odhcpd))
|
||||||
|
found = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lease_close(void)
|
lease_close(void)
|
||||||
{
|
{
|
||||||
if (lease_state.dnsmasq_file) {
|
while (lease_state.num > 0)
|
||||||
fclose(lease_state.dnsmasq_file);
|
fclose(lease_state.files[--lease_state.num].fh);
|
||||||
lease_state.dnsmasq_file = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lease_state.odhcpd_file) {
|
free(lease_state.files);
|
||||||
fclose(lease_state.odhcpd_file);
|
|
||||||
lease_state.odhcpd_file = NULL;
|
lease_state.files = NULL;
|
||||||
}
|
lease_state.num = 0;
|
||||||
|
lease_state.off = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lease_open(void)
|
lease_open(void)
|
||||||
{
|
{
|
||||||
struct uci_context *uci;
|
struct uci_context *uci;
|
||||||
char *p;
|
|
||||||
|
|
||||||
lease_close();
|
lease_close();
|
||||||
|
|
||||||
|
@ -405,11 +435,11 @@ lease_open(void)
|
||||||
|
|
||||||
lease_state.now = time(NULL);
|
lease_state.now = time(NULL);
|
||||||
|
|
||||||
p = find_leasefile(uci, "dnsmasq");
|
if (!find_leasefiles(uci, false))
|
||||||
lease_state.dnsmasq_file = fopen(p ? p : "/tmp/dhcp.leases", "r");
|
add_leasefile("/tmp/dhcp.leases", false);
|
||||||
|
|
||||||
p = find_leasefile(uci, "odhcpd");
|
if (!find_leasefiles(uci, true))
|
||||||
lease_state.odhcpd_file = fopen(p ? p : "/tmp/hosts/odhcpd", "r");
|
add_leasefile("/tmp/hosts/odhcpd", true);
|
||||||
|
|
||||||
uci_free_context(uci);
|
uci_free_context(uci);
|
||||||
}
|
}
|
||||||
|
@ -424,133 +454,126 @@ lease_next(void)
|
||||||
|
|
||||||
memset(&e, 0, sizeof(e));
|
memset(&e, 0, sizeof(e));
|
||||||
|
|
||||||
if (lease_state.dnsmasq_file) {
|
while (lease_state.off < lease_state.num) {
|
||||||
while (fgets(e.buf, sizeof(e.buf), lease_state.dnsmasq_file)) {
|
while (fgets(e.buf, sizeof(e.buf), lease_state.files[lease_state.off].fh)) {
|
||||||
p = strtok(e.buf, " \t\n");
|
if (lease_state.files[lease_state.off].odhcpd) {
|
||||||
|
strtok(e.buf, " \t\n"); /* # */
|
||||||
|
strtok(NULL, " \t\n"); /* iface */
|
||||||
|
|
||||||
if (!p)
|
e.duid = strtok(NULL, " \t\n"); /* duid */
|
||||||
continue;
|
|
||||||
|
|
||||||
n = strtol(p, NULL, 10);
|
if (!e.duid)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (n > lease_state.now)
|
p = strtok(NULL, " \t\n"); /* iaid */
|
||||||
e.expire = n - lease_state.now;
|
|
||||||
else if (n > 0)
|
|
||||||
e.expire = 0;
|
|
||||||
else
|
|
||||||
e.expire = -1;
|
|
||||||
|
|
||||||
p = strtok(NULL, " \t\n");
|
if (p)
|
||||||
|
e.af = strcmp(p, "ipv4") ? AF_INET6 : AF_INET;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
if (!p)
|
e.hostname = strtok(NULL, " \t\n"); /* name */
|
||||||
continue;
|
|
||||||
|
|
||||||
ea = ether_aton(p);
|
if (!e.hostname)
|
||||||
|
continue;
|
||||||
|
|
||||||
p = strtok(NULL, " \t\n");
|
p = strtok(NULL, " \t\n"); /* ts */
|
||||||
|
|
||||||
if (p && inet_pton(AF_INET6, p, &e.addr[0].in6)) {
|
if (!p)
|
||||||
e.af = AF_INET6;
|
continue;
|
||||||
e.n_addr = 1;
|
|
||||||
}
|
|
||||||
else if (p && inet_pton(AF_INET, p, &e.addr[0].in)) {
|
|
||||||
e.af = AF_INET;
|
|
||||||
e.n_addr = 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ea && e.af != AF_INET6)
|
n = strtol(p, NULL, 10);
|
||||||
continue;
|
|
||||||
|
|
||||||
e.hostname = strtok(NULL, " \t\n");
|
if (n > lease_state.now)
|
||||||
e.duid = strtok(NULL, " \t\n");
|
e.expire = n - lease_state.now;
|
||||||
|
else if (n >= 0)
|
||||||
|
e.expire = 0;
|
||||||
|
else
|
||||||
|
e.expire = -1;
|
||||||
|
|
||||||
if (!e.hostname || !e.duid)
|
strtok(NULL, " \t\n"); /* id */
|
||||||
continue;
|
strtok(NULL, " \t\n"); /* length */
|
||||||
|
|
||||||
if (!strcmp(e.hostname, "*"))
|
for (e.n_addr = 0, p = strtok(NULL, "/ \t\n");
|
||||||
e.hostname = NULL;
|
e.n_addr < ARRAY_SIZE(e.addr) && p != NULL;
|
||||||
|
p = strtok(NULL, "/ \t\n")) {
|
||||||
|
if (inet_pton(e.af, p, &e.addr[e.n_addr].in6))
|
||||||
|
e.n_addr++;
|
||||||
|
}
|
||||||
|
|
||||||
if (!strcmp(e.duid, "*"))
|
|
||||||
e.duid = NULL;
|
|
||||||
|
|
||||||
if (!ea && e.duid)
|
|
||||||
ea = duid2ea(e.duid);
|
ea = duid2ea(e.duid);
|
||||||
|
|
||||||
if (ea)
|
if (ea)
|
||||||
e.mac = *ea;
|
e.mac = *ea;
|
||||||
|
|
||||||
return &e;
|
if (!strcmp(e.hostname, "-"))
|
||||||
}
|
e.hostname = NULL;
|
||||||
|
|
||||||
fclose(lease_state.dnsmasq_file);
|
if (!strcmp(e.duid, "-"))
|
||||||
lease_state.dnsmasq_file = NULL;
|
e.duid = NULL;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
p = strtok(e.buf, " \t\n");
|
||||||
|
|
||||||
if (lease_state.odhcpd_file) {
|
if (!p)
|
||||||
while (fgets(e.buf, sizeof(e.buf), lease_state.odhcpd_file)) {
|
continue;
|
||||||
strtok(e.buf, " \t\n"); /* # */
|
|
||||||
strtok(NULL, " \t\n"); /* iface */
|
|
||||||
|
|
||||||
e.duid = strtok(NULL, " \t\n"); /* duid */
|
n = strtol(p, NULL, 10);
|
||||||
|
|
||||||
if (!e.duid)
|
if (n > lease_state.now)
|
||||||
continue;
|
e.expire = n - lease_state.now;
|
||||||
|
else if (n > 0)
|
||||||
|
e.expire = 0;
|
||||||
|
else
|
||||||
|
e.expire = -1;
|
||||||
|
|
||||||
p = strtok(NULL, " \t\n"); /* iaid */
|
p = strtok(NULL, " \t\n");
|
||||||
|
|
||||||
if (p)
|
if (!p)
|
||||||
e.af = strcmp(p, "ipv4") ? AF_INET6 : AF_INET;
|
continue;
|
||||||
else
|
|
||||||
continue;
|
|
||||||
|
|
||||||
e.hostname = strtok(NULL, " \t\n"); /* name */
|
ea = ether_aton(p);
|
||||||
|
|
||||||
if (!e.hostname)
|
p = strtok(NULL, " \t\n");
|
||||||
continue;
|
|
||||||
|
|
||||||
p = strtok(NULL, " \t\n"); /* ts */
|
if (p && inet_pton(AF_INET6, p, &e.addr[0].in6)) {
|
||||||
|
e.af = AF_INET6;
|
||||||
|
e.n_addr = 1;
|
||||||
|
}
|
||||||
|
else if (p && inet_pton(AF_INET, p, &e.addr[0].in)) {
|
||||||
|
e.af = AF_INET;
|
||||||
|
e.n_addr = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!p)
|
if (!ea && e.af != AF_INET6)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
n = strtol(p, NULL, 10);
|
e.hostname = strtok(NULL, " \t\n");
|
||||||
|
e.duid = strtok(NULL, " \t\n");
|
||||||
|
|
||||||
if (n > lease_state.now)
|
if (!e.hostname || !e.duid)
|
||||||
e.expire = n - lease_state.now;
|
continue;
|
||||||
else if (n >= 0)
|
|
||||||
e.expire = 0;
|
|
||||||
else
|
|
||||||
e.expire = -1;
|
|
||||||
|
|
||||||
strtok(NULL, " \t\n"); /* id */
|
if (!strcmp(e.hostname, "*"))
|
||||||
strtok(NULL, " \t\n"); /* length */
|
e.hostname = NULL;
|
||||||
|
|
||||||
for (e.n_addr = 0, p = strtok(NULL, "/ \t\n");
|
if (!strcmp(e.duid, "*"))
|
||||||
e.n_addr < ARRAY_SIZE(e.addr) && p != NULL;
|
e.duid = NULL;
|
||||||
p = strtok(NULL, "/ \t\n")) {
|
|
||||||
if (inet_pton(e.af, p, &e.addr[e.n_addr].in6))
|
if (!ea && e.duid)
|
||||||
e.n_addr++;
|
ea = duid2ea(e.duid);
|
||||||
|
|
||||||
|
if (ea)
|
||||||
|
e.mac = *ea;
|
||||||
}
|
}
|
||||||
|
|
||||||
ea = duid2ea(e.duid);
|
|
||||||
|
|
||||||
if (ea)
|
|
||||||
e.mac = *ea;
|
|
||||||
|
|
||||||
if (!strcmp(e.hostname, "-"))
|
|
||||||
e.hostname = NULL;
|
|
||||||
|
|
||||||
if (!strcmp(e.duid, "-"))
|
|
||||||
e.duid = NULL;
|
|
||||||
|
|
||||||
return &e;
|
return &e;
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(lease_state.odhcpd_file);
|
lease_state.off++;
|
||||||
lease_state.odhcpd_file = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
Loading…
Reference in a new issue