import of dnsmasq-2.38.tar.gz

This commit is contained in:
Simon Kelley
2007-02-12 20:32:07 +00:00
parent 1b7ecd111d
commit 6b01084f8e
20 changed files with 2095 additions and 1931 deletions

View File

@@ -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."),

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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)