import of dnsmasq-2.5.tar.gz

This commit is contained in:
Simon Kelley
2004-03-16 18:35:52 +00:00
parent 1cff166d37
commit 8a911ccc75
12 changed files with 116 additions and 58 deletions

View File

@@ -12,7 +12,7 @@
/* Author's email: simon@thekelleys.org.uk */
#define VERSION "2.4"
#define VERSION "2.5"
#define FTABSIZ 150 /* max number of outstanding requests */
#define TIMEOUT 20 /* drop queries after TIMEOUT seconds */

View File

@@ -75,7 +75,8 @@ void dhcp_packet(struct dhcp_context *contexts, char *packet,
struct iovec iov[2];
struct cmsghdr *cmptr;
int sz, newlen, iface_index = 0;
struct in_addr source, real_netmask, iface_addr, netmask_save, broadcast_save;
struct in_addr source, iface_netmask, iface_addr, iface_broadcast;
struct in_addr netmask_save, broadcast_save, router;
#ifdef HAVE_BPF
unsigned char iface_hwaddr[ETHER_ADDR_LEN];
#endif
@@ -112,7 +113,8 @@ void dhcp_packet(struct dhcp_context *contexts, char *packet,
if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
iface_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
if (!iface_index || !if_indextoname(iface_index, ifr.ifr_name))
if (!(ifr.ifr_ifindex = iface_index) ||
ioctl(dhcp_fd, SIOCGIFNAME, &ifr) == -1)
return;
#elif defined(IP_RECVIF)
@@ -169,17 +171,30 @@ void dhcp_packet(struct dhcp_context *contexts, char *packet,
/* If the packet came via a relay, use that address to look up the context,
else use the address of the interface is arrived on. */
source = mess->giaddr.s_addr ? mess->giaddr : iface_addr;
iface_netmask.s_addr = 0;
iface_broadcast.s_addr = 0;
if (ioctl(dhcp_fd, SIOCGIFNETMASK, &ifr) != -1)
{
iface_netmask = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
/* we can use the interface netmask if either the packet came direct,
or it came via a relay listening on the same network. This sounds unlikely,
but it happens with win4lin. */
if ((source.s_addr & iface_netmask.s_addr) != (iface_addr.s_addr & iface_netmask.s_addr))
iface_netmask.s_addr = 0;
else if (ioctl(dhcp_fd, SIOCGIFBRDADDR, &ifr) != -1)
iface_broadcast = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
}
for (context = contexts; context; context = context->next)
{
if (!context->netmask.s_addr && !mess->giaddr.s_addr && ioctl(dhcp_fd, SIOCGIFNETMASK, &ifr) != -1)
real_netmask = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
else
real_netmask = context->netmask;
if (real_netmask.s_addr &&
(source.s_addr & real_netmask.s_addr) == (context->start.s_addr & real_netmask.s_addr) &&
(source.s_addr & real_netmask.s_addr) == (context->end.s_addr & real_netmask.s_addr))
struct in_addr netmask = context->netmask.s_addr ? context->netmask : iface_netmask;
if (netmask.s_addr &&
(source.s_addr & netmask.s_addr) == (context->start.s_addr & netmask.s_addr) &&
(source.s_addr & netmask.s_addr) == (context->end.s_addr & netmask.s_addr))
break;
}
@@ -192,26 +207,34 @@ void dhcp_packet(struct dhcp_context *contexts, char *packet,
netmask_save = context->netmask;
broadcast_save = context->broadcast;
context->netmask = real_netmask;
if (!context->netmask.s_addr)
context->netmask = iface_netmask;
if (!context->broadcast.s_addr)
{
if (mess->giaddr.s_addr)
context->broadcast.s_addr = (mess->giaddr.s_addr & real_netmask.s_addr) | ~real_netmask.s_addr;
else if (ioctl(dhcp_fd, SIOCGIFBRDADDR, &ifr) != -1)
context->broadcast = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
if (iface_broadcast.s_addr)
context->broadcast = iface_broadcast;
else
context->broadcast.s_addr = (iface_addr.s_addr & real_netmask.s_addr) | ~real_netmask.s_addr;
context->broadcast.s_addr = (source.s_addr & context->netmask.s_addr) | ~context->netmask.s_addr;
}
if (ioctl(dhcp_fd, SIOCGIFMTU, &ifr) == -1)
ifr.ifr_mtu = ETHERMTU;
/* Normally, we set the default route to point to the machine which is getting the
DHCP broadcast, either this machine or a relay. In the special case that the relay
is on the same network as us, we set the default route to us, not the relay.
This is the win4lin scenario again. */
if ((source.s_addr & context->netmask.s_addr) == (iface_addr.s_addr & context->netmask.s_addr))
router = iface_addr;
else
router = source;
lease_prune(NULL, now); /* lose any expired leases */
newlen = dhcp_reply(context, iface_addr, ifr.ifr_name, ifr.ifr_mtu,
rawpacket, sz, now, namebuff,
dhcp_opts, dhcp_configs, domain_suffix, dhcp_file,
dhcp_sname, dhcp_next_server);
dhcp_sname, dhcp_next_server, router);
lease_update_file(0, now);
lease_update_dns();

View File

@@ -40,6 +40,7 @@
# include <sys/sockio.h>
#endif
#include <sys/time.h>
#include <limits.h>
#include <net/if.h>
#include <unistd.h>
#include <stdio.h>
@@ -403,5 +404,5 @@ int dhcp_reply(struct dhcp_context *context,
unsigned int sz, time_t now, char *namebuff,
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
char *domain_suffix, char *dhcp_file, char *dhcp_sname,
struct in_addr dhcp_next_server);
struct in_addr dhcp_next_server, struct in_addr router);

View File

@@ -104,7 +104,6 @@ static void send_from(int fd, int nowild, char *packet, int len,
msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
cmptr->cmsg_type = IPV6_PKTINFO;
cmptr->cmsg_level = IPV6_LEVEL;
cmptr->cmsg_level = IPPROTO_IPV6;
}
#endif
@@ -368,11 +367,10 @@ struct server *receive_query(struct listener *listen, char *packet, char *mxname
union mysockaddr source_addr;
struct iname *tmp;
struct all_addr dst_addr;
int m, n, gotit = 0;
int m, n, if_index = 0;
struct iovec iov[1];
struct msghdr msg;
struct cmsghdr *cmptr;
char if_name[IF_NAMESIZE];
union {
struct cmsghdr align; /* this ensures alignment */
#ifdef HAVE_IPV6
@@ -414,20 +412,16 @@ struct server *receive_query(struct listener *listen, char *packet, char *mxname
if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
{
dst_addr.addr.addr4 = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_spec_dst;
if_indextoname(((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex, if_name);
gotit = 1;
if_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
}
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
if (!(options & OPT_NOWILD) && listen->family == AF_INET)
{
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
{
dst_addr.addr.addr4 = *((struct in_addr *)CMSG_DATA(cmptr));
gotit = 1;
}
dst_addr.addr.addr4 = *((struct in_addr *)CMSG_DATA(cmptr));
else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
if_indextoname(((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index, if_name);
if_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index;
}
#endif
@@ -438,8 +432,7 @@ struct server *receive_query(struct listener *listen, char *packet, char *mxname
if (cmptr->cmsg_level == IPV6_LEVEL && cmptr->cmsg_type == IPV6_PKTINFO)
{
dst_addr.addr.addr6 = ((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_addr;
if_indextoname(((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_ifindex, if_name);
gotit = 1;
if_index =((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_ifindex;
}
}
#endif
@@ -450,17 +443,31 @@ struct server *receive_query(struct listener *listen, char *packet, char *mxname
/* enforce available interface configuration */
if (!(options & OPT_NOWILD))
{
if (!gotit)
struct ifreq ifr;
if (if_index == 0)
return last_server;
if (except || names)
{
#ifdef SIOCGIFNAME
ifr.ifr_ifindex = if_index;
if (ioctl(listen->fd, SIOCGIFNAME, &ifr) == -1)
return last_server;
#else
if (!if_indextoname(if_index, ifr.ifr_name))
return last_server;
#endif
}
for (tmp = except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, if_name) == 0))
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
return last_server;
if (names || addrs)
{
for (tmp = names; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, if_name) == 0))
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
break;
if (!tmp)
for (tmp = addrs; tmp; tmp = tmp->next)

View File

@@ -145,7 +145,7 @@ struct irec *enumerate_interfaces(struct iname *names,
lo->next = names->next;
names->next = lo;
}
if ((new = add_iface(iface, ifr->ifr_name,
&addr, names, addrs, except)))
{

View File

@@ -165,7 +165,6 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
char *conffile = CONFFILE;
int conffile_set = 0;
int lineno = 0;
opterr = 0;
*min_leasetime = UINT_MAX;
@@ -359,6 +358,8 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
/* new->name may be NULL if someone does
"interface=" to disable all interfaces except loop. */
new->name = safe_string_alloc(optarg);
if (strchr(optarg, ':'))
flags |= OPT_NOWILD;
break;
}
@@ -368,6 +369,8 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
new->next = *if_except;
*if_except = new;
new->name = safe_string_alloc(optarg);
if (strchr(optarg, ':'))
flags |= OPT_NOWILD;
break;
}
@@ -684,14 +687,13 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
}
new->lease_time = atoi(a[leasepos]) * fac;
if (new->lease_time < *min_leasetime)
*min_leasetime = new->lease_time;
}
}
}
new->last = new->start;
if (new->lease_time < *min_leasetime)
*min_leasetime = new->lease_time;
break;
}
@@ -803,17 +805,17 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
new->hostname = safe_string_alloc(a[j]);
}
else
{
new->lease_time = atoi(a[j]) * fac;
if (new->lease_time < *min_leasetime)
*min_leasetime = new->lease_time;
}
new->lease_time = atoi(a[j]) * fac;
}
if (option == '?')
free(new);
else
*dhcp_conf = new;
{
if (new->lease_time < *min_leasetime)
*min_leasetime = new->lease_time;
*dhcp_conf = new;
}
break;
}
@@ -1023,7 +1025,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
*resolv_files = 0;
else if (*resolv_files && (*resolv_files)->next && (flags & OPT_NO_POLL))
die("only one resolv.conf file allowed in no-poll mode.", NULL);
return flags;
}

View File

@@ -61,7 +61,7 @@ static unsigned char *do_req_options(struct dhcp_context *context,
unsigned char *req_options,
struct dhcp_opt *config_opts,
char *domainname, char *hostname,
struct in_addr relay,
struct in_addr router,
struct in_addr iface_addr,
int iface_mtu);
@@ -74,7 +74,7 @@ int dhcp_reply(struct dhcp_context *context,
unsigned int sz, time_t now, char *namebuff,
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
char *domain_suffix, char *dhcp_file, char *dhcp_sname,
struct in_addr dhcp_next_server)
struct in_addr dhcp_next_server, struct in_addr router)
{
unsigned char *opt, *clid;
struct dhcp_lease *lease;
@@ -265,7 +265,7 @@ int dhcp_reply(struct dhcp_context *context,
p = option_put(p, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(iface_addr.s_addr));
p = option_put(p, end, OPTION_LEASE_TIME, 4, expires_time);
p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
NULL, mess->giaddr, iface_addr, iface_mtu);
NULL, router, iface_addr, iface_mtu);
p = option_put(p, end, OPTION_END, 0, 0);
log_packet("OFFER" , &mess->yiaddr, mess->chaddr, iface_name, NULL);
@@ -354,7 +354,7 @@ int dhcp_reply(struct dhcp_context *context,
p = option_put(p, end, OPTION_T2, 4, ((renewal_time * 7)/8) - fuzz);
}
p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
hostname, mess->giaddr, iface_addr, iface_mtu);
hostname, router, iface_addr, iface_mtu);
p = option_put(p, end, OPTION_END, 0, 0);
return p - (unsigned char *)mess;
@@ -364,7 +364,7 @@ int dhcp_reply(struct dhcp_context *context,
p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
p = option_put(p, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(iface_addr.s_addr));
p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
hostname, mess->giaddr, iface_addr, iface_mtu);
hostname, router, iface_addr, iface_mtu);
p = option_put(p, end, OPTION_END, 0, 0);
log_packet("ACK", &mess->ciaddr, mess->chaddr, iface_name, hostname);
@@ -538,7 +538,7 @@ static unsigned char *do_req_options(struct dhcp_context *context,
unsigned char *req_options,
struct dhcp_opt *config_opts,
char *domainname, char *hostname,
struct in_addr relay,
struct in_addr router,
struct in_addr iface_addr,
int iface_mtu)
{
@@ -563,7 +563,7 @@ static unsigned char *do_req_options(struct dhcp_context *context,
if (in_list(req_options, OPTION_ROUTER) &&
!option_find2(context, config_opts, OPTION_ROUTER))
p = option_put(p, end, OPTION_ROUTER, INADDRSZ,
ntohl(relay.s_addr ? relay.s_addr : iface_addr.s_addr ));
ntohl(router.s_addr));
if (in_list(req_options, OPTION_DNSSERVER) &&
!option_find2(context, config_opts, OPTION_DNSSERVER))