Use safe SIGINT handler

This commit is contained in:
Joseph C. Lehner 2016-11-20 12:10:55 +01:00
parent b9504f17c8
commit 98fdb9e63c
5 changed files with 63 additions and 54 deletions

View file

@ -100,7 +100,7 @@ static bool get_intf_info(const char *intf, uint8_t *hwaddr, void *dummy)
bool found; bool found;
if (getifaddrs(&ifas) != 0) { if (getifaddrs(&ifas) != 0) {
perror("getifaddrs"); xperror("getifaddrs");
return false; return false;
} }
@ -152,7 +152,7 @@ static bool get_intf_info(const char *intf, uint8_t *hwaddr, DWORD *index)
adapters = malloc(bufLen); adapters = malloc(bufLen);
if (!adapters) { if (!adapters) {
perror("malloc"); xperror("malloc");
return false; return false;
} }
@ -285,7 +285,7 @@ struct ethsock *ethsock_create(const char *intf, uint16_t protocol)
sock = malloc(sizeof(struct ethsock)); sock = malloc(sizeof(struct ethsock));
if (!sock) { if (!sock) {
perror("malloc"); xperror("malloc");
return NULL; return NULL;
} }
@ -492,7 +492,7 @@ static int ethsock_arp(struct ethsock *sock, uint8_t *hwaddr, uint32_t ipaddr, s
*undo = malloc(sizeof(struct ethsock_arp_undo)); *undo = malloc(sizeof(struct ethsock_arp_undo));
if (!*undo) { if (!*undo) {
perror("malloc"); xperror("malloc");
return -1; return -1;
} }
@ -683,7 +683,7 @@ static bool set_interface_up(int fd, const char *intf, bool up)
strncpy(ifr.ifr_name, intf, IFNAMSIZ); strncpy(ifr.ifr_name, intf, IFNAMSIZ);
if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0) { if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0) {
perror("ioctl(SIOCGIFFLAGS)"); xperror("ioctl(SIOCGIFFLAGS)");
return false; return false;
} }
@ -694,7 +694,7 @@ static bool set_interface_up(int fd, const char *intf, bool up)
} }
if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0) { if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0) {
perror("ioctl(SIOCSIFFLAGS)"); xperror("ioctl(SIOCSIFFLAGS)");
return false; return false;
} }
@ -706,7 +706,7 @@ static bool set_interface_up(int fd, const char *intf, bool up)
int ethsock_ip_add(struct ethsock *sock, uint32_t ipaddr, uint32_t ipmask, struct ethsock_ip_undo **undo) int ethsock_ip_add(struct ethsock *sock, uint32_t ipaddr, uint32_t ipmask, struct ethsock_ip_undo **undo)
{ {
if (undo && !(*undo = malloc(sizeof(struct ethsock_ip_undo)))) { if (undo && !(*undo = malloc(sizeof(struct ethsock_ip_undo)))) {
perror("malloc"); xperror("malloc");
return -1; return -1;
} }
@ -729,13 +729,13 @@ int ethsock_ip_add(struct ethsock *sock, uint32_t ipaddr, uint32_t ipmask, struc
if (add) { if (add) {
set_addr(&ifr.ifr_addr, ipaddr); set_addr(&ifr.ifr_addr, ipaddr);
if (ioctl(fd, SIOCSIFADDR, &ifr) != 0) { if (ioctl(fd, SIOCSIFADDR, &ifr) != 0) {
perror("ioctl(SIOSIFADDR)"); xperror("ioctl(SIOSIFADDR)");
goto out; goto out;
} }
set_addr(&ifr.ifr_netmask, ipmask); set_addr(&ifr.ifr_netmask, ipmask);
if (ioctl(fd, SIOCSIFNETMASK, &ifr) != 0) { if (ioctl(fd, SIOCSIFNETMASK, &ifr) != 0) {
perror("ioctl(SIOCSIFNETMASK)"); xperror("ioctl(SIOCSIFNETMASK)");
goto out; goto out;
} }
@ -756,7 +756,7 @@ int ethsock_ip_add(struct ethsock *sock, uint32_t ipaddr, uint32_t ipmask, struc
//set_addr(&ifra.ifra_broadaddr, (ipaddr & ipmask) | ~ipmask); //set_addr(&ifra.ifra_broadaddr, (ipaddr & ipmask) | ~ipmask);
if (ioctl(fd, add ? SIOCAIFADDR : SIOCDIFADDR, &ifra) != 0) { if (ioctl(fd, add ? SIOCAIFADDR : SIOCDIFADDR, &ifra) != 0) {
perror(add ? "ioctl(SIOCAIFADDR)" : "ioctl(SIOCDIFADDR)"); xperroradd ? "ioctl(SIOCAIFADDR)" : "ioctl(SIOCDIFADDR)");
goto out; goto out;
} }

49
nmrp.c
View file

@ -385,21 +385,9 @@ static int is_valid_ip(struct ethsock *sock, struct in_addr *ipaddr,
return status < 0 ? status : arg.result; return status < 0 ? status : arg.result;
} }
static struct ethsock *gsock = NULL;
static struct ethsock_ip_undo *g_ip_undo = NULL;
static struct ethsock_arp_undo *g_arp_undo = NULL;
static void sigh(int sig) static void sigh(int sig)
{ {
printf("\n"); g_interrupted = 1;
if (gsock) {
ethsock_arp_del(gsock, &g_arp_undo);
ethsock_ip_del(gsock, &g_ip_undo);
ethsock_close(gsock);
gsock = NULL;
}
exit(1);
} }
static const char *spinner = "\\|/-"; static const char *spinner = "\\|/-";
@ -413,6 +401,8 @@ int nmrp_do(struct nmrpd_args *args)
time_t beg; time_t beg;
int i, status, ulreqs, expect, upload_ok, autoip; int i, status, ulreqs, expect, upload_ok, autoip;
struct ethsock *sock; struct ethsock *sock;
struct ethsock_ip_undo *ip_undo = NULL;
struct ethsock_arp_undo *arp_undo = NULL;
uint32_t intf_addr; uint32_t intf_addr;
void (*sigh_orig)(int); void (*sigh_orig)(int);
struct { struct {
@ -493,7 +483,6 @@ int nmrp_do(struct nmrpd_args *args)
return 1; return 1;
} }
gsock = sock;
sigh_orig = signal(SIGINT, sigh); sigh_orig = signal(SIGINT, sigh);
if (!autoip) { if (!autoip) {
@ -510,7 +499,7 @@ int nmrp_do(struct nmrpd_args *args)
printf("Adding %s to interface %s.\n", args->ipaddr_intf, args->intf); printf("Adding %s to interface %s.\n", args->ipaddr_intf, args->intf);
} }
if (ethsock_ip_add(sock, intf_addr, ipconf.mask.s_addr, &g_ip_undo) != 0) { if (ethsock_ip_add(sock, intf_addr, ipconf.mask.s_addr, &ip_undo) != 0) {
goto out; goto out;
} }
} }
@ -536,14 +525,14 @@ int nmrp_do(struct nmrpd_args *args)
upload_ok = 0; upload_ok = 0;
beg = time_monotonic(); beg = time_monotonic();
while (1) { while (!g_interrupted) {
printf("\rAdvertising NMRP server on %s ... %c", printf("\rAdvertising NMRP server on %s ... %c",
args->intf, spinner[i]); args->intf, spinner[i]);
fflush(stdout); fflush(stdout);
i = (i + 1) & 3; i = (i + 1) & 3;
if (pkt_send(sock, &tx) < 0) { if (pkt_send(sock, &tx) < 0) {
perror("sendto"); xperror("sendto");
goto out; goto out;
} }
@ -568,7 +557,7 @@ int nmrp_do(struct nmrpd_args *args)
expect = NMRP_C_CONF_REQ; expect = NMRP_C_CONF_REQ;
ulreqs = 0; ulreqs = 0;
do { while (!g_interrupted) {
if (expect != NMRP_C_NONE && rx.msg.code != expect) { if (expect != NMRP_C_NONE && rx.msg.code != expect) {
fprintf(stderr, "Received %s while waiting for %s!\n", fprintf(stderr, "Received %s while waiting for %s!\n",
msg_code_str(rx.msg.code), msg_code_str(expect)); msg_code_str(rx.msg.code), msg_code_str(expect));
@ -606,7 +595,7 @@ int nmrp_do(struct nmrpd_args *args)
printf("Sending configuration: %s, netmask %s.\n", printf("Sending configuration: %s, netmask %s.\n",
args->ipaddr, args->ipmask); args->ipaddr, args->ipmask);
if (ethsock_arp_add(sock, rx.eh.ether_shost, ipconf.addr.s_addr, &g_arp_undo) != 0) { if (ethsock_arp_add(sock, rx.eh.ether_shost, ipconf.addr.s_addr, &arp_undo) != 0) {
goto out; goto out;
} }
@ -714,7 +703,7 @@ int nmrp_do(struct nmrpd_args *args)
msg_hton(&tx.msg); msg_hton(&tx.msg);
if (pkt_send(sock, &tx) < 0) { if (pkt_send(sock, &tx) < 0) {
perror("sendto"); xperror("sendto");
goto out; goto out;
} }
@ -739,21 +728,21 @@ int nmrp_do(struct nmrpd_args *args)
ethsock_set_timeout(sock, args->rx_timeout); ethsock_set_timeout(sock, args->rx_timeout);
} while (1); }
status = 0; if (!g_interrupted) {
status = 0;
if (ulreqs) { if (ulreqs) {
printf("Reboot your device now.\n"); printf("Reboot your device now.\n");
} else { } else {
printf("No upload request received.\n"); printf("No upload request received.\n");
}
} }
out: out:
signal(SIGINT, sigh_orig); signal(SIGINT, sigh_orig);
gsock = NULL; ethsock_arp_del(sock, &arp_undo);
ethsock_arp_del(sock, &g_arp_undo); ethsock_ip_del(sock, &ip_undo);
ethsock_ip_del(sock, &g_ip_undo);
ethsock_close(sock); ethsock_close(sock);
return status; return status;
} }

18
nmrpd.h
View file

@ -20,24 +20,25 @@
#ifndef NMRPD_H #ifndef NMRPD_H
#define NMRPD_H #define NMRPD_H
#include <stdint.h> #include <stdint.h>
#include <signal.h>
#include <stdbool.h> #include <stdbool.h>
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
# define NMRPFLASH_WINDOWS # define NMRPFLASH_WINDOWS
#else #elif defined (__unix__)
# define NMRPFLASH_UNIX # define NMRPFLASH_UNIX
# if defined(__linux__) # if defined(__linux__)
# define NMRPFLASH_LINUX # define NMRPFLASH_LINUX
# elif defined(__APPLE__) && defined(__MACH__) # elif defined(__APPLE__) && defined(__MACH__)
# define NMRPFLASH_OSX # define NMRPFLASH_OSX
# define NMRPFLASH_BSD # define NMRPFLASH_BSD
# elif defined(__unix__) # elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
# define NMRPFLASH_BSD # define NMRPFLASH_BSD
# else # else
# warning "nmrpflash is not fully supported on your operating system" # warning "nmrpflash is not fully supported on this platform"
# endif
# endif # endif
#else
# warning "nmrpflash is not supported on this platform"
#endif #endif
#ifndef NMRPFLASH_WINDOWS #ifndef NMRPFLASH_WINDOWS
@ -105,7 +106,7 @@ const char *mac_to_str(uint8_t *mac);
void win_perror2(const char *msg, DWORD err); void win_perror2(const char *msg, DWORD err);
void sock_perror(const char *msg); void sock_perror(const char *msg);
#else #else
#define sock_perror(x) perror(x) #define sock_perror(x) xperror(x)
#endif #endif
extern int verbosity; extern int verbosity;
@ -142,4 +143,7 @@ time_t time_monotonic();
char *lltostr(long long ll, int base); char *lltostr(long long ll, int base);
uint32_t bitcount(uint32_t n); uint32_t bitcount(uint32_t n);
uint32_t netmask(uint32_t count); uint32_t netmask(uint32_t count);
void xperror(const char *msg);
extern volatile sig_atomic_t g_interrupted;
#endif #endif

18
tftp.c
View file

@ -239,6 +239,10 @@ int tftp_put(struct nmrpd_args *args)
sock = -1; sock = -1;
ret = -1; ret = -1;
if (g_interrupted) {
goto cleanup;
}
if (!strcmp(args->file_local, "-")) { if (!strcmp(args->file_local, "-")) {
fd = STDIN_FILENO; fd = STDIN_FILENO;
if (!file_remote) { if (!file_remote) {
@ -247,7 +251,7 @@ int tftp_put(struct nmrpd_args *args)
} else { } else {
fd = open(args->file_local, O_RDONLY | O_BINARY); fd = open(args->file_local, O_RDONLY | O_BINARY);
if (fd < 0) { if (fd < 0) {
perror("open"); xperror("open");
ret = fd; ret = fd;
goto cleanup; goto cleanup;
} else if (!file_remote) { } else if (!file_remote) {
@ -268,7 +272,7 @@ int tftp_put(struct nmrpd_args *args)
if (args->ipaddr_intf) { if (args->ipaddr_intf) {
if ((addr.sin_addr.s_addr = inet_addr(args->ipaddr_intf)) == INADDR_NONE) { if ((addr.sin_addr.s_addr = inet_addr(args->ipaddr_intf)) == INADDR_NONE) {
perror("inet_addr"); xperror("inet_addr");
goto cleanup; goto cleanup;
} }
@ -279,7 +283,7 @@ int tftp_put(struct nmrpd_args *args)
} }
if ((addr.sin_addr.s_addr = inet_addr(args->ipaddr)) == INADDR_NONE) { if ((addr.sin_addr.s_addr = inet_addr(args->ipaddr)) == INADDR_NONE) {
perror("inet_addr"); xperror("inet_addr");
goto cleanup; goto cleanup;
} }
addr.sin_port = htons(args->port); addr.sin_port = htons(args->port);
@ -293,7 +297,7 @@ int tftp_put(struct nmrpd_args *args)
pkt_mkwrq(tx, file_remote); pkt_mkwrq(tx, file_remote);
do { while (!g_interrupted) {
if (!timeout && pkt_num(rx) == ACK) { if (!timeout && pkt_num(rx) == ACK) {
ackblock = pkt_num(rx + 2); ackblock = pkt_num(rx + 2);
} else { } else {
@ -307,7 +311,7 @@ int tftp_put(struct nmrpd_args *args)
pkt_mknum(tx + 2, block); pkt_mknum(tx + 2, block);
len = read(fd, tx + 4, 512); len = read(fd, tx + 4, 512);
if (len < 0) { if (len < 0) {
perror("read"); xperror("read");
ret = len; ret = len;
goto cleanup; goto cleanup;
} else if (!len) { } else if (!len) {
@ -361,9 +365,9 @@ int tftp_put(struct nmrpd_args *args)
addr.sin_port = htons(port); addr.sin_port = htons(port);
} }
} }
} while(1); }
ret = 0; ret = !g_interrupted ? 0 : -1;
cleanup: cleanup:
if (fd >= 0) { if (fd >= 0) {

12
util.c
View file

@ -1,4 +1,5 @@
#include <stdio.h> #include <stdio.h>
#include <errno.h>
#include <time.h> #include <time.h>
#include <math.h> #include <math.h>
#include "nmrpd.h" #include "nmrpd.h"
@ -7,6 +8,8 @@
#include <mach/mach_time.h> #include <mach/mach_time.h>
#endif #endif
volatile sig_atomic_t g_interrupted = 0;
time_t time_monotonic() time_t time_monotonic()
{ {
#ifndef NMRPFLASH_WINDOWS #ifndef NMRPFLASH_WINDOWS
@ -49,3 +52,12 @@ uint32_t netmask(uint32_t count)
{ {
return htonl(count <= 32 ? 0xffffffff << (32 - count) : 0); return htonl(count <= 32 ? 0xffffffff << (32 - count) : 0);
} }
void xperror(const char *msg)
{
if (errno != EINTR) {
perror(msg);
} else {
printf("\n");
}
}