From ee447a142befd4d4cfd892db3d211152037e6b50 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 2 Sep 2014 21:18:05 +0000 Subject: [PATCH 1/1] Add dhcpcd-online application to ease integration with parallal startup when dhcpcd is not forked but applcation need to depend on it. systemd could use it for dhcpcd-wait-online.service for example --- src/dhcpcd-online/Makefile | 16 +++ src/dhcpcd-online/dhcpcd-online.8 | 71 ++++++++++++++ src/dhcpcd-online/dhcpcd-online.c | 186 +++++++++++++++++++++++++++++++++++++ 3 files changed, 273 insertions(+), 0 deletions(-) create mode 100644 src/dhcpcd-online/Makefile create mode 100644 src/dhcpcd-online/dhcpcd-online.8 create mode 100644 src/dhcpcd-online/dhcpcd-online.c diff --git a/src/dhcpcd-online/Makefile b/src/dhcpcd-online/Makefile new file mode 100644 index 0000000..6881899 --- /dev/null +++ b/src/dhcpcd-online/Makefile @@ -0,0 +1,16 @@ +PROG= dhcpcd-online +SRCS= dhcpcd-online.c + +MAN8= dhcpcd-online.8 + +TOPDIR= ../.. +include ${TOPDIR}/iconfig.mk + +MAN8= dhcpcd-online.8 + +CPPFLAGS+= -I${TOPDIR} + +LDADD+= ${LIB_DHCPCD} ${LIB_INTL} + +include ../libdhcpcd/Makefile.inc +include ${MKDIR}/prog.mk diff --git a/src/dhcpcd-online/dhcpcd-online.8 b/src/dhcpcd-online/dhcpcd-online.8 new file mode 100644 index 0000000..217dcdd --- /dev/null +++ b/src/dhcpcd-online/dhcpcd-online.8 @@ -0,0 +1,71 @@ +.\" Copyright (c) 2014 Roy Marples +.\" All rights reserved +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd September 2, 2014 +.Dt DHCPCD-ONLINE +.Os +.Sh NAME +.Nm dhcpcd-online +.Nd a utility to work out if +.Xr dhcpcd 8 +is in the connected state +.Sh SYNOPSIS +.Nm +.Op Fl q +.Op Fl t Ar timeout +.Op Fl x +.Sh DESCRIPTION +.Nm +connects to +.Xr dhcpcd 8 +and waits for a maximum of +.Ar timeout +seconds until the status changes to +.Va connected . +This tool is intended for use in the startup of the host system +where +.Xr dhcpcd 8 +is started in parallel with other services who depend on a network connection +being available. +.Pp +Options: +.Bl -tag --width flag +.It Fl q +Suppresses the reporting of non error messages. +.It Fl t Ar timeout +Sets the number of seconds +.Nm +waits for +.Xr dhcpcd 8 +to reach the connected state. +If not specified, a default value of 30 is used. +.It Fl x +Exits immediately if +.Xr dhcpcd 8 +is not running. +.El +.Sh AUTHORS +.An Roy Marples Aq roy@marples.name +.Sh BUGS +Please report them to http://roy.marples.name/projects/dhcpcd-ui diff --git a/src/dhcpcd-online/dhcpcd-online.c b/src/dhcpcd-online/dhcpcd-online.c new file mode 100644 index 0000000..334960c --- /dev/null +++ b/src/dhcpcd-online/dhcpcd-online.c @@ -0,0 +1,186 @@ +/* + * dhcpcd-online + * Copyright 2014 Roy Marples + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dhcpcd.h" + +#if __GNUC__ > 2 || defined(__INTEL_COMPILER) +# ifndef __dead +# define __dead __attribute__((__noreturn__)) +# endif +# ifndef __unused +# define __unused __attribute__((__unused__)) +# endif +#else +# ifndef __dead +# define __dead +# endif +# ifndef __unused +# define __unused +# endif +#endif + +static void __dead +do_exit(DHCPCD_CONNECTION *con, int code) +{ + + dhcpcd_close(con); + dhcpcd_free(con); + exit(code); +} + +static void +do_status_cb(DHCPCD_CONNECTION *con, const char *status, void __unused *arg) +{ + + syslog(LOG_INFO, "%s", status); + if (strcmp(status, "connected") == 0) + do_exit(con, EXIT_SUCCESS); +} + +int +main(int argc, char **argv) +{ + DHCPCD_CONNECTION *con; + bool xflag; + struct timespec now, end, t; + struct pollfd pfd; + int timeout, n, lerrno; + long lnum; + char *lend; + + /* Defaults */ + timeout = 30; + + xflag = false; + + openlog("dhcpcd-online", LOG_PERROR, 0); + setlogmask(LOG_UPTO(LOG_INFO)); + + while ((n = getopt(argc, argv, "qt:x")) != -1) { + switch (n) { + case 'q': + closelog(); + openlog("dhcpcd-online", 0, 0); + break; + case 't': + lnum = strtol(optarg, &lend, 0); + if (lend == NULL || *lend != '\0' || + lnum < 0 || lnum > INT_MAX) + { + syslog(LOG_ERR, "-t %s: invalid timeout", + optarg); + exit(EXIT_FAILURE); + } + timeout = (int)lnum; + break; + case 'x': + xflag = true; + break; + case '?': + fprintf(stderr, "usage: dhcpcd-online " + "[-q] [-t timeout]\n"); + exit(EXIT_FAILURE); + } + } + + if ((con = dhcpcd_new()) == NULL) { + syslog(LOG_ERR, "dhcpcd_new: %m"); + return EXIT_FAILURE; + } + + dhcpcd_set_status_callback(con, do_status_cb, NULL); + + if ((pfd.fd = dhcpcd_open(con)) == -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, "clock_gettime: %m"); + do_exit(con, EXIT_FAILURE); + } + end.tv_sec += timeout; + + for (;;) { + if (clock_gettime(CLOCK_MONOTONIC, &now) == -1) { + syslog(LOG_ERR, "clock_gettime: %m"); + do_exit(con, EXIT_FAILURE); + } + if (timespeccmp(&now, &end, >)) { + syslog(LOG_ERR, "timed out"); + do_exit(con, EXIT_FAILURE); + } + if (pfd.fd == -1) { + n = poll(NULL, 0, DHCPCD_RETRYOPEN); + } else { + /* poll(2) should really take a timespec */ + timespecsub(&end, &now, &t); + if (t.tv_sec > INT_MAX / 1000 || + (t.tv_sec == INT_MAX / 1000 && + (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); + } + 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 (lerrno != errno) { + lerrno = errno; + syslog(LOG_WARNING, "dhcpcd_open: %m"); + } + } + } else { + if (n > 0 && pfd.revents) + dhcpcd_dispatch(con); + } + } + + /* Impossible to reach here */ + do_exit(con, EXIT_FAILURE); +} -- 1.7.1