+If the current hostname contains dots then send it as a FQDN.
Ensure that static routes are always added before routers.
Use getnameinfo instead of gethostbyaddr.
Remove gateways from the ROUTES and add to GATEWAYS
-VERSION = 3.0.18_pre1
+VERSION = 3.0.18_pre2
CFLAGS ?= -O2 -pipe
# Should work for both GNU make and BSD make
(ap)->ar_hln + (ap)->ar_pln)
#define ar_tpa(ap) (((unsigned char *) ((ap) + 1)) + \
2 * (ap)->ar_hln + (ap)->ar_pln)
+#endif
+
+#ifndef arphdr_len
#define arphdr_len2(ar_hln, ar_pln) (sizeof (struct arphdr) + \
2 * (ar_hln) + 2 * (ar_pln))
#define arphdr_len(ap) (arphdr_len2 ((ap)->ar_hln, (ap)->ar_pln))
static int daemonise (const char *pidfile)
{
logger (LOG_DEBUG, "forking to background");
+
if (daemon (0, 0) < 0) {
logger (LOG_ERR, "daemon: %s", strerror (errno));
return -1;
return value;
logger (LOG_ERR, "memory exhausted");
- exit (1);
+ exit (EXIT_FAILURE);
+}
+
+char *xstrdup (const char *str)
+{
+ char *value;
+
+ if (! str)
+ return (NULL);
+
+ if ((value = strdup (str)))
+ return (value);
+
+ logger (LOG_ERR, "memory exhausted");
+ exit (EXIT_FAILURE);
}
long uptime (void);
void *xmalloc (size_t size);
-
+char *xstrdup (const char *str);
#endif
make_nis(iface->name, dhcp);
#endif
- /* Now we have made a resolv.conf we can obtain a hostname if we need one */
- if (options->dohostname && ! dhcp->hostname) {
+ /* Now we have made a resolv.conf we can obtain a hostname if we need it */
+ if (options->dohostname && ! dhcp->hostname) {
union {
struct sockaddr sa;
struct sockaddr_in sin;
socklen_t salen;
char addr[NI_MAXHOST];
struct addrinfo hints, *res;
+ int result;
salen = sizeof (struct sockaddr);
memset (&su.sa, 0, salen);
su.sin.sin_family = AF_INET;
memcpy (&su.sin.sin_addr, &dhcp->address, sizeof (struct in_addr));
- if (getnameinfo (&su.sa, salen, addr, sizeof (addr),
- NULL, 0, NI_NAMEREQD) == 0) {
+ logger (LOG_DEBUG, "Looking up hostname via DNS");
+ if ((result = getnameinfo (&su.sa, salen, addr, sizeof (addr),
+ NULL, 0, NI_NAMEREQD)) != 0)
+ logger (LOG_ERR, "Failed to lookup hostname via DNS: %s", gai_strerror (result));
+ else {
+ /* Check for a malicious PTR record */
memset (&hints, 0, sizeof (hints));
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_NUMERICHOST;
- /* Check for a malicious PTR record */
if (getaddrinfo (addr, "0", &hints, &res) == 0) {
freeaddrinfo (res);
addr[0] = '\0';
logger (LOG_ERR, "malicious PTR record detected");
+ } else if (*addr) {
+ /* Strip out the domain if it matches */
+ char *p = addr;
+ char *token = strsep (&p, ".");
+ bool match_domain = false;
+
+ if (p && *p) {
+ if (dhcp->dnssearch) {
+ char *s = xstrdup (dhcp->dnssearch);
+ char *sp = s;
+ char *t;
+
+ while ((t = strsep (&sp, " ")))
+ if (strcmp (t, p) == 0) {
+ match_domain = true;
+ break;
+ }
+ free (s);
+ } else if (dhcp->dnsdomain) {
+ if (strcmp (dhcp->dnsdomain, p) == 0)
+ match_domain = true;
+ }
+ }
+ if (match_domain)
+ strlcpy (newhostname, token, sizeof (newhostname));
+ else
+ snprintf (newhostname, sizeof (newhostname), "%s.%s", token, p);
}
}
-
- /* Split the hostname from the domain */
- if (addr[0]) {
- char *p = addr;
- char *token = strsep (&p, ".");
- if (token)
- strlcpy (newhostname, token, sizeof (newhostname));
- } else
- logger (LOG_ERR, "failed to lookup the hostname");
}
gethostname (curhostname, sizeof (curhostname));
char prefix[IF_NAMESIZE + 3];
pid_t pid;
int debug = 0;
+ int i;
const struct option longopts[] = {
{"arp", no_argument, NULL, 'a'},
{NULL, 0, NULL, 0}
};
- /* Sanitize our fd's */
- int zero;
- if ((zero = open (_PATH_DEVNULL, O_RDWR, 0)) >= 0) {
- while (zero < 3)
- zero = dup (zero);
- close(zero);
- }
+ /* Close any un-needed fd's */
+ for (i = getdtablesize() - 1; i >= 3; --i)
+ close (i);
openlog (PACKAGE, LOG_PID, LOG_LOCAL0);
options.dontp = true;
options.dogateway = true;
options.daemonise = true;
- gethostname (options.hostname, sizeof (options.hostname));
- if (strcmp (options.hostname, "(none)") == 0 ||
- strcmp (options.hostname, "localhost") == 0)
- memset (options.hostname, 0, sizeof (options.hostname));
options.timeout = DEFAULT_TIMEOUT;
while ((ch = getopt_long(argc, argv, "ac:dh:i:kl:m:nps:t:u:F:GHI:MNRY", longopts,
break;
case 'u':
{
- int i;
int offset = 0;
for (i = 0; i < userclasses; i++)
offset += (int) options.userclass[offset] + 1;
}
break;
case 'F':
- if (strcmp (optarg, "none") == 0)
+ if (strncmp (optarg, "none", strlen (optarg)) == 0)
options.fqdn = FQDN_NONE;
- else if (strcmp (optarg, "ptr") == 0)
+ else if (strncmp (optarg, "ptr", strlen (optarg)) == 0)
options.fqdn = FQDN_PTR;
- else if (strcmp (optarg, "both") == 0)
+ else if (strncmp (optarg, "both", strlen (optarg)) == 0)
options.fqdn = FQDN_BOTH;
else {
logger (LOG_ERR, "invalid value `%s' for FQDN", optarg);
exit (EXIT_FAILURE);
}
+ /* If we are given a hostname use it and set FQDN if it contains a . */
+ if (! options.hostname[0]) {
+ gethostname (options.hostname, sizeof (options.hostname));
+ if (strcmp (options.hostname, "(none)") == 0 ||
+ strcmp (options.hostname, "localhost") == 0)
+ memset (options.hostname, 0, sizeof (options.hostname));
+ }
+ if (strchr (options.hostname, '.')) {
+ if (options.fqdn == FQDN_DISABLE)
+ options.fqdn = FQDN_BOTH;
+ } else
+ options.fqdn = FQDN_DISABLE;
+
if (geteuid ()) {
logger (LOG_ERR, "you need to be root to run "PACKAGE);
exit (EXIT_FAILURE);
/* Do something with metric to satisfy compiler warnings */
metric = 0;
- dstd = strdup (inet_ntoa (destination));
+ dstd = xstrdup (inet_ntoa (destination));
if (gateway.s_addr == destination.s_addr)
logger (LOG_INFO, "%s route to %s/%d",
change ? "changing" : del ? "removing" : "adding",
if (! ifname)
return -1;
- dstd = strdup (inet_ntoa (destination));
- gend = strdup (inet_ntoa (netmask));
+ dstd = xstrdup (inet_ntoa (destination));
+ gend = xstrdup (inet_ntoa (netmask));
if (gateway.s_addr == destination.s_addr)
logger (LOG_INFO, "%s route to %s (%s) metric %d",
change ? "changing" : del ? "removing" : "adding",
fprintf (f, "%s, %s", syslog_level_msg[level], logprefix);
vfprintf (f, fmt, p);
fputc ('\n', f);
+
+ /* stdout, stderr may be re-directed to some kind of buffer.
+ * So we always flush to ensure it's written. */
+ fflush (f);
}
if (level < LOG_DEBUG || level <= loglevel) {
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/uio.h>
+#include <net/if.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#ifndef __OpenBSD__
#include <net/ethernet.h>
#endif
#include <netinet/udp.h>
-#ifndef __linux__
-#include <net/if_types.h>
-#endif
-#include <net/if.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>