/*
* dhcpcd-online
- * Copyright 2014 Roy Marples <roy@marples.name>
+ * Copyright 2014-2015 Roy Marples <roy@marples.name>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
# endif
#endif
+#ifndef timespeccmp
+#define timespeccmp(tsp, usp, cmp) \
+ (((tsp)->tv_sec == (usp)->tv_sec) ? \
+ ((tsp)->tv_nsec cmp (usp)->tv_nsec) : \
+ ((tsp)->tv_sec cmp (usp)->tv_sec))
+#endif
+#ifndef timespecsub
+#define timespecsub(tsp, usp, vsp) \
+ do { \
+ (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \
+ (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \
+ if ((vsp)->tv_nsec < 0) { \
+ (vsp)->tv_sec--; \
+ (vsp)->tv_nsec += 1000000000L; \
+ } \
+ } while (/* CONSTCOND */ 0)
+#endif
+
+/* Incase we need to pass anything else in context to status cb */
+struct ctx {
+ struct pollfd pollfd;
+};
+
static void __dead
do_exit(DHCPCD_CONNECTION *con, int code)
{
+ /* Unregister the status callback so that close doesn't spam. */
+ dhcpcd_set_status_callback(con, NULL, NULL);
+
dhcpcd_close(con);
dhcpcd_free(con);
exit(code);
}
static void
-do_status_cb(DHCPCD_CONNECTION *con, const char *status, void __unused *arg)
+status_cb(DHCPCD_CONNECTION *con,
+ unsigned int status, const char *status_msg, void *arg)
{
+ struct ctx *ctx;
- syslog(LOG_INFO, "%s", status);
- if (strcmp(status, "connected") == 0)
+ syslog(LOG_INFO, "%s", status_msg);
+ switch (status) {
+ case DHC_CONNECTED:
do_exit(con, EXIT_SUCCESS);
+ /* NOT REACHED */
+ case DHC_DOWN:
+ ctx = arg;
+ ctx->pollfd.fd = -1;
+ break;
+ }
}
int
DHCPCD_CONNECTION *con;
bool xflag;
struct timespec now, end, t;
- struct pollfd pfd;
+ struct ctx ctx;
int timeout, n, lerrno;
long lnum;
char *lend;
timeout = 30;
xflag = false;
+ ctx.pollfd.fd = -1;
+ ctx.pollfd.events = POLLIN;
+ ctx.pollfd.revents = 0;
openlog("dhcpcd-online", LOG_PERROR, 0);
setlogmask(LOG_UPTO(LOG_INFO));
syslog(LOG_ERR, "dhcpcd_new: %m");
return EXIT_FAILURE;
}
+ dhcpcd_set_status_callback(con, status_cb, &ctx);
- dhcpcd_set_status_callback(con, do_status_cb, NULL);
-
- if ((pfd.fd = dhcpcd_open(con)) == -1) {
+ if ((ctx.pollfd.fd = dhcpcd_open(con, false)) == -1) {
lerrno = errno;
syslog(LOG_WARNING, "dhcpcd_open: %m");
if (xflag)
do_exit(con, EXIT_FAILURE);
} else
lerrno = 0;
- pfd.events = POLLIN;
- pfd.revents = 0;
/* Work out our timeout time */
if (clock_gettime(CLOCK_MONOTONIC, &end) == -1) {
syslog(LOG_ERR, "timed out");
do_exit(con, EXIT_FAILURE);
}
- if (pfd.fd == -1) {
+ if (ctx.pollfd.fd == -1) {
n = poll(NULL, 0, DHCPCD_RETRYOPEN);
} else {
/* poll(2) should really take a timespec */
(t.tv_nsec + 999999) / 1000000 > INT_MAX % 1000000))
timeout = INT_MAX;
else
- timeout = (int)t.tv_sec * 1000 +
- (t.tv_nsec + 999999) / 1000000;
- n = poll(&pfd, 1, timeout);
+ timeout = (int)(t.tv_sec * 1000 +
+ (t.tv_nsec + 999999) / 1000000);
+ n = poll(&ctx.pollfd, 1, timeout);
}
if (n == -1) {
syslog(LOG_ERR, "poll: %m");
do_exit(con, EXIT_FAILURE);
}
- if (pfd.fd == -1) {
- if ((pfd.fd = dhcpcd_open(con)) == -1) {
+ if (ctx.pollfd.fd == -1) {
+ if ((ctx.pollfd.fd = dhcpcd_open(con, false)) == -1) {
if (lerrno != errno) {
lerrno = errno;
syslog(LOG_WARNING, "dhcpcd_open: %m");
}
}
} else {
- if (n > 0 && pfd.revents)
+ if (n > 0 && ctx.pollfd.revents)
dhcpcd_dispatch(con);
}
}