mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
import of dnsmasq-2.23.tar.gz
This commit is contained in:
397
src/rfc2131.c
397
src/rfc2131.c
@@ -43,6 +43,7 @@
|
||||
#define OPTION_VENDOR_ID 60
|
||||
#define OPTION_CLIENT_ID 61
|
||||
#define OPTION_USER_CLASS 77
|
||||
#define OPTION_CLIENT_FQDN 81
|
||||
#define OPTION_SUBNET_SELECT 118
|
||||
#define OPTION_END 255
|
||||
|
||||
@@ -74,11 +75,11 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
||||
struct daemon *daemon,
|
||||
char *hostname,
|
||||
struct dhcp_netid *netid,
|
||||
struct in_addr subnet_addr);
|
||||
struct in_addr subnet_addr,
|
||||
unsigned char fqdn_flags);
|
||||
|
||||
int dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_name, unsigned int sz, time_t now)
|
||||
{
|
||||
struct dhcp_context *context_tmp;
|
||||
unsigned char *opt, *clid = NULL;
|
||||
struct dhcp_lease *ltmp, *lease = NULL;
|
||||
struct dhcp_vendor *vendor;
|
||||
@@ -87,40 +88,22 @@ int dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_
|
||||
struct dhcp_packet *mess = &daemon->dhcp_packet->data;
|
||||
unsigned char *p = mess->options + sizeof(u32); /* skip cookie */
|
||||
unsigned char *end = (unsigned char *)(daemon->dhcp_packet + 1);
|
||||
char *hostname = NULL;
|
||||
char *req_options = NULL;
|
||||
char *hostname = NULL, *offer_hostname = NULL, *client_hostname = NULL;
|
||||
unsigned char *req_options = NULL;
|
||||
char *message = NULL;
|
||||
unsigned int time;
|
||||
struct dhcp_config *config;
|
||||
struct dhcp_netid *netid = NULL;
|
||||
struct in_addr addr, subnet_addr;
|
||||
struct in_addr subnet_addr;
|
||||
unsigned short fuzz = 0;
|
||||
unsigned int mess_type = 0;
|
||||
|
||||
u8 *chaddr;
|
||||
unsigned char fqdn_flags = 0;
|
||||
subnet_addr.s_addr = 0;
|
||||
|
||||
if (mess->op != BOOTREQUEST)
|
||||
return 0;
|
||||
|
||||
/* Token ring is supported when we have packet sockets
|
||||
to make the HW headers for us. We don't have the code to build
|
||||
token ring headers when using BPF. We rely on the fact that
|
||||
token ring hwaddrs are the same size as ethernet hwaddrs. */
|
||||
|
||||
#ifdef HAVE_BPF
|
||||
if (mess->htype != ARPHRD_ETHER)
|
||||
#else
|
||||
if (mess->htype != ARPHRD_ETHER && mess->htype != ARPHRD_IEEE802)
|
||||
#endif
|
||||
{
|
||||
syslog(LOG_WARNING, "DHCP request for unsupported hardware type (%d) recieved on %s",
|
||||
mess->htype, iface_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mess->hlen != ETHER_ADDR_LEN)
|
||||
return 0;
|
||||
|
||||
/* check for DHCP rather than BOOTP */
|
||||
if ((opt = option_find(mess, sz, OPTION_MESSAGE_TYPE, 1)))
|
||||
{
|
||||
@@ -147,7 +130,8 @@ int dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_
|
||||
}
|
||||
|
||||
/* do we have a lease in store? */
|
||||
lease = lease_find_by_client(mess->chaddr, clid, clid_len);
|
||||
if (mess->htype != 0)
|
||||
lease = lease_find_by_client(mess->chaddr, clid, clid_len);
|
||||
|
||||
/* If this request is missing a clid, but we've seen one before,
|
||||
use it again for option matching etc. */
|
||||
@@ -158,26 +142,75 @@ int dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_
|
||||
}
|
||||
}
|
||||
|
||||
/* htype == 0 is only allowed in DHCPINFORM, this seems to be a
|
||||
microsoftism. chaddr == NULL in that case */
|
||||
|
||||
if (mess->htype == 0 && mess_type == DHCPINFORM)
|
||||
{
|
||||
chaddr = NULL;
|
||||
if (mess->hlen != 0)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
chaddr = mess->chaddr;
|
||||
|
||||
/* Token ring is supported when we have packet sockets
|
||||
to make the HW headers for us. We don't have the code to build
|
||||
token ring headers when using BPF. We rely on the fact that
|
||||
token ring hwaddrs are the same size as ethernet hwaddrs. */
|
||||
|
||||
#ifdef HAVE_BPF
|
||||
if (mess->htype != ARPHRD_ETHER)
|
||||
#else
|
||||
if (mess->htype != ARPHRD_ETHER && mess->htype != ARPHRD_IEEE802)
|
||||
#endif
|
||||
{
|
||||
syslog(LOG_WARNING, "DHCP request for unsupported hardware type (%d) recieved on %s",
|
||||
mess->htype, iface_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mess->hlen != ETHER_ADDR_LEN)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Determine network for this packet. Our caller will have already linked all the
|
||||
contexts which match the addresses of the receiving interface but if the
|
||||
machine has an address already, or came via a relay, or we have a subnet selector,
|
||||
we search again. If we don't have have a giaddr or explicit subnet selector,
|
||||
use the ciaddr. This is necessary because a machine which got a lease via a
|
||||
relay won't use the relay to renew. */
|
||||
relay won't use the relay to renew. If matching a ciaddr fails but we have a context
|
||||
from the physical network, continue using that to allow correct DHCPNAK generation later. */
|
||||
if (mess->giaddr.s_addr || subnet_addr.s_addr || mess->ciaddr.s_addr)
|
||||
{
|
||||
addr =
|
||||
subnet_addr.s_addr ? subnet_addr :
|
||||
(mess->giaddr.s_addr ? mess->giaddr : mess->ciaddr);
|
||||
struct dhcp_context *context_tmp, *context_new = NULL;
|
||||
struct in_addr addr = mess->ciaddr;
|
||||
int force = 0;
|
||||
|
||||
for (context = NULL, context_tmp = daemon->dhcp; context_tmp; context_tmp = context_tmp->next)
|
||||
if (subnet_addr.s_addr)
|
||||
{
|
||||
addr = subnet_addr;
|
||||
force = 1;
|
||||
}
|
||||
else if (mess->giaddr.s_addr)
|
||||
{
|
||||
addr = mess->giaddr;
|
||||
force = 1;
|
||||
}
|
||||
|
||||
for (context_tmp = daemon->dhcp; context_tmp; context_tmp = context_tmp->next)
|
||||
if (context_tmp->netmask.s_addr &&
|
||||
is_same_net(addr, context_tmp->start, context_tmp->netmask) &&
|
||||
is_same_net(addr, context_tmp->end, context_tmp->netmask))
|
||||
{
|
||||
context_tmp->current = context;
|
||||
context = context_tmp;
|
||||
context_tmp->current = context_new;
|
||||
context_new = context_tmp;
|
||||
}
|
||||
|
||||
if (context_new || force)
|
||||
context = context_new;
|
||||
|
||||
}
|
||||
|
||||
if (!context)
|
||||
@@ -190,7 +223,7 @@ int dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_
|
||||
|
||||
mess->op = BOOTREPLY;
|
||||
|
||||
config = find_config(daemon->dhcp_conf, context, clid, clid_len, mess->chaddr, NULL);
|
||||
config = find_config(daemon->dhcp_conf, context, clid, clid_len, chaddr, NULL);
|
||||
|
||||
if (mess_type == 0)
|
||||
{
|
||||
@@ -199,17 +232,6 @@ int dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_
|
||||
char save = mess->file[128];
|
||||
struct in_addr *logaddr = NULL;
|
||||
|
||||
if (have_config(config, CONFIG_ADDR))
|
||||
{
|
||||
logaddr = &config->addr;
|
||||
mess->yiaddr = config->addr;
|
||||
if (lease_find_by_addr(config->addr))
|
||||
message = "address in use";
|
||||
context = narrow_context(context, config->addr);
|
||||
}
|
||||
else
|
||||
message = "no address configured";
|
||||
|
||||
if (have_config(config, CONFIG_DISABLE))
|
||||
message = "disabled";
|
||||
|
||||
@@ -218,12 +240,6 @@ int dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_
|
||||
if (have_config(config, CONFIG_NAME))
|
||||
hostname = config->hostname;
|
||||
|
||||
if (context->netid.net && !(context->flags & CONTEXT_FILTER))
|
||||
{
|
||||
context->netid.next = netid;
|
||||
netid = &context->netid;
|
||||
}
|
||||
|
||||
if (have_config(config, CONFIG_NETID))
|
||||
{
|
||||
config->netid.next = netid;
|
||||
@@ -234,7 +250,7 @@ int dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_
|
||||
if (mess->file[0])
|
||||
{
|
||||
mess->file[128] = 0; /* ensure zero term. */
|
||||
id.net = mess->file;
|
||||
id.net = (char *)mess->file;
|
||||
id.next = netid;
|
||||
netid = &id;
|
||||
}
|
||||
@@ -243,13 +259,55 @@ int dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_
|
||||
if (match_netid(id_list->list, netid))
|
||||
message = "disabled";
|
||||
|
||||
p = do_req_options(context, p, end, NULL, daemon,
|
||||
hostname, netid, subnet_addr);
|
||||
/* must do this after do_req_options since it overwrites filename field. */
|
||||
mess->siaddr = context->local;
|
||||
bootp_option_put(mess, daemon->boot_config, netid);
|
||||
p = option_end(p, end, mess);
|
||||
log_packet(NULL, logaddr, mess->chaddr, iface_name, message);
|
||||
if (!message)
|
||||
{
|
||||
if (have_config(config, CONFIG_ADDR))
|
||||
{
|
||||
logaddr = &config->addr;
|
||||
mess->yiaddr = config->addr;
|
||||
if ((lease = lease_find_by_addr(config->addr)) &&
|
||||
memcmp(lease->hwaddr, chaddr, ETHER_ADDR_LEN) != 0)
|
||||
message = "address in use";
|
||||
}
|
||||
else if (!(daemon->options & OPT_BOOTP_DYNAMIC))
|
||||
message = "no address configured";
|
||||
else
|
||||
{
|
||||
if ((lease = lease_find_by_client(mess->chaddr, NULL, 0)))
|
||||
mess->yiaddr = lease->addr;
|
||||
else if (!address_allocate(context, daemon, &mess->yiaddr, chaddr, netid, now))
|
||||
message = "no address available";
|
||||
}
|
||||
|
||||
if (!message && !lease && (!(lease = lease_allocate(chaddr, NULL, 0, mess->yiaddr))))
|
||||
message = "no leases left";
|
||||
|
||||
if (!message)
|
||||
{
|
||||
logaddr = &mess->yiaddr;
|
||||
context = narrow_context(context, mess->yiaddr);
|
||||
|
||||
if (context->netid.net && !(context->flags & CONTEXT_FILTER))
|
||||
{
|
||||
context->netid.next = netid;
|
||||
netid = &context->netid;
|
||||
}
|
||||
|
||||
lease_set_hwaddr(lease, chaddr, NULL, 0);
|
||||
if (hostname)
|
||||
lease_set_hostname(lease, hostname, daemon->domain_suffix);
|
||||
lease_set_expires(lease, 0); /* infinite lease */
|
||||
|
||||
p = do_req_options(context, p, end, NULL, daemon,
|
||||
hostname, netid, subnet_addr, fqdn_flags);
|
||||
/* must do this after do_req_options since it overwrites filename field. */
|
||||
mess->siaddr = context->local;
|
||||
bootp_option_put(mess, daemon->boot_config, netid);
|
||||
p = option_end(p, end, mess);
|
||||
}
|
||||
}
|
||||
|
||||
log_packet(NULL, logaddr, chaddr, iface_name, message);
|
||||
mess->file[128] = save;
|
||||
|
||||
if (message)
|
||||
@@ -258,27 +316,73 @@ int dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_
|
||||
return p - (unsigned char *)mess;
|
||||
}
|
||||
|
||||
if (have_config(config, CONFIG_NAME))
|
||||
hostname = config->hostname;
|
||||
if ((opt = option_find(mess, sz, OPTION_CLIENT_FQDN, 4)))
|
||||
{
|
||||
/* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */
|
||||
int len = option_len(opt);
|
||||
char *pq = daemon->dhcp_buff;
|
||||
unsigned char *pp, *op = option_ptr(opt);
|
||||
|
||||
fqdn_flags = *op;
|
||||
len -= 3;
|
||||
op += 3;
|
||||
pp = op;
|
||||
|
||||
/* Always force update, since the client has no way to do it itself. */
|
||||
if (fqdn_flags & 0x01)
|
||||
fqdn_flags |= 0x02;
|
||||
|
||||
fqdn_flags &= ~0x08;
|
||||
fqdn_flags |= 0x01;
|
||||
|
||||
if (fqdn_flags & 0x04)
|
||||
while (*op != 0 && ((op + (*op) + 1) - pp) < len)
|
||||
{
|
||||
memcpy(pq, op+1, *op);
|
||||
pq += *op;
|
||||
op += (*op)+1;
|
||||
*(pq++) = '.';
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(pq, op, len);
|
||||
pq += len + 1;
|
||||
}
|
||||
|
||||
if (pq != daemon->dhcp_buff)
|
||||
pq--;
|
||||
|
||||
*pq = 0;
|
||||
|
||||
if (canonicalise(daemon->dhcp_buff))
|
||||
offer_hostname = client_hostname = daemon->dhcp_buff;
|
||||
}
|
||||
else if ((opt = option_find(mess, sz, OPTION_HOSTNAME, 1)))
|
||||
{
|
||||
int len = option_len(opt);
|
||||
hostname = daemon->dhcp_buff;
|
||||
memcpy(hostname, option_ptr(opt), len);
|
||||
memcpy(daemon->dhcp_buff, option_ptr(opt), len);
|
||||
/* May not be zero terminated */
|
||||
hostname[len] = 0;
|
||||
/* ensure there are no strange chars in there */
|
||||
if (!canonicalise(hostname))
|
||||
hostname = NULL;
|
||||
else if ((hostname = strip_hostname(daemon, hostname)) && !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, hostname);
|
||||
if (!have_config(new, CONFIG_CLID) && !have_config(new, CONFIG_HWADDR))
|
||||
config = new;
|
||||
}
|
||||
daemon->dhcp_buff[len] = 0;
|
||||
if (canonicalise(daemon->dhcp_buff))
|
||||
client_hostname = daemon->dhcp_buff;
|
||||
}
|
||||
|
||||
if (have_config(config, CONFIG_NAME))
|
||||
{
|
||||
hostname = config->hostname;
|
||||
/* be careful not to send an OFFER with a hostname not
|
||||
matching the DISCOVER. */
|
||||
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)
|
||||
{
|
||||
/* 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, chaddr, hostname);
|
||||
if (!have_config(new, CONFIG_CLID) && !have_config(new, CONFIG_HWADDR))
|
||||
config = new;
|
||||
}
|
||||
|
||||
if (have_config(config, CONFIG_NETID))
|
||||
@@ -332,7 +436,7 @@ int dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_
|
||||
|
||||
if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS, 0)))
|
||||
{
|
||||
req_options = daemon->dhcp_buff2;
|
||||
req_options = (unsigned char *)daemon->dhcp_buff2;
|
||||
memcpy(req_options, option_ptr(opt), option_len(opt));
|
||||
req_options[option_len(opt)] = OPTION_END;
|
||||
}
|
||||
@@ -363,7 +467,7 @@ int dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_
|
||||
if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
|
||||
return 0;
|
||||
|
||||
log_packet("DECLINE", option_ptr(opt), mess->chaddr, iface_name, message);
|
||||
log_packet("DECLINE", option_ptr(opt), chaddr, iface_name, message);
|
||||
|
||||
if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
|
||||
lease_prune(lease, now);
|
||||
@@ -391,27 +495,31 @@ int dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_
|
||||
else
|
||||
message = "unknown lease";
|
||||
|
||||
log_packet("RELEASE", &mess->ciaddr, mess->chaddr, iface_name, message);
|
||||
log_packet("RELEASE", &mess->ciaddr, chaddr, iface_name, message);
|
||||
|
||||
return 0;
|
||||
|
||||
case DHCPDISCOVER:
|
||||
if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
|
||||
addr = option_addr(opt);
|
||||
if (ignore || have_config(config, CONFIG_DISABLE))
|
||||
message = "ignored";
|
||||
else if (have_config(config, CONFIG_ADDR) &&
|
||||
(!(ltmp = lease_find_by_addr(config->addr)) || ltmp == lease))
|
||||
mess->yiaddr = config->addr;
|
||||
else if (lease && address_available(context, lease->addr))
|
||||
mess->yiaddr = lease->addr;
|
||||
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, netid))
|
||||
message = "no address available";
|
||||
log_packet("DISCOVER", opt ? &addr : NULL, mess->chaddr, iface_name, message);
|
||||
|
||||
{
|
||||
struct in_addr addr;
|
||||
|
||||
if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
|
||||
addr = option_addr(opt);
|
||||
if (ignore || have_config(config, CONFIG_DISABLE))
|
||||
message = "ignored";
|
||||
else if (have_config(config, CONFIG_ADDR) &&
|
||||
(!(ltmp = lease_find_by_addr(config->addr)) || ltmp == lease))
|
||||
mess->yiaddr = config->addr;
|
||||
else if (lease && address_available(context, lease->addr))
|
||||
mess->yiaddr = lease->addr;
|
||||
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, chaddr, netid, now))
|
||||
message = "no address available";
|
||||
log_packet("DISCOVER", opt ? &addr : NULL, chaddr, iface_name, message);
|
||||
}
|
||||
|
||||
if (message)
|
||||
return 0;
|
||||
|
||||
@@ -444,10 +552,10 @@ int dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_
|
||||
p = option_put(p, end, OPTION_T2, 4, (time*7)/8);
|
||||
}
|
||||
p = do_req_options(context, p, end, req_options, daemon,
|
||||
NULL, netid, subnet_addr);
|
||||
offer_hostname, netid, subnet_addr, fqdn_flags);
|
||||
p = option_end(p, end, mess);
|
||||
|
||||
log_packet("OFFER" , &mess->yiaddr, mess->chaddr, iface_name, NULL);
|
||||
log_packet("OFFER" , &mess->yiaddr, chaddr, iface_name, NULL);
|
||||
return p - (unsigned char *)mess;
|
||||
|
||||
case DHCPREQUEST:
|
||||
@@ -493,7 +601,7 @@ int dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_
|
||||
mess->yiaddr = mess->ciaddr;
|
||||
}
|
||||
|
||||
log_packet("REQUEST", &mess->yiaddr, mess->chaddr, iface_name, NULL);
|
||||
log_packet("REQUEST", &mess->yiaddr, chaddr, iface_name, NULL);
|
||||
|
||||
if (!message)
|
||||
{
|
||||
@@ -524,23 +632,27 @@ int dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_
|
||||
else if ((ltmp = lease_find_by_addr(mess->yiaddr)) && ltmp != lease)
|
||||
message = "address in use";
|
||||
|
||||
else if (!lease && !(lease = lease_allocate(mess->chaddr, clid, clid_len, mess->yiaddr)))
|
||||
else if (!lease && !(lease = lease_allocate(chaddr, clid, clid_len, mess->yiaddr)))
|
||||
message = "no leases left";
|
||||
}
|
||||
|
||||
if (message)
|
||||
{
|
||||
log_packet("NAK", &mess->yiaddr, mess->chaddr, iface_name, message);
|
||||
log_packet("NAK", &mess->yiaddr, chaddr, iface_name, message);
|
||||
|
||||
mess->siaddr.s_addr = mess->yiaddr.s_addr = mess->ciaddr.s_addr = 0;
|
||||
bootp_option_put(mess, NULL, NULL);
|
||||
p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPNAK);
|
||||
p = option_put(p, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(context->local.s_addr));
|
||||
p = option_put_string(p, end, OPTION_MESSAGE, message);
|
||||
mess->flags |= htons(0x8000); /* broadcast */
|
||||
}
|
||||
else
|
||||
{
|
||||
log_packet("ACK", &mess->yiaddr, mess->chaddr, iface_name, hostname);
|
||||
if (!hostname)
|
||||
hostname = host_from_dns(daemon, mess->yiaddr);
|
||||
|
||||
log_packet("ACK", &mess->yiaddr, chaddr, iface_name, hostname);
|
||||
|
||||
context = narrow_context(context, mess->yiaddr);
|
||||
if (context->netid.net && !(context->flags & CONTEXT_FILTER))
|
||||
@@ -557,9 +669,7 @@ int dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_
|
||||
time = req_time;
|
||||
}
|
||||
|
||||
lease_set_hwaddr(lease, mess->chaddr, clid, clid_len);
|
||||
if (!hostname)
|
||||
hostname = host_from_dns(daemon, mess->yiaddr);
|
||||
lease_set_hwaddr(lease, chaddr, clid, clid_len);
|
||||
if (hostname)
|
||||
lease_set_hostname(lease, hostname, daemon->domain_suffix);
|
||||
lease_set_expires(lease, time == 0xffffffff ? 0 : now + (time_t)time);
|
||||
@@ -577,7 +687,7 @@ int dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_
|
||||
p = option_put(p, end, OPTION_T2, 4, ((time * 7)/8) - fuzz);
|
||||
}
|
||||
p = do_req_options(context, p, end, req_options, daemon,
|
||||
hostname, netid, subnet_addr);
|
||||
hostname, netid, subnet_addr, fqdn_flags);
|
||||
}
|
||||
|
||||
p = option_end(p, end, mess);
|
||||
@@ -587,7 +697,7 @@ int dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_
|
||||
if (ignore || have_config(config, CONFIG_DISABLE))
|
||||
message = "ignored";
|
||||
|
||||
log_packet("INFORM", &mess->ciaddr, mess->chaddr, iface_name, message);
|
||||
log_packet("INFORM", &mess->ciaddr, chaddr, iface_name, message);
|
||||
|
||||
if (message || mess->ciaddr.s_addr == 0)
|
||||
return 0;
|
||||
@@ -606,10 +716,10 @@ int dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_
|
||||
if (!hostname)
|
||||
hostname = host_from_dns(daemon, mess->yiaddr);
|
||||
p = do_req_options(context, p, end, req_options, daemon,
|
||||
hostname, netid, subnet_addr);
|
||||
hostname, netid, subnet_addr, fqdn_flags);
|
||||
p = option_end(p, end, mess);
|
||||
|
||||
log_packet("ACK", &mess->ciaddr, mess->chaddr, iface_name, hostname);
|
||||
log_packet("ACK", &mess->ciaddr, chaddr, iface_name, hostname);
|
||||
return p - (unsigned char *)mess;
|
||||
}
|
||||
|
||||
@@ -618,6 +728,11 @@ int dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_
|
||||
|
||||
static void log_packet(char *type, struct in_addr *addr, unsigned char *hwaddr, char *interface, char *string)
|
||||
{
|
||||
u8 empty[] = { 0, 0, 0, 0, 0, 0};
|
||||
|
||||
if (!hwaddr)
|
||||
hwaddr = empty;
|
||||
|
||||
syslog(LOG_INFO, "%s%s(%s)%s%s %.2x:%.2x:%.2x:%.2x:%.2x:%.2x%s%s",
|
||||
type ? "DHCP" : "BOOTP",
|
||||
type ? type : "",
|
||||
@@ -686,9 +801,9 @@ static void bootp_option_put(struct dhcp_packet *mess,
|
||||
if (tmp)
|
||||
{
|
||||
if (tmp->sname)
|
||||
strncpy(mess->sname, tmp->sname, sizeof(mess->sname)-1);
|
||||
strncpy((char *)mess->sname, tmp->sname, sizeof(mess->sname)-1);
|
||||
if (tmp->file)
|
||||
strncpy(mess->file, tmp->file, sizeof(mess->file)-1);
|
||||
strncpy((char *)mess->file, tmp->file, sizeof(mess->file)-1);
|
||||
if (tmp->next_server.s_addr)
|
||||
mess->siaddr = tmp->next_server;
|
||||
}
|
||||
@@ -864,7 +979,8 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
||||
struct daemon *daemon,
|
||||
char *hostname,
|
||||
struct dhcp_netid *netid,
|
||||
struct in_addr subnet_addr)
|
||||
struct in_addr subnet_addr,
|
||||
unsigned char fqdn_flags)
|
||||
{
|
||||
struct dhcp_opt *opt, *config_opts = daemon->dhcp_opts;
|
||||
char *vendor_class = NULL;
|
||||
@@ -903,13 +1019,56 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
||||
p = option_put_string(p, end, OPTION_DOMAINNAME, daemon->domain_suffix);
|
||||
|
||||
/* Note that we ignore attempts to set the hostname using
|
||||
--dhcp-option=12,<name> */
|
||||
if (hostname && in_list(req_options, OPTION_HOSTNAME))
|
||||
p = option_put_string(p, end, OPTION_HOSTNAME, hostname);
|
||||
|
||||
--dhcp-option=12,<name> and the fqdn using
|
||||
--dhc-option=81,<name> */
|
||||
if (hostname)
|
||||
{
|
||||
if (in_list(req_options, OPTION_HOSTNAME))
|
||||
p = option_put_string(p, end, OPTION_HOSTNAME, hostname);
|
||||
|
||||
if (fqdn_flags != 0)
|
||||
{
|
||||
int len = strlen(hostname) + 3;
|
||||
if (fqdn_flags & 0x04)
|
||||
len += 2;
|
||||
|
||||
if (daemon->domain_suffix)
|
||||
len += strlen(daemon->domain_suffix) + 1;
|
||||
|
||||
if (p + len + 1 < end)
|
||||
{
|
||||
*(p++) = OPTION_CLIENT_FQDN;
|
||||
*(p++) = len;
|
||||
*(p++) = fqdn_flags;
|
||||
*(p++) = 255;
|
||||
*(p++) = 255;
|
||||
|
||||
if (fqdn_flags & 0x04)
|
||||
{
|
||||
p = do_rfc1035_name(p, hostname);
|
||||
if (daemon->domain_suffix)
|
||||
p = do_rfc1035_name(p, daemon->domain_suffix);
|
||||
*p++ = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(p, hostname, strlen(hostname));
|
||||
p += strlen(hostname);
|
||||
if (daemon->domain_suffix)
|
||||
{
|
||||
*(p++) = '.';
|
||||
memcpy(p, daemon->domain_suffix, strlen(daemon->domain_suffix));
|
||||
p += strlen(daemon->domain_suffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (opt=config_opts; opt; opt = opt->next)
|
||||
{
|
||||
if (opt->opt == OPTION_HOSTNAME ||
|
||||
opt->opt == OPTION_CLIENT_FQDN ||
|
||||
opt->opt == OPTION_MAXMESSAGE ||
|
||||
!in_list(req_options, opt->opt) ||
|
||||
opt != option_find2(netid, config_opts, opt->opt))
|
||||
@@ -927,7 +1086,7 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
||||
|
||||
/* opt->val has terminating zero */
|
||||
if (opt->opt == OPTION_VENDOR_ID)
|
||||
vendor_class = opt->val;
|
||||
vendor_class = (char *)opt->val;
|
||||
else
|
||||
p = do_opt(opt, p, end, context->local);
|
||||
}
|
||||
@@ -937,10 +1096,10 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
||||
for (opt = daemon->vendor_opts; opt; opt = opt->next)
|
||||
if (!opt->netid || match_netid(opt->netid, netid))
|
||||
{
|
||||
if (vendor_class && strcmp(vendor_class, opt->vendor_class) != 0)
|
||||
if (vendor_class && strcmp(vendor_class, (char *)opt->vendor_class) != 0)
|
||||
syslog(LOG_WARNING, "More than one vendor class matches, using %s", vendor_class);
|
||||
else
|
||||
vendor_class = opt->vendor_class;
|
||||
vendor_class = (char *)opt->vendor_class;
|
||||
}
|
||||
|
||||
if (vendor_class)
|
||||
@@ -964,7 +1123,7 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
||||
|
||||
for (opt = daemon->vendor_opts; opt; opt = opt->next)
|
||||
if ((!opt->netid || match_netid(opt->netid, netid)) &&
|
||||
strcmp(vendor_class, opt->vendor_class) == 0)
|
||||
strcmp(vendor_class, (char *)opt->vendor_class) == 0)
|
||||
p = do_opt(opt, p, oend, context->local);
|
||||
|
||||
*plen = p - plen - 1;
|
||||
|
||||
Reference in New Issue
Block a user