Make write() and sendto() properly handle short writes and errors in ndhc.

Make ndhc write a pidfile.
Clean up defines.h and split out ifchd and ndhc specifics.
This commit is contained in:
Nicholas J. Kain 2010-11-12 18:44:49 -05:00
parent e781322b4d
commit eb6009a5ee
7 changed files with 82 additions and 30 deletions

View File

@ -1,12 +1,14 @@
#define MAX_PATH_LENGTH 1024
#ifndef IFCHD_DEFINES_H_
#define IFCHD_DEFINES_H_
#include "defines.h"
#define PID_FILE_DEFAULT "/var/run/ifchd.pid"
#define IFCHD_VERSION "0.8"
#define COMM_SOCKET_PATH "ifchange"
#define MAX_BUF 1024
#define MAXLINE 1024
#define SOCK_QUEUE 2
#define CONN_TIMEOUT 60
#define LINUX 1
#endif /* IFCHD_DEFINES_H_ */

View File

@ -1,5 +1,5 @@
/* ifchd.c - interface change daemon
* Time-stamp: <2010-11-12 17:22:34 njk>
* Time-stamp: <2010-11-12 18:40:54 njk>
*
* (C) 2004-2010 Nicholas J. Kain <njkain at gmail dot com>
*
@ -39,7 +39,7 @@
#define _GNU_SOURCE
#include <getopt.h>
#include "defines.h"
#include "ifchd-defines.h"
#include "malloc.h"
#include "log.h"
#include "chroot.h"

View File

@ -1,5 +1,5 @@
/* linux.c - ifchd Linux-specific functions
* Time-stamp: <2010-11-12 14:29:32 njk>
* Time-stamp: <2010-11-12 18:41:15 njk>
*
* (C) 2004-2010 Nicholas J. Kain <njkain at gmail dot com>
*
@ -37,7 +37,7 @@
#include <errno.h>
#include "defines.h"
#include "ifchd-defines.h"
#include "log.h"
#include "strlist.h"
#include "ifproto.h"

View File

@ -39,6 +39,7 @@
#include <pwd.h>
#include <grp.h>
#include "ndhc-defines.h"
#include "dhcpd.h"
#include "dhcpc.h"
#include "options.h"
@ -50,6 +51,7 @@
#include "chroot.h"
#include "cap.h"
#include "strl.h"
#include "pidfile.h"
#include "malloc.h"
#define VERSION "1.0"
@ -456,7 +458,8 @@ static int do_work(void)
int main(int argc, char **argv)
{
char chroot_dir[255];
char pidfile[MAX_PATH_LENGTH] = "";
char chroot_dir[MAX_PATH_LENGTH] = PID_FILE_DEFAULT;
int c, len;
struct passwd *pwd;
uid_t uid = 0;
@ -465,6 +468,7 @@ int main(int argc, char **argv)
{"clientid", required_argument, 0, 'c'},
{"foreground", no_argument, 0, 'f'},
{"background", no_argument, 0, 'b'},
{"pidfile", required_argument, 0, 'p'},
{"hostname", required_argument, 0, 'H'},
{"hostname", required_argument, 0, 'h'},
{"interface", required_argument, 0, 'i'},
@ -481,7 +485,7 @@ int main(int argc, char **argv)
/* get options */
while (1) {
int option_index = 0;
c = getopt_long(argc, argv, "c:fbH:h:i:np:qr:u:C:v", arg_options,
c = getopt_long(argc, argv, "c:fbp:H:h:i:np:qr:u:C:v", arg_options,
&option_index);
if (c == -1) break;
@ -502,6 +506,9 @@ int main(int argc, char **argv)
case 'b':
client_config.background_if_no_lease = 1;
break;
case 'p':
strlcpy(pidfile, optarg, MAX_PATH_LENGTH);
break;
case 'h':
case 'H':
len = strlen(optarg) > 255 ? 255 : strlen(optarg);
@ -549,6 +556,12 @@ int main(int argc, char **argv)
log_line("ndhc client " VERSION " started.");
if (file_exists(pidfile, "w") == -1) {
log_line("FATAL - cannot open pidfile for write!");
exit(EXIT_FAILURE);
}
write_pid(pidfile);
if (read_interface(client_config.interface, &client_config.ifindex,
NULL, client_config.arp) < 0)
exit(EXIT_FAILURE);

11
ndhc/ndhc-defines.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef NDHC_DEFINES_H_
#define NDHC_DEFINES_H_
#include "defines.h"
#define PID_FILE_DEFAULT "/var/run/ndhc.pid"
#define NDHC_VERSION "1.0"
#define MAX_BUF 1024
#endif /* NDHC_DEFINES_H_ */

View File

@ -149,11 +149,21 @@ int raw_packet(struct dhcpMessage *payload, uint32_t source_ip,
packet.ip.ttl = IPDEFTTL;
packet.ip.check = checksum(&(packet.ip), sizeof(packet.ip));
result = sendto(fd, &packet, sizeof(struct udp_dhcp_packet), 0,
(struct sockaddr *)&dest, sizeof dest);
if (result <= 0) {
log_error("write on socket failed: %s",
strerror(errno));
int remain = sizeof(struct udp_dhcp_packet);
int sent = 0;
while (1) {
result = sendto(fd, &packet + sent, remain, 0,
(struct sockaddr *)&dest, sizeof dest);
if (result == -1) {
if (errno == EINTR)
continue;
log_error("raw_packet: sendto failed: %s", strerror(errno));
break;
}
remain =- result;
sent += result;
if (remain == 0)
break;
}
out_fd:
close(fd);
@ -190,7 +200,21 @@ int kernel_packet(struct dhcpMessage *payload, uint32_t source_ip,
if (connect(fd, (struct sockaddr *)&client, sizeof(struct sockaddr)) == -1)
goto out_fd;
result = write(fd, payload, sizeof(struct dhcpMessage));
int remain = sizeof(struct dhcpMessage);
int sent = 0;
while (1) {
result = write(fd, payload + sent, remain);
if (result == -1) {
if (errno == EINTR)
continue;
log_error("kernel_packet: write failed: %s", strerror(errno));
break;
}
remain =- result;
sent += result;
if (remain == 0)
break;
}
out_fd:
close(fd);
out:

View File

@ -144,21 +144,23 @@ static int open_ifch(void) {
return sockfd;
}
static void sockwrite(int fd, const void *buf, size_t count)
static void sockwrite(int fd, const char *buf, size_t count)
{
int ret;
sockwrite_again:
ret = write(fd, buf, count);
if (ret == -1) {
if (errno == EAGAIN)
goto sockwrite_again;
log_error("error while writing to unix socket!");
exit(EXIT_FAILURE);
}
if (ret < 0) ret = 0;
if ((unsigned int)ret < strlen(buf)) {
log_error("incomplete write!");
int remain = count;
int sent = 0;
while (1) {
ret = write(fd, buf + sent, remain);
if (ret == -1) {
if (errno == EINTR)
continue;
log_error("sockwrite: write failed: %s", strerror(errno));
break;
}
remain =- ret;
sent += ret;
if (remain == 0)
break;
}
log_line("writing: %s", (char *)buf);
}