+Reduce stack usage by using malloc more.
If we're on a different subnet from the one we get DHCP for, don't
use our current address in messages. Thanks to Wilson Callan.
Skip over bogus EINTR error on select when arp checking for a
{
FILE *f;
struct stat buf;
- char resolvconf[PATH_MAX] = {0};
+ char *resolvconf = NULL;
address_t *address;
#ifdef RESOLVCONF
if (stat (RESOLVCONF, &buf) == 0) {
logger (LOG_DEBUG, "sending DNS information to resolvconf");
- snprintf (resolvconf, PATH_MAX, RESOLVCONF" -a %s", ifname);
+ asprintf (&resolvconf, RESOLVCONF" -a %s", ifname);
f = popen (resolvconf, "w");
+ free (resolvconf);
if (! f)
logger (LOG_ERR, "popen: %s", strerror (errno));
for (address = dhcp->dnsservers; address; address = address->next)
fprintf (f, "nameserver %s\n", inet_ntoa (address->address));
- if (*resolvconf)
+ if (resolvconf)
pclose (f);
else
fclose (f);
return (0);
}
-static void restore_resolv(const char *ifname)
+static void restore_resolv (const char *ifname)
{
#ifdef RESOLVCONF
struct stat buf;
}
#ifdef ENABLE_NTP
+#define BUFFERSIZE 1024
static int _make_ntp (const char *file, const char *ifname, const dhcp_t *dhcp)
{
FILE *f;
address_t *address;
char *a;
- char buffer[1024];
+ char *buffer;
int tomatch = 0;
char *token;
bool ntp = false;
return -1;
}
} else {
- memset (buffer, 0, sizeof (buffer));
- while (fgets (buffer, sizeof (buffer), f)) {
+ buffer = xmalloc (sizeof (char *) * BUFFERSIZE);
+ memset (buffer, 0, BUFFERSIZE);
+ while (fgets (buffer, BUFFERSIZE, f)) {
a = buffer;
token = strsep (&a, " ");
if (! token || strcmp (token, "server") != 0)
if (tomatch == 0)
break;
}
+ free (buffer);
fclose (f);
/* File has the same name servers that we do, so no need to restart ntp */
#endif
#ifdef ENABLE_NIS
+#define PREFIXSIZE 256
static int make_nis (const char *ifname, const dhcp_t *dhcp)
{
FILE *f;
address_t *address;
- char prefix[256] = {0};
+ char *prefix;
logger (LOG_DEBUG, "writing "NISFILE);
if (! (f = fopen(NISFILE, "w"))) {
return -1;
}
+ prefix = xmalloc (sizeof (char *) * PREFIXSIZE);
+ *prefix = '\0';
fprintf (f, "# Generated by dhcpcd for interface %s\n", ifname);
+
if (dhcp->nisdomain) {
setdomainname (dhcp->nisdomain, strlen (dhcp->nisdomain));
if (dhcp->nisservers)
- snprintf (prefix, sizeof (prefix), "domain %s server", dhcp->nisdomain);
+ snprintf (prefix, PREFIXSIZE, "domain %s server", dhcp->nisdomain);
else
fprintf (f, "domain %s broadcast\n", dhcp->nisdomain);
}
else
- snprintf (prefix, sizeof (prefix), "%s", "ypserver");
+ snprintf (prefix, PREFIXSIZE, "%s", "ypserver");
for (address = dhcp->nisservers; address; address = address->next)
fprintf (f, "%s %s\n", prefix, inet_ntoa (address->address));
+ free (prefix);
fclose (f);
exec_cmd (NISSERVICE, NISRESTARTARGS, (char *) NULL);
route_t *route = NULL;
route_t *new_route = NULL;
route_t *old_route = NULL;
- char newhostname[MAXHOSTNAMELEN] = {0};
- char curhostname[MAXHOSTNAMELEN] = {0};
+ char *newhostname = NULL;
+ char *curhostname = NULL;
if (! options || ! iface || ! dhcp)
return (-1);
make_nis(iface->name, dhcp);
#endif
+ curhostname = xmalloc (sizeof (char *) * MAXHOSTNAMELEN);
+ *curhostname = '\0';
+ newhostname = xmalloc (sizeof (char *) * MAXHOSTNAMELEN);
+ *newhostname = '\0';
+
/* Now we have made a resolv.conf we can obtain a hostname if we need it */
if (options->dohostname && (! dhcp->hostname || options->dohostname > 3)) {
union {
struct sockaddr_in sin;
} su;
socklen_t salen;
- char addr[NI_MAXHOST];
+ char *addr;
struct addrinfo hints, *res;
int result;
+ addr = xmalloc (sizeof (char *) * NI_MAXHOST);
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));
logger (LOG_DEBUG, "Looking up hostname via DNS");
- if ((result = getnameinfo (&su.sa, salen, addr, sizeof (addr),
+ if ((result = getnameinfo (&su.sa, salen, addr, NI_MAXHOST,
NULL, 0, NI_NAMEREQD)) != 0)
logger (LOG_ERR, "Failed to lookup hostname via DNS: %s", gai_strerror (result));
else {
break;
}
}
- strlcpy (newhostname, addr, sizeof (newhostname));
+ strlcpy (newhostname, addr, MAXHOSTNAMELEN);
}
}
+ free (addr);
}
- gethostname (curhostname, sizeof (curhostname));
+ gethostname (curhostname, MAXHOSTNAMELEN);
if (options->dohostname
|| strlen (curhostname) == 0
|| strcmp (curhostname, "localhost") == 0)
{
if (dhcp->hostname)
- strlcpy (newhostname, dhcp->hostname, sizeof (newhostname));
+ strlcpy (newhostname, dhcp->hostname, MAXHOSTNAMELEN);
if (*newhostname) {
logger (LOG_INFO, "setting hostname to `%s'", newhostname);
sethostname (newhostname, strlen (newhostname));
}
}
+
+ free (curhostname);
+ free (newhostname);
#ifdef ENABLE_INFO
if (! dhcp->frominfo)
unsigned long xid, char type,
const options_t *options)
{
- dhcpmessage_t message;
- struct udp_dhcp_packet packet;
- unsigned char *m = (unsigned char *) &message;
- unsigned char *p = (unsigned char *) &message.options;
+ struct udp_dhcp_packet *packet;
+ dhcpmessage_t *message;
+ unsigned char *m;
+ unsigned char *p;
unsigned char *n_params = NULL;
unsigned long l;
struct in_addr from;
uint32_t ul;
uint16_t sz;
unsigned int message_length;
+ size_t retval;
if (!iface || !options || !dhcp)
return -1;
if (type == DHCP_RELEASE)
to.s_addr = dhcp->serveraddress.s_addr;
- memset (&message, 0, sizeof (dhcpmessage_t));
+ message = xmalloc (sizeof (dhcpmessage_t));
+ memset (message, 0, sizeof (dhcpmessage_t));
+ m = (unsigned char *) message;
+ p = (unsigned char *) &message->options;
if (type == DHCP_INFORM ||
type == DHCP_RELEASE ||
type == DHCP_REQUEST)
{
- message.ciaddr = iface->previous_address.s_addr;
+ message->ciaddr = iface->previous_address.s_addr;
from.s_addr = iface->previous_address.s_addr;
/* Just incase we haven't actually configured the address yet */
if (type == DHCP_INFORM && iface->previous_address.s_addr == 0)
- message.ciaddr = dhcp->address.s_addr;
-
+ message->ciaddr = dhcp->address.s_addr;
+
/* Zero the address if we're currently on a different subnet */
if (type == DHCP_REQUEST &&
iface->previous_netmask.s_addr != dhcp->netmask.s_addr)
message->ciaddr = from.s_addr = 0;
}
- message.op = DHCP_BOOTREQUEST;
- message.hwtype = iface->family;
+ message->op = DHCP_BOOTREQUEST;
+ message->hwtype = iface->family;
switch (iface->family) {
case ARPHRD_ETHER:
case ARPHRD_IEEE802:
- message.hwlen = ETHER_ADDR_LEN;
- memcpy (&message.chaddr, &iface->hwaddr, ETHER_ADDR_LEN);
+ message->hwlen = ETHER_ADDR_LEN;
+ memcpy (&message->chaddr, &iface->hwaddr, ETHER_ADDR_LEN);
break;
case ARPHRD_IEEE1394:
case ARPHRD_INFINIBAND:
- if (message.ciaddr == 0)
- message.flags = (int16_t) htons (BROADCAST_FLAG);
- message.hwlen = 0;
+ if (message->ciaddr == 0)
+ message->flags = (int16_t) htons (BROADCAST_FLAG);
+ message->hwlen = 0;
break;
default:
logger (LOG_ERR, "dhcp: unknown hardware type %d", iface->family);
}
if (up < 0 || up > UINT16_MAX)
- message.secs = htons ((short) UINT16_MAX);
+ message->secs = htons ((short) UINT16_MAX);
else
- message.secs = htons (up);
- message.xid = xid;
- message.cookie = htonl (MAGIC_COOKIE);
+ message->secs = htons (up);
+ message->xid = xid;
+ message->cookie = htonl (MAGIC_COOKIE);
*p++ = DHCP_MESSAGETYPE;
*p++ = 1;
if (type != DHCP_INFORM) {
#define PUTADDR(_type, _val) \
- { \
- *p++ = _type; \
- *p++ = 4; \
- memcpy (p, &_val.s_addr, 4); \
- p += 4; \
- }
- if (dhcp->address.s_addr != 0 && iface->previous_address.s_addr == 0
- && type != DHCP_RELEASE)
- PUTADDR (DHCP_ADDRESS, dhcp->address);
+ { \
+ *p++ = _type; \
+ *p++ = 4; \
+ memcpy (p, &_val.s_addr, 4); \
+ p += 4; \
+ }
+ if (dhcp->address.s_addr != iface->previous_address.s_addr &&
+ type != DHCP_RELEASE)
+ PUTADDR (DHCP_ADDRESS, dhcp->address);
- if (dhcp->serveraddress.s_addr != 0 && dhcp->address.s_addr !=0 &&
- (iface->previous_address.s_addr == 0 || type == DHCP_RELEASE))
- PUTADDR (DHCP_SERVERIDENTIFIER, dhcp->serveraddress);
+ if (dhcp->serveraddress.s_addr != 0 && dhcp->address.s_addr !=0 &&
+ (iface->previous_address.s_addr == 0 || type == DHCP_RELEASE))
+ PUTADDR (DHCP_SERVERIDENTIFIER, dhcp->serveraddress);
#undef PUTADDR
}
message_length = p - m;
- memset (&packet, 0, sizeof (struct udp_dhcp_packet));
- make_dhcp_packet (&packet, (unsigned char *) &message, message_length,
+ packet = xmalloc (sizeof (struct udp_dhcp_packet));
+ memset (packet, 0, sizeof (struct udp_dhcp_packet));
+ make_dhcp_packet (packet, (unsigned char *) message, message_length,
from, to);
-
- logger (LOG_DEBUG, "sending %s with xid 0x%lx", dhcp_message[(int) type], xid);
- return send_packet (iface, ETHERTYPE_IP, (unsigned char *) &packet,
- message_length + sizeof (struct ip) +
- sizeof (struct udphdr));
+ free (message);
+
+ logger (LOG_DEBUG, "sending %s with xid 0x%lx",
+ dhcp_message[(int) type], xid);
+ retval = send_packet (iface, ETHERTYPE_IP, (unsigned char *) packet,
+ message_length + sizeof (struct ip) +
+ sizeof (struct udphdr));
+ free (packet);
+ return (retval);
}
/* Decode an RFC3397 DNS search order option into a space
#include "logger.h"
#include "version.h"
+static int doversion = 0;
+static int dohelp = 0;
+#define EXTRA_OPTS
+static const struct option longopts[] = {
+ {"arp", no_argument, NULL, 'a'},
+ {"script", required_argument, NULL, 'c'},
+ {"debug", no_argument, NULL, 'd'},
+ {"hostname", optional_argument, NULL, 'h'},
+ {"classid", optional_argument, NULL, 'i'},
+ {"release", no_argument, NULL, 'k'},
+ {"leasetime", required_argument, NULL, 'l'},
+ {"metric", required_argument, NULL, 'm'},
+ {"renew", no_argument, NULL, 'n'},
+ {"persistent", no_argument, NULL, 'p'},
+ {"inform", optional_argument, NULL, 's'},
+ {"request", optional_argument, NULL, 'r'},
+ {"timeout", required_argument, NULL, 't'},
+ {"userclass", required_argument, NULL, 'u'},
+ {"exit", no_argument, NULL, 'x'},
+ {"lastlease", no_argument, NULL, 'E'},
+ {"fqdn", required_argument, NULL, 'F'},
+ {"nogateway", no_argument, NULL, 'G'},
+ {"sethostname", no_argument, NULL, 'H'},
+ {"clientid", optional_argument, NULL, 'I'},
+ {"noipv4ll", no_argument, NULL, 'L'},
+ {"nomtu", no_argument, NULL, 'M'},
+ {"nontp", no_argument, NULL, 'N'},
+ {"nodns", no_argument, NULL, 'R'},
+ {"test", no_argument, NULL, 'T'},
+ {"nonis", no_argument, NULL, 'Y'},
+ {"help", no_argument, &dohelp, 1},
+ {"version", no_argument, &doversion, 1},
+#ifdef THERE_IS_NO_FORK
+ {"daemonised", no_argument, NULL, 'f'},
+ {"skiproutes", required_argument, NULL, 'g'},
+#endif
+ {NULL, 0, NULL, 0}
+};
+
+
#define STRINGINT(_string, _int) { \
char *_tmp; \
long _number = strtol (_string, &_tmp, 0); \
char **dhcpcd_argv = NULL;
int dhcpcd_argc = 0;
char *dhcpcd_skiproutes = NULL;
+#undef EXTRA_OPTS
+#define EXTRA_OPTS "fg:"
#endif
static pid_t read_pid (const char *pidfile)
int main(int argc, char **argv)
{
- options_t options;
- int doversion = 0;
- int dohelp = 0;
+ options_t *options;
int userclasses = 0;
int opt;
int option_index = 0;
- char prefix[IF_NAMESIZE + 3];
+ char *prefix;
pid_t pid;
int debug = 0;
int i;
int pidfd = -1;
int sig = 0;
- const struct option longopts[] = {
- {"arp", no_argument, NULL, 'a'},
- {"script", required_argument, NULL, 'c'},
- {"debug", no_argument, NULL, 'd'},
- {"hostname", optional_argument, NULL, 'h'},
- {"classid", optional_argument, NULL, 'i'},
- {"release", no_argument, NULL, 'k'},
- {"leasetime", required_argument, NULL, 'l'},
- {"metric", required_argument, NULL, 'm'},
- {"renew", no_argument, NULL, 'n'},
- {"persistent", no_argument, NULL, 'p'},
- {"inform", optional_argument, NULL, 's'},
- {"request", optional_argument, NULL, 'r'},
- {"timeout", required_argument, NULL, 't'},
- {"userclass", required_argument, NULL, 'u'},
- {"exit", no_argument, NULL, 'x'},
- {"lastlease", no_argument, NULL, 'E'},
- {"fqdn", required_argument, NULL, 'F'},
- {"nogateway", no_argument, NULL, 'G'},
- {"sethostname", no_argument, NULL, 'H'},
- {"clientid", optional_argument, NULL, 'I'},
- {"noipv4ll", no_argument, NULL, 'L'},
- {"nomtu", no_argument, NULL, 'M'},
- {"nontp", no_argument, NULL, 'N'},
- {"nodns", no_argument, NULL, 'R'},
- {"test", no_argument, NULL, 'T'},
- {"nonis", no_argument, NULL, 'Y'},
- {"help", no_argument, &dohelp, 1},
- {"version", no_argument, &doversion, 1},
-#ifdef THERE_IS_NO_FORK
- {"daemonised", no_argument, NULL, 'f'},
- {"skiproutes", required_argument, NULL, 'g'},
-#endif
- {NULL, 0, NULL, 0}
- };
-
/* Close any un-needed fd's */
for (i = getdtablesize() - 1; i >= 3; --i)
close (i);
openlog (PACKAGE, LOG_PID, LOG_LOCAL0);
- memset (&options, 0, sizeof (options_t));
- options.script = (char *) DEFAULT_SCRIPT;
- snprintf (options.classid, CLASS_ID_MAX_LEN, "%s %s", PACKAGE, VERSION);
- options.classid_len = strlen (options.classid);
-
- options.doarp = true;
- options.dodns = true;
- options.domtu = true;
- options.donis = true;
- options.dontp = true;
- options.dogateway = true;
- options.daemonise = true;
- options.doinform = false;
- options.doipv4ll = true;
- options.timeout = DEFAULT_TIMEOUT;
-
- 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 = xmalloc (sizeof (options_t));
+ memset (options, 0, sizeof (options_t));
+ options->script = (char *) DEFAULT_SCRIPT;
+ snprintf (options->classid, CLASS_ID_MAX_LEN, "%s %s", PACKAGE, VERSION);
+ options->classid_len = strlen (options->classid);
+
+ options->doarp = true;
+ options->dodns = true;
+ options->domtu = true;
+ options->donis = true;
+ options->dontp = true;
+ options->dogateway = true;
+ options->daemonise = true;
+ options->doinform = false;
+ options->doipv4ll = true;
+ options->timeout = DEFAULT_TIMEOUT;
+
+ gethostname (options->hostname, sizeof (options->hostname));
+ if (strcmp (options->hostname, "(none)") == 0 ||
+ strcmp (options->hostname, "localhost") == 0)
+ memset (options->hostname, 0, sizeof (options->hostname));
/* Don't set any optional arguments here so we retain POSIX
* compatibility with getopt */
- while ((opt = getopt_long(argc, argv, "c:dh:i:kl:m:npr:s:t:u:xAEF:GHI:LMNRTY",
+ while ((opt = getopt_long(argc, argv, EXTRA_OPTS
+ "c:dh:i:kl:m:npr:s:t:u:xAEF:GHI:LMNRTY",
longopts, &option_index)) != -1)
{
switch (opt) {
exit (EXIT_FAILURE);
break;
case 'c':
- options.script = optarg;
+ options->script = optarg;
break;
case 'd':
debug++;
setloglevel (LOG_DEBUG);
break;
case 2:
- options.daemonise = false;
+ options->daemonise = false;
break;
}
break;
#ifdef THERE_IS_NO_FORK
case 'f':
- options.daemonised = true;
+ options->daemonised = true;
close_fds ();
break;
case 'g':
#endif
case 'h':
if (! optarg)
- memset (options.hostname, 0, sizeof (options.hostname));
+ memset (options->hostname, 0, sizeof (options->hostname));
else if (strlen (optarg) > MAXHOSTNAMELEN) {
logger (LOG_ERR, "`%s' too long for HostName string, max is %d",
optarg, MAXHOSTNAMELEN);
exit (EXIT_FAILURE);
} else
- strlcpy (options.hostname, optarg, sizeof (options.hostname));
+ strlcpy (options->hostname, optarg, sizeof (options->hostname));
break;
case 'i':
if (! optarg) {
- memset (options.classid, 0, sizeof (options.classid));
- options.classid_len = 0;
+ memset (options->classid, 0, sizeof (options->classid));
+ options->classid_len = 0;
} else if (strlen (optarg) > CLASS_ID_MAX_LEN) {
logger (LOG_ERR, "`%s' too long for ClassID string, max is %d",
optarg, CLASS_ID_MAX_LEN);
exit (EXIT_FAILURE);
} else
- options.classid_len = strlcpy (options.classid, optarg,
- sizeof (options.classid));
+ options->classid_len = strlcpy (options->classid, optarg,
+ sizeof (options->classid));
break;
case 'k':
sig = SIGHUP;
break;
case 'l':
- STRINGINT (optarg, options.leasetime);
- if (options.leasetime <= 0) {
+ STRINGINT (optarg, options->leasetime);
+ if (options->leasetime <= 0) {
logger (LOG_ERR, "leasetime must be a positive value");
exit (EXIT_FAILURE);
}
break;
case 'm':
- STRINGINT (optarg, options.metric);
+ STRINGINT (optarg, options->metric);
break;
case 'n':
sig = SIGALRM;
break;
case 'p':
- options.persistent = true;
+ options->persistent = true;
break;
case 's':
- options.doinform = true;
- options.doarp = false;
+ options->doinform = true;
+ options->doarp = false;
if (! optarg || strlen (optarg) == 0) {
- options.request_address.s_addr = 0;
+ options->request_address.s_addr = 0;
break;
} else {
char *slash = strchr (optarg, '/');
* address */
*slash++ = '\0';
if (sscanf (slash, "%d", &cidr) != 1 ||
- inet_cidrtoaddr (cidr, &options.request_netmask) != 0) {
+ inet_cidrtoaddr (cidr, &options->request_netmask) != 0) {
logger (LOG_ERR, "`%s' is not a valid CIDR", slash);
exit (EXIT_FAILURE);
}
/* fall through */
}
case 'r':
- if (! options.doinform)
- options.dorequest = true;
+ if (! options->doinform)
+ options->dorequest = true;
if (strlen (optarg) > 0 &&
- ! inet_aton (optarg, &options.request_address))
+ ! inet_aton (optarg, &options->request_address))
{
logger (LOG_ERR, "`%s' is not a valid IP address", optarg);
exit (EXIT_FAILURE);
}
break;
case 't':
- STRINGINT (optarg, options.timeout);
- if (options.timeout < 0) {
+ STRINGINT (optarg, options->timeout);
+ if (options->timeout < 0) {
logger (LOG_ERR, "timeout must be a positive value");
exit (EXIT_FAILURE);
}
{
int offset = 0;
for (i = 0; i < userclasses; i++)
- offset += (int) options.userclass[offset] + 1;
+ offset += (int) options->userclass[offset] + 1;
if (offset + 1 + strlen (optarg) > USERCLASS_MAX_LEN) {
logger (LOG_ERR, "userclass overrun, max is %d",
USERCLASS_MAX_LEN);
exit (EXIT_FAILURE);
}
userclasses++;
- memcpy (options.userclass + offset + 1 , optarg, strlen (optarg));
- options.userclass[offset] = strlen (optarg);
- options.userclass_len += (strlen (optarg)) + 1;
+ memcpy (options->userclass + offset + 1 , optarg, strlen (optarg));
+ options->userclass[offset] = strlen (optarg);
+ options->userclass_len += (strlen (optarg)) + 1;
}
break;
case 'x':
logger (LOG_ERR, "arp support not compiled into dhcpcd");
exit (EXIT_FAILURE);
#endif
- options.doarp = false;
+ options->doarp = false;
break;
case 'E':
#ifndef ENABLE_INFO
logger (LOG_ERR, "info support not compiled into dhcpcd");
exit (EXIT_FAILURE);
#endif
- options.dolastlease = true;
+ options->dolastlease = true;
break;
case 'F':
if (strncmp (optarg, "none", strlen (optarg)) == 0)
- options.fqdn = FQDN_NONE;
+ options->fqdn = FQDN_NONE;
else if (strncmp (optarg, "ptr", strlen (optarg)) == 0)
- options.fqdn = FQDN_PTR;
+ options->fqdn = FQDN_PTR;
else if (strncmp (optarg, "both", strlen (optarg)) == 0)
- options.fqdn = FQDN_BOTH;
+ options->fqdn = FQDN_BOTH;
else {
logger (LOG_ERR, "invalid value `%s' for FQDN", optarg);
exit (EXIT_FAILURE);
}
break;
case 'G':
- options.dogateway = false;
+ options->dogateway = false;
break;
case 'H':
- options.dohostname++;
+ options->dohostname++;
break;
case 'I':
if (optarg) {
optarg, CLIENT_ID_MAX_LEN);
exit (EXIT_FAILURE);
}
- options.clientid_len = strlcpy (options.clientid, optarg,
- sizeof (options.clientid));
+ options->clientid_len = strlcpy (options->clientid, optarg,
+ sizeof (options->clientid));
/* empty string disabled duid */
- if (options.clientid_len == 0)
- options.clientid_len = -1;
+ if (options->clientid_len == 0)
+ options->clientid_len = -1;
} else {
- memset (options.clientid, 0, sizeof (options.clientid));
- options.clientid_len = -1;
+ memset (options->clientid, 0, sizeof (options->clientid));
+ options->clientid_len = -1;
}
break;
case 'L':
- options.doipv4ll = false;
+ options->doipv4ll = false;
break;
case 'M':
- options.domtu = false;
+ options->domtu = false;
break;
case 'N':
- options.dontp = false;
+ options->dontp = false;
break;
case 'R':
- options.dodns = false;
+ options->dodns = false;
break;
case 'T':
#ifndef ENABLE_INFO
logger (LOG_ERR, "info support not compiled into dhcpcd");
exit (EXIT_FAILURE);
#endif
- options.test = true;
- options.persistent = true;
+ options->test = true;
+ options->persistent = true;
break;
case 'Y':
- options.donis = false;
+ options->donis = false;
break;
case '?':
usage ();
argv[optind], IF_NAMESIZE);
exit (EXIT_FAILURE);
}
- strlcpy (options.interface, argv[optind],
- sizeof (options.interface));
+ strlcpy (options->interface, argv[optind],
+ sizeof (options->interface));
} else {
/* If only version was requested then exit now */
if (doversion || dohelp)
exit (EXIT_FAILURE);
}
- if (strchr (options.hostname, '.')) {
- if (options.fqdn == FQDN_DISABLE)
- options.fqdn = FQDN_BOTH;
+ if (strchr (options->hostname, '.')) {
+ if (options->fqdn == FQDN_DISABLE)
+ options->fqdn = FQDN_BOTH;
} else
- options.fqdn = FQDN_DISABLE;
+ options->fqdn = FQDN_DISABLE;
- if (options.request_address.s_addr == 0 && options.doinform) {
- if ((options.request_address.s_addr = get_address (options.interface)) != 0)
- options.keep_address = true;
+ if (options->request_address.s_addr == 0 && options->doinform) {
+ if ((options->request_address.s_addr = get_address (options->interface)) != 0)
+ options->keep_address = true;
}
if (geteuid ()) {
exit (EXIT_FAILURE);
}
- snprintf (prefix, IF_NAMESIZE, "%s: ", options.interface);
+ prefix = xmalloc (sizeof (char *) * IF_NAMESIZE + 3);
+ snprintf (prefix, IF_NAMESIZE, "%s: ", options->interface);
setlogprefix (prefix);
- snprintf (options.pidfile, sizeof (options.pidfile), PIDFILE,
- options.interface);
+ snprintf (options->pidfile, sizeof (options->pidfile), PIDFILE,
+ options->interface);
+ free (prefix);
chdir ("/");
umask (022);
exit (EXIT_FAILURE);
}
- if (options.test) {
- if (options.dorequest || options.doinform) {
+ if (options->test) {
+ if (options->dorequest || options->doinform) {
logger (LOG_ERR, "cannot test with --inform or --request");
exit (EXIT_FAILURE);
}
- if (options.dolastlease) {
+ if (options->dolastlease) {
logger (LOG_ERR, "cannot test with --lastlease");
exit (EXIT_FAILURE);
}
if (sig != 0) {
int killed = -1;
- pid = read_pid (options.pidfile);
+ pid = read_pid (options->pidfile);
if (pid != 0)
logger (LOG_INFO, "sending signal %d to pid %d", sig, pid);
logger (sig == SIGALRM ? LOG_INFO : LOG_ERR, ""PACKAGE" not running");
if (pid != 0 && (sig != SIGALRM || killed != 0))
- unlink (options.pidfile);
+ unlink (options->pidfile);
if (killed == 0)
exit (EXIT_SUCCESS);
exit (EXIT_FAILURE);
}
- if (! options.test && ! options.daemonised) {
- if ((pid = read_pid (options.pidfile)) > 0 && kill (pid, 0) == 0) {
+ if (! options->test && ! options->daemonised) {
+ if ((pid = read_pid (options->pidfile)) > 0 && kill (pid, 0) == 0) {
logger (LOG_ERR, ""PACKAGE" already running on pid %d (%s)",
- pid, options.pidfile);
+ pid, options->pidfile);
exit (EXIT_FAILURE);
}
- pidfd = open (options.pidfile, O_WRONLY | O_CREAT | O_NONBLOCK, 0660);
+ pidfd = open (options->pidfile, O_WRONLY | O_CREAT | O_NONBLOCK, 0660);
if (pidfd == -1) {
- logger (LOG_ERR, "open `%s': %s", options.pidfile, strerror (errno));
+ logger (LOG_ERR, "open `%s': %s", options->pidfile, strerror (errno));
exit (EXIT_FAILURE);
}
/* Lock the file so that only one instance of dhcpcd runs on an interface */
if (flock (pidfd, LOCK_EX | LOCK_NB) == -1) {
- logger (LOG_ERR, "flock `%s': %s", options.pidfile, strerror (errno));
+ logger (LOG_ERR, "flock `%s': %s", options->pidfile, strerror (errno));
exit (EXIT_FAILURE);
}
srandomdev ();
i = EXIT_FAILURE;
- if (dhcp_run (&options, &pidfd) == 0)
+ if (dhcp_run (options, &pidfd) == 0)
i = EXIT_SUCCESS;
+ free (options);
+
#ifdef THERE_IS_NO_FORK
/* There may have been an error before the dhcp_run function
* clears this, so just do it here to be safe */
#include "info.h"
#ifdef ENABLE_INFO
+#define BUFFERSIZE 1024
+
static char *cleanmetas (const char *cstr)
{
/* The largest single element we can have is 256 bytes according to the RFC,
so this buffer size should be safe even if it's all ' */
- static char buffer[1024];
+ static char buffer[BUFFERSIZE];
char *b = buffer;
memset (buffer, 0, sizeof (buffer));
fprintf (f, "CLIENTID='00:%s'\n", cleanmetas (options->clientid));
#ifdef ENABLE_DUID
else if (iface->duid_length > 0 && options->clientid_len != -1) {
- unsigned char duid[256];
- unsigned char *p = duid;
+ unsigned char *duid;
+ unsigned char *p;
uint32_t ul;
+ p = duid = xmalloc (iface->duid_length + 6);
*p++ = 255;
/* IAID is 4 bytes, so if the interface name is 4 bytes then use it */
p += iface->duid_length;
fprintf (f, "CLIENTID='%s'\n", hwaddr_ntoa (duid, p - duid));
+ free (duid);
}
#endif
else
bool read_info (const interface_t *iface, dhcp_t *dhcp)
{
FILE *fp;
- char buffer[1024];
+ char *buffer;
char *var;
char *value;
char *p;
dhcp->frominfo = true;
- memset (buffer, 0, sizeof (buffer));
- while ((fgets (buffer, sizeof (buffer), fp))) {
+ buffer = xmalloc (sizeof (char *) * BUFFERSIZE);
+ memset (buffer, 0, BUFFERSIZE);
+ while ((fgets (buffer, BUFFERSIZE, fp))) {
var = buffer;
/* Strip leading spaces/tabs */
}
fclose (fp);
+ free (buffer);
return (true);
}
{
int s;
struct ifreq ifr;
- interface_t *iface;
- unsigned char hwaddr[20];
+ interface_t *iface = NULL;
+ unsigned char *hwaddr = NULL;
int hwlen = 0;
sa_family_t family = 0;
unsigned short mtu;
strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
if (ioctl (s, SIOCGIFHWADDR, &ifr) == -1) {
logger (LOG_ERR, "ioctl SIOCGIFHWADDR: %s", strerror (errno));
- close (s);
- return NULL;
+ goto exit;
}
switch (ifr.ifr_hwaddr.sa_family) {
break;
default:
logger (LOG_ERR, "interface is not Ethernet, FireWire, InfiniBand or Token Ring");
- close (s);
- return NULL;
+ goto exit;
}
+ hwaddr = xmalloc (sizeof (unsigned char *) * HWADDR_LEN);
memcpy (hwaddr, ifr.ifr_hwaddr.sa_data, hwlen);
family = ifr.ifr_hwaddr.sa_family;
#else
strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
if (ioctl (s, SIOCSIFMETRIC, &ifr) == -1) {
logger (LOG_ERR, "ioctl SIOCSIFMETRIC: %s", strerror (errno));
- close (s);
- return NULL;
+ goto exit;
}
-
+
+ hwaddr = xmalloc (sizeof (unsigned char *) * HWADDR_LEN);
if (_do_interface (ifname, hwaddr, &hwlen, NULL, false, false) != 1) {
logger (LOG_ERR, "could not find interface %s", ifname);
- close (s);
- return NULL;
+ goto exit;
}
family = ARPHRD_ETHER;
strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
if (ioctl (s, SIOCGIFMTU, &ifr) == -1) {
logger (LOG_ERR, "ioctl SIOCGIFMTU: %s", strerror (errno));
- close (s);
- return NULL;
+ goto exit;
}
if (ifr.ifr_mtu < MTU_MIN) {
strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
if (ioctl (s, SIOCSIFMTU, &ifr) == -1) {
logger (LOG_ERR, "ioctl SIOCSIFMTU,: %s", strerror (errno));
- close (s);
- return NULL;
+ goto exit;
}
}
mtu = ifr.ifr_mtu;
#endif
if (ioctl (s, SIOCGIFFLAGS, &ifr) == -1) {
logger (LOG_ERR, "ioctl SIOCGIFFLAGS: %s", strerror (errno));
- close (s);
- return NULL;
+ goto exit;
}
if (! (ifr.ifr_flags & IFF_UP) || ! (ifr.ifr_flags & IFF_RUNNING)) {
ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
if (ioctl (s, SIOCSIFFLAGS, &ifr) == -1) {
logger (LOG_ERR, "ioctl SIOCSIFFLAGS: %s", strerror (errno));
- close (s);
- return NULL;
+ goto exit;
}
}
- close (s);
-
iface = xmalloc (sizeof (interface_t));
memset (iface, 0, sizeof (interface_t));
strlcpy (iface->name, ifname, IF_NAMESIZE);
/* 0 is a valid fd, so init to -1 */
iface->fd = -1;
+exit:
+ close (s);
+ free (hwaddr);
return iface;
}
gateway.s_addr == INADDR_ANY)
{
/* Make us a link layer socket */
- unsigned char hwaddr[HWADDR_LEN];
+ unsigned char *hwaddr;
int hwlen = 0;
if (netmask.s_addr == INADDR_BROADCAST)
rtm.hdr.rtm_flags |= RTF_HOST;
+ hwaddr = xmalloc (sizeof (unsigned char *) * HWADDR_LEN);
_do_interface (ifname, hwaddr, &hwlen, NULL, false, false);
memset (&su, 0, sizeof (struct sockaddr_storage));
su.sdl.sdl_len = sizeof (struct sockaddr_dl);
l = SA_SIZE (&(su.sa));
memcpy (bp, &su, l);
bp += l;
+ free (hwaddr);
} else {
rtm.hdr.rtm_flags |= RTF_GATEWAY;
ADDADDR (gateway);
This blatently taken from libnetlink.c from the iproute2 package
which is the only good source of netlink code.
*/
+#define BUFFERLEN 256
static int send_netlink(struct nlmsghdr *hdr)
{
int s;
struct iovec iov;
struct msghdr msg;
static unsigned int seq;
- char buffer[256];
+ char *buffer;
int bytes;
union
{
return -1;
}
- memset (buffer, 0, sizeof (buffer));
+ buffer = xmalloc (sizeof (char *) * BUFFERLEN);
+ memset (buffer, 0, BUFFERLEN);
iov.iov_base = buffer;
while (1) {
- iov.iov_len = sizeof (buffer);
+ iov.iov_len = BUFFERLEN;
bytes = recvmsg (s, &msg, 0);
if (bytes == -1) {
errno = -err->error;
if (errno == 0) {
close (s);
+ free (buffer);
return 0;
}
eexit:
close (s);
+ free (buffer);
return -1;
}
return 0;
}
+struct nlma
+{
+ struct nlmsghdr hdr;
+ struct ifaddrmsg ifa;
+ char buffer[64];
+};
+
+struct nlmr
+{
+ struct nlmsghdr hdr;
+ struct rtmsg rt;
+ char buffer[256];
+};
+
static int do_address(const char *ifname,
struct in_addr address, struct in_addr netmask,
struct in_addr broadcast, int del)
{
- struct
- {
- struct nlmsghdr hdr;
- struct ifaddrmsg ifa;
- char buffer[64];
- }
- nlm;
+ struct nlma *nlm;
+ int retval;
if (!ifname)
return -1;
- memset (&nlm, 0, sizeof (nlm));
+ nlm = xmalloc (sizeof (struct nlma));
+ memset (nlm, 0, sizeof (struct nlma));
- nlm.hdr.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg));
- nlm.hdr.nlmsg_flags = NLM_F_REQUEST;
+ nlm->hdr.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg));
+ nlm->hdr.nlmsg_flags = NLM_F_REQUEST;
if (! del)
- nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
- nlm.hdr.nlmsg_type = del ? RTM_DELADDR : RTM_NEWADDR;
- if (! (nlm.ifa.ifa_index = if_nametoindex (ifname))) {
+ nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
+ nlm->hdr.nlmsg_type = del ? RTM_DELADDR : RTM_NEWADDR;
+ if (! (nlm->ifa.ifa_index = if_nametoindex (ifname))) {
logger (LOG_ERR, "if_nametoindex: Couldn't find index for interface `%s'",
ifname);
+ free (nlm);
return -1;
}
- nlm.ifa.ifa_family = AF_INET;
+ nlm->ifa.ifa_family = AF_INET;
- nlm.ifa.ifa_prefixlen = inet_ntocidr (netmask);
+ nlm->ifa.ifa_prefixlen = inet_ntocidr (netmask);
/* This creates the aliased interface */
- add_attr_l (&nlm.hdr, sizeof (nlm), IFA_LABEL, ifname, strlen (ifname) + 1);
+ add_attr_l (&nlm->hdr, sizeof (struct nlma), IFA_LABEL,
+ ifname, strlen (ifname) + 1);
- add_attr_l (&nlm.hdr, sizeof (nlm), IFA_LOCAL, &address.s_addr,
- sizeof (address.s_addr));
+ add_attr_l (&nlm->hdr, sizeof (struct nlma), IFA_LOCAL,
+ &address.s_addr, sizeof (address.s_addr));
if (! del)
- add_attr_l (&nlm.hdr, sizeof (nlm), IFA_BROADCAST, &broadcast.s_addr,
- sizeof (broadcast.s_addr));
+ add_attr_l (&nlm->hdr, sizeof (struct nlma), IFA_BROADCAST,
+ &broadcast.s_addr, sizeof (broadcast.s_addr));
- return send_netlink (&nlm.hdr);
+ retval = send_netlink (&nlm->hdr);
+ free (nlm);
+ return retval;
}
static int do_route (const char *ifname,
struct in_addr gateway,
int metric, int change, int del)
{
+ struct nlmr *nlm;
unsigned int ifindex;
- struct
- {
- struct nlmsghdr hdr;
- struct rtmsg rt;
- char buffer[256];
- }
- nlm;
+ int retval;
if (! ifname)
return -1;
log_route (destination, netmask, gateway, metric, change, del);
- memset (&nlm, 0, sizeof (nlm));
+ if (! (ifindex = if_nametoindex (ifname))) {
+ logger (LOG_ERR, "if_nametoindex: Couldn't find index for interface `%s'",
+ ifname);
+ return -1;
+ }
+
+ nlm = xmalloc (sizeof (struct nlmr));
+ memset (nlm, 0, sizeof (struct nlmr));
- nlm.hdr.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
+ nlm->hdr.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
if (change)
- nlm.hdr.nlmsg_flags = NLM_F_REPLACE;
+ nlm->hdr.nlmsg_flags = NLM_F_REPLACE;
else if (! del)
- nlm.hdr.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL;
- nlm.hdr.nlmsg_flags |= NLM_F_REQUEST;
- nlm.hdr.nlmsg_type = del ? RTM_DELROUTE : RTM_NEWROUTE;
- nlm.rt.rtm_family = AF_INET;
- nlm.rt.rtm_table = RT_TABLE_MAIN;
+ nlm->hdr.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL;
+ nlm->hdr.nlmsg_flags |= NLM_F_REQUEST;
+ nlm->hdr.nlmsg_type = del ? RTM_DELROUTE : RTM_NEWROUTE;
+ nlm->rt.rtm_family = AF_INET;
+ nlm->rt.rtm_table = RT_TABLE_MAIN;
if (del)
- nlm.rt.rtm_scope = RT_SCOPE_NOWHERE;
+ nlm->rt.rtm_scope = RT_SCOPE_NOWHERE;
else {
- nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
- nlm.rt.rtm_protocol = RTPROT_BOOT;
+ nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
+ nlm->rt.rtm_protocol = RTPROT_BOOT;
if (netmask.s_addr == INADDR_BROADCAST ||
gateway.s_addr == INADDR_ANY)
- nlm.rt.rtm_scope = RT_SCOPE_LINK;
+ nlm->rt.rtm_scope = RT_SCOPE_LINK;
else
- nlm.rt.rtm_scope = RT_SCOPE_UNIVERSE;
- nlm.rt.rtm_type = RTN_UNICAST;
+ nlm->rt.rtm_scope = RT_SCOPE_UNIVERSE;
+ nlm->rt.rtm_type = RTN_UNICAST;
}
- nlm.rt.rtm_dst_len = inet_ntocidr (netmask);
- add_attr_l (&nlm.hdr, sizeof (nlm), RTA_DST, &destination.s_addr,
- sizeof (destination.s_addr));
+ nlm->rt.rtm_dst_len = inet_ntocidr (netmask);
+ add_attr_l (&nlm->hdr, sizeof (struct nlmr), RTA_DST,
+ &destination.s_addr, sizeof (destination.s_addr));
if (netmask.s_addr != INADDR_BROADCAST &&
destination.s_addr != gateway.s_addr)
- add_attr_l (&nlm.hdr, sizeof (nlm), RTA_GATEWAY, &gateway.s_addr,
- sizeof (gateway.s_addr));
+ add_attr_l (&nlm->hdr, sizeof (struct nlmr), RTA_GATEWAY,
+ &gateway.s_addr, sizeof (gateway.s_addr));
- if (! (ifindex = if_nametoindex (ifname))) {
- logger (LOG_ERR, "if_nametoindex: Couldn't find index for interface `%s'",
- ifname);
- return -1;
- }
+ add_attr_32 (&nlm->hdr, sizeof (struct nlmr), RTA_OIF, ifindex);
+ add_attr_32 (&nlm->hdr, sizeof (struct nlmr), RTA_PRIORITY, metric);
- add_attr_32 (&nlm.hdr, sizeof (nlm), RTA_OIF, ifindex);
- add_attr_32 (&nlm.hdr, sizeof (nlm), RTA_PRIORITY, metric);
-
- return send_netlink (&nlm.hdr);
+ retval = send_netlink (&nlm->hdr);
+ free (nlm);
+ return retval;
}
#else
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <unistd.h>
nleft -= 2;
}
-
if (nleft == 1) {
uint8_t a = 0;
memcpy (&a, p.i, 1);
{
int n = 0;
int fd = -1;
- char device[PATH_MAX];
+ char *device;
int flags;
struct ifreq ifr;
int buf = 0;
struct bpf_program p;
+ device = xmalloc (sizeof (char *) * PATH_MAX);
do {
snprintf (device, PATH_MAX, "/dev/bpf%d", n++);
fd = open (device, O_RDWR);
} while (fd == -1 && errno == EBUSY);
+ free (device);
if (fd == -1) {
logger (LOG_ERR, "unable to open a BPF device");