Introduction
Introduction Statistics Contact Development Disclaimer Help
Use timerfd in order to correctly handle various renewal and rebinding timeouts…
git clone git://git.codemadness.org/sdhcp
Log
Files
Refs
LICENSE
---
commit 80bdf55532fadbf9398ce7e12fe494282f45f394
parent a5616cecc1506731f1ca20ae0d31325f9b0526b4
Author: Michael Forney <[email protected]>
Date: Wed, 14 Nov 2018 18:40:38 -0800
Use timerfd in order to correctly handle various renewal and rebinding timeouts
Diffstat:
M sdhcp.c | 139 +++++++++++++++++++++++------…
M util.h | 1 +
2 files changed, 103 insertions(+), 37 deletions(-)
---
diff --git a/sdhcp.c b/sdhcp.c
@@ -1,5 +1,6 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
+#include <sys/timerfd.h>
#include <netinet/in.h>
#include <net/if.h>
@@ -47,7 +48,9 @@ enum {
DHCPnak,
DHCPrelease,
DHCPinform,
- Timeout = 200,
+ Timeout0 = 200,
+ Timeout1,
+ Timeout2,
Bootrequest = 1,
Bootreply = 2,
@@ -89,14 +92,14 @@ static time_t starttime;
static char *ifname = "eth0";
static unsigned char cid[16];
static char *program = "";
-static int sock;
+static int sock, timers[3];
/* sav */
static unsigned char server[4];
static unsigned char client[4];
static unsigned char mask[4];
static unsigned char router[4];
static unsigned char dns[4];
-static uint32_t t1;
+static uint32_t renewaltime, rebindingtime, lease;
static int dflag = 1; /* change DNS in /etc/resolv.conf ? */
static int iflag = 1; /* set IP ? */
@@ -282,7 +285,7 @@ dhcpsend(int type, int how)
break;
case DHCPrequest:
/* memcpy(bp.ciaddr, client, sizeof bp.ciaddr); */
- p = hnoptput(p, ODlease, t1, sizeof(t1));
+ p = hnoptput(p, ODlease, lease, sizeof(lease));
p = optput(p, ODipaddr, client, sizeof(client));
p = optput(p, ODserverid, server, sizeof(server));
break;
@@ -302,22 +305,34 @@ static int
dhcprecv(void)
{
unsigned char type;
- struct pollfd pfd;
-
- memset(&pfd, 0, sizeof(pfd));
- pfd.fd = sock;
- pfd.events = POLLIN;
-
- memset(&bp, 0, sizeof(bp));
- if (poll(&pfd, 1, -1) == -1) {
- if (errno != EINTR)
- eprintf("poll:");
- else
- return Timeout;
+ struct pollfd pfd[] = {
+ { .fd = sock, .events = POLLIN },
+ { .fd = timers[0], .events = POLLIN },
+ { .fd = timers[1], .events = POLLIN },
+ { .fd = timers[2], .events = POLLIN },
+ };
+ uint64_t n;
+
+ if (poll(pfd, LEN(pfd), -1) == -1)
+ eprintf("poll:");
+ if (pfd[0].revents) {
+ memset(&bp, 0, sizeof(bp));
+ udprecv(IP(255, 255, 255, 255), sock, &bp, sizeof(bp));
+ optget(&bp, &type, ODtype, sizeof(type));
+ return type;
+ }
+ if (pfd[1].revents) {
+ type = Timeout0;
+ read(timers[0], &n, sizeof(n));
+ }
+ if (pfd[2].revents) {
+ type = Timeout1;
+ read(timers[1], &n, sizeof(n));
+ }
+ if (pfd[3].revents) {
+ type = Timeout2;
+ read(timers[2], &n, sizeof(n));
}
- udprecv(IP(255, 255, 255, 255), sock, &bp, sizeof(bp));
- optget(&bp, &type, ODtype, sizeof(type));
-
return type;
}
@@ -343,32 +358,62 @@ acceptlease(void)
setenv("DNS", buf, 1);
system(program);
}
- alarm(t1);
+}
+
+static void
+settimeout(int n, const struct itimerspec *ts)
+{
+ if (timerfd_settime(timers[n], 0, ts, NULL) < 0)
+ eprintf("timerfd_settime:");
+}
+
+/* sets ts to expire halfway to the expiration of timer n, minimum of 60 secon…
+static void
+calctimeout(int n, struct itimerspec *ts)
+{
+ if (timerfd_gettime(timers[n], ts) < 0)
+ eprintf("timerfd_gettime:");
+ ts->it_value.tv_nsec /= 2;
+ if (ts->it_value.tv_sec % 2)
+ ts->it_value.tv_nsec += 500000000;
+ ts->it_value.tv_sec /= 2;
+ if (ts->it_value.tv_sec < 60) {
+ ts->it_value.tv_sec = 60;
+ ts->it_value.tv_nsec = 0;
+ }
}
static void
run(void)
{
int forked = 0;
+ struct itimerspec timeout = { 0 };
Init:
dhcpsend(DHCPdiscover, Broadcast);
- alarm(1);
+ timeout.it_value.tv_sec = 1;
+ timeout.it_value.tv_nsec = 0;
+ settimeout(0, &timeout);
goto Selecting;
Selecting:
for (;;) {
switch (dhcprecv()) {
case DHCPoffer:
- alarm(0);
+ timeout.it_value.tv_sec = 0;
+ settimeout(0, &timeout);
memcpy(client, bp.yiaddr, sizeof(client));
optget(&bp, server, ODserverid, sizeof(server));
optget(&bp, mask, OBmask, sizeof(mask));
optget(&bp, router, OBrouter, sizeof(router));
optget(&bp, dns, OBdnsserver, sizeof(dns));
- optget(&bp, &t1, ODlease, sizeof(t1));
- t1 = ntohl(t1);
+ optget(&bp, &renewaltime, ODrenewaltime, sizeof(renewa…
+ optget(&bp, &rebindingtime, ODrebindingtime, sizeof(re…
+ optget(&bp, &lease, ODlease, sizeof(lease));
+ renewaltime = ntohl(renewaltime);
+ rebindingtime = ntohl(rebindingtime);
+ lease = ntohl(lease);
goto Requesting;
- case Timeout:
+ case Timeout0:
goto Init;
}
}
@@ -390,43 +435,57 @@ Bound:
exit(0);
forked = 1;
}
+ timeout.it_value.tv_sec = renewaltime;
+ settimeout(0, &timeout);
+ timeout.it_value.tv_sec = rebindingtime;
+ settimeout(1, &timeout);
+ timeout.it_value.tv_sec = lease;;
+ settimeout(2, &timeout);
for (;;) {
switch (dhcprecv()) {
- case Timeout:
+ case Timeout0: /* t1 elapsed */
goto Renewing;
+ case Timeout1: /* t2 elapsed */
+ goto Rebinding;
+ case Timeout2: /* lease expired */
+ goto Init;
}
}
Renewing:
dhcpsend(DHCPrequest, Unicast);
+ calctimeout(1, &timeout);
+ settimeout(0, &timeout);
for (;;) {
switch (dhcprecv()) {
case DHCPack:
goto Bound;
+ case Timeout0: /* resend request */
+ goto Renewing;
+ case Timeout1: /* t2 elapsed */
+ goto Rebinding;
+ case Timeout2:
case DHCPnak:
goto Init;
- case Timeout:
- goto Rebinding;
}
}
Rebinding:
+ calctimeout(2, &timeout);
+ settimeout(0, &timeout);
dhcpsend(DHCPrequest, Broadcast);
for (;;) {
switch (dhcprecv()) {
- case DHCPnak: /* lease expired */
- goto Init;
case DHCPack:
goto Bound;
+ case Timeout0: /* resend request */
+ goto Rebinding;
+ case Timeout2: /* lease expired */
+ case DHCPnak:
+ goto Init;
}
}
}
static void
-nop(int unused)
-{
- (void)unused;
-}
-
-static void
cleanexit(int unused)
{
(void)unused;
@@ -447,6 +506,7 @@ main(int argc, char *argv[])
struct ifreq ifreq;
struct sockaddr addr;
int rnd;
+ size_t i;
ARGBEGIN {
case 'd': /* don't update DNS in /etc/resolv.conf */
@@ -472,7 +532,6 @@ main(int argc, char *argv[])
strlcpy((char *)cid, argv[1], sizeof(cid)); /* client-id */
memset(&ifreq, 0, sizeof(ifreq));
- signal(SIGALRM, nop);
signal(SIGTERM, cleanexit);
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
@@ -497,6 +556,12 @@ main(int argc, char *argv[])
read(rnd, xid, sizeof(xid));
close(rnd);
+ for (i = 0; i < LEN(timers); ++i) {
+ timers[i] = timerfd_create(CLOCK_BOOTTIME, TFD_CLOEXEC);
+ if (timers[i] == -1)
+ eprintf("timerfd_create:");
+ }
+
starttime = time(NULL);
run();
diff --git a/util.h b/util.h
@@ -1,4 +1,5 @@
#define MIN(a,b) (((a)<(b))?(a):(b))
+#define LEN(a) (sizeof(a) / sizeof((a)[0]))
#define bpdump(p,n) 1
#undef strlcpy
You are viewing proxied material from codemadness.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.