"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/rfc2131.c" between
dnsmasq-2.80.tar.gz and dnsmasq-2.81.tar.xz

About: Dnsmasq is a lightweight caching DNS forwarder and DHCP server.

rfc2131.c  (dnsmasq-2.80):rfc2131.c  (dnsmasq-2.81.tar.xz)
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley /* dnsmasq is Copyright (c) 2000-2020 Simon Kelley
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007. (at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
skipping to change at line 236 skipping to change at line 236
netid = &vendor->netid; netid = &vendor->netid;
} }
} }
} }
/* Check for RFC3011 subnet selector - only if RFC3527 one not present */ /* Check for RFC3011 subnet selector - only if RFC3527 one not present */
if (subnet_addr.s_addr == 0 && (opt = option_find(mess, sz, OPTION_SUBNET_ SELECT, INADDRSZ))) if (subnet_addr.s_addr == 0 && (opt = option_find(mess, sz, OPTION_SUBNET_ SELECT, INADDRSZ)))
subnet_addr = option_addr(opt); subnet_addr = option_addr(opt);
/* If there is no client identifier option, use the hardware address */ /* If there is no client identifier option, use the hardware address */
if ((opt = option_find(mess, sz, OPTION_CLIENT_ID, 1))) if (!option_bool(OPT_IGNORE_CLID) && (opt = option_find(mess, sz, OPTION_C LIENT_ID, 1)))
{ {
clid_len = option_len(opt); clid_len = option_len(opt);
clid = option_ptr(opt, 0); clid = option_ptr(opt, 0);
} }
/* do we have a lease in store? */ /* do we have a lease in store? */
lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, clid, clid_len); lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, clid, clid_len);
/* If this request is missing a clid, but we've seen one before, /* If this request is missing a clid, but we've seen one before,
use it again for option matching etc. */ use it again for option matching etc. */
skipping to change at line 276 skipping to change at line 276
/* Determine network for this packet. Our caller will have already linked all the /* 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 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 se lector, machine has an address already, or came via a relay, or we have a subnet se lector,
we search again. If we don't have have a giaddr or explicit 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 use the ciaddr. This is necessary because a machine which got a lease via a
relay won't use the relay to renew. If matching a ciaddr fails but we have a context 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 gen eration later. */ from the physical network, continue using that to allow correct DHCPNAK gen eration later. */
if (mess->giaddr.s_addr || subnet_addr.s_addr || mess->ciaddr.s_addr) if (mess->giaddr.s_addr || subnet_addr.s_addr || mess->ciaddr.s_addr)
{ {
struct dhcp_context *context_tmp, *context_new = NULL; struct dhcp_context *context_tmp, *context_new = NULL;
struct shared_network *share = NULL;
struct in_addr addr; struct in_addr addr;
int force = 0; int force = 0, via_relay = 0;
if (subnet_addr.s_addr) if (subnet_addr.s_addr)
{ {
addr = subnet_addr; addr = subnet_addr;
force = 1; force = 1;
} }
else if (mess->giaddr.s_addr) else if (mess->giaddr.s_addr)
{ {
addr = mess->giaddr; addr = mess->giaddr;
force = 1; force = 1;
via_relay = 1;
} }
else else
{ {
/* If ciaddr is in the hardware derived set of contexts, leave that unc hanged */ /* If ciaddr is in the hardware derived set of contexts, leave that unc hanged */
addr = mess->ciaddr; addr = mess->ciaddr;
for (context_tmp = context; context_tmp; context_tmp = context_tmp->cur rent) for (context_tmp = context; context_tmp; context_tmp = context_tmp->cur rent)
if (context_tmp->netmask.s_addr && if (context_tmp->netmask.s_addr &&
is_same_net(addr, context_tmp->start, context_tmp->netmask) && is_same_net(addr, context_tmp->start, context_tmp->netmask) &&
is_same_net(addr, context_tmp->end, context_tmp->netmask)) is_same_net(addr, context_tmp->end, context_tmp->netmask))
{ {
context_new = context; context_new = context;
break; break;
} }
} }
if (!context_new) if (!context_new)
for (context_tmp = daemon->dhcp; context_tmp; context_tmp = context_tmp-> {
next) for (context_tmp = daemon->dhcp; context_tmp; context_tmp = context_tmp
{ ->next)
struct in_addr netmask = context_tmp->netmask; {
struct in_addr netmask = context_tmp->netmask;
/* guess the netmask for relayed networks */ /* guess the netmask for relayed networks */
if (!(context_tmp->flags & CONTEXT_NETMASK) && context_tmp->netmask.s if (!(context_tmp->flags & CONTEXT_NETMASK) && context_tmp->netmask
_addr == 0) .s_addr == 0)
{ {
if (IN_CLASSA(ntohl(context_tmp->start.s_addr)) && IN_CLASSA(ntoh if (IN_CLASSA(ntohl(context_tmp->start.s_addr)) && IN_CLASSA(nt
l(context_tmp->end.s_addr))) ohl(context_tmp->end.s_addr)))
netmask.s_addr = htonl(0xff000000); netmask.s_addr = htonl(0xff000000);
else if (IN_CLASSB(ntohl(context_tmp->start.s_addr)) && IN_CLASSB else if (IN_CLASSB(ntohl(context_tmp->start.s_addr)) && IN_CLAS
(ntohl(context_tmp->end.s_addr))) SB(ntohl(context_tmp->end.s_addr)))
netmask.s_addr = htonl(0xffff0000); netmask.s_addr = htonl(0xffff0000);
else if (IN_CLASSC(ntohl(context_tmp->start.s_addr)) && IN_CLASSC else if (IN_CLASSC(ntohl(context_tmp->start.s_addr)) && IN_CLAS
(ntohl(context_tmp->end.s_addr))) SC(ntohl(context_tmp->end.s_addr)))
netmask.s_addr = htonl(0xffffff00); netmask.s_addr = htonl(0xffffff00);
} }
/* This section fills in context mainly when a client which is on a r /* check to see is a context is OK because of a shared address on
emote (relayed) the relayed subnet. */
network renews a lease without using the relay, after dnsmasq has if (via_relay)
restarted. */ for (share = daemon->shared_networks; share; share = share->next)
if (netmask.s_addr != 0 && {
is_same_net(addr, context_tmp->start, netmask) && #ifdef HAVE_DHCP6
is_same_net(addr, context_tmp->end, netmask)) if (share->shared_addr.s_addr == 0)
{ continue;
context_tmp->netmask = netmask; #endif
if (context_tmp->local.s_addr == 0) if (share->if_index != 0 ||
context_tmp->local = fallback; share->match_addr.s_addr != mess->giaddr.s_addr)
if (context_tmp->router.s_addr == 0) continue;
context_tmp->router = mess->giaddr;
if (netmask.s_addr != 0 &&
/* fill in missing broadcast addresses for relayed ranges */ is_same_net(share->shared_addr, context_tmp->start, netma
if (!(context_tmp->flags & CONTEXT_BRDCAST) && context_tmp->broad sk) &&
cast.s_addr == 0 ) is_same_net(share->shared_addr, context_tmp->end, netmask
context_tmp->broadcast.s_addr = context_tmp->start.s_addr | ~co ))
ntext_tmp->netmask.s_addr; break;
}
context_tmp->current = context_new; /* This section fills in context mainly when a client which is on a
context_new = context_tmp; remote (relayed)
} network renews a lease without using the relay, after dnsmasq ha
} s restarted. */
if (share ||
(netmask.s_addr != 0 &&
is_same_net(addr, context_tmp->start, netmask) &&
is_same_net(addr, context_tmp->end, netmask)))
{
context_tmp->netmask = netmask;
if (context_tmp->local.s_addr == 0)
context_tmp->local = fallback;
if (context_tmp->router.s_addr == 0 && !share)
context_tmp->router = mess->giaddr;
/* fill in missing broadcast addresses for relayed ranges */
if (!(context_tmp->flags & CONTEXT_BRDCAST) && context_tmp->bro
adcast.s_addr == 0 )
context_tmp->broadcast.s_addr = context_tmp->start.s_addr | ~
context_tmp->netmask.s_addr;
context_tmp->current = context_new;
context_new = context_tmp;
}
}
}
if (context_new || force) if (context_new || force)
context = context_new; context = context_new;
} }
if (!context) if (!context)
{ {
my_syslog(MS_DHCP | LOG_WARNING, _("no address range available for DHCP re quest %s %s"), my_syslog(MS_DHCP | LOG_WARNING, _("no address range available for DHCP re quest %s %s"),
subnet_addr.s_addr ? _("with subnet selector") : _("via"), subnet_addr.s_addr ? _("with subnet selector") : _("via"),
subnet_addr.s_addr ? inet_ntoa(subnet_addr) : (mess->giaddr.s_add r ? inet_ntoa(mess->giaddr) : iface_name)); subnet_addr.s_addr ? inet_ntoa(subnet_addr) : (mess->giaddr.s_add r ? inet_ntoa(mess->giaddr) : iface_name));
skipping to change at line 390 skipping to change at line 415
for (offset = 0; offset < (option_len(opt) - 5u); offset += len + 5) for (offset = 0; offset < (option_len(opt) - 5u); offset += len + 5)
{ {
len = option_uint(opt, offset + 4 , 1); len = option_uint(opt, offset + 4 , 1);
/* Need to take care that bad data can't run us off the end of the packet */ /* Need to take care that bad data can't run us off the end of the packet */
if ((offset + len + 5 <= (unsigned)(option_len(opt))) && if ((offset + len + 5 <= (unsigned)(option_len(opt))) &&
(option_uint(opt, offset, 4) == (unsigned int)o->u.encap)) (option_uint(opt, offset, 4) == (unsigned int)o->u.encap))
for (o2 = offset + 5; o2 < offset + len + 5; o2 += elen + 1) for (o2 = offset + 5; o2 < offset + len + 5; o2 += elen + 1)
{ {
elen = option_uint(opt, o2, 1); elen = option_uint(opt, o2, 1);
if ((o2 + elen + 1 <= option_len(opt)) && if ((o2 + elen + 1 <= (unsigned)option_len(opt)) &&
(match = match_bytes(o, option_ptr(opt, o2 + 1), elen))) (match = match_bytes(o, option_ptr(opt, o2 + 1), elen)))
break; break;
} }
if (match) if (match)
break; break;
} }
} }
else else
{ {
if (!(opt = option_find(mess, sz, o->opt, 1))) if (!(opt = option_find(mess, sz, o->opt, 1)))
skipping to change at line 481 skipping to change at line 506
{ {
if (sanitise(opt, daemon->namebuff)) if (sanitise(opt, daemon->namebuff))
my_syslog(MS_DHCP | LOG_INFO, _("%u vendor class: %s"), ntohl(mess->xid), daemon->namebuff); my_syslog(MS_DHCP | LOG_INFO, _("%u vendor class: %s"), ntohl(mess->xid), daemon->namebuff);
if (sanitise(option_find(mess, sz, OPTION_USER_CLASS, 1), daemon->namebuff )) if (sanitise(option_find(mess, sz, OPTION_USER_CLASS, 1), daemon->namebuff ))
my_syslog(MS_DHCP | LOG_INFO, _("%u user class: %s"), ntohl(mess->xid), d aemon->namebuff); my_syslog(MS_DHCP | LOG_INFO, _("%u user class: %s"), ntohl(mess->xid), d aemon->namebuff);
} }
mess->op = BOOTREPLY; mess->op = BOOTREPLY;
config = find_config(daemon->dhcp_conf, context, clid, clid_len, config = find_config(daemon->dhcp_conf, context, clid, clid_len,
mess->chaddr, mess->hlen, mess->htype, NULL); mess->chaddr, mess->hlen, mess->htype, NULL, run_tag_if(ne tid));
/* set "known" tag for known hosts */ /* set "known" tag for known hosts */
if (config) if (config)
{ {
known_id.net = "known"; known_id.net = "known";
known_id.next = netid; known_id.next = netid;
netid = &known_id; netid = &known_id;
} }
else if (find_config(daemon->dhcp_conf, NULL, clid, clid_len, else if (find_config(daemon->dhcp_conf, NULL, clid, clid_len,
mess->chaddr, mess->hlen, mess->htype, NULL)) mess->chaddr, mess->hlen, mess->htype, NULL, run_tag_if(ne tid)))
{ {
known_id.net = "known-othernet"; known_id.net = "known-othernet";
known_id.next = netid; known_id.next = netid;
netid = &known_id; netid = &known_id;
} }
if (mess_type == 0 && !pxe) if (mess_type == 0 && !pxe)
{ {
/* BOOTP request */ /* BOOTP request */
struct dhcp_netid id, bootp_id; struct dhcp_netid id, bootp_id;
skipping to change at line 702 skipping to change at line 727
in options. We detect this state here, and do the same in in options. We detect this state here, and do the same in
any options we send */ any options we send */
if (len > 0 && daemon->dhcp_buff[len-1] == 0) if (len > 0 && daemon->dhcp_buff[len-1] == 0)
borken_opt = 1; borken_opt = 1;
else else
daemon->dhcp_buff[len] = 0; daemon->dhcp_buff[len] = 0;
if (legal_hostname(daemon->dhcp_buff)) if (legal_hostname(daemon->dhcp_buff))
client_hostname = daemon->dhcp_buff; client_hostname = daemon->dhcp_buff;
} }
if (client_hostname && option_bool(OPT_LOG_OPTS)) if (client_hostname)
my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mess-> {
xid), client_hostname); struct dhcp_match_name *m;
size_t nl = strlen(client_hostname);
if (option_bool(OPT_LOG_OPTS))
my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mes
s->xid), client_hostname);
for (m = daemon->dhcp_name_match; m; m = m->next)
{
size_t ml = strlen(m->name);
char save = 0;
if (nl < ml)
continue;
if (nl > ml)
{
save = client_hostname[ml];
client_hostname[ml] = 0;
}
if (hostname_isequal(client_hostname, m->name) &&
(save == 0 || m->wildcard))
{
m->netid->next = netid;
netid = m->netid;
}
if (save != 0)
client_hostname[ml] = save;
}
}
if (have_config(config, CONFIG_NAME)) if (have_config(config, CONFIG_NAME))
{ {
hostname = config->hostname; hostname = config->hostname;
domain = config->domain; domain = config->domain;
hostname_auth = 1; hostname_auth = 1;
/* be careful not to send an OFFER with a hostname not matching the DISCOV ER. */ /* be careful not to send an OFFER with a hostname not matching the DISCOV ER. */
if (fqdn_flags != 0 || !client_hostname || hostname_isequal(hostname, clie nt_hostname)) if (fqdn_flags != 0 || !client_hostname || hostname_isequal(hostname, clie nt_hostname))
offer_hostname = hostname; offer_hostname = hostname;
} }
else if (client_hostname) else if (client_hostname)
{ {
struct dhcp_match_name *m;
size_t nl;
domain = strip_hostname(client_hostname); domain = strip_hostname(client_hostname);
if ((nl = strlen(client_hostname)) != 0) if (strlen(client_hostname) != 0)
{ {
hostname = client_hostname; hostname = client_hostname;
if (!config) if (!config)
{ {
/* Search again now we have a hostname. /* Search again now we have a hostname.
Only accept configs without CLID and HWADDR here, (they won't ma tch) Only accept configs without CLID and HWADDR here, (they won't ma tch)
to avoid impersonation by name. */ to avoid impersonation by name. */
struct dhcp_config *new = find_config(daemon->dhcp_conf, context, N ULL, 0, struct dhcp_config *new = find_config(daemon->dhcp_conf, context, N ULL, 0,
mess->chaddr, mess->hlen, mess->chaddr, mess->hlen,
mess->htype, hostname); mess->htype, hostname, run_ta g_if(netid));
if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr) if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
{ {
config = new; config = new;
/* set "known" tag for known hosts */ /* set "known" tag for known hosts */
known_id.net = "known"; known_id.net = "known";
known_id.next = netid; known_id.next = netid;
netid = &known_id; netid = &known_id;
} }
} }
for (m = daemon->dhcp_name_match; m; m = m->next)
{
size_t ml = strlen(m->name);
char save = 0;
if (nl < ml)
continue;
if (nl > ml)
{
save = client_hostname[ml];
client_hostname[ml] = 0;
}
if (hostname_isequal(client_hostname, m->name) &&
(save == 0 || m->wildcard))
{
m->netid->next = netid;
netid = m->netid;
}
if (save != 0)
client_hostname[ml] = save;
}
} }
} }
if (config) if (config)
{ {
struct dhcp_netid_list *list; struct dhcp_netid_list *list;
for (list = config->netid; list; list = list->next) for (list = config->netid; list; list = list->next)
{ {
list->list->next = netid; list->list->next = netid;
 End of changes. 17 change blocks. 
79 lines changed or deleted 108 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)