#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
+#include <error.h>
+#include <errno.h>
#ifdef __APPLE__
#define BIND_8_COMPAT
if(res_init() < 0) {
- fprintf(stderr,"@res_init failed\n");
+ error(0, 0, "@res_init failed");
return NULL;
}
if (ipinfo_no >= 0) {
DEB_syslog(LOG_INFO, "hcreate(%d)", IIHASH_HI);
if (!(iihash = hcreate(IIHASH_HI)))
- perror("ipinfo hash");
+ error(0, errno, "ipinfo hash");
}
}
//#endif
//#include <netdb.h>
//#include <resolv.h>
+#include <error.h>
+#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
//#include <ctype.h>
int pid;
if (pipe (todns) < 0) {
- perror ("can't make a pipe for DNS process");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "can't make a pipe for DNS process");
}
if (pipe (fromdns) < 0) {
- perror ("can't make a pipe for DNS process");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "can't make a pipe for DNS process");
}
fflush (stdout);
pid = fork ();
//pid = 1;
if (pid < 0) {
- perror ("can't fork for DNS process");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "can't fork for DNS process");
}
if (pid == 0) {
char buf[2048];
// Automatically reap children.
if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
- perror("signal");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "signal");
}
#if 0
sprintf (result, "%s %s\n", strlongip (&host), hostname);
//printf ("resolved: %s -> %s (%d)\n", strlongip (&host), hostname, rv);
rv = write (fromdns[1], result, strlen (result));
- if (rv < 0) perror ("write DNS lookup result");
+ if (rv < 0)
+ error (0, errno, "write DNS lookup result");
}
exit(EXIT_SUCCESS);
if (r)
r->name = strdup (name);
else
- fprintf (stderr, "dns_ack: Couldn't find host %s\n", host);
+ error (0, 0, "dns_ack: Couldn't find host %s", host);
}
}
sprintf (buf, "%s\n", strlongip (ip));
rv = write (todns[1], buf, strlen (buf));
- if (rv < 0) perror ("couldn't write to resolver process");
+ if (rv < 0)
+ error (0, errno, "couldn't write to resolver process");
}
return strlongip (ip);
}
}
static void
-append_to_names(const char* progname, const char* item) {
+append_to_names(const char* item) {
names_t* name = calloc(1, sizeof(names_t));
if (name == NULL) {
- fprintf(stderr, "%s: memory allocation failure\n", progname);
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "memory allocation failure");
}
name->name = strdup(item);
name->next = names;
}
static void
-read_from_file(const char* progname, const char *filename) {
+read_from_file(const char *filename) {
FILE *in;
char line[512];
} else {
in = fopen(filename, "r");
if (! in) {
- fprintf(stderr, "%s: fopen: %s\n", progname, strerror(errno));
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "open %s", filename);
}
}
while (fgets(line, sizeof(line), in)) {
char* name = trim(line);
- append_to_names(progname, name);
+ append_to_names(name);
}
if (ferror(in)) {
- fprintf(stderr, "%s: ferror: %s\n", progname, strerror(errno));
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "ferror %s", filename);
}
if (in != stdin) fclose(in);
*/
static void
-lock(const char* progname, FILE *f) {
+lock(FILE *f) {
int fd;
struct stat buf;
static struct flock lock;
fd = fileno(f);
if ((fstat(fd, &buf) == 0) && S_ISREG(buf.st_mode)) {
if (fcntl(fd, F_SETLKW, &lock) == -1) {
- fprintf(stderr, "%s: fcntl: %s (ignored)\n",
- progname, strerror(errno));
+ error(0, errno, "fcntl (ignored)");
}
}
}
*/
static void
-unlock(const char* progname, FILE *f) {
+unlock(FILE *f) {
int fd;
struct stat buf;
static struct flock lock;
fd = fileno(f);
if ((fstat(fd, &buf) == 0) && S_ISREG(buf.st_mode)) {
if (fcntl(fd, F_SETLKW, &lock) == -1) {
- fprintf(stderr, "%s: fcntl: %s (ignored)\n",
- progname, strerror(errno));
+ error(0, errno, "fcntl (ignored)");
}
}
}
case 'i':
WaitTime = strtofloat_or_err(optarg, "invalid argument");
if (WaitTime <= 0.0) {
- fprintf (stderr, "mtr: wait time must be positive\n");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, 0, "wait time must be positive");
}
if (getuid() != 0 && WaitTime < 1.0) {
- fprintf (stderr, "non-root users cannot request an interval < 1.0 seconds\r\n");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, 0, "non-root users cannot request an interval < 1.0 seconds");
}
break;
case 'f':
}
break;
case 'F':
- read_from_file(argv[0], optarg);
+ read_from_file(optarg);
break;
case 'm':
maxTTL = strtoint_or_err(optarg, "invalid argument");
case 'o':
/* Check option before passing it on to fld_active. */
if (strlen (optarg) > MAXFLD) {
- fprintf (stderr, "Too many fields: %s\n", optarg);
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, 0, "Too many fields: %s", optarg);
}
for (i=0; optarg[i]; i++) {
if(!strchr (available_options, optarg[i])) {
- fprintf (stderr, "Unknown field identifier: %c\n", optarg[i]);
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, 0, "Unknown field identifier: %c", optarg[i]);
}
}
strcpy ((char*)fld_active, optarg);
case 'G':
GraceTime = strtofloat_or_err(optarg, "invalid argument");
if (GraceTime <= 0.0) {
- fprintf (stderr, "mtr: wait time must be positive\n");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, 0, "wait time must be positive");
}
break;
case 'Q':
break;
case 'u':
if (mtrtype != IPPROTO_ICMP) {
- fprintf(stderr, "-u , -T and -S are mutually exclusive.\n");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, 0, "-u , -T and -S are mutually exclusive");
}
mtrtype = IPPROTO_UDP;
break;
case 'T':
if (mtrtype != IPPROTO_ICMP) {
- fprintf(stderr, "-u , -T and -S are mutually exclusive.\n");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, 0, "-u , -T and -S are mutually exclusive");
}
if (!remoteport) {
remoteport = 80;
case 'S':
#ifdef HAS_SCTP
if (mtrtype != IPPROTO_ICMP) {
- fprintf(stderr, "-u , -T and -S are mutually exclusive.\n");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, 0, "-u , -T and -S are mutually exclusive");
}
if (!remoteport) {
remoteport = 80;
}
mtrtype = IPPROTO_SCTP;
#else
- fprintf (stderr, "No SCTP support found at compiletime\n");
- exit (EXIT_FAILURE);
+ error(EXIT_FAILURE, 0, "No SCTP support found at compiletime");
#endif
break;
case 'b':
case 'P':
remoteport = strtoint_or_err(optarg, "invalid argument");
if (remoteport > 65535 || remoteport < 1) {
- fprintf(stderr, "Illegal port number.\n");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, 0, "Illegal port number: %d", remoteport);
}
break;
case 'L':
localport = strtoint_or_err(optarg, "invalid argument");
if (localport > 65535 || localport < MinPort) {
- fprintf(stderr, "Illegal local port number.\n");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, 0, "Illegal port number: %d", localport);
}
break;
case 'Z':
af = AF_INET6;
break;
#else
- fprintf( stderr, "IPv6 not enabled.\n" );
+ error(EXIT_FAILURE, 0, "IPv6 not enabled");
break;
#endif
#ifdef HAVE_IPINFO
#else
case 'y':
case 'z':
- fprintf( stderr, "IPINFO not enabled.\n" );
+ error(EXIT_FAILURE, 0, "IPINFO not enabled");
break;
#endif
#ifdef SO_MARK
break;
#else
case 'M':
- fprintf( stderr, "SO_MARK not enabled.\n" );
+ error(EXIT_FAILURE, 0, "SO_MARK not enabled");
break;
#endif
}
p = strtok (NULL, " \t");
}
if (p != NULL) {
- fprintf (stderr, "Warning: extra arguments ignored: %s", p);
+ error(0, 0, "Warning: extra arguments ignored: %s", p);
}
parse_arg (argc, argv);
struct hostent * host = NULL;
int net_preopen_result;
struct addrinfo hints, *res;
- int error;
+ int gai_error;
struct hostent trhost;
char * alptr[2];
struct sockaddr_in * sa4;
/* Get the raw sockets first thing, so we can drop to user euid immediately */
if ( ( net_preopen_result = net_preopen () ) ) {
- fprintf( stderr, "mtr: unable to get raw sockets.\n" );
- exit( EXIT_FAILURE );
+ error(EXIT_FAILURE, errno, "Unable to get raw sockets");
}
/* Now drop to user permissions */
if (setgid(getgid()) || setuid(getuid())) {
- fprintf (stderr, "mtr: Unable to drop permissions.\n");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "Unable to drop permissions");
}
/* Double check, just in case */
if ((geteuid() != getuid()) || (getegid() != getgid())) {
- fprintf (stderr, "mtr: Unable to drop permissions.\n");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "Unable to drop permissions");
}
/* reset the random seed */
while (optind < argc) {
char* name = argv[optind++];
- append_to_names(argv[0], name);
+ append_to_names(name);
}
/* Now that we know mtrtype we can select which socket to use */
if (net_selectsocket() != 0) {
- fprintf( stderr, "mtr: Couldn't determine raw socket type.\n" );
- exit( EXIT_FAILURE );
+ error(EXIT_FAILURE, 0, "Couldn't determine raw socket type");
}
if (PrintVersion) {
time_t now = time(NULL);
- if (!names) append_to_names (argv[0], "localhost"); // default: localhost.
+ if (!names) append_to_names ("localhost"); // default: localhost.
names_t* head = names;
while (names != NULL) {
}
if (net_preopen_result != 0) {
- fprintf(stderr, "mtr: Unable to get raw socket. (Executable not suid?)\n");
+ error(0, 0, "Unable to get raw socket. (Executable not suid?)");
if ( DisplayMode != DisplayCSV ) exit(EXIT_FAILURE);
else {
names = names->next;
memset( &hints, 0, sizeof hints );
hints.ai_family = af;
hints.ai_socktype = SOCK_DGRAM;
- error = getaddrinfo( Hostname, NULL, &hints, &res );
- if ( error ) {
- if (error == EAI_SYSTEM)
- perror ("Failed to resolve host");
+ gai_error = getaddrinfo( Hostname, NULL, &hints, &res );
+ if ( gai_error ) {
+ if (gai_error == EAI_SYSTEM)
+ error(0, 0, "Failed to resolve host: %s", Hostname);
else
- fprintf (stderr, "Failed to resolve host: %s\n", gai_strerror(error));
+ error(0, 0, "Failed to resolve host: %s: %s", Hostname, gai_strerror(gai_error));
if ( DisplayMode != DisplayCSV ) exit(EXIT_FAILURE);
else {
break;
#endif
default:
- fprintf( stderr, "mtr unknown address type\n" );
+ error(0, 0, "unknown address type");
if ( DisplayMode != DisplayCSV ) exit(EXIT_FAILURE);
else {
names = names->next;
alptr[1] = NULL;
if (net_open(host) != 0) {
- fprintf(stderr, "mtr: Unable to start net module.\n");
+ error(0, 0, "Unable to start net module");
if ( DisplayMode != DisplayCSV ) exit(EXIT_FAILURE);
else {
names = names->next;
}
if (net_set_interfaceaddress (InterfaceAddress) != 0) {
- fprintf( stderr, "mtr: Couldn't set interface address.\n" );
+ error(0, 0, "Couldn't set interface address: %s", InterfaceAddress);
if ( DisplayMode != DisplayCSV ) exit(EXIT_FAILURE);
else {
names = names->next;
}
- lock(argv[0], stdout);
+ lock(stdout);
display_open();
dns_open();
net_end_transit();
display_close(now);
- unlock(argv[0], stdout);
+ unlock(stdout);
if ( DisplayMode != DisplayCSV ) break;
else names = names->next;
#include <math.h>
#include <errno.h>
#include <string.h>
+#include <error.h>
+
#include "mtr.h"
#include "net.h"
if (bind(s, (struct sockaddr *) &local, len)) {
display_clear();
- perror("bind()");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "bind()");
}
if (getsockname(s, (struct sockaddr *) &local, &len)) {
display_clear();
- perror("getsockname()");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "getsockname()");
}
// opt = 1;
flags = fcntl(s, F_GETFL, 0);
if (flags < 0) {
display_clear();
- perror("ioctl FIONBIO");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "fcntl(F_GETFL)");
}
if (fcntl (s, F_SETFL, flags | O_NONBLOCK) < 0) {
display_clear();
- perror("ioctl FIONBIO");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "fcntl(F_SETFL, O_NONBLOCK)");
}
case AF_INET:
if (setsockopt(s, IPPROTO_IP, IP_TTL, &ttl, sizeof (ttl))) {
display_clear();
- perror("setsockopt IP_TTL");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "setsockopt IP_TTL");
}
if (setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof (tos))) {
display_clear();
- perror("setsockopt IP_TOS");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "setsockopt IP_TOS");
}
break;
#ifdef ENABLE_IPV6
case AF_INET6:
if (setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof (ttl))) {
display_clear();
- perror("setsockopt IP_TTL");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "setsockopt IPPROTO_IPV6 ttl");
}
break;
#endif
#ifdef SO_MARK
if (mark >= 0 && setsockopt( s, SOL_SOCKET, SO_MARK, &mark, sizeof mark ) ) {
- perror( "setsockopt SO_MARK" );
- exit( EXIT_FAILURE );
+ error(EXIT_FAILURE, errno, "setsockopt SO_MARK");
}
#endif
#endif
default:
display_clear();
- perror("unknown AF?");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, 0, "unknown address family");
}
save_sequence(index, port);
s = socket(af, SOCK_STREAM, IPPROTO_SCTP);
if (s < 0) {
display_clear();
- perror("socket()");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "socket()");
}
memset(&local, 0, sizeof (local));
if (bind(s, (struct sockaddr *) &local, len)) {
display_clear();
- perror("bind()");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "bind()");
}
if (getsockname(s, (struct sockaddr *) &local, &len)) {
display_clear();
- perror("getsockname()");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "getsockname()");
}
opt = 1;
if (ioctl(s, FIONBIO, &opt)) {
display_clear();
- perror("ioctl FIONBIO");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "ioctl FIONBIO");
}
switch (af) {
case AF_INET:
if (setsockopt(s, IPPROTO_IP, IP_TTL, &ttl, sizeof (ttl))) {
display_clear();
- perror("setsockopt IP_TTL");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "setsockopt IP_TTL");
}
if (setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof (tos))) {
display_clear();
- perror("setsockopt IP_TOS");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "setsockopt IP_TOS");
}
break;
#ifdef ENABLE_IPV6
case AF_INET6:
if (setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof (ttl))) {
display_clear();
- perror("setsockopt IP_TTL");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "setsockopt IPPROTO_IPV6 ttl");
}
break;
#endif
#ifdef SO_MARK
if (mark >= 0 && setsockopt( s, SOL_SOCKET, SO_MARK, &mark, sizeof mark ) ) {
- perror( "setsockopt SO_MARK" );
- exit( EXIT_FAILURE );
+ error(EXIT_FAILURE, errno, "setsockopt SO_MARK");
}
#endif
#endif
default:
display_clear();
- perror("unknown AF?");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, 0, "unknown address family");
}
save_sequence(index, port);
#if !defined(IP_HDRINCL) && defined(IP_TOS) && defined(IP_TTL)
iphsize = 0;
if ( setsockopt( sendsock, IPPROTO_IP, IP_TOS, &tos, sizeof tos ) ) {
- perror( "setsockopt IP_TOS" );
- exit( EXIT_FAILURE );
+ error(EXIT_FAILURE, errno, "setsockopt IP_TOS");
}
if ( setsockopt( sendsock, IPPROTO_IP, IP_TTL, &ttl, sizeof ttl ) ) {
- perror( "setsockopt IP_TTL" );
- exit( EXIT_FAILURE );
+ error(EXIT_FAILURE, errno, "setsockopt IP_TTL");
}
#else
iphsize = sizeof (struct IPHeader);
iphsize = 0;
if ( setsockopt( sendsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
&ttl, sizeof ttl ) ) {
- perror( "setsockopt IPV6_UNICAST_HOPS" );
- exit( EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "setsockopt IPV6_UNICAST_HOPS");
}
echotype = ICMP6_ECHO_REQUEST;
salen = sizeof (struct sockaddr_in6);
#ifdef SO_MARK
if (mark >= 0 && setsockopt( sendsock, SOL_SOCKET, SO_MARK, &mark, sizeof mark ) ) {
- perror( "setsockopt SO_MARK" );
- exit( EXIT_FAILURE );
+ error(EXIT_FAILURE, errno, "setsockopt SO_MARK");
}
#endif
offset = sizeof(struct UDPHeader);
}
if ( setsockopt(sendsock, IPPROTO_IPV6, IPV6_CHECKSUM, &offset, sizeof(offset)) ) {
- perror( "setsockopt IPV6_CHECKSUM" );
- exit( EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "setsockopt IPV6_CHECKSUM");
}
break;
}
num = recvfrom(recvsock, packet, MAXPACKET, 0,
fromsockaddr, &fromsockaddrsize);
if(num < 0) {
- perror("recvfrom failed");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "recvfrom failed");
}
switch ( af ) {
oldflags = fcntl(fd, F_GETFD);
if (oldflags == -1) {
- perror("Couldn't get fd's flags");
+ error(0, errno, "Couldn't get fd's flags");
return;
}
if (fcntl(fd, F_SETFD, oldflags | FD_CLOEXEC))
- perror("Couldn't set fd's flags");
+ error(0, errno, "Couldn't set fd's flags");
#endif
}
/* FreeBSD wants this to avoid sending out packets with protocol type RAW
to the network. */
if (setsockopt(sendsock4, SOL_IP, IP_HDRINCL, &trueopt, sizeof(trueopt))) {
- perror("setsockopt(IP_HDRINCL,1)");
+ error(0, errno, "setsockopt IP_HDRINCL");
return -1;
}
#endif /* IP_HDRINCL */
#ifdef ENABLE_IPV6
case AF_INET6:
if (sendsock6 < 0 || recvsock6 < 0) {
- fprintf( stderr, "Could not open IPv6 socket\n" );
- exit( EXIT_FAILURE );
+ error(EXIT_FAILURE, errno, "Could not open IPv6 socket");
}
sendsock = sendsock6;
recvsock = recvsock6;
break;
#endif
default:
- fprintf( stderr, "net_open bad address type\n" );
- exit( EXIT_FAILURE );
+ error(EXIT_FAILURE, 0, "net_open bad address type");
}
len = sizeof name_struct;
break;
#endif
default:
- fprintf( stderr, "net_reopen bad address type\n" );
- exit( EXIT_FAILURE );
+ error(EXIT_FAILURE, 0, "net_reopen bad address type");
}
net_reset ();
s = socket (af, SOCK_DGRAM, 0);
if (s < 0) {
- perror("udp socket()");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "udp socket()");
}
if (connect(s, (struct sockaddr *) &remote, len)) {
- perror("udp connect() failed");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "udp connect()");
}
getsockname(s, name, &len);
case AF_INET:
ssa4->sin_port = 0;
if ( inet_aton( InterfaceAddress, &(ssa4->sin_addr) ) < 1 ) {
- fprintf( stderr, "mtr: bad interface address: %s\n", InterfaceAddress );
+ error(0, 0, "bad interface address: %s", InterfaceAddress);
return( 1 );
}
len = sizeof (struct sockaddr);
case AF_INET6:
ssa6->sin6_port = 0;
if ( inet_pton( af, InterfaceAddress, &(ssa6->sin6_addr) ) < 1 ) {
- fprintf( stderr, "mtr: bad interface address: %s\n", InterfaceAddress );
+ error(0, 0, "bad interface address: %s", InterfaceAddress);
return( 1 );
}
len = sizeof (struct sockaddr_in6);
}
if ( bind( sendsock, sourcesockaddr, len ) == -1 ) {
- perror("mtr: failed to bind to interface");
+ error(0, 0, "failed to bind to interface: %s", InterfaceAddress);
return( 1 );
}
getsockname (sendsock, name, &len);
#endif
default:
fprintf( stderr, "sockaddrtop unknown address type\n" );
+ error(0, 0, "sockaddrtop unknown address type");
strptr[0] = '\0';
return;
}
#include <string.h>
#include <math.h>
#include <errno.h>
+#include <error.h>
#include "mtr.h"
#include "dns.h"
} while ((rv < 0) && (errno == EINTR));
if (rv < 0) {
- perror ("Select failed");
- exit(EXIT_FAILURE);
+ error(EXIT_FAILURE, errno, "Select failed");
}
anyset = 0;