mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
import of dnsmasq-2.38.tar.gz
This commit is contained in:
37
src/cache.c
37
src/cache.c
@@ -13,7 +13,7 @@
|
||||
#include "dnsmasq.h"
|
||||
|
||||
static struct crec *cache_head, *cache_tail, **hash_table;
|
||||
static struct crec *dhcp_inuse, *dhcp_spare, *new_chain;
|
||||
static struct crec *dhcp_spare, *new_chain;
|
||||
static int cache_inserted, cache_live_freed, insert_error;
|
||||
static union bigname *big_free;
|
||||
static int bignames_left, log_queries, cache_size, hash_size;
|
||||
@@ -74,7 +74,7 @@ void cache_init(int size, int logq)
|
||||
addrbuff = NULL;
|
||||
|
||||
cache_head = cache_tail = NULL;
|
||||
dhcp_inuse = dhcp_spare = NULL;
|
||||
dhcp_spare = NULL;
|
||||
new_chain = NULL;
|
||||
hash_table = NULL;
|
||||
cache_size = size;
|
||||
@@ -170,7 +170,7 @@ static void cache_hash(struct crec *crecp)
|
||||
up = &((*up)->hash_next);
|
||||
|
||||
if (crecp->flags & F_IMMORTAL)
|
||||
while (*up && (!(*up)->flags & F_IMMORTAL))
|
||||
while (*up && !((*up)->flags & F_IMMORTAL))
|
||||
up = &((*up)->hash_next);
|
||||
}
|
||||
crecp->hash_next = *up;
|
||||
@@ -282,9 +282,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
|
||||
|
||||
if (flags & F_FORWARD)
|
||||
{
|
||||
for (up = hash_bucket(name), crecp = *up;
|
||||
crecp && ((crecp->flags & F_REVERSE) || !(crecp->flags & F_IMMORTAL));
|
||||
crecp = crecp->hash_next)
|
||||
for (up = hash_bucket(name), crecp = *up; crecp; crecp = crecp->hash_next)
|
||||
if (is_expired(now, crecp) || is_outdated_cname_pointer(crecp))
|
||||
{
|
||||
*up = crecp->hash_next;
|
||||
@@ -601,8 +599,7 @@ struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
|
||||
crecp = crecp->hash_next)
|
||||
if (!is_expired(now, crecp))
|
||||
{
|
||||
if ((crecp->flags & F_REVERSE) &&
|
||||
(crecp->flags & prot) &&
|
||||
if ((crecp->flags & prot) &&
|
||||
memcmp(&crecp->addr.addr, addr, addrlen) == 0)
|
||||
{
|
||||
if (crecp->flags & (F_HOSTS | F_DHCP))
|
||||
@@ -834,25 +831,19 @@ void cache_reload(int opts, char *buff, char *domain_suffix, struct hostsfile *a
|
||||
|
||||
void cache_unhash_dhcp(void)
|
||||
{
|
||||
struct crec *tmp, *cache, **up;
|
||||
struct crec *cache, **up;
|
||||
int i;
|
||||
|
||||
for (i=0; i<hash_size; i++)
|
||||
for (cache = hash_table[i], up = &hash_table[i]; cache; cache = cache->hash_next)
|
||||
if (cache->flags & F_DHCP)
|
||||
*up = cache->hash_next;
|
||||
{
|
||||
*up = cache->hash_next;
|
||||
cache->next = dhcp_spare;
|
||||
dhcp_spare = cache;
|
||||
}
|
||||
else
|
||||
up = &cache->hash_next;
|
||||
|
||||
/* prev field links all dhcp entries */
|
||||
for (cache = dhcp_inuse; cache; cache = tmp)
|
||||
{
|
||||
tmp = cache->prev;
|
||||
cache->prev = dhcp_spare;
|
||||
dhcp_spare = cache;
|
||||
}
|
||||
|
||||
dhcp_inuse = NULL;
|
||||
}
|
||||
|
||||
void cache_add_dhcp_entry(struct daemon *daemon, char *host_name,
|
||||
@@ -893,7 +884,7 @@ void cache_add_dhcp_entry(struct daemon *daemon, char *host_name,
|
||||
}
|
||||
|
||||
if ((crec = dhcp_spare))
|
||||
dhcp_spare = dhcp_spare->prev;
|
||||
dhcp_spare = dhcp_spare->next;
|
||||
else /* need new one */
|
||||
crec = malloc(sizeof(struct crec));
|
||||
|
||||
@@ -906,14 +897,10 @@ void cache_add_dhcp_entry(struct daemon *daemon, char *host_name,
|
||||
crec->ttd = ttd;
|
||||
crec->addr.addr.addr.addr4 = *host_address;
|
||||
crec->name.namep = host_name;
|
||||
crec->prev = dhcp_inuse;
|
||||
dhcp_inuse = crec;
|
||||
cache_hash(crec);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dump_cache(struct daemon *daemon, time_t now)
|
||||
{
|
||||
syslog(LOG_INFO, _("time %lu, cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#define VERSION "2.37"
|
||||
#define VERSION "2.38"
|
||||
|
||||
#define FTABSIZ 150 /* max number of outstanding requests (default) */
|
||||
#define MAX_PROCS 20 /* max no children for TCP requests */
|
||||
@@ -180,7 +180,7 @@ NOTES:
|
||||
# error HAVE_ISC_READER is not compatible with HAVE_BROKEN_RTC
|
||||
#endif
|
||||
|
||||
/* Allow TFTP to be disabled with CFLAGS=-DNO_TFTP */
|
||||
/* Allow TFTP to be disabled with COPT=-DNO_TFTP */
|
||||
#ifdef NO_TFTP
|
||||
#undef HAVE_TFTP
|
||||
#endif
|
||||
@@ -276,6 +276,7 @@ typedef unsigned long in_addr_t;
|
||||
|
||||
#endif
|
||||
/* Decide if we're going to support IPv6 */
|
||||
/* IPv6 can be forced off with "make COPTS=-DNO_IPV6" */
|
||||
/* We assume that systems which don't have IPv6
|
||||
headers don't have ntop and pton either */
|
||||
|
||||
|
||||
@@ -114,6 +114,7 @@ extern int capset(cap_user_header_t header, cap_user_data_t data);
|
||||
#define OPT_RELOAD (1<<24)
|
||||
#define OPT_TFTP (1<<25)
|
||||
#define OPT_TFTP_SECURE (1<<26)
|
||||
#define OPT_TFTP_NOBLOCK (1<<27)
|
||||
|
||||
struct all_addr {
|
||||
union {
|
||||
@@ -365,7 +366,9 @@ struct dhcp_opt {
|
||||
|
||||
#define DHOPT_ADDR 1
|
||||
#define DHOPT_STRING 2
|
||||
#define DHOPT_VENDOR_MATCH 4
|
||||
#define DHOPT_ENCAPSULATE 4
|
||||
#define DHOPT_VENDOR_MATCH 8
|
||||
#define DHOPT_FORCE 16
|
||||
|
||||
struct dhcp_boot {
|
||||
char *file, *sname;
|
||||
@@ -474,7 +477,7 @@ struct daemon {
|
||||
struct hostsfile *addn_hosts;
|
||||
struct dhcp_context *dhcp;
|
||||
struct dhcp_config *dhcp_conf;
|
||||
struct dhcp_opt *dhcp_opts, *vendor_opts;
|
||||
struct dhcp_opt *dhcp_opts;
|
||||
struct dhcp_vendor *dhcp_vendors;
|
||||
struct dhcp_mac *dhcp_macs;
|
||||
struct dhcp_boot *boot_config;
|
||||
|
||||
@@ -447,7 +447,9 @@ void reply_query(struct serverfd *sfd, struct daemon *daemon, time_t now)
|
||||
{
|
||||
struct server *server = forward->sentto;
|
||||
|
||||
if ((header->rcode == SERVFAIL || header->rcode == REFUSED) && forward->forwardall == 0)
|
||||
if ((header->rcode == SERVFAIL || header->rcode == REFUSED) &&
|
||||
!(daemon->options & OPT_ORDER) &&
|
||||
forward->forwardall == 0)
|
||||
/* for broken servers, attempt to send to another one. */
|
||||
{
|
||||
unsigned char *pheader;
|
||||
|
||||
45
src/option.c
45
src/option.c
@@ -35,6 +35,8 @@ struct myoption {
|
||||
#define LOPT_PTR 261
|
||||
#define LOPT_BRIDGE 262
|
||||
#define LOPT_TFTP_MAX 263
|
||||
#define LOPT_FORCE 264
|
||||
#define LOPT_NOBLOCK 265
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
static const struct option opts[] =
|
||||
@@ -117,6 +119,8 @@ static const struct myoption opts[] =
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
{"bridge-interface", 1, 0 , LOPT_BRIDGE },
|
||||
#endif
|
||||
{"dhcp-option-force", 1, 0, LOPT_FORCE },
|
||||
{"tftp-no-blocksize", 0, 0, LOPT_NOBLOCK },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
@@ -151,6 +155,7 @@ static const struct optflags optmap[] = {
|
||||
{ LOPT_RELOAD, OPT_RELOAD },
|
||||
{ LOPT_TFTP, OPT_TFTP },
|
||||
{ LOPT_SECURE, OPT_TFTP_SECURE },
|
||||
{ LOPT_NOBLOCK, OPT_TFTP_NOBLOCK },
|
||||
{ 'v', 0},
|
||||
{ 'w', 0},
|
||||
{ 0, 0 }
|
||||
@@ -190,7 +195,8 @@ static const struct {
|
||||
{ "-n, --no-poll", gettext_noop("Do NOT poll %s file, reload only on SIGHUP."), RESOLVFILE },
|
||||
{ "-N, --no-negcache", gettext_noop("Do NOT cache failed search results."), NULL },
|
||||
{ "-o, --strict-order", gettext_noop("Use nameservers strictly in the order given in %s."), RESOLVFILE },
|
||||
{ "-O, --dhcp-option=<optspec>", gettext_noop("Set extra options to be set to DHCP clients."), NULL },
|
||||
{ "-O, --dhcp-option=<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL },
|
||||
{ " --dhcp-option-force=<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},
|
||||
{ "-p, --port=number", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL },
|
||||
{ "-P, --edns-packet-max=<size>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },
|
||||
{ "-q, --log-queries", gettext_noop("Log queries."), NULL },
|
||||
@@ -234,17 +240,18 @@ static const struct {
|
||||
{ " --tftp-root=<directory>", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
|
||||
{ " --tftp-secure", gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
|
||||
{ " --tftp-max=<connections>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
|
||||
{ " --tftp-no-blocksize", gettext_noop("Disable the TFTP blocksize extension."), NULL },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
/* We hide metacharaters in quoted strings by mapping them into the ASCII control
|
||||
character space. Note that the \0, \t \a \b \r and \n characters are carefully placed in the
|
||||
character space. Note that the \0, \t \a \b \r \033 and \n characters are carefully placed in the
|
||||
following sequence so that they map to themselves: it is therefore possible to call
|
||||
unhide_metas repeatedly on string without breaking things.
|
||||
The transformation gets undone by opt_canonicalise, atoi_check and safe_string_alloc, and a
|
||||
couple of other places. */
|
||||
|
||||
static const char meta[] = "\000123456\a\b\t\n78\r90abcdefABCDEF:,.";
|
||||
static const char meta[] = "\000123456\a\b\t\n78\r90abcdefABCDE\033F:,.";
|
||||
|
||||
static void one_file(struct daemon *daemon, char *file, int nest);
|
||||
|
||||
@@ -380,15 +387,15 @@ static void do_usage(void)
|
||||
}
|
||||
|
||||
/* This is too insanely large to keep in-line in the switch */
|
||||
static char *parse_dhcp_opt(struct daemon *daemon, char *arg)
|
||||
static char *parse_dhcp_opt(struct daemon *daemon, char *arg, int forced)
|
||||
{
|
||||
struct dhcp_opt *new = safe_malloc(sizeof(struct dhcp_opt));
|
||||
char lenchar = 0, *cp;
|
||||
int addrs, digs, is_addr, is_hex, is_dec, is_vend = 0;
|
||||
int addrs, digs, is_addr, is_hex, is_dec;
|
||||
char *comma, *problem = NULL;
|
||||
|
||||
new->len = 0;
|
||||
new->flags = 0;
|
||||
new->flags = forced ? DHOPT_FORCE : 0;
|
||||
new->netid = NULL;
|
||||
new->val = NULL;
|
||||
new->vendor_class = NULL;
|
||||
@@ -408,7 +415,7 @@ static char *parse_dhcp_opt(struct daemon *daemon, char *arg)
|
||||
if (strstr(arg, "vendor:") == arg)
|
||||
{
|
||||
new->vendor_class = (unsigned char *)safe_string_alloc(arg+7);
|
||||
is_vend = 1;
|
||||
new->flags |= DHOPT_ENCAPSULATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -488,7 +495,7 @@ static char *parse_dhcp_opt(struct daemon *daemon, char *arg)
|
||||
new->len = 2;
|
||||
else if (lenchar == 'i')
|
||||
new->len = 4;
|
||||
else if (new->vendor_class)
|
||||
else if (new->flags & DHOPT_ENCAPSULATE)
|
||||
{
|
||||
if (val & 0xffff0000)
|
||||
new->len = 4;
|
||||
@@ -517,12 +524,12 @@ static char *parse_dhcp_opt(struct daemon *daemon, char *arg)
|
||||
/* max length of address/subnet descriptor is five bytes,
|
||||
add one for the option 120 enc byte too */
|
||||
new->val = op = safe_malloc((5 * addrs) + 1);
|
||||
if (!new->vendor_class)
|
||||
new->flags |= DHOPT_ADDR;
|
||||
|
||||
if (!(new->flags & DHOPT_ENCAPSULATE) && new->opt == 120)
|
||||
{
|
||||
if (new->opt == 120)
|
||||
*(op++) = 1; /* RFC 3361 "enc byte" */
|
||||
else
|
||||
new->flags |= DHOPT_ADDR;
|
||||
*(op++) = 1; /* RFC 3361 "enc byte" */
|
||||
new->flags &= ~DHOPT_ADDR;
|
||||
}
|
||||
while (addrs--)
|
||||
{
|
||||
@@ -558,7 +565,7 @@ static char *parse_dhcp_opt(struct daemon *daemon, char *arg)
|
||||
else
|
||||
{
|
||||
/* text arg */
|
||||
if ((new->opt == 119 || new->opt == 120) && !new->vendor_class)
|
||||
if ((new->opt == 119 || new->opt == 120) && !(new->flags & DHOPT_ENCAPSULATE))
|
||||
{
|
||||
/* dns search, RFC 3397, or SIP, RFC 3361 */
|
||||
unsigned char *q, *r, *tail;
|
||||
@@ -643,11 +650,6 @@ static char *parse_dhcp_opt(struct daemon *daemon, char *arg)
|
||||
free(new->vendor_class);
|
||||
free(new);
|
||||
}
|
||||
else if (is_vend)
|
||||
{
|
||||
new->next = daemon->vendor_opts;
|
||||
daemon->vendor_opts = new;
|
||||
}
|
||||
else
|
||||
{
|
||||
new->next = daemon->dhcp_opts;
|
||||
@@ -1501,7 +1503,8 @@ static char *one_opt(struct daemon *daemon, int option, char *arg, char *problem
|
||||
}
|
||||
|
||||
case 'O':
|
||||
if ((problem = parse_dhcp_opt(daemon, arg)))
|
||||
case LOPT_FORCE:
|
||||
if ((problem = parse_dhcp_opt(daemon, arg, option == LOPT_FORCE)))
|
||||
option = '?';
|
||||
break;
|
||||
|
||||
@@ -1899,6 +1902,8 @@ static void one_file(struct daemon *daemon, char *file, int nest)
|
||||
p[1] = '\b';
|
||||
else if (p[1] == 'r')
|
||||
p[1] = '\r';
|
||||
else if (p[1] == 'e') /* escape */
|
||||
p[1] = '\033';
|
||||
memmove(p, p+1, strlen(p+1)+1);
|
||||
}
|
||||
*p = hide_meta(*p);
|
||||
|
||||
212
src/rfc2131.c
212
src/rfc2131.c
@@ -87,35 +87,10 @@ static void do_options(struct dhcp_context *context,
|
||||
unsigned char fqdn_flags,
|
||||
int null_term,
|
||||
unsigned char *agent_id);
|
||||
|
||||
/* find a good value to use as MAC address for logging and address-allocation hashing.
|
||||
This is normally just the chaddr field from the DHCP packet,
|
||||
but eg Firewire will have hlen == 0 and use the client-id instead.
|
||||
This could be anything, but will normally be EUI64 for Firewire.
|
||||
We assume that if the first byte of the client-id equals the htype byte
|
||||
then the client-id is using the usual encoding and use the rest of the
|
||||
client-id: if not we can use the whole client-id. This should give
|
||||
sane MAC address logs. */
|
||||
static unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
|
||||
int clid_len, unsigned char *clid, int *len_out)
|
||||
{
|
||||
if (hwlen == 0 && clid && clid_len > 3)
|
||||
{
|
||||
if ((clid[0] == ARPHRD_EUI64 && hwtype == ARPHRD_IEEE1394) || clid[0] == hwtype)
|
||||
{
|
||||
*len_out = clid_len - 1 ;
|
||||
return clid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*len_out = clid_len;
|
||||
return clid;
|
||||
}
|
||||
}
|
||||
|
||||
*len_out = hwlen;
|
||||
return hwaddr;
|
||||
}
|
||||
int clid_len, unsigned char *clid, int *len_out);
|
||||
static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
|
||||
|
||||
|
||||
size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_name,
|
||||
size_t sz, time_t now, int unicast_dest)
|
||||
@@ -123,7 +98,6 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa
|
||||
unsigned char *opt, *clid = NULL;
|
||||
struct dhcp_lease *ltmp, *lease = NULL;
|
||||
struct dhcp_vendor *vendor;
|
||||
struct dhcp_opt *dopt;
|
||||
struct dhcp_mac *mac;
|
||||
struct dhcp_netid_list *id_list;
|
||||
int clid_len = 0, ignore = 0, do_classes = 0, selecting = 0;
|
||||
@@ -311,7 +285,7 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa
|
||||
if (mess_type == 0)
|
||||
{
|
||||
/* BOOTP request */
|
||||
struct dhcp_netid id;
|
||||
struct dhcp_netid id, bootp_id;
|
||||
struct in_addr *logaddr = NULL;
|
||||
|
||||
/* must have a MAC addr for bootp */
|
||||
@@ -341,6 +315,12 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa
|
||||
id.next = netid;
|
||||
netid = &id;
|
||||
}
|
||||
|
||||
/* Add "bootp" as a tag to allow different options, address ranges etc
|
||||
for BOOTP clients */
|
||||
bootp_id.net = "bootp";
|
||||
bootp_id.next = netid;
|
||||
netid = &bootp_id;
|
||||
|
||||
for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
|
||||
if (match_netid(id_list->list, netid, 0))
|
||||
@@ -409,7 +389,7 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa
|
||||
|
||||
log_packet(daemon, NULL, logaddr, mess->chaddr, mess->hlen, iface_name, message);
|
||||
|
||||
return message ? dhcp_packet_size(mess) : 0;
|
||||
return message ? 0 : dhcp_packet_size(mess);
|
||||
}
|
||||
|
||||
if ((opt = option_find(mess, sz, OPTION_CLIENT_FQDN, 4)))
|
||||
@@ -534,23 +514,7 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa
|
||||
}
|
||||
|
||||
/* mark vendor-encapsulated options which match the client-supplied vendor class */
|
||||
opt = option_find(mess, sz, OPTION_VENDOR_ID, 1);
|
||||
for (dopt = daemon->vendor_opts; dopt; dopt = dopt->next)
|
||||
{
|
||||
int i, len = 0;
|
||||
dopt->flags &= ~DHOPT_VENDOR_MATCH;
|
||||
if (opt)
|
||||
{
|
||||
if (dopt->vendor_class)
|
||||
len = strlen((char *)dopt->vendor_class);
|
||||
for (i = 0; i <= (option_len(opt) - len); i++)
|
||||
if (len == 0 || memcmp(dopt->vendor_class, option_ptr(opt)+i, len) == 0)
|
||||
{
|
||||
dopt->flags |= DHOPT_VENDOR_MATCH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
match_vendor_opts(option_find(mess, sz, OPTION_VENDOR_ID, 1), daemon->dhcp_opts);
|
||||
|
||||
/* if all the netids in the ignore list are present, ignore this client */
|
||||
for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
|
||||
@@ -961,6 +925,41 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* find a good value to use as MAC address for logging and address-allocation hashing.
|
||||
This is normally just the chaddr field from the DHCP packet,
|
||||
but eg Firewire will have hlen == 0 and use the client-id instead.
|
||||
This could be anything, but will normally be EUI64 for Firewire.
|
||||
We assume that if the first byte of the client-id equals the htype byte
|
||||
then the client-id is using the usual encoding and use the rest of the
|
||||
client-id: if not we can use the whole client-id. This should give
|
||||
sane MAC address logs. */
|
||||
static unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
|
||||
int clid_len, unsigned char *clid, int *len_out)
|
||||
{
|
||||
if (hwlen == 0 && clid && clid_len > 3)
|
||||
{
|
||||
if (clid[0] == hwtype)
|
||||
{
|
||||
*len_out = clid_len - 1 ;
|
||||
return clid + 1;
|
||||
}
|
||||
|
||||
#if defined(ARPHRD_EUI64) && defined(ARPHRD_IEEE1394)
|
||||
if (clid[0] == ARPHRD_EUI64 && hwtype == ARPHRD_IEEE1394)
|
||||
{
|
||||
*len_out = clid_len - 1 ;
|
||||
return clid + 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
*len_out = clid_len;
|
||||
return clid;
|
||||
}
|
||||
|
||||
*len_out = hwlen;
|
||||
return hwaddr;
|
||||
}
|
||||
|
||||
static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config,
|
||||
struct dhcp_lease *lease, unsigned char *opt, time_t now)
|
||||
{
|
||||
@@ -1178,7 +1177,7 @@ static unsigned char *free_space(struct dhcp_packet *mess, unsigned char *end, i
|
||||
}
|
||||
|
||||
if (!p)
|
||||
syslog(LOG_WARNING, _("cannot send DHCP option %d: no space left in packet"), opt);
|
||||
syslog(LOG_WARNING, _("cannot send DHCP/BOOTP option %d: no space left in packet"), opt);
|
||||
}
|
||||
|
||||
if (p)
|
||||
@@ -1223,7 +1222,7 @@ static int do_opt(struct dhcp_opt *opt, unsigned char *p, struct in_addr local,
|
||||
|
||||
if (p && len != 0)
|
||||
{
|
||||
if (opt->flags & DHOPT_ADDR)
|
||||
if ((opt->flags & DHOPT_ADDR) && !(opt->flags & DHOPT_ENCAPSULATE))
|
||||
{
|
||||
int j;
|
||||
struct in_addr *a = (struct in_addr *)opt->val;
|
||||
@@ -1246,8 +1245,8 @@ static int do_opt(struct dhcp_opt *opt, unsigned char *p, struct in_addr local,
|
||||
static int in_list(unsigned char *list, int opt)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* If no requested options, send everything, not nothing. */
|
||||
|
||||
/* If no requested options, send everything, not nothing. */
|
||||
if (!list)
|
||||
return 1;
|
||||
|
||||
@@ -1262,13 +1261,35 @@ static struct dhcp_opt *option_find2(struct dhcp_netid *netid, struct dhcp_opt *
|
||||
{
|
||||
struct dhcp_opt *tmp;
|
||||
for (tmp = opts; tmp; tmp = tmp->next)
|
||||
if (tmp->opt == opt)
|
||||
if (tmp->opt == opt && !(tmp->flags & DHOPT_ENCAPSULATE))
|
||||
if (match_netid(tmp->netid, netid, 1) || match_netid(tmp->netid, netid, 0))
|
||||
return tmp;
|
||||
|
||||
return netid ? option_find2(NULL, opts, opt) : NULL;
|
||||
}
|
||||
|
||||
/* mark vendor-encapsulated options which match the client-supplied or
|
||||
config-supplied vendor class */
|
||||
static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt)
|
||||
{
|
||||
for (; dopt; dopt = dopt->next)
|
||||
{
|
||||
dopt->flags &= ~DHOPT_VENDOR_MATCH;
|
||||
if (opt && (dopt->flags & DHOPT_ENCAPSULATE))
|
||||
{
|
||||
int i, len = 0;
|
||||
if (dopt->vendor_class)
|
||||
len = strlen((char *)dopt->vendor_class);
|
||||
for (i = 0; i <= (option_len(opt) - len); i++)
|
||||
if (len == 0 || memcmp(dopt->vendor_class, option_ptr(opt)+i, len) == 0)
|
||||
{
|
||||
dopt->flags |= DHOPT_VENDOR_MATCH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_packet(struct dhcp_packet *mess, unsigned char *end)
|
||||
{
|
||||
memset(mess->sname, 0, sizeof(mess->sname));
|
||||
@@ -1292,7 +1313,7 @@ static void do_options(struct dhcp_context *context,
|
||||
struct dhcp_opt *opt, *config_opts = daemon->dhcp_opts;
|
||||
struct dhcp_boot *boot;
|
||||
unsigned char *p, *end = agent_id ? agent_id : real_end;
|
||||
int len;
|
||||
int len, force_encap = 0;
|
||||
unsigned char f0 = 0, s0 = 0;
|
||||
|
||||
/* decide which dhcp-boot option we're using */
|
||||
@@ -1428,17 +1449,23 @@ static void do_options(struct dhcp_context *context,
|
||||
}
|
||||
}
|
||||
|
||||
for (opt=config_opts; opt; opt = opt->next)
|
||||
for (opt = config_opts; opt; opt = opt->next)
|
||||
{
|
||||
/* was it asked for, or are we sending it anyway? */
|
||||
if (!(opt->flags & DHOPT_FORCE) && !in_list(req_options, opt->opt))
|
||||
continue;
|
||||
|
||||
/* prohibit some used-internally options */
|
||||
if (opt->opt == OPTION_HOSTNAME ||
|
||||
opt->opt == OPTION_CLIENT_FQDN ||
|
||||
opt->opt == OPTION_MAXMESSAGE ||
|
||||
opt->opt == OPTION_VENDOR_CLASS_OPT ||
|
||||
opt->opt == OPTION_OVERLOAD ||
|
||||
opt->opt == OPTION_PAD ||
|
||||
opt->opt == OPTION_END ||
|
||||
!in_list(req_options, opt->opt) ||
|
||||
opt != option_find2(netid, config_opts, opt->opt))
|
||||
opt->opt == OPTION_END)
|
||||
continue;
|
||||
|
||||
/* netids match and not encapsulated? */
|
||||
if (opt != option_find2(netid, config_opts, opt->opt))
|
||||
continue;
|
||||
|
||||
/* For the options we have default values on
|
||||
@@ -1453,41 +1480,66 @@ static void do_options(struct dhcp_context *context,
|
||||
|
||||
len = do_opt(opt, NULL, context->local, null_term);
|
||||
if ((p = free_space(mess, end, opt->opt, len)))
|
||||
do_opt(opt, p, context->local, null_term);
|
||||
}
|
||||
{
|
||||
do_opt(opt, p, context->local, null_term);
|
||||
|
||||
if (in_list(req_options, OPTION_VENDOR_CLASS_OPT))
|
||||
/* If we send a vendor-id, revisit which vendor-ops we consider
|
||||
it appropriate to send. */
|
||||
if (opt->opt == OPTION_VENDOR_ID)
|
||||
match_vendor_opts(p - 2, config_opts);
|
||||
}
|
||||
}
|
||||
|
||||
/* prune encapsulated options based on netid, and look if we're forcing them to be sent */
|
||||
for (opt = config_opts; opt; opt = opt->next)
|
||||
if (opt->flags & DHOPT_VENDOR_MATCH)
|
||||
{
|
||||
if (!match_netid(opt->netid, netid, 1) && !match_netid(opt->netid, netid, 0))
|
||||
opt->flags &= ~DHOPT_VENDOR_MATCH;
|
||||
else if (opt->flags & DHOPT_FORCE)
|
||||
force_encap = 1;
|
||||
}
|
||||
|
||||
if (force_encap || in_list(req_options, OPTION_VENDOR_CLASS_OPT))
|
||||
{
|
||||
int enc_len = 0;
|
||||
|
||||
struct dhcp_opt *start;
|
||||
|
||||
/* find size in advance */
|
||||
for (opt = daemon->vendor_opts; opt; opt = opt->next)
|
||||
for (start = opt = config_opts; opt; opt = opt->next)
|
||||
if (opt->flags & DHOPT_VENDOR_MATCH)
|
||||
{
|
||||
if (!match_netid(opt->netid, netid, 1) && !match_netid(opt->netid, netid, 0))
|
||||
opt->flags &= ~DHOPT_VENDOR_MATCH;
|
||||
int new = do_opt(opt, NULL, context->local, null_term) + 2;
|
||||
if (enc_len + new <= 255)
|
||||
enc_len += new;
|
||||
else
|
||||
{
|
||||
int new = enc_len + do_opt(opt, NULL, context->local, null_term) + 2;
|
||||
if (new <= 255)
|
||||
enc_len = new;
|
||||
else
|
||||
{
|
||||
syslog(LOG_WARNING, _("cannot send encapsulated option %d: no space left in wrapper"), opt->opt);
|
||||
opt->flags &= ~DHOPT_VENDOR_MATCH;
|
||||
}
|
||||
p = free_space(mess, end, OPTION_VENDOR_CLASS_OPT, enc_len);
|
||||
for (; start && start != opt; start = start->next)
|
||||
if (p && (start->flags & DHOPT_VENDOR_MATCH))
|
||||
{
|
||||
len = do_opt(start, p + 2, context->local, null_term);
|
||||
*(p++) = start->opt;
|
||||
*(p++) = len;
|
||||
p += len;
|
||||
}
|
||||
enc_len = new;
|
||||
start = opt;
|
||||
}
|
||||
}
|
||||
|
||||
if ((p = free_space(mess, end, OPTION_VENDOR_CLASS_OPT, enc_len)))
|
||||
|
||||
if (enc_len != 0 &&
|
||||
(p = free_space(mess, end, OPTION_VENDOR_CLASS_OPT, enc_len + 1)))
|
||||
{
|
||||
for (opt = daemon->vendor_opts; opt; opt = opt->next)
|
||||
if (opt->flags & DHOPT_VENDOR_MATCH)
|
||||
for (; start; start = start->next)
|
||||
if (start->flags & DHOPT_VENDOR_MATCH)
|
||||
{
|
||||
len = do_opt(opt, p + 2, context->local, null_term);
|
||||
*(p++) = opt->opt;
|
||||
len = do_opt(start, p + 2, context->local, null_term);
|
||||
*(p++) = start->opt;
|
||||
*(p++) = len;
|
||||
p += len;
|
||||
}
|
||||
*p = OPTION_END;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -160,7 +160,8 @@ void tftp_request(struct listener *listen, struct daemon *daemon, time_t now)
|
||||
while ((opt = next(&p, end)))
|
||||
{
|
||||
if (strcasecmp(opt, "blksize") == 0 &&
|
||||
(opt = next(&p, end)))
|
||||
(opt = next(&p, end)) &&
|
||||
!(daemon->options & OPT_TFTP_NOBLOCK))
|
||||
{
|
||||
transfer->blocksize = atoi(opt);
|
||||
if (transfer->blocksize < 1)
|
||||
|
||||
Reference in New Issue
Block a user