# Should work for both GNU make and BSD make
-VERSION = 3.0.7_pre1
+VERSION = 3.0.7_pre2
INSTALL ?= install
+CFLAGS ?= -O2
+
# Loads of nice flags to ensure our code is good
-# And yes, we require C99 style code which means gcc-3 as a minimum
-CFLAGS = -O2 -pedantic -std=gnu99 \
- -Wall -Wunused -Wimplicit -Wshadow -Wformat=2 \
+# We define _BSD_SOURCE for maximum portability
+CFLAGS += -D_BSD_SOURCE -pedantic -std=c99 \
+ -Wall -Werror -Wunused -Wimplicit -Wshadow -Wformat=2 \
-Wmissing-declarations -Wno-missing-prototypes -Wwrite-strings \
-Wbad-function-cast -Wnested-externs -Wcomment -Winline \
- -Wchar-subscripts -Wcast-align -Wno-format-nonliteral \
- -Wsequence-point -Wextra -Werror
+ -Wchar-subscripts -Wcast-align -Wno-format-nonliteral
+
+# Early GCC versions don't support these flags, so you may need to comment
+# this line out
+CFLAGS += -Wsequence-point -Wextra -Wdeclaration-after-statement
DESTDIR =
SBINDIR = $(DESTDIR)/sbin
/* OK, a lot of this was lifting from iputils as the existing code
for dhcpcd was kinda klunky and had some issues */
-#define _BSD_SOURCE
-
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/select.h>
int arp_check (interface_t *iface, struct in_addr address)
{
+ unsigned char buf[256];
+ struct arphdr *ah = (struct arphdr *) buf;
+ unsigned char reply[4096];
+ int bytes;
+ unsigned char buffer[iface->buffer_length];
+ struct timeval tv;
+ long timeout = 0;
+ fd_set rset;
+
if (! iface->arpable)
{
logger (LOG_DEBUG, "arp_check: interface `%s' is not ARPable",
return 0;
}
- unsigned char buf[256];
- struct arphdr *ah = (struct arphdr *) buf;
-
memset (buf, 0, sizeof (buf));
ah->ar_hrd = htons (ARPHRD_ETHER);
open_socket (iface, true);
send_packet (iface, ETHERTYPE_ARP, (unsigned char *) &buf, arphdr_len(ah));
- unsigned char reply[4096];
- int bytes;
- unsigned char buffer[iface->buffer_length];
-
- struct timeval tv;
- long timeout = 0;
- fd_set rset;
-
timeout = uptime() + TIMEOUT;
while (1)
{
+ int buflen = sizeof (buffer);
+ int bufpos = -1;
+
tv.tv_sec = timeout - uptime ();
tv.tv_usec = 0;
continue;
memset (buffer, 0, sizeof (buffer));
- int buflen = sizeof (buffer);
- int bufpos = -1;
while (bufpos != 0)
{
}
else if (retval > 0 && mode != SOCKET_CLOSED && FD_ISSET(iface->fd, &rset))
{
+ int valid = 0;
+ struct dhcp_t *new_dhcp;
/* Allocate our buffer space for BPF.
We cannot do this until we have opened our socket as we don't
the first one fails for any reason, we can use the next. */
memset (&message, 0, sizeof (struct dhcpmessage_t));
- int valid = 0;
- struct dhcp_t *new_dhcp;
new_dhcp = xmalloc (sizeof (dhcp_t));
while (buffer_pos != 0)
static char *cleanmetas (char *cstr)
{
+ register char *c = cstr;
+
if (! cstr)
return NULL;
- register char *c = cstr;
-
do
if (*c == 39)
*c = ' ';
static void exec_script (const char *script, const char *infofile,
const char *arg)
{
+ struct stat buf;
+ pid_t pid;
+ char *const argc[4] =
+ { (char *) script, (char *) infofile, (char *) arg, NULL };
+
if (! script || ! infofile || ! arg)
return;
- struct stat buf;
if (stat (script, &buf) < 0)
{
if (strcmp (script, DEFAULT_SCRIPT) != 0)
return;
}
- char *const argc[4] =
- { (char *) script, (char *) infofile, (char *) arg, NULL };
logger (LOG_DEBUG, "exec \"%s %s %s\"", script, infofile, arg);
-
+
/* We don't wait for the user script to finish - do we trust it? */
/* Don't use vfork as we lose our memory when dhcpcd exits
causing the script to fail */
- pid_t pid;
if ((pid = fork ()) == 0)
{
if (execv (script, argc))
static void restore_resolv(const char *ifname)
{
struct stat buf;
+ pid_t pid;
+ char *const argc[4] =
+ { (char *) RESOLVCONF, (char *) "-d", (char *) ifname, NULL };
if (stat (RESOLVCONF, &buf) < 0)
return;
logger (LOG_DEBUG, "removing information from resolvconf");
- char *const argc[4] = { (char *) RESOLVCONF, (char *) "-d", (char *) ifname, NULL };
-
/* Don't wait around here as we should only be called when
dhcpcd is closing down and something may do a kill -9
if we take too long */
/* Don't use vfork as we lose our memory when dhcpcd exits
causing the script to fail */
- pid_t pid;
if ((pid = fork ()) == 0)
{
if (execve (argc[0], argc, NULL))
if (dhcp->routes)
{
route_t *new_routes = NULL;
+ int remember;
for (route = dhcp->routes; route; route = route->next)
{
&& ! options->dogateway)
continue;
- int remember = add_route (iface->name, route->destination,
+ remember = add_route (iface->name, route->destination,
route->netmask, route->gateway,
options->metric);
/* If we failed to add the route, we may have already added it
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;
unsigned char *n_params = NULL;
unsigned long l;
struct in_addr from;
struct in_addr to;
+ long up = uptime() - iface->start_uptime;
+ uint32_t ul;
+ uint16_t sz;
+ unsigned int message_length;
if (!iface || !options || !dhcp)
return -1;
message.op = DHCP_BOOTREQUEST;
message.hwtype = ARPHRD_ETHER;
message.hwlen = ETHER_ADDR_LEN;
- long up = uptime() - iface->start_uptime;
if (up < 0 || up > UINT16_MAX)
message.secs = htons (UINT16_MAX);
else
{
*p++ = DHCP_MAXMESSAGESIZE;
*p++ = 2;
- uint16_t sz = htons (sizeof (dhcpmessage_t));
+ sz = htons (sizeof (dhcpmessage_t));
memcpy (p, &sz, 2);
p += 2;
}
{
*p++ = DHCP_LEASETIME;
*p++ = 4;
- uint32_t ul = htonl (options->leasetime);
+ ul = htonl (options->leasetime);
memcpy (p, &ul, 4);
p += 4;
}
*p++ = DHCP_END;
- unsigned int message_length = p - m;
+ message_length = p - m;
- struct udp_dhcp_packet packet;
memset (&packet, 0, sizeof (struct udp_dhcp_packet));
make_dhcp_packet (&packet, (unsigned char *) &message, message_length,
from, to);
* and return the last route set */
static route_t *decodeCSR(unsigned char *p, int len)
{
+ unsigned char *q = p;
+ int cidr;
+ int ocets;
+ route_t *first;
+ route_t *route;
+
/* Minimum is 5 -first is CIDR and a router length of 4 */
if (len < 5)
return NULL;
- unsigned char *q = p;
- int cidr;
- int ocets;
- route_t *first = xmalloc (sizeof (route_t));
- route_t *route = first;
+ first = xmalloc (sizeof (route_t));
+ route = first;
while (q - p < len)
{
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+/* We need to define this to get kill on GNU systems */
+#ifdef __linux__
+#define _POSIX_SOURCE
+#endif
+
+#include <sys/types.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <errno.h>
#define STRINGINT(_string, _int) { \
char *_tmp; \
- errno = 0; \
long _number = strtol (_string, &_tmp, 0); \
+ errno = 0; \
if ((errno != 0 && _number == 0) || _string == _tmp || \
(errno == ERANGE && (_number == LONG_MAX || _number == LONG_MIN))) \
{ \
" [-u userclass] [-F [none | ptr | both]] [-I clientID]\n");
}
+
int main(int argc, char **argv)
{
options_t options;
-
- /* Sanitize our fd's */
- int zero;
- if ((zero = open (_PATH_DEVNULL, O_RDWR, 0)) >= 0)
- {
- while (zero < 3)
- zero = dup (zero);
- close(zero);
- }
-
- 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.doarp = false;
- options.dodns = true;
- options.donis = true;
- options.dontp = true;
- options.dogateway = 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;
-
int doversion = 0;
int dohelp = 0;
int userclasses = 0;
+ int ch;
+ int option_index = 0;
+ char prefix[IF_NAMESIZE + 3];
const struct option longopts[] =
{
{NULL, 0, NULL, 0}
};
- int ch;
- int option_index = 0;
+ /* Sanitize our fd's */
+ int zero;
+ if ((zero = open (_PATH_DEVNULL, O_RDWR, 0)) >= 0)
+ {
+ while (zero < 3)
+ zero = dup (zero);
+ close(zero);
+ }
+
+ 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.doarp = false;
+ options.dodns = true;
+ options.donis = true;
+ options.dontp = true;
+ options.dogateway = 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:NRY", longopts,
&option_index)) != -1)
switch (ch)
exit (EXIT_FAILURE);
}
- char prefix[IF_NAMESIZE + 3];
snprintf (prefix, IF_NAMESIZE, "%s: ", options.interface);
setlogprefix (prefix);
snprintf (options.pidfile, sizeof (options.pidfile), PIDFILE,
if (options.signal != 0)
{
+ int killed = -1;
pid_t pid = read_pid (options.pidfile);
if (pid != 0)
logger (LOG_INFO, "sending signal %d to pid %d", options.signal, pid);
-
- int killed = -1;
+
if (! pid || (killed = kill (pid, options.signal)))
logger (options.signal == SIGALRM ? LOG_INFO : LOG_ERR, ""PACKAGE" not running");
void free_address (address_t *addresses)
{
- if (!addresses)
- return;
-
address_t *p = addresses;
address_t *n = NULL;
+ if (! addresses)
+ return;
+
while (p)
{
n = p->next;
void free_route (route_t *routes)
{
- if (!routes)
- return;
-
route_t *p = routes;
route_t *n = NULL;
+ if (!routes)
+ return;
+
while (p)
{
n = p->next;
interface_t *read_interface (const char *ifname, int metric)
{
- if (! ifname)
- return NULL;
int s;
struct ifreq ifr;
#ifndef __linux__
struct ifaddrs *ifap;
struct ifaddrs *p;
+#endif
+ if (! ifname)
+ return NULL;
+
+#ifndef __linux__
if (getifaddrs (&ifap) != 0)
return NULL;
for (p = ifap; p; p = p->ifa_next)
{
+ struct sockaddr_dl *sdl = (struct sockaddr_dl *) p->ifa_addr;
+
if (strcmp (p->ifa_name, ifname) != 0)
continue;
- struct sockaddr_dl *sdl = (struct sockaddr_dl *) p->ifa_addr;
if (p->ifa_addr->sa_family != AF_LINK || sdl->sdl_type != IFT_ETHER)
{
logger (LOG_ERR, "not Ethernet");
static int do_address (const char *ifname, struct in_addr address,
struct in_addr netmask, struct in_addr broadcast, int del)
{
+ int s;
+ struct ifaliasreq ifa;
+
if (! ifname)
return -1;
- int s;
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
logger (LOG_ERR, "socket: %s", strerror (errno));
return -1;
}
- struct ifaliasreq ifa;
memset (&ifa, 0, sizeof (ifa));
strcpy (ifa.ifra_name, ifname);
int metric,
int change, int del)
{
+ int s;
+ char *destd;
+ char *gend;
+ struct rtm
+ {
+ struct rt_msghdr hdr;
+ struct sockaddr_in destination;
+ struct sockaddr_in gateway;
+ struct sockaddr_in netmask;
+ } rtm;
+ static int seq;
+
if (! ifname)
return -1;
/* Do something with metric to satisfy compiler warnings */
metric = 0;
- char *destd = strdup (inet_ntoa (destination));
- char *gend = strdup (inet_ntoa (netmask));
+ destd = strdup (inet_ntoa (destination));
+ gend = strdup (inet_ntoa (netmask));
logger (LOG_INFO, "%s route to %s (%s) via %s",
change ? "changing" : del ? "removing" : "adding",
destd, gend, inet_ntoa(gateway));
if (gend)
free (gend);
- int s;
if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) < 0)
{
logger (LOG_ERR, "socket: %s", strerror (errno));
return -1;
}
- struct rtm
- {
- struct rt_msghdr hdr;
- struct sockaddr_in destination;
- struct sockaddr_in gateway;
- struct sockaddr_in netmask;
- } rtm;
memset (&rtm, 0, sizeof (struct rtm));
rtm.hdr.rtm_version = RTM_VERSION;
- static int seq;
rtm.hdr.rtm_seq = ++seq;
rtm.hdr.rtm_type = change ? RTM_CHANGE : del ? RTM_DELETE : RTM_ADD;
static int send_netlink(struct nlmsghdr *hdr)
{
int s;
+ pid_t mypid = getpid ();
+ struct sockaddr_nl nl;
+ struct iovec iov;
+ struct msghdr msg;
+ static unsigned int seq;
+ char buffer[16384];
+ struct nlmsghdr *h;
+
if ((s = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0)
{
logger (LOG_ERR, "socket: %s", strerror (errno));
return -1;
}
- pid_t mypid = getpid ();
- struct sockaddr_nl nl;
memset (&nl, 0, sizeof (struct sockaddr_nl));
nl.nl_family = AF_NETLINK;
if (bind (s, (struct sockaddr *) &nl, sizeof (nl)) < 0)
return -1;
}
- struct iovec iov;
memset (&iov, 0, sizeof (struct iovec));
iov.iov_base = hdr;
iov.iov_len = hdr->nlmsg_len;
- struct msghdr msg;
memset (&msg, 0, sizeof (struct msghdr));
msg.msg_name = &nl;
msg.msg_namelen = sizeof (nl);
/* Request a reply */
hdr->nlmsg_flags |= NLM_F_ACK;
- static unsigned int seq;
hdr->nlmsg_seq = ++seq;
if (sendmsg (s, &msg, 0) < 0)
return -1;
}
- char buffer[16384];
memset (buffer, 0, sizeof (buffer));
iov.iov_base = buffer;
- struct nlmsghdr *h;
while (1)
{
- iov.iov_len = sizeof (buffer);
int bytes = recvmsg(s, &msg, 0);
+ iov.iov_len = sizeof (buffer);
if (bytes < 0)
{
return 0;
}
-
static int do_address(const char *ifname,
struct in_addr address, struct in_addr netmask,
struct in_addr broadcast, int del)
{
- if (!ifname)
- return -1;
-
struct
{
struct nlmsghdr hdr;
char buffer[256];
}
nlm;
+ uint32_t mask = htonl (netmask.s_addr);
+
+ if (!ifname)
+ return -1;
memset (&nlm, 0, sizeof (nlm));
nlm.ifa.ifa_family = AF_INET;
/* Store the netmask in the prefix */
- uint32_t mask = htonl (netmask.s_addr);
while (mask)
{
nlm.ifa.ifa_prefixlen++;
struct in_addr gateway,
int metric, int change, int del)
{
+ char *dstd;
+ char *gend;
+ struct
+ {
+ struct nlmsghdr hdr;
+ struct rtmsg rt;
+ char buffer[256];
+ }
+ nlm;
+ uint32_t mask = htonl (netmask.s_addr);
+
if (! ifname)
return -1;
- char *dstd = strdup (inet_ntoa (destination));
- char *gend = strdup (inet_ntoa (netmask));
+ dstd = strdup (inet_ntoa (destination));
+ gend = strdup (inet_ntoa (netmask));
logger (LOG_INFO, "%s route to %s (%s) via %s, metric %d",
change ? "changing" : del ? "removing" : "adding",
dstd, gend, inet_ntoa (gateway), metric);
if (gend)
free (gend);
- struct
- {
- struct nlmsghdr hdr;
- struct rtmsg rt;
- char buffer[256];
- }
- nlm;
memset (&nlm, 0, sizeof (nlm));
nlm.hdr.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
}
/* Store the netmask in the prefix */
- uint32_t mask = htonl (netmask.s_addr);
while (mask)
{
nlm.rt.rtm_dst_len++;
int del_address (const char *ifname, struct in_addr address)
{
+ struct in_addr t;
+
logger (LOG_INFO, "deleting IP address %s", inet_ntoa (address));
- struct in_addr t;
memset (&t, 0, sizeof (t));
return (do_address (ifname, address, t, t, 1));
}
#ifdef HAVE_IFADDRS_H
int flush_addresses (const char *ifname)
{
- if (! ifname)
- return -1;
-
struct ifaddrs *ifap;
struct ifaddrs *p;
+ int retval = 0;
+ if (! ifname)
+ return -1;
if (getifaddrs (&ifap) != 0)
return -1;
- int retval = 0;
for (p = ifap; p; p = p->ifa_next)
{
+ struct sockaddr_in *sin = (struct sockaddr_in*) p->ifa_addr;
if (strcmp (p->ifa_name, ifname) != 0)
continue;
- struct sockaddr_in *sin = (struct sockaddr_in*) p->ifa_addr;
if (sin->sin_family == AF_INET)
if (del_address (ifname, sin->sin_addr) < 0)
retval = -1;
int flush_addresses (const char *ifname)
{
int s;
+ struct ifconf ifc;
+ int retval = 0;
+ int i;
+ void *ifrs;
+ int nifs;
+ struct ifreq *ifr;
+
if ((s = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
{
logger (LOG_ERR, "socket: %s", strerror (errno));
return -1;
}
- struct ifconf ifc;
memset (&ifc, 0, sizeof (struct ifconf));
ifc.ifc_buf = NULL;
if (ioctl (s, SIOCGIFCONF, &ifc) < 0)
close (s);
}
- void *ifrs = xmalloc (ifc.ifc_len);
+ ifrs = xmalloc (ifc.ifc_len);
ifc.ifc_buf = ifrs;
if (ioctl (s, SIOCGIFCONF, &ifc) < 0)
{
close (s);
- int nifs = ifc.ifc_len / sizeof (struct ifreq);
- struct ifreq *ifr = ifrs;
- int retval = 0;
- int i;
+ nifs = ifc.ifc_len / sizeof (struct ifreq);
+ ifr = ifrs;
for (i = 0; i < nifs; i++)
{
+ struct sockaddr_in *in = (struct sockaddr_in *) &ifr->ifr_addr;
+
if (ifr->ifr_addr.sa_family != AF_INET
|| strcmp (ifname, ifr->ifr_name) != 0)
continue;
- struct sockaddr_in *in = (struct sockaddr_in *) &ifr->ifr_addr;
if (del_address (ifname, in->sin_addr) < 0)
retval = -1;
ifr++;
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* We use BSD structure so our code is more portable */
-#define _BSD_SOURCE
-
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
-#include <time.h>
#include <unistd.h>
#include "dhcp.h"
int n = 0;
int fd = 0;
char device[PATH_MAX];
+ int flags;
+ struct ifreq ifr;
+ int buf = 0;
+ struct bpf_program p;
do
{
return -1;
}
- int flags;
if ((flags = fcntl (fd, F_GETFD, 0)) < 0
|| fcntl (fd, F_SETFD, flags | FD_CLOEXEC) < 0)
{
return -1;
}
- struct ifreq ifr;
strncpy (ifr.ifr_name, iface->name, sizeof (ifr.ifr_name));
if (ioctl (fd, BIOCSETIF, &ifr) < 0)
{
}
/* Get the required BPF buffer length from the kernel. */
- int buf = 0;
if (ioctl (fd, BIOCGBLEN, &buf) < 0)
{
logger (LOG_ERR, "ioctl BIOCGBLEN: %s", strerror (errno));
}
iface->buffer_length = buf;
- int flag = 1;
- if (ioctl (fd, BIOCIMMEDIATE, &flag) < 0)
+ if (ioctl (fd, BIOCIMMEDIATE, &flags) < 0)
{
logger (LOG_ERR, "ioctl BIOCIMMEDIATE: %s", strerror (errno));
close (fd);
}
/* Install the DHCP filter */
- struct bpf_program p;
if (arp)
{
p.bf_insns = arp_bpf_filter;
int send_packet (const interface_t *iface, int type,
const unsigned char *data, int len)
{
+ int retval = -1;
+ struct iovec iov[2];
+
/* We only support ethernet atm */
struct ether_header hw;
memset (&hw, 0, sizeof (struct ether_header));
memset (&hw.ether_dhost, 0xff, ETHER_ADDR_LEN);
hw.ether_type = htons (type);
- int retval = -1;
- struct iovec iov[2];
-
iov[0].iov_base = &hw;
iov[0].iov_len = sizeof (struct ether_header);
iov[1].iov_base = (unsigned char *) data;
if (*buffer_len < 1)
{
logger (LOG_ERR, "read: %s", strerror (errno));
- struct timespec tv;
- tv.tv_sec = 5;
- tv.tv_nsec = 0;
- nanosleep (&tv, NULL);
+ sleep (3);
return -1;
}
}
packet = (struct bpf_hdr *) buf;
while (packet)
{
+ int len = -1;
+
/* Ensure that the entire packet is in our buffer */
if (*buffer_pos + packet->bh_hdrlen + packet->bh_caplen
> (unsigned) *buffer_len)
hdr = (unsigned char *) ((char *) hw + sizeof (struct ether_header));
/* If it's an ARP reply, then just send it back */
- int len = -1;
if (hw->ether_type == htons (ETHERTYPE_ARP))
{
len = packet->bh_caplen - sizeof (struct ether_header);
unsigned char *buffer, int *buffer_len, int *buffer_pos)
{
long bytes;
+ struct udp_dhcp_packet *dhcp;
- /* We don't use the given buffer, but we need to rewind the position */
+ /* We don't use the given buffer, but we need to rewind the position */
*buffer_pos = 0;
memset (buffer, 0, iface->buffer_length);
if (bytes < 0)
{
logger (LOG_ERR, "read: %s", strerror (errno));
- struct timespec tv;
- tv.tv_sec = 5;
- tv.tv_nsec = 0;
- nanosleep (&tv, NULL);
+ sleep (3);
return -1;
}
return -1;
}
- struct udp_dhcp_packet *dhcp = (struct udp_dhcp_packet *) buffer;
+ dhcp = (struct udp_dhcp_packet *) buffer;
if (bytes < ntohs (dhcp->ip.ip_len))
{
logger (LOG_DEBUG, "truncated packet, ignoring");