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 PID_FILE_DEFAULT "/var/run/ifchd.pid"
#define IFCHD_VERSION "0.8" #define IFCHD_VERSION "0.8"
#define COMM_SOCKET_PATH "ifchange" #define COMM_SOCKET_PATH "ifchange"
#define MAX_BUF 1024 #define MAX_BUF 1024
#define MAXLINE 1024
#define SOCK_QUEUE 2 #define SOCK_QUEUE 2
#define CONN_TIMEOUT 60 #define CONN_TIMEOUT 60
#define LINUX 1
#endif /* IFCHD_DEFINES_H_ */

View File

@ -1,5 +1,5 @@
/* ifchd.c - interface change daemon /* 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> * (C) 2004-2010 Nicholas J. Kain <njkain at gmail dot com>
* *
@ -39,7 +39,7 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include <getopt.h> #include <getopt.h>
#include "defines.h" #include "ifchd-defines.h"
#include "malloc.h" #include "malloc.h"
#include "log.h" #include "log.h"
#include "chroot.h" #include "chroot.h"

View File

@ -1,5 +1,5 @@
/* linux.c - ifchd Linux-specific functions /* 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> * (C) 2004-2010 Nicholas J. Kain <njkain at gmail dot com>
* *
@ -37,7 +37,7 @@
#include <errno.h> #include <errno.h>
#include "defines.h" #include "ifchd-defines.h"
#include "log.h" #include "log.h"
#include "strlist.h" #include "strlist.h"
#include "ifproto.h" #include "ifproto.h"

View File

@ -39,6 +39,7 @@
#include <pwd.h> #include <pwd.h>
#include <grp.h> #include <grp.h>
#include "ndhc-defines.h"
#include "dhcpd.h" #include "dhcpd.h"
#include "dhcpc.h" #include "dhcpc.h"
#include "options.h" #include "options.h"
@ -50,6 +51,7 @@
#include "chroot.h" #include "chroot.h"
#include "cap.h" #include "cap.h"
#include "strl.h" #include "strl.h"
#include "pidfile.h"
#include "malloc.h" #include "malloc.h"
#define VERSION "1.0" #define VERSION "1.0"
@ -456,7 +458,8 @@ static int do_work(void)
int main(int argc, char **argv) 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; int c, len;
struct passwd *pwd; struct passwd *pwd;
uid_t uid = 0; uid_t uid = 0;
@ -465,6 +468,7 @@ int main(int argc, char **argv)
{"clientid", required_argument, 0, 'c'}, {"clientid", required_argument, 0, 'c'},
{"foreground", no_argument, 0, 'f'}, {"foreground", no_argument, 0, 'f'},
{"background", no_argument, 0, 'b'}, {"background", no_argument, 0, 'b'},
{"pidfile", required_argument, 0, 'p'},
{"hostname", required_argument, 0, 'H'}, {"hostname", required_argument, 0, 'H'},
{"hostname", required_argument, 0, 'h'}, {"hostname", required_argument, 0, 'h'},
{"interface", required_argument, 0, 'i'}, {"interface", required_argument, 0, 'i'},
@ -481,7 +485,7 @@ int main(int argc, char **argv)
/* get options */ /* get options */
while (1) { while (1) {
int option_index = 0; 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); &option_index);
if (c == -1) break; if (c == -1) break;
@ -502,6 +506,9 @@ int main(int argc, char **argv)
case 'b': case 'b':
client_config.background_if_no_lease = 1; client_config.background_if_no_lease = 1;
break; break;
case 'p':
strlcpy(pidfile, optarg, MAX_PATH_LENGTH);
break;
case 'h': case 'h':
case 'H': case 'H':
len = strlen(optarg) > 255 ? 255 : strlen(optarg); len = strlen(optarg) > 255 ? 255 : strlen(optarg);
@ -549,6 +556,12 @@ int main(int argc, char **argv)
log_line("ndhc client " VERSION " started."); 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, if (read_interface(client_config.interface, &client_config.ifindex,
NULL, client_config.arp) < 0) NULL, client_config.arp) < 0)
exit(EXIT_FAILURE); 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.ttl = IPDEFTTL;
packet.ip.check = checksum(&(packet.ip), sizeof(packet.ip)); packet.ip.check = checksum(&(packet.ip), sizeof(packet.ip));
result = sendto(fd, &packet, sizeof(struct udp_dhcp_packet), 0, int remain = sizeof(struct udp_dhcp_packet);
int sent = 0;
while (1) {
result = sendto(fd, &packet + sent, remain, 0,
(struct sockaddr *)&dest, sizeof dest); (struct sockaddr *)&dest, sizeof dest);
if (result <= 0) { if (result == -1) {
log_error("write on socket failed: %s", if (errno == EINTR)
strerror(errno)); continue;
log_error("raw_packet: sendto failed: %s", strerror(errno));
break;
}
remain =- result;
sent += result;
if (remain == 0)
break;
} }
out_fd: out_fd:
close(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) if (connect(fd, (struct sockaddr *)&client, sizeof(struct sockaddr)) == -1)
goto out_fd; 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: out_fd:
close(fd); close(fd);
out: out:

View File

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