import of dnsmasq-2.40.tar.gz
diff --git a/src/rfc2131.c b/src/rfc2131.c
index 76846ac..6b9d994 100644
--- a/src/rfc2131.c
+++ b/src/rfc2131.c
@@ -74,17 +74,16 @@
int opt, char *string, int null_term);
static struct in_addr option_addr(unsigned char *opt);
static unsigned int option_uint(unsigned char *opt, int size);
-static void log_packet(struct daemon *daemon, char *type, void *addr,
+static void log_packet(char *type, void *addr,
unsigned char *ext_mac, int mac_len, char *interface, char *string);
static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize);
static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize);
-static size_t dhcp_packet_size(struct daemon *daemon, struct dhcp_packet *mess, struct dhcp_netid *netid);
+static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *netid);
static void clear_packet(struct dhcp_packet *mess, unsigned char *end);
static void do_options(struct dhcp_context *context,
struct dhcp_packet *mess,
unsigned char *real_end,
unsigned char *req_options,
- struct daemon *daemon,
char *hostname,
struct dhcp_netid *netid,
struct in_addr subnet_addr,
@@ -96,8 +95,8 @@
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)
+size_t dhcp_reply(struct dhcp_context *context, char *iface_name,
+ size_t sz, time_t now, int unicast_dest, int *is_inform)
{
unsigned char *opt, *clid = NULL;
struct dhcp_lease *ltmp, *lease = NULL;
@@ -121,6 +120,7 @@
unsigned char *agent_id = NULL;
unsigned char *emac = NULL;
int emac_len;
+ struct dhcp_netid known_id;
subnet_addr.s_addr = 0;
@@ -324,6 +324,14 @@
config = find_config(daemon->dhcp_conf, context, clid, clid_len,
mess->chaddr, mess->hlen, mess->htype, NULL);
+
+ /* set "known" tag for known hosts */
+ if (config)
+ {
+ known_id.net = "known";
+ known_id.next = netid;
+ netid = &known_id;
+ }
if (mess_type == 0)
{
@@ -394,7 +402,7 @@
lease_prune(lease, now);
lease = NULL;
}
- if (!address_allocate(context, daemon, &mess->yiaddr, mess->chaddr, mess->hlen, netid, now))
+ if (!address_allocate(context, &mess->yiaddr, mess->chaddr, mess->hlen, netid, now))
message = _("no address available");
}
else
@@ -428,14 +436,14 @@
lease_set_expires(lease, 0xffffffff, now); /* infinite lease */
clear_packet(mess, end);
- do_options(context, mess, end, NULL, daemon,
+ do_options(context, mess, end, NULL,
hostname, netid, subnet_addr, 0, 0, NULL);
}
}
- log_packet(daemon, NULL, logaddr, mess->chaddr, mess->hlen, iface_name, message);
+ log_packet(NULL, logaddr, mess->chaddr, mess->hlen, iface_name, message);
- return message ? 0 : dhcp_packet_size(daemon, mess, netid);
+ return message ? 0 : dhcp_packet_size(mess, netid);
}
if ((opt = option_find(mess, sz, OPTION_CLIENT_FQDN, 4)))
@@ -504,16 +512,27 @@
if (fqdn_flags != 0 || !client_hostname || hostname_isequal(hostname, client_hostname))
offer_hostname = hostname;
}
- else if (client_hostname && (hostname = strip_hostname(daemon, client_hostname)) && !config)
+ else if (client_hostname)
{
- /* Search again now we have a hostname.
- Only accept configs without CLID and HWADDR here, (they won't match)
- to avoid impersonation by name. */
- struct dhcp_config *new = find_config(daemon->dhcp_conf, context, NULL, 0,
- mess->chaddr, mess->hlen,
- mess->htype, hostname);
- if (!have_config(new, CONFIG_CLID) && !have_config(new, CONFIG_HWADDR))
- config = new;
+ char *d = strip_hostname(client_hostname);
+ if (d)
+ my_syslog(LOG_WARNING, _("Ignoring domain %s for DHCP host name %s"), d, client_hostname);
+
+ if (strlen(client_hostname) != 0)
+ {
+ hostname = client_hostname;
+ if (!config)
+ {
+ /* Search again now we have a hostname.
+ Only accept configs without CLID and HWADDR here, (they won't match)
+ to avoid impersonation by name. */
+ struct dhcp_config *new = find_config(daemon->dhcp_conf, context, NULL, 0,
+ mess->chaddr, mess->hlen,
+ mess->htype, hostname);
+ if (!have_config(new, CONFIG_CLID) && !have_config(new, CONFIG_HWADDR))
+ config = new;
+ }
+ }
}
if (have_config(config, CONFIG_NETID))
@@ -610,7 +629,7 @@
if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
return 0;
- log_packet(daemon, "DECLINE", option_ptr(opt), emac, emac_len, iface_name, daemon->dhcp_buff);
+ log_packet("DECLINE", option_ptr(opt), emac, emac_len, iface_name, daemon->dhcp_buff);
if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
lease_prune(lease, now);
@@ -642,7 +661,7 @@
else
message = _("unknown lease");
- log_packet(daemon, "RELEASE", &mess->ciaddr, emac, emac_len, iface_name, message);
+ log_packet("RELEASE", &mess->ciaddr, emac, emac_len, iface_name, message);
return 0;
@@ -670,7 +689,7 @@
unsigned char *mac = extended_hwaddr(ltmp->hwaddr_type, ltmp->hwaddr_len,
ltmp->hwaddr, ltmp->clid_len, ltmp->clid, &len);
my_syslog(LOG_WARNING, _("not using configured address %s because it is leased to %s"),
- addrs, print_mac(daemon, mac, len));
+ addrs, print_mac(daemon->namebuff, mac, len));
}
else
{
@@ -695,16 +714,18 @@
else if (opt && address_available(context, addr) && !lease_find_by_addr(addr) &&
!config_find_by_address(daemon->dhcp_conf, addr))
mess->yiaddr = addr;
- else if (!address_allocate(context, daemon, &mess->yiaddr, mess->chaddr, mess->hlen, netid, now))
+ else if (emac_len == 0)
+ message = _("no unique-id");
+ else if (!address_allocate(context, &mess->yiaddr, emac, emac_len, netid, now))
message = _("no address available");
}
- log_packet(daemon, "DISCOVER", opt ? option_ptr(opt) : NULL, emac, emac_len, iface_name, message);
+ log_packet("DISCOVER", opt ? option_ptr(opt) : NULL, emac, emac_len, iface_name, message);
if (message || !(context = narrow_context(context, mess->yiaddr)))
return 0;
- log_packet(daemon, "OFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL);
+ log_packet("OFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL);
if (context->netid.net)
{
@@ -723,10 +744,10 @@
option_put(mess, end, OPTION_T1, 4, (time/2));
option_put(mess, end, OPTION_T2, 4, (time*7)/8);
}
- do_options(context, mess, end, req_options, daemon, offer_hostname,
+ do_options(context, mess, end, req_options, offer_hostname,
netid, subnet_addr, fqdn_flags, borken_opt, agent_id);
- return dhcp_packet_size(daemon, mess, netid);
+ return dhcp_packet_size(mess, netid);
case DHCPREQUEST:
if (ignore || have_config(config, CONFIG_DISABLE))
@@ -787,7 +808,7 @@
mess->yiaddr = mess->ciaddr;
}
- log_packet(daemon, "REQUEST", &mess->yiaddr, emac, emac_len, iface_name, NULL);
+ log_packet("REQUEST", &mess->yiaddr, emac, emac_len, iface_name, NULL);
if (!message)
{
@@ -830,7 +851,7 @@
else if ((ltmp = lease_find_by_addr(mess->yiaddr)) && ltmp != lease)
message = _("address in use");
- else if (!clid && mess->hlen == 0)
+ else if (emac_len == 0)
message = _("no unique-id");
else if (!lease)
@@ -844,7 +865,7 @@
if (message)
{
- log_packet(daemon, "NAK", &mess->yiaddr, emac, emac_len, iface_name, message);
+ log_packet("NAK", &mess->yiaddr, emac, emac_len, iface_name, message);
mess->yiaddr.s_addr = 0;
clear_packet(mess, end);
@@ -874,9 +895,8 @@
/* If the user-class option started as counted strings, the first byte will be zero. */
if (len != 0 && ucp[0] == 0)
ucp++, len--;
- if (lease->userclass)
- free(lease->userclass);
- if ((lease->userclass = malloc(len+1)))
+ free(lease->userclass);
+ if ((lease->userclass = whine_malloc(len+1)))
{
memcpy(lease->userclass, ucp, len);
lease->userclass[len] = 0;
@@ -887,9 +907,8 @@
{
int len = option_len(opt);
unsigned char *ucp = option_ptr(opt);
- if (lease->vendorclass)
- free(lease->vendorclass);
- if ((lease->vendorclass = malloc(len+1)))
+ free(lease->vendorclass);
+ if ((lease->vendorclass = whine_malloc(len+1)))
{
memcpy(lease->vendorclass, ucp, len);
lease->vendorclass[len] = 0;
@@ -898,7 +917,7 @@
}
}
- if (!hostname_auth && (client_hostname = host_from_dns(daemon, mess->yiaddr)))
+ if (!hostname_auth && (client_hostname = host_from_dns(mess->yiaddr)))
{
hostname = client_hostname;
hostname_auth = 1;
@@ -927,7 +946,7 @@
lease_set_expires(lease, time, now);
- log_packet(daemon, "ACK", &mess->yiaddr, emac, emac_len, iface_name, hostname);
+ log_packet("ACK", &mess->yiaddr, emac, emac_len, iface_name, hostname);
clear_packet(mess, end);
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
@@ -940,24 +959,34 @@
option_put(mess, end, OPTION_T1, 4, (time/2) - fuzz);
option_put(mess, end, OPTION_T2, 4, ((time/8)*7) - fuzz);
}
- do_options(context, mess, end, req_options, daemon, hostname,
+ do_options(context, mess, end, req_options, hostname,
netid, subnet_addr, fqdn_flags, borken_opt, agent_id);
}
- return dhcp_packet_size(daemon, mess, netid);
+ return dhcp_packet_size(mess, netid);
case DHCPINFORM:
if (ignore || have_config(config, CONFIG_DISABLE))
message = _("ignored");
- log_packet(daemon, "INFORM", &mess->ciaddr, emac, emac_len, iface_name, message);
+ log_packet("INFORM", &mess->ciaddr, emac, emac_len, iface_name, message);
if (message || mess->ciaddr.s_addr == 0 ||
!(context = narrow_context(context, mess->ciaddr)))
return 0;
- log_packet(daemon, "ACK", &mess->ciaddr, emac, emac_len, iface_name, hostname);
+ /* Find a least based on IP address if we didn't
+ get one from MAC address/client-d */
+ if (!lease &&
+ (lease = lease_find_by_addr(mess->ciaddr)) &&
+ lease->hostname)
+ hostname = lease->hostname;
+
+ if (!hostname)
+ hostname = host_from_dns(mess->ciaddr);
+ log_packet("ACK", &mess->ciaddr, emac, emac_len, iface_name, hostname);
+
if (context->netid.net)
{
context->netid.next = netid;
@@ -967,12 +996,20 @@
clear_packet(mess, end);
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(context->local.s_addr));
- if (!hostname)
- hostname = host_from_dns(daemon, mess->yiaddr);
- do_options(context, mess, end, req_options, daemon, hostname,
+
+ if (lease)
+ {
+ if (lease->expires == 0)
+ time = 0xffffffff;
+ else
+ time = (unsigned int)difftime(lease->expires, now);
+ option_put(mess, end, OPTION_LEASE_TIME, 4, time);
+ }
+ do_options(context, mess, end, req_options, hostname,
netid, subnet_addr, fqdn_flags, borken_opt, agent_id);
- return dhcp_packet_size(daemon, mess, netid);
+ *is_inform = 1; /* handle reply differently */
+ return dhcp_packet_size(mess, netid);
}
return 0;
@@ -1064,8 +1101,8 @@
return 1;
}
-static void log_packet(struct daemon *daemon, char *type, void *addr,
- unsigned char *ext_mac, int mac_len, char *interface, char *string)
+static void log_packet(char *type, void *addr, unsigned char *ext_mac,
+ int mac_len, char *interface, char *string)
{
struct in_addr a;
@@ -1079,11 +1116,11 @@
interface,
addr ? inet_ntoa(a) : "",
addr ? " " : "",
- print_mac(daemon, ext_mac, mac_len),
+ print_mac(daemon->namebuff, ext_mac, mac_len),
string ? string : "");
}
-static void log_options(struct daemon *daemon, unsigned char *start)
+static void log_options(unsigned char *start)
{
while (*start != OPTION_END)
{
@@ -1093,7 +1130,7 @@
start[1], start[0],
text ? ":" : "", text ? text : "",
start[1] == 0 ? "" : " ",
- start[1] == 0 ? "" : print_mac(daemon, &start[2], trunc),
+ start[1] == 0 ? "" : print_mac(daemon->namebuff, &start[2], trunc),
trunc == start[1] ? "" : "...");
start += start[1] + 2;
}
@@ -1194,7 +1231,7 @@
return NULL;
}
-static size_t dhcp_packet_size(struct daemon *daemon, struct dhcp_packet *mess, struct dhcp_netid *netid)
+static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *netid)
{
unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
unsigned char *overload;
@@ -1222,19 +1259,19 @@
{
*dhcp_skip_opts(mess->file) = OPTION_END;
if (daemon->options & OPT_LOG_OPTS)
- log_options(daemon, mess->file);
+ log_options(mess->file);
}
if (option_uint(overload, 1) & 2)
{
*dhcp_skip_opts(mess->sname) = OPTION_END;
if (daemon->options & OPT_LOG_OPTS)
- log_options(daemon, mess->sname);
+ log_options(mess->sname);
}
}
*p++ = OPTION_END;
if (daemon->options & OPT_LOG_OPTS)
- log_options(daemon, &mess->options[0] + sizeof(u32));
+ log_options(&mess->options[0] + sizeof(u32));
ret = (size_t)(p - (unsigned char *)mess);
@@ -1419,7 +1456,6 @@
struct dhcp_packet *mess,
unsigned char *real_end,
unsigned char *req_options,
- struct daemon *daemon,
char *hostname,
struct dhcp_netid *netid,
struct in_addr subnet_addr,