summaryrefslogtreecommitdiffstats
path: root/btime.c
diff options
context:
space:
mode:
authorNate Straz <nstraz@redhat.com>2006-08-03 14:48:40 +0000
committerNathan Straz <nstraz@redhat.com>2008-09-23 09:37:46 -0400
commitd1b5e0346ac271397d4d1df2417c3378f46ef4cb (patch)
treec2a2dde809428605f4cafaa604483feec1f49df8 /btime.c
parentc750cf3977831da3646bbfa0085147c27f4422ce (diff)
downloadqarsh-d1b5e0346ac271397d4d1df2417c3378f46ef4cb.zip
qarsh-d1b5e0346ac271397d4d1df2417c3378f46ef4cb.tar.gz
qarsh-d1b5e0346ac271397d4d1df2417c3378f46ef4cb.tar.xz
Add cookies to the heartbeat packet for added safety.v1.10-1
Two factors forced this change. 1. ports were being re-used so quickly that we could get lingering packets from past hosts when getting the btime for a new host. 2. We can't control which IP a btime response is sent from if a system has more than one interface. Adding a cookie allows us to know that a response came from whom we sent it.
Diffstat (limited to 'btime.c')
-rw-r--r--btime.c60
1 files changed, 46 insertions, 14 deletions
diff --git a/btime.c b/btime.c
index bb0857e..5e151be 100644
--- a/btime.c
+++ b/btime.c
@@ -13,6 +13,7 @@
#include "btime_int.h"
static int same_addr(struct sockaddr_in *a, struct sockaddr_in *b);
+static void gen_cookie(char *s);
/*
* btime --
*
@@ -27,15 +28,16 @@ unsigned int
btime(const char *host)
{
int sd;
- char msg[BTIME_MSGLEN];
+ char cookie[BTIME_MSGLEN];
+ char response[BTIME_MSGLEN];
struct sockaddr_in serv_addr;
struct sockaddr_in my_addr;
struct sockaddr_in resp_addr;
- int serv_addr_len;
- int resp_addr_len;
+ socklen_t serv_addr_len;
+ socklen_t resp_addr_len;
struct hostent *hostent;
in_addr_t inaddr;
- unsigned int btime;
+ unsigned int btime = 0;
ssize_t nbytes;
int retry;
@@ -69,10 +71,11 @@ btime(const char *host)
return 0;
}
- memset(msg, 0, BTIME_MSGLEN);
+ memset(cookie, 0, BTIME_MSGLEN);
+ gen_cookie(cookie);
for (retry = 0; retry < MAX_RETRY; retry++) {
serv_addr_len = sizeof serv_addr;
- if ((nbytes = sendto(sd, &msg, BTIME_MSGLEN, MSG_DONTWAIT,
+ if ((nbytes = sendto(sd, &cookie, BTIME_MSGLEN, MSG_DONTWAIT,
(struct sockaddr *)&serv_addr, serv_addr_len)) < 0) {
if (errno == EAGAIN) {
usleep(retry * 100);
@@ -87,18 +90,34 @@ btime(const char *host)
memset(&resp_addr, 0, sizeof resp_addr);
- memset(msg, 0, BTIME_MSGLEN);
+ memset(response, 0, BTIME_MSGLEN);
for (retry = 0; retry < MAX_RETRY; retry++) {
resp_addr_len = sizeof resp_addr;
- if ((nbytes = recvfrom(sd, &msg, BTIME_MSGLEN, MSG_DONTWAIT,
+ if ((nbytes = recvfrom(sd, &response, BTIME_MSGLEN, MSG_DONTWAIT,
(struct sockaddr *)&resp_addr, &resp_addr_len)) < 0) {
if (errno == EAGAIN) {
usleep(retry * 100);
+ continue;
} else {
/* Non EAGAIN error... */
break;
}
+ }
+
+ if (nbytes == 0) {
+ /* Nothing received, try again */
+ continue;
+ } else if (response[0] == 'B' && response[1] == 'T') {
+ /* Check for new style cookie */
+ if (memcmp(cookie, response, COOKIE_LEN) == 0) {
+ btime = strtoul(response+COOKIE_LEN, NULL, 10);
+ break;
+ } else {
+ fprintf(stderr, "Ignoring invalid cookie\n");
+ continue;
+ }
} else if (!same_addr(&serv_addr, &resp_addr)) {
+ /* If no cookie, check peer */
char *rstr = strdup(inet_ntoa(resp_addr.sin_addr));
char *sstr = strdup(inet_ntoa(serv_addr.sin_addr));
fprintf(stderr, "Got response from %s instead of %s\n",
@@ -107,16 +126,12 @@ btime(const char *host)
free(sstr);
continue;
} else {
+ /* If peer matches, accept the bare btime */
+ btime = strtoul(response, (char **)NULL, 10);
break;
}
}
- if (nbytes == 0) {
- btime = 0;
- } else {
- btime = strtoul(msg, (char **)NULL, 10);
- }
-
close(sd);
return btime;
@@ -141,3 +156,20 @@ same_addr(struct sockaddr_in *a, struct sockaddr_in *b)
return 1;
}
}
+/* gen_cookie
+ *
+ * Generate a random string that btimed will send back to us.
+ */
+static void gen_cookie(char *s)
+{
+ char *a = s;
+ int i;
+
+ *a++ = 'B';
+ *a++ = 'T';
+ for (i = 0; i < COOKIE_RANDOM_PARTS; i++) {
+ *(int *)a = random();
+ a += sizeof(int);
+ }
+ *a = '\n';
+}