summaryrefslogtreecommitdiff
path: root/src/script.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/script.c')
-rw-r--r--src/script.c45
1 files changed, 29 insertions, 16 deletions
diff --git a/src/script.c b/src/script.c
index f272c19..3579331 100644
--- a/src/script.c
+++ b/src/script.c
@@ -118,9 +118,10 @@ static void fqdn_to_env(const char *name, const uint8_t *fqdn, size_t len)
char *buf = realloc(NULL, len + buf_len + 2);
memcpy(buf, name, buf_len);
buf[buf_len++] = '=';
- int l = 1;
- while (l > 0 && fqdn < fqdn_end) {
- l = dn_expand(fqdn, fqdn_end, fqdn, &buf[buf_len], buf_size - buf_len);
+ while (fqdn < fqdn_end) {
+ int l = dn_expand(fqdn, fqdn_end, fqdn, &buf[buf_len], buf_size - buf_len);
+ if (l <= 0)
+ break;
fqdn += l;
buf_len += strlen(&buf[buf_len]);
buf[buf_len++] = ' ';
@@ -156,7 +157,10 @@ static void entry_to_env(const char *name, const void *data, size_t len, enum en
{
size_t buf_len = strlen(name);
const struct odhcp6c_entry *e = data;
- char *buf = realloc(NULL, buf_len + 2 + (len / sizeof(*e)) * 144);
+ // Worst case: ENTRY_PREFIX with iaid != 1 and exclusion
+ const size_t max_entry_len = (INET6_ADDRSTRLEN-1 + 5 + 22 + 15 + 10 +
+ INET6_ADDRSTRLEN-1 + 11 + 1);
+ char *buf = realloc(NULL, buf_len + 2 + (len / sizeof(*e)) * max_entry_len);
memcpy(buf, name, buf_len);
buf[buf_len++] = '=';
@@ -164,28 +168,34 @@ static void entry_to_env(const char *name, const void *data, size_t len, enum en
inet_ntop(AF_INET6, &e[i].target, &buf[buf_len], INET6_ADDRSTRLEN);
buf_len += strlen(&buf[buf_len]);
if (type != ENTRY_HOST) {
- buf_len += snprintf(&buf[buf_len], 6, "/%"PRIu16, e[i].length);
+ snprintf(&buf[buf_len], 6, "/%"PRIu16, e[i].length);
+ buf += strlen(&buf[buf_len]);
if (type == ENTRY_ROUTE) {
buf[buf_len++] = ',';
if (!IN6_IS_ADDR_UNSPECIFIED(&e[i].router)) {
inet_ntop(AF_INET6, &e[i].router, &buf[buf_len], INET6_ADDRSTRLEN);
buf_len += strlen(&buf[buf_len]);
}
- buf_len += snprintf(&buf[buf_len], 24, ",%u", e[i].valid);
- buf_len += snprintf(&buf[buf_len], 12, ",%u", e[i].priority);
+ snprintf(&buf[buf_len], 23, ",%u,%u", e[i].valid, e[i].priority);
+ buf += strlen(&buf[buf_len]);
} else {
- buf_len += snprintf(&buf[buf_len], 24, ",%u,%u", e[i].preferred, e[i].valid);
+ snprintf(&buf[buf_len], 23, ",%u,%u", e[i].preferred, e[i].valid);
+ buf += strlen(&buf[buf_len]);
}
- if (type == ENTRY_PREFIX && ntohl(e[i].iaid) != 1)
- buf_len += snprintf(&buf[buf_len], 16, ",class=%08x", ntohl(e[i].iaid));
+ if (type == ENTRY_PREFIX && ntohl(e[i].iaid) != 1) {
+ snprintf(&buf[buf_len], 16, ",class=%08x", ntohl(e[i].iaid));
+ buf += strlen(&buf[buf_len]);
+ }
if (type == ENTRY_PREFIX && e[i].priority) {
// priority and router are abused for prefix exclusion
- buf_len += snprintf(&buf[buf_len], 12, ",excluded=");
+ snprintf(&buf[buf_len], 11, ",excluded=");
+ buf_len += strlen(&buf[buf_len]);
inet_ntop(AF_INET6, &e[i].router, &buf[buf_len], INET6_ADDRSTRLEN);
buf_len += strlen(&buf[buf_len]);
- buf_len += snprintf(&buf[buf_len], 24, "/%u", e[i].priority);
+ snprintf(&buf[buf_len], 12, "/%u", e[i].priority);
+ buf_len += strlen(&buf[buf_len]);
}
}
buf[buf_len++] = ' ';
@@ -217,7 +227,7 @@ static void search_to_env(const char *name, const uint8_t *start, size_t len)
static void int_to_env(const char *name, int value)
{
- size_t len = 12 + strlen(name);
+ size_t len = 13 + strlen(name);
char *buf = realloc(NULL, len);
snprintf(buf, len, "%s=%d", name, value);
putenv(buf);
@@ -272,7 +282,8 @@ static void s46_to_env(enum odhcp6c_state state, const uint8_t *data, size_t len
size_t prefix6len = rule->prefix6_len;
prefix6len = (prefix6len % 8 == 0) ? prefix6len / 8 : prefix6len / 8 + 1;
- if (olen < sizeof(struct dhcpv6_s46_rule) + prefix6len)
+ if (prefix6len > sizeof(in6) ||
+ olen < sizeof(struct dhcpv6_s46_rule) + prefix6len)
continue;
memcpy(&in6, rule->ipv6_prefix, prefix6len);
@@ -301,7 +312,8 @@ static void s46_to_env(enum odhcp6c_state state, const uint8_t *data, size_t len
size_t prefix6len = dmr->dmr_prefix6_len;
prefix6len = (prefix6len % 8 == 0) ? prefix6len / 8 : prefix6len / 8 + 1;
- if (olen < sizeof(struct dhcpv6_s46_dmr) + prefix6len)
+ if (prefix6len > sizeof(in6) ||
+ olen < sizeof(struct dhcpv6_s46_dmr) + prefix6len)
continue;
memcpy(&in6, dmr->dmr_ipv6_prefix, prefix6len);
@@ -320,7 +332,8 @@ static void s46_to_env(enum odhcp6c_state state, const uint8_t *data, size_t len
size_t prefix6len = bind->bindprefix6_len;
prefix6len = (prefix6len % 8 == 0) ? prefix6len / 8 : prefix6len / 8 + 1;
- if (olen < sizeof(struct dhcpv6_s46_v4v6bind) + prefix6len)
+ if (prefix6len > sizeof(in6) ||
+ olen < sizeof(struct dhcpv6_s46_v4v6bind) + prefix6len)
continue;
memcpy(&in6, bind->bind_ipv6_prefix, prefix6len);