mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-13 17:00:49 +00:00
Compare commits
24
Commits
v2.93test7
...
v2.93test9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ad74926d4 | ||
|
|
a6069da373 | ||
|
|
14f53171ca | ||
|
|
8fd06d2cc0 | ||
|
|
d152e81e42 | ||
|
|
e0bec3342b | ||
|
|
dd707937d5 | ||
|
|
c5f46412a3 | ||
|
|
cd04c0ce20 | ||
|
|
0630a45ae1 | ||
|
|
3ea905b98b | ||
|
|
ca509cb611 | ||
|
|
8ceb8ee9b5 | ||
|
|
1c4a97edb5 | ||
|
|
9e3e0465cd | ||
|
|
b12a9249f6 | ||
|
|
9dec84ca42 | ||
|
|
68c149e9dd | ||
|
|
5ea054b264 | ||
|
|
b95d5a2577 | ||
|
|
5be5dc1f16 | ||
|
|
48348a2d77 | ||
|
|
b4a0663654 | ||
|
|
53313014b5 |
No files matched your search
+5
-3
@@ -1515,7 +1515,7 @@ The normal default DNS server (the same address as the DHCP server)
|
|||||||
will not be appropriate when there is no route bewteen the
|
will not be appropriate when there is no route bewteen the
|
||||||
two, so this will have to be explicitly configured.
|
two, so this will have to be explicitly configured.
|
||||||
.TP
|
.TP
|
||||||
.B \-U, --dhcp-vendorclass=set:<tag>,[enterprise:<IANA-enterprise number>,]<vendor-class>
|
.B \-U, --dhcp-vendorclass=set:<tag>,[enterprise:<IANA-enterprise number>,][<vendor-class>]
|
||||||
Map from a vendor-class string to a tag. Most DHCP clients provide a
|
Map from a vendor-class string to a tag. Most DHCP clients provide a
|
||||||
"vendor class" which represents, in some sense, the type of host. This option
|
"vendor class" which represents, in some sense, the type of host. This option
|
||||||
maps vendor classes to tags, so that DHCP options may be selectively delivered
|
maps vendor classes to tags, so that DHCP options may be selectively delivered
|
||||||
@@ -1529,9 +1529,11 @@ allow fuzzy matching. The set: prefix is optional but allowed for
|
|||||||
consistency.
|
consistency.
|
||||||
|
|
||||||
Note that in IPv6 only, vendorclasses are namespaced with an
|
Note that in IPv6 only, vendorclasses are namespaced with an
|
||||||
IANA-allocated enterprise number. This is given with enterprise:
|
IANA-allocated enterprise number. This may be given with an enterprise:
|
||||||
keyword and specifies that only vendorclasses matching the specified
|
keyword and specifies that only vendorclasses matching the specified
|
||||||
number should be searched.
|
number should be searched. Similarly, an enterprise number may be given
|
||||||
|
with no vendor-class string. This always matches vendorclasses with
|
||||||
|
the given enterprise number.
|
||||||
.TP
|
.TP
|
||||||
.B \-j, --dhcp-userclass=set:<tag>,<user-class>
|
.B \-j, --dhcp-userclass=set:<tag>,<user-class>
|
||||||
Map from a user-class string to a tag (with substring
|
Map from a user-class string to a tag (with substring
|
||||||
|
|||||||
@@ -1084,6 +1084,9 @@ int cache_recv_insert(time_t now, int fd)
|
|||||||
!read_write(fd, (unsigned char *)&validatecountp, sizeof(validatecountp), RW_READ)))
|
!read_write(fd, (unsigned char *)&validatecountp, sizeof(validatecountp), RW_READ)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (op == PIPE_OP_KILLED)
|
||||||
|
my_syslog(LOG_INFO, _("TCP process for DNSSEC validation timed out"));
|
||||||
|
|
||||||
/* There's a tiny chance that the frec may have been freed
|
/* There's a tiny chance that the frec may have been freed
|
||||||
and reused before the TCP process returns. Detect that with
|
and reused before the TCP process returns. Detect that with
|
||||||
the uid field which is unique modulo 2^32 for each use. */
|
the uid field which is unique modulo 2^32 for each use. */
|
||||||
|
|||||||
+6
-7
@@ -882,7 +882,7 @@ char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len,
|
|||||||
buf[j++] = c;
|
buf[j++] = c;
|
||||||
}
|
}
|
||||||
i = l;
|
i = l;
|
||||||
if (val[i] != 0 && j < buf_len)
|
if (i < opt_len && val[i] != 0 && j < buf_len)
|
||||||
buf[j++] = '.';
|
buf[j++] = '.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -892,21 +892,20 @@ char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len,
|
|||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
|
|
||||||
i = 0, j = 0;
|
i = 0, j = 0;
|
||||||
while (1)
|
while (i + 2 <= opt_len)
|
||||||
{
|
{
|
||||||
p = &val[i];
|
p = &val[i];
|
||||||
GETSHORT(len, p);
|
GETSHORT(len, p);
|
||||||
|
if (i + 2 + len > opt_len)
|
||||||
|
break; /* malformed: body extends beyond option */
|
||||||
for (k = 0; k < len && j < buf_len; k++)
|
for (k = 0; k < len && j < buf_len; k++)
|
||||||
{
|
{
|
||||||
char c = *p++;
|
char c = *p++;
|
||||||
if (isprint((unsigned char)c))
|
if (isprint((unsigned char)c))
|
||||||
buf[j++] = c;
|
buf[j++] = c;
|
||||||
}
|
}
|
||||||
i += len +2;
|
i += len + 2;
|
||||||
if (i >= opt_len)
|
if (i < opt_len && j < buf_len)
|
||||||
break;
|
|
||||||
|
|
||||||
if (j < buf_len)
|
|
||||||
buf[j++] = ',';
|
buf[j++] = ',';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1385,8 +1385,6 @@ static void sig_handler(int sig)
|
|||||||
read_write(daemon->pipe_to_parent, (unsigned char *)(&daemon->forward_to_tcp), sizeof(daemon->forward_to_tcp), RW_WRITE);
|
read_write(daemon->pipe_to_parent, (unsigned char *)(&daemon->forward_to_tcp), sizeof(daemon->forward_to_tcp), RW_WRITE);
|
||||||
read_write(daemon->pipe_to_parent, (unsigned char *)(&daemon->forward_to_tcp->uid), sizeof(daemon->forward_to_tcp->uid), RW_WRITE);
|
read_write(daemon->pipe_to_parent, (unsigned char *)(&daemon->forward_to_tcp->uid), sizeof(daemon->forward_to_tcp->uid), RW_WRITE);
|
||||||
|
|
||||||
my_syslog(LOG_INFO, _("TCP process for DNSSEC validation timed out"));
|
|
||||||
|
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1473,6 +1473,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
|
|||||||
char *keyname, int class, int *validate_count);
|
char *keyname, int class, int *validate_count);
|
||||||
int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name,
|
int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name,
|
||||||
char *keyname, int class, int *validate_count);
|
char *keyname, int class, int *validate_count);
|
||||||
|
int cache_neg_ds(char *name, int flags, int class, time_t now, int neg_ttl);
|
||||||
int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class,
|
int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class,
|
||||||
int check_unsigned, int *neganswer, int *prim_ok, int *nons, int *nsec_ttl, int *validate_count);
|
int check_unsigned, int *neganswer, int *prim_ok, int *nons, int *nsec_ttl, int *validate_count);
|
||||||
int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen);
|
int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen);
|
||||||
|
|||||||
+15
-12
@@ -1027,21 +1027,21 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
|
|||||||
(flags = in_arpa_name_2_addr(name, &a)) &&
|
(flags = in_arpa_name_2_addr(name, &a)) &&
|
||||||
((flags == F_IPV6 && private_net6(&a.addr6, 0)) || (flags == F_IPV4 && private_net(a.addr4, 0))))
|
((flags == F_IPV6 && private_net6(&a.addr6, 0)) || (flags == F_IPV4 && private_net(a.addr4, 0))))
|
||||||
{
|
{
|
||||||
my_syslog(LOG_INFO, _("Insecure reply received for DS %s, assuming that's OK for a RFC-1918 address."), name);
|
my_syslog(LOG_INFO, _("insecure reply received for DS %s, assuming that's OK for a RFC-1918 address"), name);
|
||||||
neganswer = 1;
|
neganswer = 1;
|
||||||
nons = 0; /* If we're faking a DS, fake one with an NS. */
|
nons = 0; /* If we're faking a DS, fake one with an NS. */
|
||||||
neg_ttl = DNSSEC_ASSUMED_DS_TTL;
|
neg_ttl = DNSSEC_ASSUMED_DS_TTL;
|
||||||
}
|
}
|
||||||
else if (lookup_domain(name, F_DOMAINSRV, NULL, NULL))
|
else if (lookup_domain(name, F_DOMAINSRV, NULL, NULL))
|
||||||
{
|
{
|
||||||
my_syslog(LOG_INFO, _("Insecure reply received for DS %s, assuming non-DNSSEC domain-specific server."), name);
|
my_syslog(LOG_INFO, _("insecure reply received for DS %s, assuming non-DNSSEC domain-specific server"), name);
|
||||||
neganswer = 1;
|
neganswer = 1;
|
||||||
nons = 0; /* If we're faking a DS, fake one with an NS. */
|
nons = 0; /* If we're faking a DS, fake one with an NS. */
|
||||||
neg_ttl = DNSSEC_ASSUMED_DS_TTL;
|
neg_ttl = DNSSEC_ASSUMED_DS_TTL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
my_syslog(LOG_WARNING, _("Insecure DS reply received for %s, check domain configuration and upstream DNS server DNSSEC support"), name);
|
my_syslog(LOG_WARNING, _("insecure DS reply received for %s, check domain configuration and upstream DNS server DNSSEC support"), name);
|
||||||
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DS - not secure", 0);
|
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DS - not secure", 0);
|
||||||
return STAT_BOGUS | DNSSEC_FAIL_INDET;
|
return STAT_BOGUS | DNSSEC_FAIL_INDET;
|
||||||
}
|
}
|
||||||
@@ -1147,38 +1147,41 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
|
|||||||
if (RCODE(header) == NXDOMAIN)
|
if (RCODE(header) == NXDOMAIN)
|
||||||
flags |= F_NXDOMAIN;
|
flags |= F_NXDOMAIN;
|
||||||
|
|
||||||
/* We only cache validated DS records, DNSSECOK flag hijacked
|
|
||||||
to store presence/absence of NS. */
|
|
||||||
if (nons)
|
if (nons)
|
||||||
{
|
{
|
||||||
if (lookup_domain(name, F_DOMAINSRV, NULL, NULL))
|
if (lookup_domain(name, F_DOMAINSRV, NULL, NULL))
|
||||||
{
|
{
|
||||||
my_syslog(LOG_WARNING, _("Negative DS reply without NS record received for %s, assuming non-DNSSEC domain-specific server."), name);
|
my_syslog(LOG_WARNING, _("negative DS reply without NS record received for %s, assuming non-DNSSEC domain-specific server"), name);
|
||||||
nons = 0;
|
nons = 0;
|
||||||
|
neg_ttl = DNSSEC_ASSUMED_DS_TTL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* We only cache validated DS records, DNSSECOK flag hijacked
|
/* We only cache validated DS records, DNSSECOK flag hijacked
|
||||||
to store presence/absence of NS. */
|
to store presence/absence of NS. */
|
||||||
flags &= ~F_DNSSECOK;
|
flags &= ~F_DNSSECOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL,
|
||||||
|
servfail ? "SERVFAIL" : (nons ? "no DS/cut" : "no DS"), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return cache_neg_ds(name, flags, class, now, neg_ttl);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int cache_neg_ds(char *name, int flags, int class, time_t now, int ttl)
|
||||||
|
{
|
||||||
cache_start_insert();
|
cache_start_insert();
|
||||||
|
|
||||||
/* Use TTL from NSEC for negative cache entries */
|
/* Use TTL from NSEC for negative cache entries */
|
||||||
if (!cache_insert(name, NULL, class, now, neg_ttl, flags))
|
if (!cache_insert(name, NULL, class, now, ttl, flags))
|
||||||
return STAT_ABANDONED;
|
return STAT_ABANDONED;
|
||||||
|
|
||||||
cache_end_insert();
|
cache_end_insert();
|
||||||
|
|
||||||
if (neganswer)
|
|
||||||
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL,
|
|
||||||
servfail ? "SERVFAIL" : (nons ? "no DS/cut" : "no DS"), 0);
|
|
||||||
|
|
||||||
return STAT_OK;
|
return STAT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* 4034 6.1 */
|
/* 4034 6.1 */
|
||||||
static int hostname_cmp(const char *a, const char *b)
|
static int hostname_cmp(const char *a, const char *b)
|
||||||
{
|
{
|
||||||
|
|||||||
+5
-5
@@ -175,8 +175,8 @@ int is_rev_synth(int flag, union all_addr *addr, char *name)
|
|||||||
*p = '-';
|
*p = '-';
|
||||||
}
|
}
|
||||||
|
|
||||||
strncat(name, ".", MAXDNAME);
|
strncat(name, ".", MAXDNAME - strlen(name) - 1);
|
||||||
strncat(name, c->domain, MAXDNAME);
|
strncat(name, c->domain, MAXDNAME - strlen(name) - 1);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -201,12 +201,12 @@ int is_rev_synth(int flag, union all_addr *addr, char *name)
|
|||||||
for (i = 0; i < 16; i += 2)
|
for (i = 0; i < 16; i += 2)
|
||||||
{
|
{
|
||||||
sprintf(frag, "%s%02x%02x", i == 0 ? "" : "-", addr->addr6.s6_addr[i], addr->addr6.s6_addr[i+1]);
|
sprintf(frag, "%s%02x%02x", i == 0 ? "" : "-", addr->addr6.s6_addr[i], addr->addr6.s6_addr[i+1]);
|
||||||
strncat(name, frag, MAXDNAME);
|
strncat(name, frag, MAXDNAME - strlen(name) - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
strncat(name, ".", MAXDNAME);
|
strncat(name, ".", MAXDNAME - strlen(name) - 1);
|
||||||
strncat(name, c->domain, MAXDNAME);
|
strncat(name, c->domain, MAXDNAME - strlen(name) - 1);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -85,7 +85,8 @@ void dump_init(void)
|
|||||||
/* count existing records */
|
/* count existing records */
|
||||||
while (read_write(daemon->dumpfd, (void *)&pcap_header, sizeof(pcap_header), RW_READ))
|
while (read_write(daemon->dumpfd, (void *)&pcap_header, sizeof(pcap_header), RW_READ))
|
||||||
{
|
{
|
||||||
lseek(daemon->dumpfd, pcap_header.incl_len, SEEK_CUR);
|
if (lseek(daemon->dumpfd, pcap_header.incl_len, SEEK_CUR) == (off_t)-1)
|
||||||
|
break;
|
||||||
packet_count++;
|
packet_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -469,6 +469,8 @@ int check_source(struct dns_header *header, size_t plen, unsigned char *pseudohe
|
|||||||
{
|
{
|
||||||
GETSHORT(code, p);
|
GETSHORT(code, p);
|
||||||
GETSHORT(len, p);
|
GETSHORT(len, p);
|
||||||
|
if (i + 4 + len > rdlen)
|
||||||
|
break; /* malformed: option body extends beyond RDATA */
|
||||||
if (code == EDNS0_OPTION_CLIENT_SUBNET)
|
if (code == EDNS0_OPTION_CLIENT_SUBNET)
|
||||||
{
|
{
|
||||||
if (peer)
|
if (peer)
|
||||||
|
|||||||
+24
-8
@@ -954,6 +954,7 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
|
|||||||
/* As soon as anything returns BOGUS, we stop and unwind, to do otherwise
|
/* As soon as anything returns BOGUS, we stop and unwind, to do otherwise
|
||||||
would invite infinite loops, since the answers to DNSKEY and DS queries
|
would invite infinite loops, since the answers to DNSKEY and DS queries
|
||||||
will not be cached, so they'll be repeated. */
|
will not be cached, so they'll be repeated. */
|
||||||
|
ds_retry:
|
||||||
if (forward->flags & FREC_DNSKEY_QUERY)
|
if (forward->flags & FREC_DNSKEY_QUERY)
|
||||||
status = dnssec_validate_by_ds(now, header, plen, daemon->namebuff, daemon->keyname, forward->class, &orig->validate_counter);
|
status = dnssec_validate_by_ds(now, header, plen, daemon->namebuff, daemon->keyname, forward->class, &orig->validate_counter);
|
||||||
else if (forward->flags & FREC_DS_QUERY)
|
else if (forward->flags & FREC_DS_QUERY)
|
||||||
@@ -1084,6 +1085,18 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If there's no server for the parent of a domain-specific server's domain,
|
||||||
|
assume that said server's contents it legitimately unsigned, as if the parent
|
||||||
|
contained a negative DS record. This is part of the same logic that's found
|
||||||
|
in dnssec_validate_ds() when it gets a negative DS repsonse. */
|
||||||
|
if (STAT_ISEQUAL(status, STAT_NEED_DS) && serverind == -1 && lookup_domain(daemon->keyname, F_DOMAINSRV, NULL, NULL) &&
|
||||||
|
cache_neg_ds(daemon->keyname, F_FORWARD | F_DS | F_NEG | F_DNSSECOK, forward->class, now, DNSSEC_ASSUMED_DS_TTL) == STAT_OK)
|
||||||
|
{
|
||||||
|
my_syslog(LOG_WARNING, _("no server for parent domain of %s, assuming unsigned domain"), daemon->keyname);
|
||||||
|
blockdata_free(stash);
|
||||||
|
goto ds_retry;
|
||||||
|
}
|
||||||
|
|
||||||
/* error unwind */
|
/* error unwind */
|
||||||
free_rfds(&rfds);
|
free_rfds(&rfds);
|
||||||
blockdata_free(newstash);
|
blockdata_free(newstash);
|
||||||
@@ -1192,11 +1205,11 @@ void reply_query(int fd, time_t now)
|
|||||||
server = daemon->serverarray[serv];
|
server = daemon->serverarray[serv];
|
||||||
if (server->sfd && server->sfd->fd == fd)
|
if (server->sfd && server->sfd->fd == fd)
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (serv == last)
|
if (serv == last)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* spoof check: answer must come from known server, also
|
/* spoof check: answer must come from known server, also
|
||||||
we may have sent the same query to multiple servers from
|
we may have sent the same query to multiple servers from
|
||||||
@@ -2162,9 +2175,12 @@ static ssize_t tcp_talk(int first, int last, int start, struct dns_header *heade
|
|||||||
someone might be attempting to insert bogus values into the cache by
|
someone might be attempting to insert bogus values into the cache by
|
||||||
sending replies containing questions and bogus answers.
|
sending replies containing questions and bogus answers.
|
||||||
Try another server, or give up */
|
Try another server, or give up */
|
||||||
p = (unsigned char *)(((struct dns_header *)recvbuff->iov_base)+1);
|
struct dns_header *header = (struct dns_header *)recvbuff->iov_base;
|
||||||
if (extract_name(((struct dns_header *)recvbuff->iov_base), rsize, &p, daemon->namebuff, EXTR_NAME_COMPARE, 4) != 1)
|
p = (unsigned char *)(header+1);
|
||||||
|
if (rsize < (unsigned int)sizeof(struct dns_header) || !(header->hb3 & HB3_QR) || ntohs(header->qdcount) != 1 ||
|
||||||
|
extract_name(header, rsize, &p, daemon->namebuff, EXTR_NAME_COMPARE, 4) != 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
GETSHORT(rtype, p);
|
GETSHORT(rtype, p);
|
||||||
GETSHORT(rclass, p);
|
GETSHORT(rclass, p);
|
||||||
|
|
||||||
@@ -2452,18 +2468,18 @@ void tcp_request(int confd, time_t now, struct iovec *bigbuff,
|
|||||||
!read_write(confd, (unsigned char *)daemon->packet, size, RW_READ))
|
!read_write(confd, (unsigned char *)daemon->packet, size, RW_READ))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (size < (int)sizeof(struct dns_header))
|
/* header == query */
|
||||||
|
header = (struct dns_header *)daemon->packet;
|
||||||
|
|
||||||
|
if (size < (int)sizeof(struct dns_header) || (header->hb3 & HB3_QR))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Make sure we have a buffer big enough for the largest answer. */
|
/* Make sure we have a buffer big enough for the largest answer. */
|
||||||
expand_buf(bigbuff, 65536 + MAXDNAME + RRFIXEDSZ);
|
expand_buf(bigbuff, 65536 + MAXDNAME + RRFIXEDSZ);
|
||||||
out_header = bigbuff->iov_base;
|
out_header = bigbuff->iov_base;
|
||||||
|
|
||||||
/* header == query */
|
|
||||||
header = (struct dns_header *)daemon->packet;
|
|
||||||
|
|
||||||
/* Add edns0 pheader to query */
|
/* Add edns0 pheader to query */
|
||||||
size = add_edns0_config(header, size, ((unsigned char *) header) + daemon->edns_pktsz, &peer_addr, now, &cacheable);
|
size = add_edns0_config(header, size, ((unsigned char *) header) + daemon->packet_buff_sz, &peer_addr, now, &cacheable);
|
||||||
|
|
||||||
/* Clear buffer to avoid risk of information disclosure. */
|
/* Clear buffer to avoid risk of information disclosure. */
|
||||||
memset(bigbuff->iov_base, 0, bigbuff->iov_len);
|
memset(bigbuff->iov_base, 0, bigbuff->iov_len);
|
||||||
|
|||||||
+3
-1
@@ -740,9 +740,11 @@ static unsigned char *grab_extradata_lua(unsigned char *buf, unsigned char *end,
|
|||||||
if (!buf || (buf == end))
|
if (!buf || (buf == end))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
for (next = buf; *next != 0; next++)
|
for (next = buf; ; next++)
|
||||||
if (next == end)
|
if (next == end)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
else if (*next == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
if (next != buf)
|
if (next != buf)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ static int read_leases(time_t now, FILE *leasestream)
|
|||||||
if (lease)
|
if (lease)
|
||||||
{
|
{
|
||||||
opt_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
|
opt_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
|
||||||
|
if (opt_len < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (strcmp(daemon->dhcp_buff3, "vendorclass") == 0)
|
if (strcmp(daemon->dhcp_buff3, "vendorclass") == 0)
|
||||||
lease_set_vendorclass(lease, (unsigned char *)daemon->packet, opt_len);
|
lease_set_vendorclass(lease, (unsigned char *)daemon->packet, opt_len);
|
||||||
@@ -99,6 +101,8 @@ static int read_leases(time_t now, FILE *leasestream)
|
|||||||
|
|
||||||
|
|
||||||
hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
|
hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
|
||||||
|
if (hw_len < 0)
|
||||||
|
hw_len = 0;
|
||||||
/* For backwards compatibility, no explicit MAC address type means ether. */
|
/* For backwards compatibility, no explicit MAC address type means ether. */
|
||||||
if (hw_type == 0 && hw_len != 0)
|
if (hw_type == 0 && hw_len != 0)
|
||||||
hw_type = ARPHRD_ETHER;
|
hw_type = ARPHRD_ETHER;
|
||||||
@@ -131,7 +135,11 @@ static int read_leases(time_t now, FILE *leasestream)
|
|||||||
die (_("too many stored leases"), NULL, EC_MISC);
|
die (_("too many stored leases"), NULL, EC_MISC);
|
||||||
|
|
||||||
if (strcmp(daemon->packet, "*") != 0)
|
if (strcmp(daemon->packet, "*") != 0)
|
||||||
|
{
|
||||||
clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
|
clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
|
||||||
|
if (clid_len < 0)
|
||||||
|
clid_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet,
|
lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet,
|
||||||
hw_len, hw_type, clid_len, now, 0);
|
hw_len, hw_type, clid_len, now, 0);
|
||||||
|
|||||||
+17
-15
@@ -4580,20 +4580,16 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
only allowed for agent-options. */
|
only allowed for agent-options. */
|
||||||
|
|
||||||
arg = comma;
|
arg = comma;
|
||||||
if ((comma = split(arg)))
|
if (option == 'U' && strstr(arg, "enterprise:") == arg)
|
||||||
{
|
{
|
||||||
if (option != 'U' || strstr(arg, "enterprise:") != arg)
|
comma = split(arg);
|
||||||
{
|
|
||||||
free(new->netid.net);
|
|
||||||
ret_err_free(gen_err, new);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
new->enterprise = atoi(arg+11);
|
new->enterprise = atoi(arg+11);
|
||||||
|
arg = comma;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
comma = arg;
|
|
||||||
|
|
||||||
for (dig = 0, colon = 0, p = (unsigned char *)comma; *p; p++)
|
if (arg)
|
||||||
|
{
|
||||||
|
for (dig = 0, colon = 0, p = (unsigned char *)arg; *p; p++)
|
||||||
if (isxdigit(*p))
|
if (isxdigit(*p))
|
||||||
dig = 1;
|
dig = 1;
|
||||||
else if (*p == ':')
|
else if (*p == ':')
|
||||||
@@ -4601,18 +4597,24 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
|
||||||
unhide_metas(comma);
|
unhide_metas(arg);
|
||||||
if (option == 'U' || option == 'j' || *p || !dig || !colon)
|
if (option == 'U' || option == 'j' || *p || !dig || !colon)
|
||||||
{
|
{
|
||||||
new->len = strlen(comma);
|
new->len = strlen(arg);
|
||||||
new->data = opt_malloc(new->len);
|
new->data = opt_malloc(new->len);
|
||||||
memcpy(new->data, comma, new->len);
|
memcpy(new->data, arg, new->len);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
new->len = parse_hex(comma, (unsigned char *)comma, strlen(comma), NULL, NULL);
|
new->len = parse_hex(comma, (unsigned char *)arg, strlen(arg), NULL, NULL);
|
||||||
new->data = opt_malloc(new->len);
|
new->data = opt_malloc(new->len);
|
||||||
memcpy(new->data, comma, new->len);
|
memcpy(new->data, arg, new->len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (option != 'U' || new->enterprise == 0)
|
||||||
|
{
|
||||||
|
free(new->netid.net);
|
||||||
|
ret_err_free(gen_err, new);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (option)
|
switch (option)
|
||||||
|
|||||||
+6
-3
@@ -317,7 +317,7 @@ unsigned char *skip_name(unsigned char *ansp, struct dns_header *header, size_t
|
|||||||
else if (label_type == 0x40)
|
else if (label_type == 0x40)
|
||||||
{
|
{
|
||||||
/* Extended label type */
|
/* Extended label type */
|
||||||
unsigned int count;
|
unsigned int count, llen;
|
||||||
|
|
||||||
if (!CHECK_LEN(header, ansp, plen, 2))
|
if (!CHECK_LEN(header, ansp, plen, 2))
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -328,9 +328,12 @@ unsigned char *skip_name(unsigned char *ansp, struct dns_header *header, size_t
|
|||||||
count = *(ansp++); /* Bits in bitstring */
|
count = *(ansp++); /* Bits in bitstring */
|
||||||
|
|
||||||
if (count == 0) /* count == 0 means 256 bits */
|
if (count == 0) /* count == 0 means 256 bits */
|
||||||
ansp += 32;
|
llen = 32;
|
||||||
else
|
else
|
||||||
ansp += ((count-1)>>3)+1;
|
llen = ((count-1)>>3)+1;
|
||||||
|
|
||||||
|
if (!ADD_RDLEN(header, ansp, plen, llen))
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* label type == 0 Bottom six bits is length */
|
{ /* label type == 0 Bottom six bits is length */
|
||||||
|
|||||||
+2
-2
@@ -597,7 +597,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
if (mess->file[0])
|
if (mess->file[0])
|
||||||
{
|
{
|
||||||
memcpy(daemon->dhcp_buff2, mess->file, sizeof(mess->file));
|
memcpy(daemon->dhcp_buff2, mess->file, sizeof(mess->file));
|
||||||
daemon->dhcp_buff2[sizeof(mess->file) + 1] = 0; /* ensure zero term. */
|
daemon->dhcp_buff2[sizeof(mess->file)] = 0; /* ensure zero term. */
|
||||||
id.net = (char *)daemon->dhcp_buff2;
|
id.net = (char *)daemon->dhcp_buff2;
|
||||||
id.next = netid;
|
id.next = netid;
|
||||||
netid = &id;
|
netid = &id;
|
||||||
@@ -3248,7 +3248,7 @@ unsigned int relay_reply4(struct dhcp_packet *mess, size_t sz, char *arrival_int
|
|||||||
|
|
||||||
/* delete agent info before return RFC 3046 para 2.1 */
|
/* delete agent info before return RFC 3046 para 2.1 */
|
||||||
*opt = OPTION_END;
|
*opt = OPTION_END;
|
||||||
memset(opt + 1, 0, option_len(opt) + 2);
|
memset(opt + 1, 0, option_len(opt) + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mess->giaddr.s_addr == relay->local.addr4.s_addr)
|
else if (mess->giaddr.s_addr == relay->local.addr4.s_addr)
|
||||||
|
|||||||
+45
-63
@@ -39,9 +39,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu
|
|||||||
static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_opts);
|
static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_opts);
|
||||||
static void log6_packet(struct state *state, char *type, struct in6_addr *addr, char *string);
|
static void log6_packet(struct state *state, char *type, struct in6_addr *addr, char *string);
|
||||||
static void log6_quiet(struct state *state, char *type, struct in6_addr *addr, char *string);
|
static void log6_quiet(struct state *state, char *type, struct in6_addr *addr, char *string);
|
||||||
static void *opt6_find (uint8_t *opts, uint8_t *end, unsigned int search, unsigned int minsize);
|
static void *opt6_find (uint8_t *opts, uint8_t *end, unsigned int search, int minsize);
|
||||||
static void *opt6_first(uint8_t *opt, uint8_t *end);
|
static void *opt6_first(uint8_t *opt, uint8_t *end);
|
||||||
static void *opt6_next(uint8_t *opts, uint8_t *end);
|
|
||||||
static unsigned int opt6_uint(unsigned char *opt, int offset, int size);
|
static unsigned int opt6_uint(unsigned char *opt, int offset, int size);
|
||||||
static void get_context_tag(struct state *state, struct dhcp_context *context);
|
static void get_context_tag(struct state *state, struct dhcp_context *context);
|
||||||
static int check_ia(struct state *state, void *opt, void **endp, void **ia_option);
|
static int check_ia(struct state *state, void *opt, void **endp, void **ia_option);
|
||||||
@@ -63,6 +62,7 @@ static void calculate_times(struct dhcp_context *context, unsigned int *min_time
|
|||||||
#define opt6_len(opt) ((int)(opt6_uint(opt, -2, 2)))
|
#define opt6_len(opt) ((int)(opt6_uint(opt, -2, 2)))
|
||||||
#define opt6_type(opt) (opt6_uint(opt, -4, 2))
|
#define opt6_type(opt) (opt6_uint(opt, -4, 2))
|
||||||
#define opt6_ptr(opt, i) ((void *)&(((uint8_t *)(opt))[4+(i)]))
|
#define opt6_ptr(opt, i) ((void *)&(((uint8_t *)(opt))[4+(i)]))
|
||||||
|
#define opt6_next(opt, end) (opt6_first(opt6_ptr((opt), opt6_len((opt))), (end)))
|
||||||
|
|
||||||
#define opt6_user_vendor_ptr(opt, i) ((void *)&(((uint8_t *)(opt))[2+(i)]))
|
#define opt6_user_vendor_ptr(opt, i) ((void *)&(((uint8_t *)(opt))[2+(i)]))
|
||||||
#define opt6_user_vendor_len(opt) ((int)(opt6_uint(opt, -4, 2)))
|
#define opt6_user_vendor_len(opt) ((int)(opt6_uint(opt, -4, 2)))
|
||||||
@@ -392,10 +392,23 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu
|
|||||||
if (opt6_len(opt) < 4)
|
if (opt6_len(opt) < 4)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (vendor->enterprise != opt6_uint(opt, 0, 4))
|
if (vendor->enterprise != 0 && vendor->enterprise != opt6_uint(opt, 0, 4))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* matching enterprise, no string match. */
|
||||||
|
if (vendor->enterprise != 0 && vendor->len == 0)
|
||||||
|
{
|
||||||
|
vendor->netid.next = state->tags;
|
||||||
|
state->tags = &vendor->netid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
offset = 4;
|
offset = 4;
|
||||||
|
|
||||||
|
/* If we're going to search the strings below, there must be at least one empty string to search
|
||||||
|
I think a vendor_class option with just the enterprise number is valid. */
|
||||||
|
if (opt6_len(opt) < 6)
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note that format if user/vendor classes is different to DHCP options - no option types. */
|
/* Note that format if user/vendor classes is different to DHCP options - no option types. */
|
||||||
@@ -662,7 +675,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu
|
|||||||
for (c = state->context; c; c = c->current)
|
for (c = state->context; c; c = c->current)
|
||||||
c->flags &= ~CONTEXT_CONF_USED;
|
c->flags &= ~CONTEXT_CONF_USED;
|
||||||
|
|
||||||
for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
|
for (opt = opt6_first(state->packet_options, state->end); opt; opt = opt6_next(opt, state->end))
|
||||||
{
|
{
|
||||||
void *ia_option, *ia_end;
|
void *ia_option, *ia_end;
|
||||||
unsigned int min_time = 0xffffffff;
|
unsigned int min_time = 0xffffffff;
|
||||||
@@ -826,7 +839,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu
|
|||||||
if (ignore)
|
if (ignore)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
|
for (opt = opt6_first(state->packet_options, state->end); opt; opt = opt6_next(opt, state->end))
|
||||||
{
|
{
|
||||||
void *ia_option, *ia_end;
|
void *ia_option, *ia_end;
|
||||||
unsigned int min_time = 0xffffffff;
|
unsigned int min_time = 0xffffffff;
|
||||||
@@ -937,7 +950,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu
|
|||||||
|
|
||||||
log6_quiet(state, msg_type == DHCP6RENEW ? "DHCPRENEW" : "DHCPREBIND", NULL, NULL);
|
log6_quiet(state, msg_type == DHCP6RENEW ? "DHCPRENEW" : "DHCPREBIND", NULL, NULL);
|
||||||
|
|
||||||
for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
|
for (opt = opt6_first(state->packet_options, state->end); opt; opt = opt6_next(opt, state->end))
|
||||||
{
|
{
|
||||||
void *ia_option, *ia_end;
|
void *ia_option, *ia_end;
|
||||||
unsigned int min_time = 0xffffffff;
|
unsigned int min_time = 0xffffffff;
|
||||||
@@ -1072,7 +1085,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu
|
|||||||
|
|
||||||
log6_quiet(state, "DHCPCONFIRM", NULL, NULL);
|
log6_quiet(state, "DHCPCONFIRM", NULL, NULL);
|
||||||
|
|
||||||
for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
|
for (opt = opt6_first(state->packet_options, state->end); opt; opt = opt6_next(opt, state->end))
|
||||||
{
|
{
|
||||||
void *ia_option, *ia_end;
|
void *ia_option, *ia_end;
|
||||||
|
|
||||||
@@ -1148,7 +1161,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu
|
|||||||
|
|
||||||
log6_quiet(state, "DHCPRELEASE", NULL, NULL);
|
log6_quiet(state, "DHCPRELEASE", NULL, NULL);
|
||||||
|
|
||||||
for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
|
for (opt = opt6_first(state->packet_options, state->end); opt; opt = opt6_next(opt, state->end))
|
||||||
{
|
{
|
||||||
void *ia_option, *ia_end;
|
void *ia_option, *ia_end;
|
||||||
int made_ia = 0;
|
int made_ia = 0;
|
||||||
@@ -1213,7 +1226,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu
|
|||||||
|
|
||||||
log6_quiet(state, "DHCPDECLINE", NULL, NULL);
|
log6_quiet(state, "DHCPDECLINE", NULL, NULL);
|
||||||
|
|
||||||
for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
|
for (opt = opt6_first(state->packet_options, state->end); opt; opt = opt6_next(opt, state->end))
|
||||||
{
|
{
|
||||||
void *ia_option, *ia_end;
|
void *ia_option, *ia_end;
|
||||||
int made_ia = 0;
|
int made_ia = 0;
|
||||||
@@ -1585,10 +1598,7 @@ static int check_ia(struct state *state, void *opt, void **endp, void **ia_optio
|
|||||||
{
|
{
|
||||||
*ia_option = NULL;
|
*ia_option = NULL;
|
||||||
|
|
||||||
/* must be a minimal option to check without stepping outside received packet. */
|
/* callee ensures packet is long enough for opt6_len(opt) to be valid and believe-able. */
|
||||||
if (opt6_ptr(opt, 4) > state->end)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
state->ia_type = opt6_type(opt);
|
state->ia_type = opt6_type(opt);
|
||||||
|
|
||||||
if (state->ia_type != OPTION6_IA_NA && state->ia_type != OPTION6_IA_TA)
|
if (state->ia_type != OPTION6_IA_NA && state->ia_type != OPTION6_IA_TA)
|
||||||
@@ -1600,10 +1610,7 @@ static int check_ia(struct state *state, void *opt, void **endp, void **ia_optio
|
|||||||
if (state->ia_type == OPTION6_IA_TA && opt6_len(opt) < 4)
|
if (state->ia_type == OPTION6_IA_TA && opt6_len(opt) < 4)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Check we don't overflow the received packet. */
|
*endp = opt6_ptr(opt, opt6_len(opt));
|
||||||
if ((*endp = opt6_ptr(opt, opt6_len(opt))) > state->end)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
state->iaid = opt6_uint(opt, 0, 4);
|
state->iaid = opt6_uint(opt, 0, 4);
|
||||||
*ia_option = opt6_find(opt6_ptr(opt, state->ia_type == OPTION6_IA_NA ? 12 : 4), *endp, OPTION6_IAADDR, 24);
|
*ia_option = opt6_find(opt6_ptr(opt, state->ia_type == OPTION6_IA_NA ? 12 : 4), *endp, OPTION6_IAADDR, 24);
|
||||||
|
|
||||||
@@ -1918,10 +1925,10 @@ static void update_leases(struct state *state, struct dhcp_context *context, str
|
|||||||
lease_add_extradata(lease, (unsigned char *)daemon->dhcp_buff2, strlen(daemon->dhcp_buff2), 0);
|
lease_add_extradata(lease, (unsigned char *)daemon->dhcp_buff2, strlen(daemon->dhcp_buff2), 0);
|
||||||
|
|
||||||
if (opt6_len(opt) >= 6)
|
if (opt6_len(opt) >= 6)
|
||||||
for (enc_opt = opt6_ptr(opt, 4); enc_opt; enc_opt = opt6_next(enc_opt, enc_end))
|
for (enc_opt = opt6_ptr(opt, 4); enc_opt; enc_opt = opt6_user_vendor_next(enc_opt, enc_end))
|
||||||
{
|
{
|
||||||
lease->vendorclass_count++;
|
lease->vendorclass_count++;
|
||||||
lease_add_extradata(lease, opt6_ptr(enc_opt, 0), opt6_len(enc_opt), 0);
|
lease_add_extradata(lease, opt6_user_vendor_ptr(enc_opt, 0), opt6_user_vendor_len(enc_opt), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1978,8 +1985,8 @@ static void update_leases(struct state *state, struct dhcp_context *context, str
|
|||||||
if ((opt = opt6_find(state->packet_options, state->end, OPTION6_USER_CLASS, 2)))
|
if ((opt = opt6_find(state->packet_options, state->end, OPTION6_USER_CLASS, 2)))
|
||||||
{
|
{
|
||||||
void *enc_opt, *enc_end = opt6_ptr(opt, opt6_len(opt));
|
void *enc_opt, *enc_end = opt6_ptr(opt, opt6_len(opt));
|
||||||
for (enc_opt = opt6_ptr(opt, 0); enc_opt; enc_opt = opt6_next(enc_opt, enc_end))
|
for (enc_opt = opt6_ptr(opt, 0); enc_opt; enc_opt = opt6_user_vendor_next(enc_opt, enc_end))
|
||||||
lease_add_extradata(lease, opt6_ptr(enc_opt, 0), opt6_len(enc_opt), 0);
|
lease_add_extradata(lease, opt6_user_vendor_ptr(enc_opt, 0), opt6_user_vendor_len(enc_opt), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1994,10 +2001,10 @@ static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_op
|
|||||||
void *opt;
|
void *opt;
|
||||||
char *desc = nest ? "nest" : "sent";
|
char *desc = nest ? "nest" : "sent";
|
||||||
|
|
||||||
if (!option_bool(OPT_LOG_OPTS) || start_opts == end_opts)
|
if (!option_bool(OPT_LOG_OPTS))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (opt = start_opts; opt; opt = opt6_next(opt, end_opts))
|
for (opt = opt6_first(start_opts, end_opts); opt; opt = opt6_next(opt, end_opts))
|
||||||
{
|
{
|
||||||
int type = opt6_type(opt);
|
int type = opt6_type(opt);
|
||||||
void *ia_options = NULL;
|
void *ia_options = NULL;
|
||||||
@@ -2030,9 +2037,15 @@ static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_op
|
|||||||
}
|
}
|
||||||
else if (type == OPTION6_STATUS_CODE)
|
else if (type == OPTION6_STATUS_CODE)
|
||||||
{
|
{
|
||||||
|
if (opt6_len(opt) >= 2)
|
||||||
|
{
|
||||||
|
int slen = opt6_len(opt) - 2;
|
||||||
int len = sprintf(daemon->namebuff, "%u ", opt6_uint(opt, 0, 2));
|
int len = sprintf(daemon->namebuff, "%u ", opt6_uint(opt, 0, 2));
|
||||||
memcpy(daemon->namebuff + len, opt6_ptr(opt, 2), opt6_len(opt)-2);
|
if (slen > (MAXDNAME * 2) - len - 1)
|
||||||
daemon->namebuff[len + opt6_len(opt) - 2] = 0;
|
slen = (MAXDNAME * 2) - len - 1;
|
||||||
|
memcpy(daemon->namebuff + len, opt6_ptr(opt, 2), slen);
|
||||||
|
daemon->namebuff[len + slen] = 0;
|
||||||
|
}
|
||||||
optname = "status";
|
optname = "status";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2091,35 +2104,20 @@ static void log6_packet(struct state *state, char *type, struct in6_addr *addr,
|
|||||||
string ? string : "");
|
string ? string : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *opt6_find (uint8_t *opts, uint8_t *end, unsigned int search, unsigned int minsize)
|
static void *opt6_find(uint8_t *opts, uint8_t *end, unsigned int search, int minsize)
|
||||||
{
|
{
|
||||||
u16 opt, opt_len;
|
for (opts = opt6_first(opts, end); opts; opts = opt6_next(opts, end))
|
||||||
void *start;
|
if (opt6_type(opts) == search && opt6_len(opts) >= minsize)
|
||||||
|
return opts;
|
||||||
|
|
||||||
if (!opts)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
if (end - opts < 4)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
start = opts;
|
|
||||||
GETSHORT(opt, opts);
|
|
||||||
GETSHORT(opt_len, opts);
|
|
||||||
|
|
||||||
if (opt_len > (end - opts))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (opt == search && (opt_len >= minsize))
|
|
||||||
return start;
|
|
||||||
|
|
||||||
opts += opt_len;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *opt6_first(uint8_t *opt, uint8_t *end)
|
static void *opt6_first(uint8_t *opt, uint8_t *end)
|
||||||
{
|
{
|
||||||
|
if (!opt)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
/* make sure we have option number and length. */
|
/* make sure we have option number and length. */
|
||||||
if ((uint8_t *)opt6_ptr(opt, 0) > end)
|
if ((uint8_t *)opt6_ptr(opt, 0) > end)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -2131,22 +2129,6 @@ static void *opt6_first(uint8_t *opt, uint8_t *end)
|
|||||||
return opt;
|
return opt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *opt6_next(uint8_t *opts, uint8_t *end)
|
|
||||||
{
|
|
||||||
u16 opt_len;
|
|
||||||
|
|
||||||
if (end - opts < 4)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
opts += 2;
|
|
||||||
GETSHORT(opt_len, opts);
|
|
||||||
|
|
||||||
if (opt_len >= (end - opts))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return opts + opt_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int opt6_uint(unsigned char *opt, int offset, int size)
|
static unsigned int opt6_uint(unsigned char *opt, int offset, int size)
|
||||||
{
|
{
|
||||||
/* this worries about unaligned data and byte order */
|
/* this worries about unaligned data and byte order */
|
||||||
|
|||||||
+6
-1
@@ -545,8 +545,13 @@ static struct tftp_file *check_tftp_fileperm(char *packet, ssize_t *len, char *p
|
|||||||
int fd = -1;
|
int fd = -1;
|
||||||
|
|
||||||
/* trick to ban moving out of the subtree */
|
/* trick to ban moving out of the subtree */
|
||||||
if (prefix && strstr(namebuff, "/../"))
|
if (prefix)
|
||||||
|
{
|
||||||
|
char *suspect = strstr(namebuff, "/..");
|
||||||
|
|
||||||
|
if (suspect && (suspect[3] == '/' || suspect[3] == 0))
|
||||||
goto perm;
|
goto perm;
|
||||||
|
}
|
||||||
|
|
||||||
if ((fd = open(namebuff, O_RDONLY)) == -1)
|
if ((fd = open(namebuff, O_RDONLY)) == -1)
|
||||||
{
|
{
|
||||||
|
|||||||
+2
-3
@@ -105,8 +105,6 @@ u32 rand32(void)
|
|||||||
|
|
||||||
u64 rand64(void)
|
u64 rand64(void)
|
||||||
{
|
{
|
||||||
static int outleft = 0;
|
|
||||||
|
|
||||||
if (outleft < 2)
|
if (outleft < 2)
|
||||||
{
|
{
|
||||||
if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
|
if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
|
||||||
@@ -581,6 +579,7 @@ void prettyprint_time(char *buf, unsigned int t)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned int x, p = 0;
|
unsigned int x, p = 0;
|
||||||
|
buf[0] = '\0';
|
||||||
if ((x = t/86400))
|
if ((x = t/86400))
|
||||||
p += sprintf(&buf[p], "%ud", x);
|
p += sprintf(&buf[p], "%ud", x);
|
||||||
if ((x = (t/3600)%24))
|
if ((x = (t/3600)%24))
|
||||||
@@ -991,7 +990,7 @@ int expand_workspace_real(const char *func, unsigned int line, unsigned char ***
|
|||||||
if (!(p = whine_realloc_real("expand_workspace", func, line, *wkspc, new * sizeof(unsigned char *))))
|
if (!(p = whine_realloc_real("expand_workspace", func, line, *wkspc, new * sizeof(unsigned char *))))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
memset(p+old, 0, new-old);
|
memset(p+old, 0, (new-old) * sizeof(unsigned char *));
|
||||||
|
|
||||||
*wkspc = p;
|
*wkspc = p;
|
||||||
*szp = new;
|
*szp = new;
|
||||||
|
|||||||
Reference in new issue
Block a user