Change ifchange_*() so that the interface and ip keywords are only sent to

ifchd if it is necessary to do so, just as is the case for other keywords.

Make data sending in ifchange_*() collect all keywords into a buffer that
is sent in a single sockwrite() rather than performing a sockwrite() for
every keyword.

Minor documentation updates.
This commit is contained in:
Nicholas J. Kain 2011-07-05 19:25:19 -04:00
parent 3316505f3c
commit daf42ccb29
2 changed files with 54 additions and 36 deletions

15
README
View File

@ -36,9 +36,18 @@ the ability to service multiple client requests simultaneously; a single ifchd
is sufficient for multiple ndhc clients. Only exotic setups should require is sufficient for multiple ndhc clients. Only exotic setups should require
this functionality, but it does exist. this functionality, but it does exist.
Note that ndhc does not support the entire DHCP client protocol. Only the Note that ndhc does not support the entire DHCP client protocol. Notably, DHCP
minimum necessary featureset is implemented. This behavior should be familiar options concatenation and IPv4 Link Local Addressing as defined in RFC3927 are
to anyone who has used software that purports to be be secure. not and will not be supported.
On the other hand, ndhc fully implements RFC5227's address conflict detection
and defense. Great care is taken to ensure that address conflicts will be
detected, and ndhc also has extensive support for address defense. Care is
taken to prevent unintentional ARP flooding under any circumstance.
ndhc also monitors hardware link status via netlink events and reacts
appropriately when interface carrier status changes or an interface is
explicitly deconfigured.
USAGE USAGE
----- -----

View File

@ -1,5 +1,5 @@
/* ifchange.c - functions to call the interface change daemon /* ifchange.c - functions to call the interface change daemon
* Time-stamp: <2011-07-04 22:03:35 njk> * Time-stamp: <2011-07-05 19:22:50 njk>
* *
* (c) 2004-2011 Nicholas J. Kain <njkain at gmail dot com> * (c) 2004-2011 Nicholas J. Kain <njkain at gmail dot com>
* *
@ -37,6 +37,7 @@
#include "arp.h" #include "arp.h"
#include "log.h" #include "log.h"
#include "io.h" #include "io.h"
#include "strl.h"
#include "ifchange.h" #include "ifchange.h"
static int cfg_deconfig; // Set if the interface has already been deconfigured. static int cfg_deconfig; // Set if the interface has already been deconfigured.
@ -154,8 +155,6 @@ static void sockwrite(int fd, const char *buf, size_t count)
{ {
if (safe_write(fd, buf, count) == -1) if (safe_write(fd, buf, count) == -1)
log_error("sockwrite: write failed: %s", strerror(errno)); log_error("sockwrite: write failed: %s", strerror(errno));
else
log_line("sent to ifchd: %s", buf);
} }
void ifchange_deconfig(void) void ifchange_deconfig(void)
@ -168,10 +167,9 @@ void ifchange_deconfig(void)
sockfd = open_ifch(); sockfd = open_ifch();
snprintf(buf, sizeof buf, "interface:%s:", client_config.interface); snprintf(buf, sizeof buf, "interface:%s:ip:0.0.0.0:",
sockwrite(sockfd, buf, strlen(buf)); client_config.interface);
log_line("sent to ifchd: ip:0.0.0.0:");
snprintf(buf, sizeof buf, "ip:0.0.0.0:");
sockwrite(sockfd, buf, strlen(buf)); sockwrite(sockfd, buf, strlen(buf));
cfg_deconfig = 1; cfg_deconfig = 1;
@ -180,56 +178,67 @@ void ifchange_deconfig(void)
close(sockfd); close(sockfd);
} }
static void send_cmd(int sockfd, struct dhcpmsg *packet, uint8_t code) static size_t send_client_ip(char *out, size_t olen, struct dhcpmsg *packet)
{
char ip[32], ipb[64];
if (!memcmp(&packet->yiaddr, &cfg_packet.yiaddr, sizeof packet->yiaddr))
return 0;
inet_ntop(AF_INET, &packet->yiaddr, ip, sizeof ip);
snprintf(ipb, sizeof ipb, "ip:%s:", ip);
strlcat(out, ipb, olen);
log_line("sent to ifchd: %s", ipb);
return strlen(ipb);
}
static size_t send_cmd(char *out, size_t olen, struct dhcpmsg *packet,
uint8_t code)
{ {
char buf[256]; char buf[256];
uint8_t *optdata, *olddata; uint8_t *optdata, *olddata;
ssize_t optlen, oldlen; ssize_t optlen, oldlen;
if (!packet) if (!packet)
return; return 0;
memset(buf, '\0', sizeof buf); memset(buf, '\0', sizeof buf);
optdata = get_option_data(packet, code, &optlen); optdata = get_option_data(packet, code, &optlen);
if (!optlen) if (!optlen)
return; return 0;
olddata = get_option_data(&cfg_packet, code, &oldlen); olddata = get_option_data(&cfg_packet, code, &oldlen);
if (oldlen == optlen && !memcmp(optdata, olddata, optlen)) if (oldlen == optlen && !memcmp(optdata, olddata, optlen))
return; return 0;
if (ifchd_cmd(buf, sizeof buf, optdata, optlen, code) == -1) if (ifchd_cmd(buf, sizeof buf, optdata, optlen, code) == -1)
return; return 0;
sockwrite(sockfd, buf, strlen(buf)); strlcat(out, buf, olen);
log_line("sent to ifchd: %s", buf);
return strlen(buf);
} }
void ifchange_bind(struct dhcpmsg *packet) void ifchange_bind(struct dhcpmsg *packet)
{ {
char buf[2048];
int sockfd; int sockfd;
char buf[256]; int tbs = 0;
char ip[32];
if (!packet) if (!packet)
return; return;
sockfd = open_ifch();
snprintf(buf, sizeof buf, "interface:%s:", client_config.interface); snprintf(buf, sizeof buf, "interface:%s:", client_config.interface);
sockwrite(sockfd, buf, strlen(buf)); tbs |= send_client_ip(buf, sizeof buf, packet);
tbs |= send_cmd(buf, sizeof buf, packet, DHCP_SUBNET);
inet_ntop(AF_INET, &packet->yiaddr, ip, sizeof ip); tbs |= send_cmd(buf, sizeof buf, packet, DHCP_ROUTER);
snprintf(buf, sizeof buf, "ip:%s:", ip); tbs |= send_cmd(buf, sizeof buf, packet, DHCP_DNS_SERVER);
sockwrite(sockfd, buf, strlen(buf)); tbs |= send_cmd(buf, sizeof buf, packet, DHCP_HOST_NAME);
tbs |= send_cmd(buf, sizeof buf, packet, DHCP_DOMAIN_NAME);
send_cmd(sockfd, packet, DHCP_SUBNET); tbs |= send_cmd(buf, sizeof buf, packet, DHCP_MTU);
send_cmd(sockfd, packet, DHCP_ROUTER); tbs |= send_cmd(buf, sizeof buf, packet, DHCP_BROADCAST);
send_cmd(sockfd, packet, DHCP_DNS_SERVER); tbs |= send_cmd(buf, sizeof buf, packet, DHCP_WINS_SERVER);
send_cmd(sockfd, packet, DHCP_HOST_NAME); if (tbs) {
send_cmd(sockfd, packet, DHCP_DOMAIN_NAME); sockfd = open_ifch();
send_cmd(sockfd, packet, DHCP_MTU); sockwrite(sockfd, buf, strlen(buf));
send_cmd(sockfd, packet, DHCP_BROADCAST); close(sockfd);
send_cmd(sockfd, packet, DHCP_WINS_SERVER); }
cfg_deconfig = 0; cfg_deconfig = 0;
memcpy(&cfg_packet, packet, sizeof cfg_packet); memcpy(&cfg_packet, packet, sizeof cfg_packet);
close(sockfd);
} }