mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
import of dnsmasq-2.51.tar.gz
This commit is contained in:
35
src/cache.c
35
src/cache.c
@@ -226,7 +226,7 @@ char *cache_get_name(struct crec *crecp)
|
||||
{
|
||||
if (crecp->flags & F_BIGNAME)
|
||||
return crecp->name.bname->name;
|
||||
else if (crecp->flags & F_DHCP)
|
||||
else if (crecp->flags & (F_DHCP | F_CONFIG))
|
||||
return crecp->name.namep;
|
||||
|
||||
return crecp->name.sname;
|
||||
@@ -366,7 +366,7 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
|
||||
|
||||
log_query(flags | F_UPSTREAM, name, addr, NULL);
|
||||
|
||||
/* CONFIG bit no needed except for logging */
|
||||
/* CONFIG bit means something else when stored in cache entries */
|
||||
flags &= ~F_CONFIG;
|
||||
|
||||
/* if previous insertion failed give up now. */
|
||||
@@ -693,10 +693,10 @@ static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrl
|
||||
if (!nameexists)
|
||||
for (a = daemon->cnames; a; a = a->next)
|
||||
if (hostname_isequal(cache->name.sname, a->target) &&
|
||||
(lookup = whine_malloc(sizeof(struct crec) + strlen(a->alias)+1-SMALLDNAME)))
|
||||
(lookup = whine_malloc(sizeof(struct crec))))
|
||||
{
|
||||
lookup->flags = F_FORWARD | F_IMMORTAL | F_HOSTS | F_CNAME;
|
||||
strcpy(lookup->name.sname, a->alias);
|
||||
lookup->flags = F_FORWARD | F_IMMORTAL | F_CONFIG | F_HOSTS | F_CNAME;
|
||||
lookup->name.namep = a->alias;
|
||||
lookup->addr.cname.cache = cache;
|
||||
lookup->addr.cname.uid = index;
|
||||
cache_hash(lookup);
|
||||
@@ -821,35 +821,38 @@ static int read_hostsfile(char *filename, int index, int cache_size)
|
||||
while (atnl == 0)
|
||||
{
|
||||
struct crec *cache;
|
||||
int fqdn;
|
||||
int fqdn, nomem;
|
||||
char *canon;
|
||||
|
||||
if ((atnl = gettok(f, token)) == EOF)
|
||||
break;
|
||||
|
||||
fqdn = !!strchr(token, '.');
|
||||
|
||||
if (canonicalise(token))
|
||||
if ((canon = canonicalise(token, &nomem)))
|
||||
{
|
||||
/* If set, add a version of the name with a default domain appended */
|
||||
if ((daemon->options & OPT_EXPAND) && domain_suffix && !fqdn &&
|
||||
(cache = whine_malloc(sizeof(struct crec) +
|
||||
strlen(token)+2+strlen(domain_suffix)-SMALLDNAME)))
|
||||
strlen(canon)+2+strlen(domain_suffix)-SMALLDNAME)))
|
||||
{
|
||||
strcpy(cache->name.sname, token);
|
||||
strcpy(cache->name.sname, canon);
|
||||
strcat(cache->name.sname, ".");
|
||||
strcat(cache->name.sname, domain_suffix);
|
||||
add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup);
|
||||
addr_dup = 1;
|
||||
name_count++;
|
||||
}
|
||||
if ((cache = whine_malloc(sizeof(struct crec) + strlen(token)+1-SMALLDNAME)))
|
||||
if ((cache = whine_malloc(sizeof(struct crec) + strlen(canon)+1-SMALLDNAME)))
|
||||
{
|
||||
strcpy(cache->name.sname, token);
|
||||
strcpy(cache->name.sname, canon);
|
||||
add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup);
|
||||
name_count++;
|
||||
}
|
||||
free(canon);
|
||||
|
||||
}
|
||||
else
|
||||
else if (!nomem)
|
||||
my_syslog(LOG_ERR, _("bad name at %s line %d"), filename, lineno);
|
||||
}
|
||||
}
|
||||
@@ -1103,7 +1106,7 @@ void cache_add_dhcp_entry(char *host_name,
|
||||
|
||||
if (aliasc)
|
||||
{
|
||||
aliasc->flags = F_FORWARD | F_DHCP | F_CNAME;
|
||||
aliasc->flags = F_FORWARD | F_CONFIG | F_DHCP | F_CNAME;
|
||||
if (ttd == 0)
|
||||
aliasc->flags |= F_IMMORTAL;
|
||||
else
|
||||
@@ -1285,12 +1288,12 @@ void log_query(unsigned short flags, char *name, struct all_addr *addr, char *ar
|
||||
dest = "<CNAME>";
|
||||
}
|
||||
|
||||
if (flags & F_DHCP)
|
||||
if (flags & F_CONFIG)
|
||||
source = "config";
|
||||
else if (flags & F_DHCP)
|
||||
source = "DHCP";
|
||||
else if (flags & F_HOSTS)
|
||||
source = arg;
|
||||
else if (flags & F_CONFIG)
|
||||
source = "config";
|
||||
else if (flags & F_UPSTREAM)
|
||||
source = "reply";
|
||||
else if (flags & F_SERVER)
|
||||
|
||||
20
src/config.h
20
src/config.h
@@ -14,13 +14,15 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define VERSION "2.50"
|
||||
#define VERSION "2.51"
|
||||
|
||||
#define FTABSIZ 150 /* max number of outstanding requests (default) */
|
||||
#define MAX_PROCS 20 /* max no children for TCP requests */
|
||||
#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
|
||||
#define EDNS_PKTSZ 1280 /* default max EDNS.0 UDP packet from RFC2671 */
|
||||
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
|
||||
#define FORWARD_TEST 50 /* try all servers every 50 queries */
|
||||
#define FORWARD_TIME 10 /* or 10 seconds */
|
||||
#define RANDOM_SOCKS 64 /* max simultaneous random ports */
|
||||
#define LEASE_RETRY 60 /* on error, retry writing leasefile after LEASE_RETRY seconds */
|
||||
#define CACHESIZ 150 /* default cache size */
|
||||
@@ -126,6 +128,9 @@ HAVE_TFTP
|
||||
HAVE_DHCP
|
||||
define this to get dnsmasq's DHCP server.
|
||||
|
||||
HAVE_SCRIPT
|
||||
define this to get the ability to call scripts on lease-change
|
||||
|
||||
HAVE_GETOPT_LONG
|
||||
define this if you have GNU libc or GNU getopt.
|
||||
|
||||
@@ -162,6 +167,7 @@ NOTES:
|
||||
/* platform independent options- uncomment to enable */
|
||||
#define HAVE_DHCP
|
||||
#define HAVE_TFTP
|
||||
#define HAVE_SCRIPT
|
||||
/* #define HAVE_BROKEN_RTC */
|
||||
/* #define HAVE_DBUS */
|
||||
|
||||
@@ -175,6 +181,13 @@ NOTES:
|
||||
#undef HAVE_DHCP
|
||||
#endif
|
||||
|
||||
/* Allow scripts to be disabled with COPTS=-DNO_SCRIPT */
|
||||
#ifdef NO_SCRIPT
|
||||
#undef HAVE_SCRIPT
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* platform dependent options. */
|
||||
|
||||
/* Must preceed __linux__ since uClinux defines __linux__ too. */
|
||||
@@ -273,3 +286,8 @@ NOTES:
|
||||
# define ADDRSTRLEN 16 /* 4*3 + 3 dots + NULL */
|
||||
#endif
|
||||
|
||||
/* Can't do scripts without fork */
|
||||
#ifdef NOFORK
|
||||
# undef HAVE_SCRIPT
|
||||
#endif
|
||||
|
||||
|
||||
17
src/dbus.c
17
src/dbus.c
@@ -390,16 +390,25 @@ void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset)
|
||||
}
|
||||
}
|
||||
|
||||
void emit_dbus_signal(int action, char *mac, char *hostname, char *addr)
|
||||
void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname)
|
||||
{
|
||||
DBusConnection *connection = (DBusConnection *)daemon->dbus;
|
||||
DBusMessage* message = NULL;
|
||||
DBusMessageIter args;
|
||||
const char *action_str;
|
||||
char *action_str, *addr, *mac = daemon->namebuff;
|
||||
unsigned char *p;
|
||||
int i;
|
||||
|
||||
if (!connection)
|
||||
return;
|
||||
|
||||
|
||||
if (!hostname)
|
||||
hostname = "";
|
||||
|
||||
p = extended_hwaddr(lease->hwaddr_type, lease->hwaddr_len,
|
||||
lease->hwaddr, lease->clid_len, lease->clid, &i);
|
||||
print_mac(mac, p, i);
|
||||
|
||||
if (action == ACTION_DEL)
|
||||
action_str = "DhcpLeaseDeleted";
|
||||
else if (action == ACTION_ADD)
|
||||
@@ -409,6 +418,8 @@ void emit_dbus_signal(int action, char *mac, char *hostname, char *addr)
|
||||
else
|
||||
return;
|
||||
|
||||
addr = inet_ntoa(lease->addr);
|
||||
|
||||
if (!(message = dbus_message_new_signal(DNSMASQ_PATH, DNSMASQ_SERVICE, action_str)))
|
||||
return;
|
||||
|
||||
|
||||
33
src/dhcp.c
33
src/dhcp.c
@@ -754,6 +754,8 @@ void dhcp_read_ethers(void)
|
||||
|
||||
while (fgets(buff, MAXDNAME, f))
|
||||
{
|
||||
char *host = NULL;
|
||||
|
||||
lineno++;
|
||||
|
||||
while (strlen(buff) > 0 && isspace((int)buff[strlen(buff)-1]))
|
||||
@@ -792,19 +794,28 @@ void dhcp_read_ethers(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!canonicalise(ip))
|
||||
int nomem;
|
||||
if (!(host = canonicalise(ip, &nomem)) || !legal_hostname(host))
|
||||
{
|
||||
my_syslog(MS_DHCP | LOG_ERR, _("bad name at %s line %d"), ETHERSFILE, lineno);
|
||||
if (!nomem)
|
||||
my_syslog(MS_DHCP | LOG_ERR, _("bad name at %s line %d"), ETHERSFILE, lineno);
|
||||
free(host);
|
||||
continue;
|
||||
}
|
||||
|
||||
flags = CONFIG_NAME;
|
||||
|
||||
for (config = daemon->dhcp_conf; config; config = config->next)
|
||||
if ((config->flags & CONFIG_NAME) && hostname_isequal(config->hostname, ip))
|
||||
if ((config->flags & CONFIG_NAME) && hostname_isequal(config->hostname, host))
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (config && (config->flags & CONFIG_FROM_ETHERS))
|
||||
{
|
||||
my_syslog(MS_DHCP | LOG_ERR, _("ignoring %s line %d, duplicate name or IP address"), ETHERSFILE, lineno);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!config)
|
||||
{
|
||||
for (config = daemon->dhcp_conf; config; config = config->next)
|
||||
@@ -834,10 +845,8 @@ void dhcp_read_ethers(void)
|
||||
|
||||
if (flags & CONFIG_NAME)
|
||||
{
|
||||
if ((config->hostname = whine_malloc(strlen(ip)+1)))
|
||||
strcpy(config->hostname, ip);
|
||||
else
|
||||
config->flags &= ~CONFIG_NAME;
|
||||
config->hostname = host;
|
||||
host = NULL;
|
||||
}
|
||||
|
||||
if (flags & CONFIG_ADDR)
|
||||
@@ -856,6 +865,9 @@ void dhcp_read_ethers(void)
|
||||
config->hwaddr->next = NULL;
|
||||
}
|
||||
count++;
|
||||
|
||||
free(host);
|
||||
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
@@ -945,7 +957,8 @@ void dhcp_update_configs(struct dhcp_config *configs)
|
||||
|
||||
/* If we've not found a hostname any other way, try and see if there's one in /etc/hosts
|
||||
for this address. If it has a domain part, that must match the set domain and
|
||||
it gets stripped. */
|
||||
it gets stripped. The set of legal domain names is bigger than the set of legal hostnames
|
||||
so check here that the domain name is legal as a hostname. */
|
||||
char *host_from_dns(struct in_addr addr)
|
||||
{
|
||||
struct crec *lookup;
|
||||
@@ -963,7 +976,7 @@ char *host_from_dns(struct in_addr addr)
|
||||
hostname[255] = 0;
|
||||
d1 = strip_hostname(hostname);
|
||||
d2 = get_domain(addr);
|
||||
if (d1 && (!d2 || hostname_isequal(d1, d2)))
|
||||
if (!legal_hostname(hostname) || (d1 && (!d2 || !hostname_isequal(d1, d2))))
|
||||
hostname = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,11 +45,16 @@ static char *compile_opts =
|
||||
"no-"
|
||||
#endif
|
||||
"DHCP "
|
||||
#if defined(HAVE_DHCP) && !defined(HAVE_SCRIPT)
|
||||
"no-scripts "
|
||||
#endif
|
||||
#ifndef HAVE_TFTP
|
||||
"no-"
|
||||
#endif
|
||||
"TFTP";
|
||||
|
||||
|
||||
|
||||
static volatile pid_t pid = 0;
|
||||
static volatile int pipewrite;
|
||||
|
||||
@@ -68,7 +73,7 @@ int main (int argc, char **argv)
|
||||
struct iname *if_tmp;
|
||||
int piperead, pipefd[2], err_pipe[2];
|
||||
struct passwd *ent_pw = NULL;
|
||||
#ifdef HAVE_DHCP
|
||||
#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
|
||||
uid_t script_uid = 0;
|
||||
gid_t script_gid = 0;
|
||||
#endif
|
||||
@@ -202,7 +207,7 @@ int main (int argc, char **argv)
|
||||
if (daemon->port != 0)
|
||||
pre_allocate_sfds();
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
|
||||
/* Note getpwnam returns static storage */
|
||||
if (daemon->dhcp && daemon->lease_change_command && daemon->scriptuser)
|
||||
{
|
||||
@@ -352,7 +357,7 @@ int main (int argc, char **argv)
|
||||
|
||||
/* if we are to run scripts, we need to fork a helper before dropping root. */
|
||||
daemon->helperfd = -1;
|
||||
#if defined(HAVE_DHCP) && !defined(NO_FORK)
|
||||
#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
|
||||
if (daemon->dhcp && daemon->lease_change_command)
|
||||
daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
|
||||
#endif
|
||||
@@ -603,7 +608,7 @@ int main (int argc, char **argv)
|
||||
bump_maxfd(piperead, &maxfd);
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
# ifndef NO_FORK
|
||||
# ifdef HAVE_SCRIPT
|
||||
while (helper_buf_empty() && do_script_run(now));
|
||||
|
||||
if (!helper_buf_empty())
|
||||
@@ -674,7 +679,7 @@ int main (int argc, char **argv)
|
||||
if (daemon->dhcp && FD_ISSET(daemon->dhcpfd, &rset))
|
||||
dhcp_packet(now);
|
||||
|
||||
# ifndef NO_FORK
|
||||
# ifdef HAVE_SCRIPT
|
||||
if (daemon->helperfd != -1 && FD_ISSET(daemon->helperfd, &wset))
|
||||
helper_write();
|
||||
# endif
|
||||
@@ -857,7 +862,7 @@ static void async_event(int pipe, time_t now)
|
||||
if (daemon->tcp_pids[i] != 0)
|
||||
kill(daemon->tcp_pids[i], SIGALRM);
|
||||
|
||||
#if defined(HAVE_DHCP) && !defined(NO_FORK)
|
||||
#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
|
||||
/* handle pending lease transitions */
|
||||
if (daemon->helperfd != -1)
|
||||
{
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
/* get these before config.h for IPv6 stuff... */
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
@@ -55,7 +56,6 @@
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#if defined(HAVE_SOLARIS_NETWORK)
|
||||
#include <sys/sockio.h>
|
||||
@@ -335,7 +335,7 @@ struct server {
|
||||
struct irec {
|
||||
union mysockaddr addr;
|
||||
struct in_addr netmask; /* only valid for IPv4 */
|
||||
int dhcp_ok;
|
||||
int dhcp_ok, mtu;
|
||||
struct irec *next;
|
||||
};
|
||||
|
||||
@@ -410,9 +410,9 @@ struct dhcp_lease {
|
||||
#endif
|
||||
int hwaddr_len, hwaddr_type;
|
||||
unsigned char hwaddr[DHCP_CHADDR_MAX];
|
||||
struct in_addr addr, override;
|
||||
unsigned char *vendorclass, *userclass;
|
||||
unsigned int vendorclass_len, userclass_len;
|
||||
struct in_addr addr, override, giaddr;
|
||||
unsigned char *vendorclass, *userclass, *supplied_hostname;
|
||||
unsigned int vendorclass_len, userclass_len, supplied_hostname_len;
|
||||
int last_interface;
|
||||
struct dhcp_lease *next;
|
||||
};
|
||||
@@ -626,6 +626,7 @@ extern struct daemon {
|
||||
struct dhcp_mac *dhcp_macs;
|
||||
struct dhcp_boot *boot_config;
|
||||
struct pxe_service *pxe_services;
|
||||
int enable_pxe;
|
||||
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *force_broadcast, *bootp_dynamic;
|
||||
char *dhcp_hosts_file, *dhcp_opts_file;
|
||||
int dhcp_max, tftp_max;
|
||||
@@ -646,6 +647,8 @@ extern struct daemon {
|
||||
struct irec *interfaces;
|
||||
struct listener *listeners;
|
||||
struct server *last_server;
|
||||
time_t forwardtime;
|
||||
int forwardcount;
|
||||
struct server *srv_save; /* Used for resend on DoD */
|
||||
size_t packet_len; /* " " */
|
||||
struct randfd *rfd_save; /* " " */
|
||||
@@ -719,8 +722,8 @@ size_t resize_packet(HEADER *header, size_t plen,
|
||||
/* util.c */
|
||||
void rand_init(void);
|
||||
unsigned short rand16(void);
|
||||
int legal_char(char c);
|
||||
int canonicalise(char *s);
|
||||
int legal_hostname(char *c);
|
||||
char *canonicalise(char *s, int *nomem);
|
||||
unsigned char *do_rfc1035_name(unsigned char *p, char *sval);
|
||||
void *safe_malloc(size_t size);
|
||||
void safe_pipe(int *fd, int read_noblock);
|
||||
@@ -863,7 +866,7 @@ int iface_enumerate(void *parm, int (*ipv4_callback)(), int (*ipv6_callback)());
|
||||
char *dbus_init(void);
|
||||
void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset);
|
||||
void set_dbus_listeners(int *maxfdp, fd_set *rset, fd_set *wset, fd_set *eset);
|
||||
void emit_dbus_signal(int action, char *mac, char *hostname, char *addr);
|
||||
void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname);
|
||||
#endif
|
||||
|
||||
/* helper.c */
|
||||
|
||||
@@ -262,10 +262,14 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
|
||||
if (type != 0 || (daemon->options & OPT_ORDER))
|
||||
start = daemon->servers;
|
||||
else if (!(start = daemon->last_server))
|
||||
else if (!(start = daemon->last_server) ||
|
||||
daemon->forwardcount++ > FORWARD_TEST ||
|
||||
difftime(now, daemon->forwardtime) > FORWARD_TIME)
|
||||
{
|
||||
start = daemon->servers;
|
||||
forward->forwardall = 1;
|
||||
daemon->forwardcount = 0;
|
||||
daemon->forwardtime = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
62
src/helper.c
62
src/helper.c
@@ -28,15 +28,15 @@
|
||||
main process.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_DHCP) && !defined(NO_FORK)
|
||||
#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
|
||||
|
||||
static void my_setenv(const char *name, const char *value, int *error);
|
||||
|
||||
struct script_data
|
||||
{
|
||||
unsigned char action, hwaddr_len, hwaddr_type;
|
||||
unsigned char clid_len, hostname_len, uclass_len, vclass_len;
|
||||
struct in_addr addr;
|
||||
unsigned char clid_len, hostname_len, uclass_len, vclass_len, shost_len;
|
||||
struct in_addr addr, giaddr;
|
||||
unsigned int remaining_time;
|
||||
#ifdef HAVE_BROKEN_RTC
|
||||
unsigned int length;
|
||||
@@ -101,7 +101,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
|
||||
/* close all the sockets etc, we don't need them here. This closes err_fd, so that
|
||||
main process can return. */
|
||||
for (max_fd--; max_fd > 0; max_fd--)
|
||||
for (max_fd--; max_fd >= 0; max_fd--)
|
||||
if (max_fd != STDOUT_FILENO && max_fd != STDERR_FILENO &&
|
||||
max_fd != STDIN_FILENO && max_fd != pipefd[0] && max_fd != event_fd)
|
||||
close(max_fd);
|
||||
@@ -155,7 +155,8 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
sprintf(daemon->dhcp_buff2, "%lu ", (unsigned long)data.expires);
|
||||
#endif
|
||||
|
||||
if (!read_write(pipefd[0], buf, data.hostname_len + data.uclass_len + data.vclass_len, 1))
|
||||
if (!read_write(pipefd[0], buf,
|
||||
data.hostname_len + data.uclass_len + data.vclass_len + data.shost_len, 1))
|
||||
continue;
|
||||
|
||||
/* possible fork errors are all temporary resource problems */
|
||||
@@ -232,6 +233,19 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
}
|
||||
}
|
||||
|
||||
if (data.shost_len != 0)
|
||||
{
|
||||
buf[data.shost_len - 1] = 0; /* don't trust zero-term */
|
||||
/* cannot have = chars in env - truncate if found . */
|
||||
if ((p = strchr((char *)buf, '=')))
|
||||
*p = 0;
|
||||
my_setenv("DNSMASQ_SUPPLIED_HOSTNAME", (char *)buf, &err);
|
||||
buf += data.shost_len;
|
||||
}
|
||||
|
||||
if (data.giaddr.s_addr != 0)
|
||||
my_setenv("DNSMASQ_RELAY_ADDRESS", inet_ntoa(data.giaddr), &err);
|
||||
|
||||
sprintf(daemon->dhcp_buff2, "%u ", data.remaining_time);
|
||||
my_setenv("DNSMASQ_TIME_REMAINING", daemon->dhcp_buff2, &err);
|
||||
|
||||
@@ -240,7 +254,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
char *dot;
|
||||
hostname = (char *)buf;
|
||||
hostname[data.hostname_len - 1] = 0;
|
||||
if (!canonicalise(hostname))
|
||||
if (!legal_hostname(hostname))
|
||||
hostname = NULL;
|
||||
else if ((dot = strchr(hostname, '.')))
|
||||
{
|
||||
@@ -285,16 +299,9 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
|
||||
{
|
||||
unsigned char *p;
|
||||
size_t size;
|
||||
int i;
|
||||
unsigned int hostname_len = 0, clid_len = 0, vclass_len = 0, uclass_len = 0;
|
||||
unsigned int hostname_len = 0, clid_len = 0, vclass_len = 0;
|
||||
unsigned int uclass_len = 0, shost_len = 0;
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
p = extended_hwaddr(lease->hwaddr_type, lease->hwaddr_len,
|
||||
lease->hwaddr, lease->clid_len, lease->clid, &i);
|
||||
print_mac(daemon->namebuff, p, i);
|
||||
emit_dbus_signal(action, daemon->namebuff, hostname ? hostname : "", inet_ntoa(lease->addr));
|
||||
#endif
|
||||
|
||||
/* no script */
|
||||
if (daemon->helperfd == -1)
|
||||
return;
|
||||
@@ -303,12 +310,14 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
|
||||
vclass_len = lease->vendorclass_len;
|
||||
if (lease->userclass)
|
||||
uclass_len = lease->userclass_len;
|
||||
if (lease->supplied_hostname)
|
||||
shost_len = lease->supplied_hostname_len;
|
||||
if (lease->clid)
|
||||
clid_len = lease->clid_len;
|
||||
if (hostname)
|
||||
hostname_len = strlen(hostname) + 1;
|
||||
|
||||
size = sizeof(struct script_data) + clid_len + vclass_len + uclass_len + hostname_len;
|
||||
size = sizeof(struct script_data) + clid_len + vclass_len + uclass_len + shost_len + hostname_len;
|
||||
|
||||
if (size > buf_size)
|
||||
{
|
||||
@@ -332,8 +341,10 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
|
||||
buf->clid_len = clid_len;
|
||||
buf->vclass_len = vclass_len;
|
||||
buf->uclass_len = uclass_len;
|
||||
buf->shost_len = shost_len;
|
||||
buf->hostname_len = hostname_len;
|
||||
buf->addr = lease->addr;
|
||||
buf->giaddr = lease->giaddr;
|
||||
memcpy(buf->hwaddr, lease->hwaddr, lease->hwaddr_len);
|
||||
buf->interface[0] = 0;
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
@@ -372,14 +383,17 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
|
||||
memcpy(p, lease->userclass, uclass_len);
|
||||
p += uclass_len;
|
||||
}
|
||||
/* substitute * for space: spaces are allowed in hostnames (for DNS-SD)
|
||||
and are likley to be a security hole in most scripts. */
|
||||
for (i = 0; i < (int)hostname_len; i++)
|
||||
if ((daemon->options & OPT_LEASE_RO) && hostname[i] == ' ')
|
||||
*(p++) = '*';
|
||||
else
|
||||
*(p++) = hostname[i];
|
||||
|
||||
if (shost_len != 0)
|
||||
{
|
||||
memcpy(p, lease->supplied_hostname, shost_len);
|
||||
p += shost_len;
|
||||
}
|
||||
if (hostname_len != 0)
|
||||
{
|
||||
memcpy(p, hostname, hostname_len);
|
||||
p += hostname_len;
|
||||
}
|
||||
|
||||
bytes_in_buf = p - (unsigned char *)buf;
|
||||
}
|
||||
|
||||
|
||||
61
src/lease.c
61
src/lease.c
@@ -42,14 +42,20 @@ void lease_init(time_t now)
|
||||
initial state of the database. If leasefile-ro is
|
||||
set without a script, we just do without any
|
||||
lease database. */
|
||||
if (!daemon->lease_change_command)
|
||||
#ifdef HAVE_SCRIPT
|
||||
if (daemon->lease_change_command)
|
||||
{
|
||||
file_dirty = dns_dirty = 0;
|
||||
return;
|
||||
strcpy(daemon->dhcp_buff, daemon->lease_change_command);
|
||||
strcat(daemon->dhcp_buff, " init");
|
||||
leasestream = popen(daemon->dhcp_buff, "r");
|
||||
}
|
||||
strcpy(daemon->dhcp_buff, daemon->lease_change_command);
|
||||
strcat(daemon->dhcp_buff, " init");
|
||||
leasestream = popen(daemon->dhcp_buff, "r");
|
||||
else
|
||||
#endif
|
||||
{
|
||||
file_dirty = dns_dirty = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -100,19 +106,14 @@ void lease_init(time_t now)
|
||||
lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, hw_len, hw_type, clid_len);
|
||||
|
||||
if (strcmp(daemon->dhcp_buff, "*") != 0)
|
||||
{
|
||||
char *p;
|
||||
/* unprotect spaces */
|
||||
for (p = strchr(daemon->dhcp_buff, '*'); p; p = strchr(p, '*'))
|
||||
*p = ' ';
|
||||
lease_set_hostname(lease, daemon->dhcp_buff, 0);
|
||||
}
|
||||
lease_set_hostname(lease, daemon->dhcp_buff, 0);
|
||||
|
||||
/* set these correctly: the "old" events are generated later from
|
||||
the startup synthesised SIGHUP. */
|
||||
lease->new = lease->changed = 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SCRIPT
|
||||
if (!daemon->lease_stream)
|
||||
{
|
||||
int rc = 0;
|
||||
@@ -133,6 +134,7 @@ void lease_init(time_t now)
|
||||
die(_("lease-init script returned exit code %s"), daemon->dhcp_buff, WEXITSTATUS(rc) + EC_INIT_OFFSET);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Some leases may have expired */
|
||||
file_dirty = 0;
|
||||
@@ -173,7 +175,6 @@ void lease_update_file(time_t now)
|
||||
struct dhcp_lease *lease;
|
||||
time_t next_event;
|
||||
int i, err = 0;
|
||||
char *p;
|
||||
|
||||
if (file_dirty != 0 && daemon->lease_stream)
|
||||
{
|
||||
@@ -199,15 +200,8 @@ void lease_update_file(time_t now)
|
||||
}
|
||||
|
||||
ourprintf(&err, " %s ", inet_ntoa(lease->addr));
|
||||
|
||||
/* substitute * for space: "*" is an illegal name, as is " " */
|
||||
if (lease->hostname)
|
||||
for (p = lease->hostname; *p; p++)
|
||||
ourprintf(&err, "%c", *p == ' ' ? '*' : *p);
|
||||
else
|
||||
ourprintf(&err, "*");
|
||||
ourprintf(&err, " ");
|
||||
|
||||
ourprintf(&err, "%s ", lease->hostname ? lease->hostname : "*");
|
||||
|
||||
if (lease->clid && lease->clid_len != 0)
|
||||
{
|
||||
for (i = 0; i < lease->clid_len - 1; i++)
|
||||
@@ -550,7 +544,7 @@ int do_script_run(time_t now)
|
||||
/* If the lease still has an old_hostname, do the "old" action on that first */
|
||||
if (lease->old_hostname)
|
||||
{
|
||||
#ifndef NO_FORK
|
||||
#ifdef HAVE_SCRIPT
|
||||
queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
|
||||
#endif
|
||||
free(lease->old_hostname);
|
||||
@@ -560,8 +554,11 @@ int do_script_run(time_t now)
|
||||
else
|
||||
{
|
||||
kill_name(lease);
|
||||
#ifndef NO_FORK
|
||||
#ifdef HAVE_SCRIPT
|
||||
queue_script(ACTION_DEL, lease, lease->old_hostname, now);
|
||||
#endif
|
||||
#ifdef HAVE_DBUS
|
||||
emit_dbus_signal(ACTION_DEL, lease, lease->old_hostname);
|
||||
#endif
|
||||
old_leases = lease->next;
|
||||
|
||||
@@ -569,6 +566,7 @@ int do_script_run(time_t now)
|
||||
free(lease->clid);
|
||||
free(lease->vendorclass);
|
||||
free(lease->userclass);
|
||||
free(lease->supplied_hostname);
|
||||
free(lease);
|
||||
|
||||
return 1;
|
||||
@@ -579,7 +577,7 @@ int do_script_run(time_t now)
|
||||
for (lease = leases; lease; lease = lease->next)
|
||||
if (lease->old_hostname)
|
||||
{
|
||||
#ifndef NO_FORK
|
||||
#ifdef HAVE_SCRIPT
|
||||
queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
|
||||
#endif
|
||||
free(lease->old_hostname);
|
||||
@@ -591,9 +589,13 @@ int do_script_run(time_t now)
|
||||
if (lease->new || lease->changed ||
|
||||
(lease->aux_changed && (daemon->options & OPT_LEASE_RO)))
|
||||
{
|
||||
#ifndef NO_FORK
|
||||
#ifdef HAVE_SCRIPT
|
||||
queue_script(lease->new ? ACTION_ADD : ACTION_OLD, lease,
|
||||
lease->fqdn ? lease->fqdn : lease->hostname, now);
|
||||
#endif
|
||||
#ifdef HAVE_DBUS
|
||||
emit_dbus_signal(lease->new ? ACTION_ADD : ACTION_OLD, lease,
|
||||
lease->fqdn ? lease->fqdn : lease->hostname);
|
||||
#endif
|
||||
lease->new = lease->changed = lease->aux_changed = 0;
|
||||
|
||||
@@ -603,7 +605,10 @@ int do_script_run(time_t now)
|
||||
|
||||
free(lease->userclass);
|
||||
lease->userclass = NULL;
|
||||
|
||||
|
||||
free(lease->supplied_hostname);
|
||||
lease->supplied_hostname = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
||||
union mysockaddr *addr, struct in_addr netmask)
|
||||
{
|
||||
struct irec *iface;
|
||||
int fd;
|
||||
int fd, mtu = 0, loopback;
|
||||
struct ifreq ifr;
|
||||
int dhcp_ok = 1;
|
||||
struct iname *tmp;
|
||||
@@ -142,12 +142,17 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
loopback = ifr.ifr_flags & IFF_LOOPBACK;
|
||||
|
||||
if (ioctl(fd, SIOCGIFMTU, &ifr) != -1)
|
||||
mtu = ifr.ifr_mtu;
|
||||
|
||||
close(fd);
|
||||
|
||||
/* If we are restricting the set of interfaces to use, make
|
||||
sure that loopback interfaces are in that set. */
|
||||
if (daemon->if_names && (ifr.ifr_flags & IFF_LOOPBACK))
|
||||
if (daemon->if_names && loopback)
|
||||
{
|
||||
struct iname *lo;
|
||||
for (lo = daemon->if_names; lo; lo = lo->next)
|
||||
@@ -188,6 +193,7 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
||||
iface->addr = *addr;
|
||||
iface->netmask = netmask;
|
||||
iface->dhcp_ok = dhcp_ok;
|
||||
iface->mtu = mtu;
|
||||
iface->next = *irecp;
|
||||
*irecp = iface;
|
||||
return 1;
|
||||
|
||||
207
src/option.c
207
src/option.c
@@ -406,6 +406,7 @@ static const struct {
|
||||
{ "domain-search", 119, 0 },
|
||||
{ "sip-server", 120, 0 },
|
||||
{ "classless-static-route", 121, 0 },
|
||||
{ "server-ip-address", 255, OT_ADDR_LIST }, /* special, internal only, sets siaddr */
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
@@ -530,13 +531,24 @@ static char *split(char *s)
|
||||
return split_chr(s, ',');
|
||||
}
|
||||
|
||||
static int canonicalise_opt(char *s)
|
||||
static char *canonicalise_opt(char *s)
|
||||
{
|
||||
char *ret;
|
||||
int nomem;
|
||||
|
||||
if (!s)
|
||||
return 0;
|
||||
|
||||
unhide_metas(s);
|
||||
return canonicalise(s);
|
||||
if (!(ret = canonicalise(s, &nomem)) && nomem)
|
||||
{
|
||||
if (mem_recover)
|
||||
longjmp(mem_jmp, 1);
|
||||
else
|
||||
die(_("could not get memory"), NULL, EC_NOMEM);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int atoi_check(char *a, int *res)
|
||||
@@ -646,7 +658,7 @@ static void display_opts(void)
|
||||
printf(_("Known DHCP options:\n"));
|
||||
|
||||
for (i = 0; opttab[i].name; i++)
|
||||
if (opttab[i].size != OT_INTERNAL)
|
||||
if (!(opttab[i].size & OT_INTERNAL))
|
||||
printf("%3d %s\n", opttab[i].val, opttab[i].name);
|
||||
}
|
||||
|
||||
@@ -684,7 +696,7 @@ static char *parse_dhcp_opt(char *arg, int flags)
|
||||
if (strstr(arg, "option:") == arg)
|
||||
{
|
||||
for (i = 0; opttab[i].name; i++)
|
||||
if (opttab[i].size != OT_INTERNAL &&
|
||||
if (!(opttab[i].size & OT_INTERNAL) &&
|
||||
strcasecmp(opttab[i].name, arg+7) == 0)
|
||||
{
|
||||
new->opt = opttab[i].val;
|
||||
@@ -873,7 +885,8 @@ static char *parse_dhcp_opt(char *arg, int flags)
|
||||
|
||||
while (arg && *arg)
|
||||
{
|
||||
if (!canonicalise_opt(arg))
|
||||
char *dom;
|
||||
if (!(dom = arg = canonicalise_opt(arg)))
|
||||
{
|
||||
problem = _("bad domain in dhcp-option");
|
||||
break;
|
||||
@@ -898,7 +911,8 @@ static char *parse_dhcp_opt(char *arg, int flags)
|
||||
arg++;
|
||||
}
|
||||
*q++ = 0;
|
||||
|
||||
free(dom);
|
||||
|
||||
/* Now tail-compress using earlier names. */
|
||||
newlen = q - p;
|
||||
for (tail = p + len; *tail; tail += (*tail) + 1)
|
||||
@@ -1018,25 +1032,51 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
DIR *dir_stream;
|
||||
struct dirent *ent;
|
||||
char *directory, *path;
|
||||
struct list {
|
||||
char *suffix;
|
||||
struct list *next;
|
||||
} *ignore_suffix = NULL, *li;
|
||||
|
||||
comma = split(arg);
|
||||
if (!(directory = opt_string_alloc(arg)))
|
||||
break;
|
||||
|
||||
for (arg = comma; arg; arg = comma)
|
||||
{
|
||||
comma = split(arg);
|
||||
li = opt_malloc(sizeof(struct list));
|
||||
li->next = ignore_suffix;
|
||||
ignore_suffix = li;
|
||||
/* Have to copy: buffer is overwritten */
|
||||
li->suffix = opt_string_alloc(arg);
|
||||
};
|
||||
|
||||
if (!(dir_stream = opendir(directory)))
|
||||
die(_("cannot access directory %s: %s"), directory, EC_FILE);
|
||||
|
||||
|
||||
while ((ent = readdir(dir_stream)))
|
||||
{
|
||||
size_t len = strlen(ent->d_name);
|
||||
struct stat buf;
|
||||
|
||||
/* ignore emacs backups and dotfiles */
|
||||
|
||||
/* ignore emacs backups and dotfiles */
|
||||
if (len == 0 ||
|
||||
ent->d_name[len - 1] == '~' ||
|
||||
(ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') ||
|
||||
ent->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
for (li = ignore_suffix; li; li = li->next)
|
||||
{
|
||||
/* check for proscribed suffices */
|
||||
size_t ls = strlen(li->suffix);
|
||||
if (len > ls &&
|
||||
strcmp(li->suffix, &ent->d_name[len - ls]) == 0)
|
||||
break;
|
||||
}
|
||||
if (li)
|
||||
continue;
|
||||
|
||||
path = opt_malloc(strlen(directory) + len + 2);
|
||||
strcpy(path, directory);
|
||||
strcat(path, "/");
|
||||
@@ -1055,6 +1095,13 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
|
||||
closedir(dir_stream);
|
||||
free(directory);
|
||||
for(; ignore_suffix; ignore_suffix = li)
|
||||
{
|
||||
li = ignore_suffix->next;
|
||||
free(ignore_suffix->suffix);
|
||||
free(ignore_suffix);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1127,32 +1174,32 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
{
|
||||
int pref = 1;
|
||||
struct mx_srv_record *new;
|
||||
|
||||
char *name, *target = NULL;
|
||||
|
||||
if ((comma = split(arg)))
|
||||
{
|
||||
char *prefstr;
|
||||
if ((prefstr=split(comma)) && !atoi_check16(prefstr, &pref))
|
||||
if ((prefstr = split(comma)) && !atoi_check16(prefstr, &pref))
|
||||
problem = _("bad MX preference");
|
||||
}
|
||||
|
||||
if (!canonicalise_opt(arg) || (comma && !canonicalise_opt(comma)))
|
||||
if (!(name = canonicalise_opt(arg)) ||
|
||||
(comma && !(target = canonicalise_opt(comma))))
|
||||
problem = _("bad MX name");
|
||||
|
||||
|
||||
new = opt_malloc(sizeof(struct mx_srv_record));
|
||||
new->next = daemon->mxnames;
|
||||
daemon->mxnames = new;
|
||||
new->issrv = 0;
|
||||
new->name = opt_string_alloc(arg);
|
||||
new->target = opt_string_alloc(comma); /* may be NULL */
|
||||
new->name = name;
|
||||
new->target = target; /* may be NULL */
|
||||
new->weight = pref;
|
||||
break;
|
||||
}
|
||||
|
||||
case 't': /* --mx-target */
|
||||
if (!canonicalise_opt(arg))
|
||||
if (!(daemon->mxtarget = canonicalise_opt(arg)))
|
||||
problem = _("bad MX target");
|
||||
else
|
||||
daemon->mxtarget = opt_string_alloc(arg);
|
||||
break;
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
@@ -1161,8 +1208,10 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
break;
|
||||
|
||||
case '6': /* --dhcp-script */
|
||||
# ifdef NO_FORK
|
||||
# if defined(NO_FORK)
|
||||
problem = _("cannot run scripts under uClinux");
|
||||
# elif !defined(HAVE_SCRIPT)
|
||||
problem = _("recompile with HAVE_SCRIPT defined to enable lease-change scripts");
|
||||
# else
|
||||
daemon->lease_change_command = opt_string_alloc(arg);
|
||||
# endif
|
||||
@@ -1186,12 +1235,12 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
daemon->options |= OPT_RESOLV_DOMAIN;
|
||||
else
|
||||
{
|
||||
char *d;
|
||||
comma = split(arg);
|
||||
if (!canonicalise_opt(arg))
|
||||
if (!(d = canonicalise_opt(arg)))
|
||||
option = '?';
|
||||
else
|
||||
{
|
||||
char *d = opt_string_alloc(arg);
|
||||
if (comma)
|
||||
{
|
||||
struct cond_domain *new = safe_malloc(sizeof(struct cond_domain));
|
||||
@@ -1346,10 +1395,8 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
/* # matches everything and becomes a zero length domain string */
|
||||
if (strcmp(arg, "#") == 0)
|
||||
domain = "";
|
||||
else if (!canonicalise_opt(arg) && strlen(arg) != 0)
|
||||
else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
|
||||
option = '?';
|
||||
else
|
||||
domain = opt_string_alloc(arg); /* NULL if strlen is zero */
|
||||
serv = opt_malloc(sizeof(struct server));
|
||||
memset(serv, 0, sizeof(struct server));
|
||||
serv->next = newlist;
|
||||
@@ -1662,7 +1709,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
if (!(a[k] = split(a[k-1])))
|
||||
break;
|
||||
|
||||
if (option == '?' || (k < 2) || ((new->start.s_addr = inet_addr(a[0])) == (in_addr_t)-1))
|
||||
if ((k < 2) || ((new->start.s_addr = inet_addr(a[0])) == (in_addr_t)-1))
|
||||
option = '?';
|
||||
else if (strcmp(a[1], "static") == 0)
|
||||
{
|
||||
@@ -1860,15 +1907,12 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
new->flags |= CONFIG_DISABLE;
|
||||
else
|
||||
{
|
||||
int len = strlen(a[j]) + 1;
|
||||
if (!canonicalise_opt(a[j]))
|
||||
if (!(new->hostname = canonicalise_opt(a[j])) ||
|
||||
!legal_hostname(new->hostname))
|
||||
problem = _("bad DHCP host name");
|
||||
else if ((new->hostname = opt_malloc(len)))
|
||||
{
|
||||
new->flags |= CONFIG_NAME;
|
||||
strcpy(new->hostname, a[j]);
|
||||
new->domain = NULL;
|
||||
}
|
||||
else
|
||||
new->flags |= CONFIG_NAME;
|
||||
new->domain = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1983,6 +2027,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
|
||||
new->next = daemon->dhcp_opts;
|
||||
daemon->dhcp_opts = new;
|
||||
daemon->enable_pxe = 1;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -2051,6 +2096,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
s->next = new;
|
||||
}
|
||||
|
||||
daemon->enable_pxe = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2243,19 +2289,20 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
case LOPT_INTNAME: /* --interface-name */
|
||||
{
|
||||
struct interface_name *new, **up;
|
||||
|
||||
char *domain = NULL;
|
||||
|
||||
comma = split(arg);
|
||||
|
||||
if (!comma || !canonicalise_opt(arg))
|
||||
if (!comma || !(domain = canonicalise_opt(arg)))
|
||||
problem = _("bad interface name");
|
||||
|
||||
|
||||
new = opt_malloc(sizeof(struct interface_name));
|
||||
new->next = NULL;
|
||||
/* Add to the end of the list, so that first name
|
||||
of an interface is used for PTR lookups. */
|
||||
for (up = &daemon->int_names; *up; up = &((*up)->next));
|
||||
*up = new;
|
||||
new->name = opt_string_alloc(arg);
|
||||
new->name = domain;
|
||||
new->intr = opt_string_alloc(comma);
|
||||
break;
|
||||
}
|
||||
@@ -2268,14 +2315,22 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
option = '?';
|
||||
else
|
||||
{
|
||||
for (new = daemon->cnames; new; new = new->next)
|
||||
if (hostname_isequal(new->alias, arg))
|
||||
problem = _("duplicate CNAME");
|
||||
new = opt_malloc(sizeof(struct cname));
|
||||
new->next = daemon->cnames;
|
||||
daemon->cnames = new;
|
||||
new->alias = opt_string_alloc(arg);
|
||||
new->target = opt_string_alloc(comma);
|
||||
char *alias = canonicalise_opt(arg);
|
||||
char *target = canonicalise_opt(comma);
|
||||
|
||||
if (!alias || !target)
|
||||
problem = _("bad CNAME");
|
||||
else
|
||||
{
|
||||
for (new = daemon->cnames; new; new = new->next)
|
||||
if (hostname_isequal(new->alias, arg))
|
||||
problem = _("duplicate CNAME");
|
||||
new = opt_malloc(sizeof(struct cname));
|
||||
new->next = daemon->cnames;
|
||||
daemon->cnames = new;
|
||||
new->alias = alias;
|
||||
new->target = target;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2283,19 +2338,21 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
case LOPT_PTR: /* --ptr-record */
|
||||
{
|
||||
struct ptr_record *new;
|
||||
|
||||
char *dom, *target = NULL;
|
||||
|
||||
comma = split(arg);
|
||||
|
||||
if (!canonicalise_opt(arg))
|
||||
if (!(dom = canonicalise_opt(arg)) ||
|
||||
(comma && !(target = canonicalise_opt(comma))))
|
||||
problem = _("bad PTR record");
|
||||
|
||||
new = opt_malloc(sizeof(struct ptr_record));
|
||||
new->next = daemon->ptr;
|
||||
daemon->ptr = new;
|
||||
new->name = opt_string_alloc(arg);
|
||||
new->ptr = NULL;
|
||||
if (comma)
|
||||
new->ptr = opt_string_alloc(comma);
|
||||
else
|
||||
{
|
||||
new = opt_malloc(sizeof(struct ptr_record));
|
||||
new->next = daemon->ptr;
|
||||
daemon->ptr = new;
|
||||
new->name = dom;
|
||||
new->ptr = target;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2305,6 +2362,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
int k = 0;
|
||||
struct naptr *new;
|
||||
int order, pref;
|
||||
char *name, *replace = NULL;
|
||||
|
||||
if ((a[0] = arg))
|
||||
for (k = 1; k < 7; k++)
|
||||
@@ -2313,22 +2371,21 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
|
||||
|
||||
if (k < 6 ||
|
||||
!canonicalise_opt(a[0]) ||
|
||||
!(name = canonicalise_opt(a[0])) ||
|
||||
!atoi_check16(a[1], &order) ||
|
||||
!atoi_check16(a[2], &pref) ||
|
||||
(k == 7 && !canonicalise_opt(a[6])))
|
||||
(k == 7 && !(replace = canonicalise_opt(a[6]))))
|
||||
problem = _("bad NAPTR record");
|
||||
else
|
||||
{
|
||||
new = opt_malloc(sizeof(struct naptr));
|
||||
new->next = daemon->naptr;
|
||||
daemon->naptr = new;
|
||||
new->name = opt_string_alloc(a[0]);
|
||||
new->name = name;
|
||||
new->flags = opt_string_alloc(a[3]);
|
||||
new->services = opt_string_alloc(a[4]);
|
||||
new->regexp = opt_string_alloc(a[5]);
|
||||
if (k == 7)
|
||||
new->replace = opt_string_alloc(a[6]);
|
||||
new->replace = replace;
|
||||
new->order = order;
|
||||
new->pref = pref;
|
||||
}
|
||||
@@ -2345,12 +2402,6 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
|
||||
gen_prob = _("TXT record string too long");
|
||||
|
||||
if (!canonicalise_opt(arg))
|
||||
{
|
||||
problem = _("bad TXT record");
|
||||
break;
|
||||
}
|
||||
|
||||
if ((q = (unsigned char *)comma))
|
||||
while (1)
|
||||
{
|
||||
@@ -2394,7 +2445,13 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
/* ensure arg is terminated */
|
||||
if (comma)
|
||||
*comma = 0;
|
||||
new->name = opt_string_alloc(arg);
|
||||
|
||||
if (!(new->name = canonicalise_opt(arg)))
|
||||
{
|
||||
problem = _("bad TXT record");
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2406,19 +2463,16 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
|
||||
comma = split(arg);
|
||||
|
||||
if (!canonicalise_opt(arg))
|
||||
if (!(name = canonicalise_opt(arg)))
|
||||
problem = _("bad SRV record");
|
||||
|
||||
name = opt_string_alloc(arg);
|
||||
|
||||
if (comma)
|
||||
{
|
||||
arg = comma;
|
||||
comma = split(arg);
|
||||
if (!canonicalise_opt(arg))
|
||||
problem = _("bad SRV target");
|
||||
if (!(target = canonicalise_opt(arg))
|
||||
) problem = _("bad SRV target");
|
||||
|
||||
target = opt_string_alloc(arg);
|
||||
if (comma)
|
||||
{
|
||||
arg = comma;
|
||||
@@ -2683,7 +2737,7 @@ void reread_dhcp(void)
|
||||
}
|
||||
|
||||
one_file(daemon->dhcp_hosts_file, 1, LOPT_BANK);
|
||||
my_syslog(LOG_INFO, _("read %s"), daemon->dhcp_hosts_file);
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("read %s"), daemon->dhcp_hosts_file);
|
||||
}
|
||||
|
||||
if (daemon->dhcp_opts_file)
|
||||
@@ -2714,7 +2768,7 @@ void reread_dhcp(void)
|
||||
}
|
||||
|
||||
one_file(daemon->dhcp_opts_file, 1, LOPT_OPTS);
|
||||
my_syslog(LOG_INFO, _("read %s"), daemon->dhcp_opts_file);
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("read %s"), daemon->dhcp_opts_file);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -2898,8 +2952,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
||||
continue;
|
||||
|
||||
if ((token = strtok(NULL, " \t\n\r")) &&
|
||||
canonicalise_opt(token) &&
|
||||
(daemon->domain_suffix = opt_string_alloc(token)))
|
||||
(daemon->domain_suffix = canonicalise_opt(token)))
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -138,7 +138,8 @@ static int extract_name(HEADER *header, size_t plen, unsigned char **pp,
|
||||
for(j=0; j<l; j++, p++)
|
||||
if (isExtract)
|
||||
{
|
||||
if (legal_char(*p))
|
||||
unsigned char c = *p;
|
||||
if (isascii(c) && !iscntrl(c) && c != '.')
|
||||
*cp++ = *p;
|
||||
else
|
||||
return 0;
|
||||
|
||||
@@ -415,7 +415,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
|
||||
if (match_netid(id_list->list, netid, 0))
|
||||
message = _("disabled");
|
||||
message = _("ignored");
|
||||
|
||||
if (!message)
|
||||
{
|
||||
@@ -536,7 +536,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
*pq = 0;
|
||||
|
||||
if (canonicalise(daemon->dhcp_buff))
|
||||
if (legal_hostname(daemon->dhcp_buff))
|
||||
offer_hostname = client_hostname = daemon->dhcp_buff;
|
||||
}
|
||||
else if ((opt = option_find(mess, sz, OPTION_HOSTNAME, 1)))
|
||||
@@ -550,7 +550,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
borken_opt = 1;
|
||||
else
|
||||
daemon->dhcp_buff[len] = 0;
|
||||
if (canonicalise(daemon->dhcp_buff))
|
||||
if (legal_hostname(daemon->dhcp_buff))
|
||||
client_hostname = daemon->dhcp_buff;
|
||||
}
|
||||
|
||||
@@ -708,7 +708,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
clid = NULL;
|
||||
|
||||
/* Check if client is PXE client. */
|
||||
if ((opt = option_find(mess, sz, OPTION_VENDOR_ID, 9)) &&
|
||||
if (daemon->enable_pxe &&
|
||||
(opt = option_find(mess, sz, OPTION_VENDOR_ID, 9)) &&
|
||||
strncmp(option_ptr(opt, 0), "PXEClient", 9) == 0)
|
||||
{
|
||||
if ((opt = option_find(mess, sz, OPTION_PXE_UUID, 17)))
|
||||
@@ -728,6 +729,9 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
unsigned char save71[4];
|
||||
struct dhcp_opt opt71;
|
||||
|
||||
if (ignore)
|
||||
return 0;
|
||||
|
||||
if (layer & 0x8000)
|
||||
{
|
||||
my_syslog(MS_DHCP | LOG_ERR, _("PXE BIS not supported"));
|
||||
@@ -807,8 +811,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
prune_vendor_opts(netid);
|
||||
do_encap_opts(pxe_opts(pxearch, netid), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
|
||||
|
||||
log_packet("PXE", NULL, emac, emac_len, iface_name, "proxy", mess->xid);
|
||||
return dhcp_packet_size(mess, netid, agent_id, real_end);
|
||||
log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy" : "proxy-ignored", mess->xid);
|
||||
return ignore ? 0 : dhcp_packet_size(mess, netid, agent_id, real_end);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1133,6 +1137,9 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
{
|
||||
if (do_classes)
|
||||
{
|
||||
if (mess->giaddr.s_addr)
|
||||
lease->giaddr = mess->giaddr;
|
||||
|
||||
lease->changed = 1;
|
||||
/* copy user-class and vendor class into new lease, for the script */
|
||||
if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
|
||||
@@ -1162,6 +1169,18 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
lease->vendorclass_len = len+1;
|
||||
}
|
||||
}
|
||||
if ((opt = option_find(mess, sz, OPTION_HOSTNAME, 1)))
|
||||
{
|
||||
int len = option_len(opt);
|
||||
unsigned char *ucp = option_ptr(opt, 0);
|
||||
free(lease->supplied_hostname);
|
||||
if ((lease->supplied_hostname = whine_malloc(len+1)))
|
||||
{
|
||||
memcpy(lease->supplied_hostname, ucp, len);
|
||||
lease->supplied_hostname[len] = 0;
|
||||
lease->supplied_hostname_len = len+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hostname_auth && (client_hostname = host_from_dns(mess->yiaddr)))
|
||||
@@ -1538,7 +1557,6 @@ static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *neti
|
||||
/* move agent_id back down to the end of the packet */
|
||||
if (agent_id)
|
||||
{
|
||||
unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
|
||||
memmove(p, agent_id, real_end - agent_id);
|
||||
p += real_end - agent_id;
|
||||
memset(p, 0, real_end - p); /* in case of overlap */
|
||||
@@ -1547,9 +1565,8 @@ static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *neti
|
||||
/* We do logging too */
|
||||
if (netid && (daemon->options & OPT_LOG_OPTS))
|
||||
{
|
||||
char *p = daemon->namebuff;
|
||||
*p = 0;
|
||||
for (; netid; netid = netid->next)
|
||||
char *s = daemon->namebuff;
|
||||
for (*s = 0; netid; netid = netid->next)
|
||||
{
|
||||
/* kill dupes. */
|
||||
for (n = netid->next; n; n = n->next)
|
||||
@@ -1558,13 +1575,12 @@ static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *neti
|
||||
|
||||
if (!n)
|
||||
{
|
||||
strncat (p, netid->net, MAXDNAME);
|
||||
strncat (s, netid->net, (MAXDNAME-1) - strlen(s));
|
||||
if (netid->next)
|
||||
strncat (p, ", ", MAXDNAME);
|
||||
strncat (s, ", ", (MAXDNAME-1) - strlen(s));
|
||||
}
|
||||
}
|
||||
p[MAXDNAME - 1] = 0;
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("%u tags: %s"), ntohl(mess->xid), p);
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("%u tags: %s"), ntohl(mess->xid), s);
|
||||
}
|
||||
|
||||
/* add END options to the regions. */
|
||||
@@ -2074,21 +2090,26 @@ static void do_options(struct dhcp_context *context,
|
||||
}
|
||||
else
|
||||
/* Use the values of the relevant options if no dhcp-boot given and
|
||||
they're not explicitly asked for as options. */
|
||||
they're not explicitly asked for as options. OPTION_END is used
|
||||
as an internal way to specify siaddr without using dhcp-boot, for use in
|
||||
dhcp-optsfile. */
|
||||
{
|
||||
if ((!req_options || !in_list(req_options, OPTION_FILENAME)) && mess->file[0] == 0 &&
|
||||
(opt = option_find2(netid, config_opts, OPTION_FILENAME)))
|
||||
(opt = option_find2(netid, config_opts, OPTION_FILENAME)) && !(opt->flags & DHOPT_FORCE))
|
||||
{
|
||||
strncpy((char *)mess->file, (char *)opt->val, sizeof(mess->file)-1);
|
||||
done_file = 1;
|
||||
}
|
||||
|
||||
if ((!req_options || !in_list(req_options, OPTION_SNAME)) &&
|
||||
(opt = option_find2(netid, config_opts, OPTION_SNAME)))
|
||||
(opt = option_find2(netid, config_opts, OPTION_SNAME)) && !(opt->flags & DHOPT_FORCE))
|
||||
{
|
||||
strncpy((char *)mess->sname, (char *)opt->val, sizeof(mess->sname)-1);
|
||||
done_server = 1;
|
||||
}
|
||||
|
||||
if ((opt = option_find2(netid, config_opts, OPTION_END)))
|
||||
mess->siaddr.s_addr = ((struct in_addr *)opt->val)->s_addr;
|
||||
}
|
||||
|
||||
/* We don't want to do option-overload for BOOTP, so make the file and sname
|
||||
|
||||
24
src/tftp.c
24
src/tftp.c
@@ -46,12 +46,13 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
struct sockaddr_in addr, peer;
|
||||
struct msghdr msg;
|
||||
struct iovec iov;
|
||||
int is_err = 1, if_index = 0;
|
||||
struct ifreq ifr;
|
||||
int is_err = 1, if_index = 0, mtu = 0;
|
||||
struct iname *tmp;
|
||||
struct tftp_transfer *transfer;
|
||||
int port = daemon->start_tftp_port; /* may be zero to use ephemeral port */
|
||||
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
|
||||
int mtu = IP_PMTUDISC_DONT;
|
||||
int mtuflag = IP_PMTUDISC_DONT;
|
||||
#endif
|
||||
|
||||
union {
|
||||
@@ -83,7 +84,10 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
return;
|
||||
|
||||
if (daemon->options & OPT_NOWILD)
|
||||
addr = listen->iface->addr.in;
|
||||
{
|
||||
addr = listen->iface->addr.in;
|
||||
mtu = listen->iface->mtu;
|
||||
}
|
||||
else
|
||||
{
|
||||
char name[IF_NAMESIZE];
|
||||
@@ -125,7 +129,10 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && (strcmp(tmp->name, name) == 0))
|
||||
return;
|
||||
|
||||
|
||||
strncpy(name, ifr.ifr_name, IF_NAMESIZE);
|
||||
if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
|
||||
mtu = ifr.ifr_mtu;
|
||||
}
|
||||
|
||||
addr.sin_port = htons(port);
|
||||
@@ -158,7 +165,7 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
{
|
||||
if (bind(transfer->sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1 ||
|
||||
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
|
||||
setsockopt(transfer->sockfd, SOL_IP, IP_MTU_DISCOVER, &mtu, sizeof(mtu)) == -1 ||
|
||||
setsockopt(transfer->sockfd, SOL_IP, IP_MTU_DISCOVER, &mtuflag, sizeof(mtuflag)) == -1 ||
|
||||
#endif
|
||||
!fix_fd(transfer->sockfd))
|
||||
{
|
||||
@@ -202,6 +209,9 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
transfer->blocksize = 1;
|
||||
if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4)
|
||||
transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4;
|
||||
/* 32 bytes for IP, UDP and TFTP headers */
|
||||
if (mtu != 0 && transfer->blocksize > (unsigned)mtu - 32)
|
||||
transfer->blocksize = (unsigned)mtu - 32;
|
||||
transfer->opt_blocksize = 1;
|
||||
transfer->block = 0;
|
||||
}
|
||||
@@ -213,6 +223,10 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
}
|
||||
}
|
||||
|
||||
/* cope with backslashes from windows boxen. */
|
||||
while ((p = strchr(filename, '\\')))
|
||||
*p = '/';
|
||||
|
||||
strcpy(daemon->namebuff, "/");
|
||||
if (daemon->tftp_prefix)
|
||||
{
|
||||
|
||||
117
src/util.c
117
src/util.c
@@ -24,6 +24,9 @@
|
||||
#include <sys/times.h>
|
||||
#endif
|
||||
|
||||
#ifdef LOCALEDIR
|
||||
#include <idna.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ARC4RANDOM
|
||||
void rand_init(void)
|
||||
@@ -95,48 +98,110 @@ unsigned short rand16(void)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
int legal_char(char c)
|
||||
static int check_name(char *in)
|
||||
{
|
||||
/* check for legal char a-z A-Z 0-9 -
|
||||
(also / , used for RFC2317 and _ used in windows queries
|
||||
and space, for DNS-SD stuff) */
|
||||
if ((c >= 'A' && c <= 'Z') ||
|
||||
(c >= 'a' && c <= 'z') ||
|
||||
(c >= '0' && c <= '9') ||
|
||||
c == '-' || c == '/' || c == '_' || c == ' ')
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int canonicalise(char *s)
|
||||
{
|
||||
/* check for legal chars and remove trailing .
|
||||
/* remove trailing .
|
||||
also fail empty string and label > 63 chars */
|
||||
size_t dotgap = 0, l = strlen(s);
|
||||
size_t dotgap = 0, l = strlen(in);
|
||||
char c;
|
||||
int nowhite = 0;
|
||||
|
||||
|
||||
if (l == 0 || l > MAXDNAME) return 0;
|
||||
|
||||
if (s[l-1] == '.')
|
||||
|
||||
if (in[l-1] == '.')
|
||||
{
|
||||
if (l == 1) return 0;
|
||||
s[l-1] = 0;
|
||||
in[l-1] = 0;
|
||||
}
|
||||
|
||||
while ((c = *s))
|
||||
for (; (c = *in); in++)
|
||||
{
|
||||
if (c == '.')
|
||||
dotgap = 0;
|
||||
else if (!legal_char(c) || (++dotgap > MAXLABEL))
|
||||
else if (++dotgap > MAXLABEL)
|
||||
return 0;
|
||||
else if (isascii(c) && iscntrl(c))
|
||||
/* iscntrl only gives expected results for ascii */
|
||||
return 0;
|
||||
#ifndef LOCALEDIR
|
||||
else if (!isascii(c))
|
||||
return 0;
|
||||
#endif
|
||||
else if (c != ' ')
|
||||
nowhite = 1;
|
||||
s++;
|
||||
}
|
||||
return nowhite;
|
||||
|
||||
if (!nowhite)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Hostnames have a more limited valid charset than domain names
|
||||
so check for legal char a-z A-Z 0-9 - _
|
||||
Note that this may receive a FQDN, so only check the first label
|
||||
for the tighter criteria. */
|
||||
int legal_hostname(char *name)
|
||||
{
|
||||
char c;
|
||||
|
||||
if (!check_name(name))
|
||||
return 0;
|
||||
|
||||
for (; (c = *name); name++)
|
||||
/* check for legal char a-z A-Z 0-9 - _ . */
|
||||
{
|
||||
if ((c >= 'A' && c <= 'Z') ||
|
||||
(c >= 'a' && c <= 'z') ||
|
||||
(c >= '0' && c <= '9') ||
|
||||
c == '-' || c == '_')
|
||||
continue;
|
||||
|
||||
/* end of hostname part */
|
||||
if (c == '.')
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *canonicalise(char *in, int *nomem)
|
||||
{
|
||||
char *ret = NULL;
|
||||
#ifdef LOCALEDIR
|
||||
int rc;
|
||||
#endif
|
||||
|
||||
if (nomem)
|
||||
*nomem = 0;
|
||||
|
||||
if (!check_name(in))
|
||||
return NULL;
|
||||
|
||||
#ifdef LOCALEDIR
|
||||
if ((rc = idna_to_ascii_lz(in, &ret, 0)) != IDNA_SUCCESS)
|
||||
{
|
||||
if (ret)
|
||||
free(ret);
|
||||
|
||||
if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR))
|
||||
{
|
||||
my_syslog(LOG_ERR, _("failed to allocate memory"));
|
||||
*nomem = 1;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
if ((ret = whine_malloc(strlen(in)+1)))
|
||||
strcpy(ret, in);
|
||||
else if (nomem)
|
||||
*nomem = 1;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
|
||||
|
||||
Reference in New Issue
Block a user