1997-05-03 19:18:21 +00:00
|
|
|
/* This is a simple name server for GNUstep Distributed Objects
|
2002-02-25 18:10:58 +00:00
|
|
|
Copyright (C) 1996, 1997, 1998, 2002 Free Software Foundation, Inc.
|
1997-05-03 19:18:21 +00:00
|
|
|
|
|
|
|
Written by: Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
|
|
|
Created: October 1996
|
|
|
|
|
|
|
|
This file is part of the GNUstep Base Library.
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
2005-07-15 22:51:23 +00:00
|
|
|
modify it under the terms of the GNU General Public
|
1997-05-03 19:18:21 +00:00
|
|
|
License as published by the Free Software Foundation; either
|
2008-06-08 10:38:33 +00:00
|
|
|
version 2 of the License, or (at your option) any later version.
|
1997-05-03 19:18:21 +00:00
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
2005-07-15 22:51:23 +00:00
|
|
|
General Public License for more details.
|
1997-05-03 19:18:21 +00:00
|
|
|
|
2005-07-15 22:51:23 +00:00
|
|
|
You should have received a copy of the GNU General Public
|
1997-05-03 19:18:21 +00:00
|
|
|
License along with this library; if not, write to the Free
|
2006-03-03 11:54:27 +00:00
|
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02111 USA.
|
1997-05-03 19:18:21 +00:00
|
|
|
*/
|
|
|
|
|
2008-11-21 15:50:13 +00:00
|
|
|
/* Ported to mingw 07/12/00 by Bjorn Giesler <Bjoern.Giesler@gmx.de> */
|
2000-07-18 11:34:30 +00:00
|
|
|
|
2006-07-06 17:14:33 +00:00
|
|
|
#include "config.h"
|
2010-02-22 21:43:45 +00:00
|
|
|
|
2010-03-19 12:26:42 +00:00
|
|
|
#if !defined(__MINGW__)
|
|
|
|
# if defined(__MINGW32__) || defined(__MINGW64__)
|
|
|
|
# define __MINGW__
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
1997-05-03 19:18:21 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2002-02-24 18:28:40 +00:00
|
|
|
#include <stdarg.h>
|
1997-05-03 19:18:21 +00:00
|
|
|
#include <unistd.h> /* for gethostname() */
|
2010-03-19 12:10:11 +00:00
|
|
|
#ifndef __MINGW__
|
1997-05-03 19:18:21 +00:00
|
|
|
#include <sys/param.h> /* for MAXHOSTNAMELEN */
|
|
|
|
#include <sys/types.h>
|
2002-07-29 19:37:40 +00:00
|
|
|
#include <sys/stat.h>
|
1997-09-01 21:59:51 +00:00
|
|
|
#include <netinet/in.h>
|
1997-05-03 19:18:21 +00:00
|
|
|
#include <arpa/inet.h> /* for inet_ntoa() */
|
2010-03-19 12:10:11 +00:00
|
|
|
#endif /* !__MINGW__ */
|
1997-05-03 19:18:21 +00:00
|
|
|
#include <errno.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <string.h> /* for strchr() */
|
1999-06-24 19:30:29 +00:00
|
|
|
#include <ctype.h> /* for strchr() */
|
2000-07-18 11:34:30 +00:00
|
|
|
#include <fcntl.h>
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2010-03-16 15:08:20 +00:00
|
|
|
#include <stdint.h>
|
2002-02-25 18:10:58 +00:00
|
|
|
#include <winsock2.h>
|
|
|
|
#include <ws2tcpip.h>
|
2000-07-18 11:34:30 +00:00
|
|
|
#include <wininet.h>
|
|
|
|
#include <process.h>
|
|
|
|
#include <sys/time.h>
|
2000-06-06 16:50:52 +00:00
|
|
|
#else
|
1997-05-03 19:18:21 +00:00
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/resource.h>
|
|
|
|
#include <netdb.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <sys/socket.h>
|
1997-09-01 21:59:51 +00:00
|
|
|
#include <sys/file.h>
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(HAVE_TIME_H)
|
2002-02-24 18:28:40 +00:00
|
|
|
#include <time.h>
|
|
|
|
#endif
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(HAVE_PWD_H)
|
2001-05-08 07:57:51 +00:00
|
|
|
#include <pwd.h>
|
|
|
|
#endif
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(HAVE_GRP_H)
|
2002-07-29 19:37:40 +00:00
|
|
|
#include <grp.h>
|
|
|
|
#endif
|
2001-05-08 07:57:51 +00:00
|
|
|
|
2002-04-18 06:02:22 +00:00
|
|
|
#if HAVE_GETOPT_H
|
|
|
|
#include <getopt.h>
|
|
|
|
#endif
|
2002-02-24 18:28:40 +00:00
|
|
|
|
1997-05-03 19:18:21 +00:00
|
|
|
/*
|
|
|
|
* Stuff for setting the sockets into non-blocking mode.
|
|
|
|
*/
|
2012-08-26 08:55:49 +00:00
|
|
|
#if defined(__POSIX_SOURCE) || defined(__EXT_POSIX1_198808)
|
1997-05-03 19:18:21 +00:00
|
|
|
#define NBLK_OPT O_NONBLOCK
|
|
|
|
#else
|
|
|
|
#define NBLK_OPT FNDELAY
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <net/if.h>
|
2000-06-13 14:50:40 +00:00
|
|
|
#if !defined(SIOCGIFCONF) || defined(__CYGWIN__)
|
1997-05-03 19:18:21 +00:00
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#ifndef SIOCGIFCONF
|
|
|
|
#include <sys/sockio.h>
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
1998-05-29 15:25:41 +00:00
|
|
|
#if defined(__svr4__)
|
2012-08-26 08:55:49 +00:00
|
|
|
#if defined(HAVE_SYS_STROPTS_H)
|
1998-05-29 15:25:41 +00:00
|
|
|
#include <sys/stropts.h>
|
|
|
|
#endif
|
2012-08-26 08:55:49 +00:00
|
|
|
#endif
|
2010-03-19 12:10:11 +00:00
|
|
|
#endif /* !__MINGW__ */
|
2000-06-13 14:50:40 +00:00
|
|
|
|
2002-02-24 19:58:31 +00:00
|
|
|
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(HAVE_SYSLOG_H)
|
2002-02-24 19:58:31 +00:00
|
|
|
#include <syslog.h>
|
2012-08-26 08:55:49 +00:00
|
|
|
#elif defined(HAVE_SYS_SLOG_H)
|
|
|
|
# include <sys/slog.h>
|
|
|
|
# if defined(HAVE_SYS_SLOGCODES_H)
|
|
|
|
# include <sys/slogcodes.h>
|
|
|
|
# endif
|
2002-02-24 19:58:31 +00:00
|
|
|
#endif
|
|
|
|
|
2008-10-30 14:22:19 +00:00
|
|
|
#if HAVE_STRERROR
|
|
|
|
#define lastErr() strerror(errno)
|
|
|
|
#else
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2008-10-30 14:22:19 +00:00
|
|
|
static errbuf[BUFSIZ];
|
|
|
|
#define lastErr() (sprintf(errbuf, "WSAGetLastError()=%d", WSAGetLastError()), errbuf)
|
|
|
|
#else
|
|
|
|
static errbuf[BUFSIZ];
|
|
|
|
#define lastErr() (sprintf(errbuf, "%m"), errbuf)
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
1997-05-03 19:18:21 +00:00
|
|
|
#include "gdomap.h"
|
|
|
|
/*
|
|
|
|
* ABOUT THIS PROGRAM
|
|
|
|
*
|
|
|
|
* This is a simple name server for GNUstep Distributed Objects
|
|
|
|
* The server program listens on a well known port (service name 'gdomap')
|
|
|
|
*
|
|
|
|
* The officially assigned port is 538. On most systems port numbers
|
|
|
|
* under 1024 can only be used by root (for security). So this program
|
|
|
|
* needs to be run as root.
|
|
|
|
*
|
|
|
|
* This is UNIX code - I have no idea how portable to other OSs it may be.
|
|
|
|
*
|
|
|
|
* For detailed information about the communication protocol used - see
|
|
|
|
* the include file.
|
|
|
|
*/
|
|
|
|
|
1998-02-03 14:20:00 +00:00
|
|
|
/* For IRIX machines, which don't define this */
|
|
|
|
#ifndef IPPORT_USERRESERVED
|
|
|
|
#define IPPORT_USERRESERVED 5000
|
|
|
|
#endif /* IPPORT_USERRESERVED */
|
|
|
|
|
1997-05-03 19:18:21 +00:00
|
|
|
#define QUEBACKLOG (16) /* How many coonections to queue. */
|
|
|
|
#define MAX_IFACE (256) /* How many network interfaces. */
|
|
|
|
#define IASIZE (sizeof(struct in_addr))
|
|
|
|
|
1998-02-26 17:55:42 +00:00
|
|
|
#define MAX_EXTRA ((GDO_NAME_MAX_LEN - 2 * IASIZE)/IASIZE)
|
|
|
|
|
2005-04-20 02:58:17 +00:00
|
|
|
#define ROUND(V, A) \
|
|
|
|
({ typeof(V) __v=(V); typeof(A) __a=(A); \
|
|
|
|
__a*((__v+__a-1)/__a); })
|
|
|
|
|
1998-10-27 20:58:22 +00:00
|
|
|
typedef unsigned char *uptr;
|
2010-03-19 12:10:11 +00:00
|
|
|
#ifndef __MINGW__
|
2002-02-26 09:43:04 +00:00
|
|
|
static int is_daemon = 0; /* Currently running as daemon. */
|
2005-02-21 14:44:18 +00:00
|
|
|
#endif
|
2010-05-06 05:09:12 +00:00
|
|
|
static int in_config = 0; /* Reading config file. */
|
2002-03-20 12:03:30 +00:00
|
|
|
static int debug = 0; /* Extra debug gdomap_logging. */
|
2002-02-26 09:43:04 +00:00
|
|
|
static int nobcst = 0; /* turn off broadcast probing. */
|
|
|
|
static int nofork = 0; /* turn off fork() for debugging. */
|
|
|
|
static int noprobe = 0; /* disable probe for unknown servers. */
|
|
|
|
static int interval = 600; /* Minimum time (sec) between probes. */
|
|
|
|
static char *pidfile = NULL; /* file to write PID to */
|
|
|
|
|
|
|
|
static int udp_sent = 0;
|
|
|
|
static int tcp_sent = 0;
|
|
|
|
static int udp_read = 0;
|
|
|
|
static int tcp_read = 0;
|
|
|
|
static int soft_int = 0;
|
|
|
|
|
|
|
|
static long last_probe;
|
|
|
|
static struct in_addr loopback;
|
|
|
|
|
|
|
|
static unsigned short my_port; /* Set in init_iface() */
|
|
|
|
|
|
|
|
static unsigned long class_a_net;
|
|
|
|
static struct in_addr class_a_mask;
|
|
|
|
static unsigned long class_b_net;
|
|
|
|
static struct in_addr class_b_mask;
|
|
|
|
static unsigned long class_c_net;
|
1998-02-26 17:55:42 +00:00
|
|
|
struct in_addr class_c_mask;
|
|
|
|
|
2013-04-14 16:25:27 +00:00
|
|
|
static char *local_hostname = 0;
|
|
|
|
|
1997-05-03 19:18:21 +00:00
|
|
|
/*
|
|
|
|
* Predeclare some of the functions used.
|
|
|
|
*/
|
1997-09-01 21:59:51 +00:00
|
|
|
static void dump_stats();
|
2010-03-19 12:10:11 +00:00
|
|
|
#ifndef __MINGW__
|
2000-07-24 12:03:14 +00:00
|
|
|
static void dump_tables();
|
2005-02-21 14:44:18 +00:00
|
|
|
#endif
|
1997-05-03 19:18:21 +00:00
|
|
|
static void handle_accept();
|
|
|
|
static void handle_io();
|
|
|
|
static void handle_read(int);
|
|
|
|
static void handle_recv();
|
|
|
|
static void handle_request(int);
|
1997-09-01 21:59:51 +00:00
|
|
|
static void handle_send();
|
1997-05-03 19:18:21 +00:00
|
|
|
static void handle_write(int);
|
|
|
|
static void init_iface();
|
1998-05-29 15:25:41 +00:00
|
|
|
static void load_iface(const char* from);
|
1997-05-03 19:18:21 +00:00
|
|
|
static void init_ports();
|
|
|
|
static void init_probe();
|
2005-07-08 11:48:37 +00:00
|
|
|
static void queue_msg(struct sockaddr_in* a, uptr d, unsigned l);
|
1997-09-01 21:59:51 +00:00
|
|
|
static void queue_pop();
|
2002-02-26 09:43:04 +00:00
|
|
|
static void queue_probe(struct in_addr* to, struct in_addr *from,
|
|
|
|
int num_extras, struct in_addr* extra, int is_reply);
|
1997-05-03 19:18:21 +00:00
|
|
|
|
2004-05-22 03:16:01 +00:00
|
|
|
char *xgethostname (void);
|
1997-05-03 19:18:21 +00:00
|
|
|
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2003-09-22 22:51:23 +00:00
|
|
|
#ifndef HAVE_GETOPT
|
2003-09-22 03:55:32 +00:00
|
|
|
/* A simple implementation of getopt() */
|
|
|
|
|
|
|
|
static int
|
|
|
|
indexof(char c, char *string)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < strlen(string); i++)
|
|
|
|
{
|
|
|
|
if (string[i] == c)
|
|
|
|
{
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *optarg;
|
|
|
|
|
|
|
|
static char
|
|
|
|
getopt(int argc, char **argv, char *options)
|
|
|
|
{
|
|
|
|
static int argi;
|
|
|
|
static char *arg;
|
|
|
|
int index;
|
|
|
|
char retval = '\0';
|
|
|
|
|
|
|
|
optarg = NULL;
|
|
|
|
if (argi == 0)
|
|
|
|
{
|
|
|
|
argi = 1;
|
|
|
|
}
|
|
|
|
while (argi < argc)
|
|
|
|
{
|
|
|
|
arg = argv[argi];
|
|
|
|
if (strlen(arg) == 2)
|
|
|
|
{
|
|
|
|
if (arg[0] == '-')
|
|
|
|
{
|
|
|
|
if ((index = indexof(arg[1], options)) != -1)
|
|
|
|
{
|
|
|
|
retval = arg[1];
|
|
|
|
if (index < strlen(options))
|
|
|
|
{
|
|
|
|
if (options[index+1] == ':')
|
|
|
|
{
|
|
|
|
if (argi < argc-1)
|
|
|
|
{
|
|
|
|
argi++;
|
|
|
|
optarg = argv[argi];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return -1; /* ':' given, but argv exhausted */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
argi++;
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif
|
2003-09-22 22:51:23 +00:00
|
|
|
#endif
|
2003-09-22 03:55:32 +00:00
|
|
|
|
|
|
|
|
2002-02-24 19:58:31 +00:00
|
|
|
static char ebuf[2048];
|
2002-02-24 18:28:40 +00:00
|
|
|
|
2002-03-13 16:49:56 +00:00
|
|
|
|
2012-08-26 08:55:49 +00:00
|
|
|
#if defined(HAVE_SYSLOG) || defined(HAVE_SLOGF)
|
|
|
|
# if defined(HAVE_SLOGF)
|
|
|
|
# define LOG_CRIT _SLOG_CRITICAL
|
|
|
|
# define LOG_DEBUG _SLOG_DEBUG1
|
|
|
|
# define LOG_ERR _SLOG_ERROR
|
|
|
|
# define LOG_INFO _SLOG_INFO
|
|
|
|
# define LOG_WARNING _SLOG_WARNING
|
|
|
|
# define syslog(prio, msg,...) slogf(_SLOG_SETCODE(_SLOG_SYSLOG, 0), prio, msg, __VA_ARGS__)
|
|
|
|
# endif
|
2002-02-24 18:28:40 +00:00
|
|
|
|
2014-03-19 08:18:09 +00:00
|
|
|
static int log_priority = 0;
|
2002-02-24 18:28:40 +00:00
|
|
|
|
2002-03-14 06:54:44 +00:00
|
|
|
static void
|
|
|
|
gdomap_log (int prio)
|
2002-02-24 18:28:40 +00:00
|
|
|
{
|
2010-05-06 05:09:12 +00:00
|
|
|
if (in_config)
|
|
|
|
{
|
|
|
|
#ifndef __MINGW__
|
|
|
|
if (geteuid () != getuid ())
|
|
|
|
{
|
|
|
|
strcpy(ebuf, "problem with config file");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
if (is_daemon)
|
2002-02-25 18:10:58 +00:00
|
|
|
{
|
2012-08-26 08:55:49 +00:00
|
|
|
#if defined(HAVE_SLOGF)
|
|
|
|
// QNX doesn't like 0 as the prio. It means "shutdown" to them.
|
|
|
|
syslog (prio ? log_priority : prio, "%s", ebuf);
|
|
|
|
# else
|
2010-01-10 14:38:16 +00:00
|
|
|
syslog (log_priority | prio, "%s", ebuf);
|
2012-08-26 08:55:49 +00:00
|
|
|
#endif
|
2002-02-25 18:10:58 +00:00
|
|
|
}
|
2002-03-18 16:22:28 +00:00
|
|
|
else if (prio == LOG_INFO)
|
2002-02-25 18:10:58 +00:00
|
|
|
{
|
2002-04-22 21:57:36 +00:00
|
|
|
write (1, ebuf, strlen (ebuf));
|
|
|
|
write (1, "\n", 1);
|
2002-02-25 18:10:58 +00:00
|
|
|
}
|
|
|
|
else
|
2002-02-24 18:28:40 +00:00
|
|
|
{
|
2002-02-24 19:58:31 +00:00
|
|
|
write (2, ebuf, strlen (ebuf));
|
2002-02-24 18:28:40 +00:00
|
|
|
write (2, "\n", 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prio == LOG_CRIT)
|
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
if (is_daemon)
|
2002-02-25 18:10:58 +00:00
|
|
|
{
|
2012-08-26 08:55:49 +00:00
|
|
|
syslog (LOG_CRIT, "%s", "exiting.");
|
2002-02-25 18:10:58 +00:00
|
|
|
}
|
|
|
|
else
|
2002-02-24 18:28:40 +00:00
|
|
|
{
|
|
|
|
fprintf (stderr, "exiting.\n");
|
|
|
|
fflush (stderr);
|
|
|
|
}
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
2002-02-24 18:28:40 +00:00
|
|
|
}
|
|
|
|
}
|
2002-02-24 19:58:31 +00:00
|
|
|
#else
|
|
|
|
|
2002-02-25 18:10:58 +00:00
|
|
|
#define LOG_CRIT 2
|
2002-02-24 19:58:31 +00:00
|
|
|
#define LOG_DEBUG 0
|
2002-02-25 18:10:58 +00:00
|
|
|
#define LOG_ERR 1
|
2002-02-24 19:58:31 +00:00
|
|
|
#define LOG_INFO 0
|
|
|
|
#define LOG_WARNING 0
|
|
|
|
void
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log (int prio)
|
2002-02-24 19:58:31 +00:00
|
|
|
{
|
2010-05-06 08:45:39 +00:00
|
|
|
if (in_config)
|
|
|
|
{
|
|
|
|
#ifndef __MINGW__
|
|
|
|
if (geteuid () != getuid ())
|
|
|
|
{
|
|
|
|
strcpy(ebuf, "problem with config file");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
2002-02-24 19:58:31 +00:00
|
|
|
write (2, ebuf, strlen (ebuf));
|
|
|
|
write (2, "\n", 1);
|
|
|
|
if (prio == LOG_CRIT)
|
|
|
|
{
|
|
|
|
fprintf (stderr, "exiting.\n");
|
|
|
|
fflush (stderr);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
2002-02-24 19:58:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2002-02-24 18:28:40 +00:00
|
|
|
|
1998-03-10 19:01:24 +00:00
|
|
|
/*
|
|
|
|
* Structure for linked list of addresses to probe rather than
|
|
|
|
* probing entire network.
|
|
|
|
*/
|
|
|
|
typedef struct plstruct {
|
1998-10-29 16:20:53 +00:00
|
|
|
struct plstruct *next;
|
|
|
|
int direct;
|
|
|
|
struct in_addr addr;
|
1998-03-10 19:01:24 +00:00
|
|
|
} plentry;
|
|
|
|
|
|
|
|
static plentry *plist = 0;
|
|
|
|
|
1997-05-03 19:18:21 +00:00
|
|
|
/*
|
|
|
|
* Variables used for determining if a connection is from a process
|
|
|
|
* on the local host.
|
|
|
|
*/
|
2002-02-26 09:43:04 +00:00
|
|
|
static int interfaces = 0; /* Number of interfaces. */
|
|
|
|
static struct in_addr *addr; /* Address of each interface. */
|
|
|
|
static unsigned char *bcok; /* Broadcast OK for interface? */
|
|
|
|
static struct in_addr *bcst; /* Broadcast for interface. */
|
|
|
|
static struct in_addr *mask; /* Netmask of each interface. */
|
1997-05-03 19:18:21 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
is_local_host(struct in_addr a)
|
|
|
|
{
|
1998-10-29 16:20:53 +00:00
|
|
|
int i;
|
1997-05-03 19:18:21 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
for (i = 0; i < interfaces; i++)
|
|
|
|
{
|
|
|
|
if (a.s_addr == addr[i].s_addr)
|
|
|
|
{
|
1998-12-05 06:50:15 +00:00
|
|
|
return 1;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
1998-12-05 06:50:15 +00:00
|
|
|
return 0;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
is_local_net(struct in_addr a)
|
|
|
|
{
|
1998-10-29 16:20:53 +00:00
|
|
|
int i;
|
1997-05-03 19:18:21 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
for (i = 0; i < interfaces; i++)
|
|
|
|
{
|
2000-02-22 08:32:04 +00:00
|
|
|
if ((mask[i].s_addr && addr[i].s_addr) == (mask[i].s_addr && a.s_addr))
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
1998-12-05 06:50:15 +00:00
|
|
|
return 1;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
1998-12-05 06:50:15 +00:00
|
|
|
return 0;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Variables used for handling non-blocking I/O on channels.
|
|
|
|
*/
|
2002-02-26 09:43:04 +00:00
|
|
|
static int tcp_desc = -1; /* Socket for incoming TCP connections. */
|
|
|
|
static int udp_desc = -1; /* Socket for UDP communications. */
|
|
|
|
static fd_set read_fds; /* Descriptors which are readable. */
|
|
|
|
static fd_set write_fds; /* Descriptors which are writable. */
|
1997-05-03 19:18:21 +00:00
|
|
|
|
2000-07-18 11:34:30 +00:00
|
|
|
|
|
|
|
/* Internal info structures. Rewritten Wed Jul 12 14:51:19 2000 by
|
|
|
|
Bjoern Giesler <Bjoern.Giesler@gmx.de> to work on Win32. */
|
|
|
|
|
|
|
|
typedef struct {
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
SOCKET s;
|
|
|
|
#else
|
|
|
|
int s;
|
2010-03-19 12:10:11 +00:00
|
|
|
#endif /* __MINGW__ */
|
1998-10-29 16:20:53 +00:00
|
|
|
struct sockaddr_in addr; /* Address of process making request. */
|
2010-03-16 15:08:20 +00:00
|
|
|
socklen_t pos; /* Position reading data. */
|
1998-10-29 16:20:53 +00:00
|
|
|
union {
|
|
|
|
gdo_req r;
|
|
|
|
unsigned char b[GDO_REQ_SIZE];
|
|
|
|
} buf;
|
2002-02-26 09:43:04 +00:00
|
|
|
} RInfo; /* State of reading each request. */
|
1997-05-03 19:18:21 +00:00
|
|
|
|
2000-07-18 11:34:30 +00:00
|
|
|
typedef struct {
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
SOCKET s;
|
|
|
|
#else
|
|
|
|
int s;
|
2010-03-19 12:10:11 +00:00
|
|
|
#endif /* __MINGW__ */
|
1998-10-29 16:20:53 +00:00
|
|
|
int len; /* Length of data to be written. */
|
|
|
|
int pos; /* Amount of data already written. */
|
|
|
|
char* buf; /* Buffer for data. */
|
2002-02-26 09:43:04 +00:00
|
|
|
} WInfo;
|
2000-07-18 11:34:30 +00:00
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
static RInfo *_rInfo = NULL;
|
|
|
|
static unsigned _rInfoCapacity = 0;
|
|
|
|
static unsigned _rInfoCount = 0;
|
|
|
|
static WInfo *_wInfo = NULL;
|
|
|
|
static unsigned _wInfoCapacity = 0;
|
|
|
|
static unsigned _wInfoCount = 0;
|
2000-07-18 11:34:30 +00:00
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
static void
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2002-02-26 09:43:04 +00:00
|
|
|
delRInfo(SOCKET s)
|
2000-07-18 11:34:30 +00:00
|
|
|
#else
|
2002-02-26 09:43:04 +00:00
|
|
|
delRInfo(int s)
|
2010-03-19 12:10:11 +00:00
|
|
|
#endif /* __MINGW__ */
|
2000-07-18 11:34:30 +00:00
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
unsigned int i;
|
2000-07-18 11:34:30 +00:00
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
for (i = 0; i < _rInfoCount; i++)
|
2000-07-18 11:34:30 +00:00
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
if (_rInfo[i].s == s)
|
2000-07-18 11:34:30 +00:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
if (i == _rInfoCount)
|
2000-07-18 11:34:30 +00:00
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"%s requested unallocated RInfo struct (socket %d)",
|
2002-02-24 19:58:31 +00:00
|
|
|
__FUNCTION__, s);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
2000-07-18 11:34:30 +00:00
|
|
|
return;
|
|
|
|
}
|
2002-02-27 05:59:00 +00:00
|
|
|
_rInfoCount--;
|
|
|
|
if (i != _rInfoCount) /* not last element */
|
2000-07-18 11:34:30 +00:00
|
|
|
{
|
2002-02-27 13:37:42 +00:00
|
|
|
memmove(&(_rInfo[i]), &(_rInfo[i+1]), (_rInfoCount-i)*sizeof(RInfo));
|
2000-07-18 11:34:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
|
|
|
|
static RInfo *
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2002-02-26 09:43:04 +00:00
|
|
|
getRInfo(SOCKET s, int make)
|
2000-07-18 11:34:30 +00:00
|
|
|
#else
|
2002-02-26 09:43:04 +00:00
|
|
|
getRInfo(int s, int make)
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
unsigned int i;
|
2000-07-18 11:34:30 +00:00
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
for (i = 0; i < _rInfoCount; i++)
|
2000-07-18 11:34:30 +00:00
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
if (_rInfo[i].s == s)
|
2000-07-18 11:34:30 +00:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
if (i == _rInfoCount)
|
2000-07-18 11:34:30 +00:00
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
if (make)
|
2000-07-18 11:34:30 +00:00
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
if (_rInfoCount >= _rInfoCapacity)
|
|
|
|
{
|
|
|
|
RInfo *tmp;
|
|
|
|
|
|
|
|
_rInfoCapacity = _rInfoCount + 1;
|
|
|
|
tmp = (RInfo *)calloc(_rInfoCapacity, sizeof(RInfo));
|
|
|
|
if (_rInfoCount > 0)
|
|
|
|
{
|
|
|
|
memcpy(tmp, _rInfo, sizeof(RInfo)*_rInfoCount);
|
|
|
|
free(_rInfo);
|
|
|
|
}
|
|
|
|
_rInfo = tmp;
|
|
|
|
}
|
|
|
|
_rInfoCount++;
|
|
|
|
_rInfo[_rInfoCount-1].s = s;
|
|
|
|
return &(_rInfo[_rInfoCount-1]);
|
2000-07-18 11:34:30 +00:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
return &(_rInfo[i]);
|
2000-07-18 11:34:30 +00:00
|
|
|
}
|
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
static void
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2002-02-26 09:43:04 +00:00
|
|
|
delWInfo(SOCKET s)
|
2000-07-18 11:34:30 +00:00
|
|
|
#else
|
2002-02-26 09:43:04 +00:00
|
|
|
delWInfo(int s)
|
2010-03-19 12:10:11 +00:00
|
|
|
#endif /* __MINGW__ */
|
2000-07-18 11:34:30 +00:00
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
unsigned int i;
|
2000-07-18 11:34:30 +00:00
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
for (i = 0; i < _wInfoCount; i++)
|
2000-07-18 11:34:30 +00:00
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
if (_wInfo[i].s == s)
|
2000-07-18 11:34:30 +00:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
if (i == _wInfoCount)
|
2000-07-18 11:34:30 +00:00
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"%s requested unallocated WInfo struct (socket %d)",
|
2002-02-26 09:43:04 +00:00
|
|
|
__FUNCTION__, s);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
2000-07-18 11:34:30 +00:00
|
|
|
return;
|
|
|
|
}
|
2002-02-27 05:59:00 +00:00
|
|
|
_wInfoCount--;
|
|
|
|
if (i != _wInfoCount) /* not last element */
|
2000-07-18 11:34:30 +00:00
|
|
|
{
|
2002-02-27 13:37:42 +00:00
|
|
|
memmove(&(_wInfo[i]), &(_wInfo[i+1]), (_wInfoCount-i)*sizeof(WInfo));
|
2000-07-18 11:34:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
|
|
|
|
static WInfo *
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2002-02-26 09:43:04 +00:00
|
|
|
getWInfo(SOCKET s, int make)
|
2000-07-18 11:34:30 +00:00
|
|
|
#else
|
2002-02-26 09:43:04 +00:00
|
|
|
getWInfo(int s, int make)
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
unsigned int i;
|
2000-07-18 11:34:30 +00:00
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
for (i = 0; i < _wInfoCount; i++)
|
2000-07-18 11:34:30 +00:00
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
if (_wInfo[i].s == s)
|
2000-07-18 11:34:30 +00:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
if (i == _wInfoCount)
|
2000-07-18 11:34:30 +00:00
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
if (make)
|
2000-07-18 11:34:30 +00:00
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
if (_wInfoCount >= _wInfoCapacity)
|
|
|
|
{
|
|
|
|
WInfo *tmp;
|
|
|
|
|
|
|
|
_wInfoCapacity = _wInfoCount + 1;
|
|
|
|
tmp = (WInfo *)calloc(_wInfoCapacity, sizeof(WInfo));
|
|
|
|
if (_wInfoCount > 0)
|
|
|
|
{
|
|
|
|
memcpy(tmp, _wInfo, sizeof(WInfo)*_wInfoCount);
|
|
|
|
free(_wInfo);
|
|
|
|
}
|
|
|
|
_wInfo = tmp;
|
|
|
|
}
|
|
|
|
_wInfoCount++;
|
|
|
|
_wInfo[_wInfoCount-1].s = s;
|
|
|
|
return &(_wInfo[_wInfoCount-1]);
|
2000-07-18 11:34:30 +00:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
return &(_wInfo[i]);
|
2000-07-18 11:34:30 +00:00
|
|
|
}
|
1997-05-03 19:18:21 +00:00
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
|
|
|
|
static struct u_data {
|
1998-10-29 16:20:53 +00:00
|
|
|
struct sockaddr_in addr; /* Address to send to. */
|
|
|
|
int pos; /* Number of bytes already sent. */
|
|
|
|
int len; /* Length of data to send. */
|
|
|
|
uptr dat; /* Data to be sent. */
|
|
|
|
struct u_data *next; /* Next message to send. */
|
1997-09-01 21:59:51 +00:00
|
|
|
} *u_queue = 0;
|
2002-02-26 09:43:04 +00:00
|
|
|
static int udp_pending = 0;
|
1997-05-03 19:18:21 +00:00
|
|
|
|
|
|
|
/*
|
1997-09-01 21:59:51 +00:00
|
|
|
* Name - queue_msg()
|
|
|
|
* Purpose - Add a message to the queue of those to be sent
|
|
|
|
* on the UDP socket.
|
1997-05-03 19:18:21 +00:00
|
|
|
*/
|
2002-02-26 09:43:04 +00:00
|
|
|
static void
|
2005-07-08 11:48:37 +00:00
|
|
|
queue_msg(struct sockaddr_in* a, uptr d, unsigned l)
|
1997-05-03 19:18:21 +00:00
|
|
|
{
|
1998-10-29 16:20:53 +00:00
|
|
|
struct u_data* entry = (struct u_data*)malloc(sizeof(struct u_data));
|
|
|
|
|
|
|
|
memcpy(&entry->addr, a, sizeof(*a));
|
|
|
|
entry->pos = 0;
|
|
|
|
entry->len = l;
|
|
|
|
entry->dat = malloc(l);
|
|
|
|
memcpy(entry->dat, d, l);
|
|
|
|
entry->next = 0;
|
|
|
|
if (u_queue)
|
|
|
|
{
|
|
|
|
struct u_data* tmp = u_queue;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
while (tmp->next)
|
|
|
|
{
|
|
|
|
tmp = tmp->next;
|
|
|
|
}
|
|
|
|
tmp->next = entry;
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
u_queue = entry;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
udp_pending++;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
static void
|
1997-09-01 21:59:51 +00:00
|
|
|
queue_pop()
|
|
|
|
{
|
1998-10-29 16:20:53 +00:00
|
|
|
struct u_data* tmp = u_queue;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
if (tmp)
|
|
|
|
{
|
|
|
|
u_queue = tmp->next;
|
|
|
|
free(tmp->dat);
|
|
|
|
free(tmp);
|
|
|
|
udp_pending--;
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
|
|
|
}
|
1997-05-03 19:18:21 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Primitive mapping stuff.
|
|
|
|
*/
|
|
|
|
typedef struct {
|
2000-07-18 15:50:36 +00:00
|
|
|
uptr name; /* Service name registered. */
|
|
|
|
unsigned int port; /* Port it was mapped to. */
|
1998-10-29 16:20:53 +00:00
|
|
|
unsigned short size; /* Number of bytes in name. */
|
2000-07-18 15:50:36 +00:00
|
|
|
unsigned char net; /* Type of port registered. */
|
|
|
|
unsigned char svc; /* Type of port registered. */
|
1997-05-03 19:18:21 +00:00
|
|
|
} map_ent;
|
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
static int map_used = 0;
|
|
|
|
static int map_size = 0;
|
|
|
|
static map_ent **map = 0;
|
1997-05-03 19:18:21 +00:00
|
|
|
|
|
|
|
static int
|
1998-10-27 20:58:22 +00:00
|
|
|
compare(uptr n0, int l0, uptr n1, int l1)
|
1997-05-03 19:18:21 +00:00
|
|
|
{
|
1998-10-29 16:20:53 +00:00
|
|
|
if (l0 == l1)
|
|
|
|
{
|
1998-12-05 06:50:15 +00:00
|
|
|
return memcmp(n0, n1, l0);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else if (l0 < l1)
|
|
|
|
{
|
1998-12-05 06:50:15 +00:00
|
|
|
return -1;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-12-05 06:50:15 +00:00
|
|
|
return 1;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Name - map_add()
|
|
|
|
* Purpose - Create a new map entry structure and insert it
|
|
|
|
* into the map in the appropriate position.
|
|
|
|
*/
|
|
|
|
static map_ent*
|
1998-10-27 20:58:22 +00:00
|
|
|
map_add(uptr n, unsigned char l, unsigned int p, unsigned char t)
|
1997-05-03 19:18:21 +00:00
|
|
|
{
|
2013-07-13 11:02:30 +00:00
|
|
|
map_ent *m;
|
1998-10-29 16:20:53 +00:00
|
|
|
int i;
|
1997-05-03 19:18:21 +00:00
|
|
|
|
2013-07-13 11:02:30 +00:00
|
|
|
m = (map_ent*)malloc(sizeof(map_ent));
|
|
|
|
if (0 == m)
|
|
|
|
{
|
|
|
|
perror("no memory for map entry");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
m->port = p;
|
2005-07-08 11:48:37 +00:00
|
|
|
m->name = (unsigned char*)malloc(l);
|
2013-07-13 11:02:30 +00:00
|
|
|
if (0 == m->name)
|
|
|
|
{
|
|
|
|
perror("no memory for map entry name");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
m->size = l;
|
|
|
|
m->net = (t & GDO_NET_MASK);
|
|
|
|
m->svc = (t & GDO_SVC_MASK);
|
2002-02-27 13:37:42 +00:00
|
|
|
memcpy(m->name, n, l);
|
1997-05-03 19:18:21 +00:00
|
|
|
|
2013-07-13 11:02:30 +00:00
|
|
|
if (map_used == map_size)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2013-07-13 11:02:30 +00:00
|
|
|
map_size += 16;
|
|
|
|
if (map)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2013-07-13 11:02:30 +00:00
|
|
|
map = (map_ent**)realloc(map, map_size * sizeof(map_ent*));
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
2013-07-13 11:02:30 +00:00
|
|
|
map = (map_ent**)calloc(map_size, sizeof(map_ent*));
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
2013-07-13 11:02:30 +00:00
|
|
|
if (0 == map)
|
|
|
|
{
|
|
|
|
perror("no memory for map");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
for (i = 0; i < map_used; i++)
|
|
|
|
{
|
|
|
|
if (compare(map[i]->name, map[i]->size, m->name, m->size) > 0)
|
|
|
|
{
|
|
|
|
int j;
|
1997-05-03 19:18:21 +00:00
|
|
|
|
2004-06-16 14:48:05 +00:00
|
|
|
for (j = map_used; j > i; j--)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
|
|
|
map[j] = map[j-1];
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
break;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
map[i] = m;
|
|
|
|
map_used++;
|
|
|
|
if (debug > 2)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Added port %d to map for %.*s",
|
|
|
|
m->port, m->size, m->name);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-12-05 06:50:15 +00:00
|
|
|
return m;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Name - map_by_name()
|
|
|
|
* Purpose - Search the map for an entry for a particular name
|
|
|
|
*/
|
|
|
|
static map_ent*
|
1998-10-27 20:58:22 +00:00
|
|
|
map_by_name(uptr n, int s)
|
1997-05-03 19:18:21 +00:00
|
|
|
{
|
1998-10-29 16:20:53 +00:00
|
|
|
int lower = 0;
|
|
|
|
int upper = map_used;
|
|
|
|
int index;
|
|
|
|
|
|
|
|
if (debug > 2)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Searching map for %.*s", s, n);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
|
|
|
for (index = upper/2; upper != lower; index = lower + (upper - lower)/2)
|
|
|
|
{
|
|
|
|
int i = compare(map[index]->name, map[index]->size, n, s);
|
|
|
|
|
|
|
|
if (i < 0)
|
|
|
|
{
|
|
|
|
lower = index + 1;
|
|
|
|
}
|
|
|
|
else if (i > 0)
|
|
|
|
{
|
|
|
|
upper = index;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
break;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
if (index<map_used && compare(map[index]->name,map[index]->size,n,s) == 0)
|
|
|
|
{
|
|
|
|
if (debug > 2)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Found port %d for %.*s", map[index]->port, s, n);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-12-05 06:50:15 +00:00
|
|
|
return map[index];
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
if (debug > 2)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Failed to find map entry for %.*s", s, n);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-12-05 06:50:15 +00:00
|
|
|
return 0;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
|
1998-11-02 11:48:42 +00:00
|
|
|
/*
|
|
|
|
* Name - map_by_port()
|
|
|
|
* Purpose - Search the map for an entry for a particular port
|
|
|
|
*/
|
|
|
|
static map_ent*
|
|
|
|
map_by_port(unsigned p, unsigned char t)
|
|
|
|
{
|
|
|
|
int index;
|
|
|
|
|
|
|
|
if (debug > 2)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Searching map for %u:%x", p, t);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1998-11-02 11:48:42 +00:00
|
|
|
}
|
|
|
|
for (index = 0; index < map_used; index++)
|
|
|
|
{
|
|
|
|
map_ent *e = map[index];
|
|
|
|
|
|
|
|
if (e->port == p && (e->net | e->svc) == t)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (index < map_used)
|
|
|
|
{
|
|
|
|
if (debug > 2)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Found port %d with name %s",
|
1998-11-02 11:48:42 +00:00
|
|
|
map[index]->port, map[index]->name);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1998-11-02 11:48:42 +00:00
|
|
|
}
|
1998-12-05 06:50:15 +00:00
|
|
|
return map[index];
|
1998-11-02 11:48:42 +00:00
|
|
|
}
|
|
|
|
if (debug > 2)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Failed to find map entry for %u:%x", p, t);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1998-11-02 11:48:42 +00:00
|
|
|
}
|
1998-12-05 06:50:15 +00:00
|
|
|
return 0;
|
1998-11-02 11:48:42 +00:00
|
|
|
}
|
|
|
|
|
1997-05-03 19:18:21 +00:00
|
|
|
/*
|
|
|
|
* Name - map_del()
|
|
|
|
* Purpose - Remove a mapping entry from the map and release
|
|
|
|
* the memory it uses.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
map_del(map_ent* e)
|
|
|
|
{
|
1998-10-29 16:20:53 +00:00
|
|
|
int i;
|
1997-05-03 19:18:21 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
if (debug > 2)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Removing port %d from map for %.*s",
|
|
|
|
e->port, e->size, e->name);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
for (i = 0; i < map_used; i++)
|
|
|
|
{
|
|
|
|
if (map[i] == e)
|
|
|
|
{
|
|
|
|
int j;
|
|
|
|
|
|
|
|
free(e->name);
|
|
|
|
free(e);
|
|
|
|
for (j = i + 1; j < map_used; j++)
|
|
|
|
{
|
|
|
|
map[j-1] = map[j];
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
map_used--;
|
|
|
|
return;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Variables and functions for keeping track of the IP addresses of
|
|
|
|
* hosts which are running the name server.
|
|
|
|
*/
|
2002-02-26 09:43:04 +00:00
|
|
|
static unsigned long prb_used = 0;
|
|
|
|
static unsigned long prb_size = 0;
|
1998-02-26 17:55:42 +00:00
|
|
|
typedef struct {
|
1998-10-29 16:20:53 +00:00
|
|
|
struct in_addr sin;
|
2003-10-08 08:58:18 +00:00
|
|
|
time_t when;
|
1998-02-26 17:55:42 +00:00
|
|
|
} prb_type;
|
2002-02-26 09:43:04 +00:00
|
|
|
static prb_type **prb = 0;
|
1998-02-26 17:55:42 +00:00
|
|
|
|
1997-05-03 19:18:21 +00:00
|
|
|
/*
|
|
|
|
* Name - prb_add()
|
1999-08-21 05:29:10 +00:00
|
|
|
* Purpose - Create a new probe entry in the list.
|
|
|
|
* The new entry is always placed at the end of the list
|
|
|
|
* so that the list remains in the order in which hosts
|
|
|
|
* have been contancted.
|
1997-05-03 19:18:21 +00:00
|
|
|
*/
|
1998-02-26 17:55:42 +00:00
|
|
|
static void
|
1997-05-03 19:18:21 +00:00
|
|
|
prb_add(struct in_addr *p)
|
|
|
|
{
|
1999-08-21 05:29:10 +00:00
|
|
|
prb_type *n = 0;
|
2003-01-03 20:14:47 +00:00
|
|
|
unsigned int i;
|
1997-05-03 19:18:21 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
if (is_local_host(*p) != 0)
|
|
|
|
{
|
|
|
|
return;
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
if (is_local_net(*p) == 0)
|
|
|
|
{
|
|
|
|
return;
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
|
1999-08-21 05:29:10 +00:00
|
|
|
/*
|
|
|
|
* If we already have an entry for this address, remove it from the list
|
|
|
|
* ready for re-insertion in the correct place.
|
|
|
|
*/
|
2013-04-14 16:25:27 +00:00
|
|
|
i = prb_used;
|
|
|
|
while (i-- > 0)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
1999-08-21 05:29:10 +00:00
|
|
|
if (memcmp(&prb[i]->sin, p, IASIZE) == 0)
|
|
|
|
{
|
|
|
|
n = prb[i];
|
2013-04-14 16:25:27 +00:00
|
|
|
prb_used--;
|
|
|
|
while (i++ < prb_used)
|
1999-08-21 05:29:10 +00:00
|
|
|
{
|
|
|
|
prb[i-1] = prb[i];
|
|
|
|
}
|
2013-04-14 16:25:27 +00:00
|
|
|
break;
|
1999-08-21 05:29:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create a new entry structure if necessary.
|
|
|
|
* Set the current time in the structure, so we know when we last had contact.
|
|
|
|
*/
|
2013-04-14 16:25:27 +00:00
|
|
|
if (0 == n)
|
1999-08-21 05:29:10 +00:00
|
|
|
{
|
2013-04-14 16:25:27 +00:00
|
|
|
n = (prb_type*)calloc(sizeof(prb_type), 1);
|
1999-08-21 05:29:10 +00:00
|
|
|
n->sin = *p;
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
n->when = time(0);
|
1997-05-03 19:18:21 +00:00
|
|
|
|
1999-08-21 05:29:10 +00:00
|
|
|
/*
|
|
|
|
* Grow the list if we need more space.
|
|
|
|
*/
|
1998-10-29 16:20:53 +00:00
|
|
|
if (prb_used >= prb_size)
|
|
|
|
{
|
2013-04-14 16:25:27 +00:00
|
|
|
prb_size = prb_used + 16;
|
|
|
|
if (prb)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2013-04-14 16:25:27 +00:00
|
|
|
prb = (prb_type**)realloc(prb, prb_size * sizeof(prb_type*));
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
2013-04-14 16:25:27 +00:00
|
|
|
prb = (prb_type**)calloc(prb_size * sizeof(prb_type*), 1);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-08-21 05:29:10 +00:00
|
|
|
/*
|
|
|
|
* Append the new item at the end of the list.
|
|
|
|
*/
|
2013-04-14 16:25:27 +00:00
|
|
|
prb[prb_used++] = n;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Name - prb_del()
|
|
|
|
* Purpose - Remove an entry from the list.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
prb_del(struct in_addr *p)
|
|
|
|
{
|
2013-04-14 16:25:27 +00:00
|
|
|
unsigned int i = prb_used;
|
1997-05-03 19:18:21 +00:00
|
|
|
|
2013-04-14 16:25:27 +00:00
|
|
|
while (i-- > 0)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
|
|
|
if (memcmp(&prb[i]->sin, p, IASIZE) == 0)
|
|
|
|
{
|
|
|
|
free(prb[i]);
|
2013-04-14 16:25:27 +00:00
|
|
|
prb_used--;
|
|
|
|
while (i++ < prb_used)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2013-04-14 16:25:27 +00:00
|
|
|
prb[i - 1] = prb[i];
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
return;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-02-26 17:55:42 +00:00
|
|
|
/*
|
1998-04-02 14:27:40 +00:00
|
|
|
* Remove any server from which we have had no messages in the last
|
|
|
|
* thirty minutes (as long as we have sent as probe in that time).
|
1998-02-26 17:55:42 +00:00
|
|
|
*/
|
|
|
|
static void
|
2003-10-08 08:58:18 +00:00
|
|
|
prb_tim(time_t when)
|
1998-02-26 17:55:42 +00:00
|
|
|
{
|
2013-04-14 16:25:27 +00:00
|
|
|
int i = prb_used;
|
1998-02-26 17:55:42 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
when -= 1800;
|
2013-04-14 16:25:27 +00:00
|
|
|
while (i-- > 0)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2000-02-22 08:32:04 +00:00
|
|
|
if (noprobe == 0 && prb[i]->when < when && prb[i]->when < last_probe)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
|
|
|
prb_del(&prb[i]->sin);
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1997-05-03 19:18:21 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Name - clear_chan()
|
|
|
|
* Purpose - Release all resources associated with a channel
|
|
|
|
* and remove it from the list of requests being
|
|
|
|
* serviced.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
clear_chan(int desc)
|
|
|
|
{
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2002-02-25 20:44:41 +00:00
|
|
|
if (desc != INVALID_SOCKET)
|
2000-07-18 11:34:30 +00:00
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
if (desc >= 0 && desc < FD_SETSIZE)
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
WInfo *wi;
|
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
FD_CLR(desc, &write_fds);
|
|
|
|
if (desc == tcp_desc || desc == udp_desc)
|
|
|
|
{
|
|
|
|
FD_SET(desc, &read_fds);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
FD_CLR(desc, &read_fds);
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
closesocket(desc);
|
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
close(desc);
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
if ((wi = getWInfo(desc, 0)) != 0)
|
2000-07-18 11:34:30 +00:00
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
if (wi->buf)
|
2000-07-18 11:34:30 +00:00
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
free(wi->buf);
|
|
|
|
wi->buf = 0;
|
2000-07-18 11:34:30 +00:00
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
wi->len = 0;
|
|
|
|
wi->pos = 0;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
2000-07-18 11:34:30 +00:00
|
|
|
if (!(desc == tcp_desc || desc == udp_desc))
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
if (wi != 0)
|
2000-07-18 11:34:30 +00:00
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
delWInfo(desc);
|
2000-07-18 11:34:30 +00:00
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
delRInfo(desc);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
static void
|
|
|
|
dump_stats()
|
|
|
|
{
|
1998-10-29 16:20:53 +00:00
|
|
|
int tcp_pending = 0;
|
2003-01-03 20:14:47 +00:00
|
|
|
unsigned int i;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
for (i = 0; i < _wInfoCount; i++)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
if (_wInfo[i].len > 0)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
|
|
|
tcp_pending++;
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
|
|
|
}
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"tcp messages waiting for send - %d", tcp_pending);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_INFO);
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"udp messages waiting for send - %d", udp_pending);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_INFO);
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "size of name-to-port map - %d", map_used);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_INFO);
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "number of known name servers - %ld", prb_used);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_INFO);
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "TCP %d read, %d sent", tcp_read, tcp_sent);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_INFO);
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "UDP %d read, %d sent", udp_read, udp_sent);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_INFO);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
|
|
|
|
2010-03-19 12:10:11 +00:00
|
|
|
#ifndef __MINGW__
|
2000-07-24 12:03:14 +00:00
|
|
|
static void
|
|
|
|
dump_tables()
|
|
|
|
{
|
|
|
|
FILE *fptr;
|
|
|
|
|
|
|
|
soft_int++;
|
2010-05-05 09:23:01 +00:00
|
|
|
if (access(".", W_OK) != 0)
|
|
|
|
{
|
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Failed to access gdomap.dump file for output\n");
|
|
|
|
gdomap_log(LOG_ERR);
|
|
|
|
return;
|
|
|
|
}
|
2000-07-24 12:03:14 +00:00
|
|
|
fptr = fopen("gdomap.dump", "w");
|
|
|
|
if (fptr != 0)
|
|
|
|
{
|
|
|
|
fprintf(fptr, "\n");
|
|
|
|
fprintf(fptr, "Known nameserver addresses\n");
|
|
|
|
fprintf(fptr, "==========================\n");
|
|
|
|
if (prb_used == 0)
|
|
|
|
{
|
|
|
|
fprintf(fptr, "None.\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
unsigned int i;
|
2000-07-24 12:03:14 +00:00
|
|
|
|
|
|
|
for (i = 0; i < prb_used; i++)
|
|
|
|
{
|
|
|
|
fprintf(fptr, "%16s %s\n",
|
2002-02-24 18:28:40 +00:00
|
|
|
inet_ntoa(prb[i]->sin), (const char*)ctime(&prb[i]->when));
|
2000-07-24 12:03:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(fptr, "\n");
|
|
|
|
fclose(fptr);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Failed to open gdomap.dump file for output\n");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
2000-07-24 12:03:14 +00:00
|
|
|
}
|
|
|
|
}
|
2005-02-21 14:44:18 +00:00
|
|
|
#endif
|
2000-07-24 12:03:14 +00:00
|
|
|
|
1997-05-03 19:18:21 +00:00
|
|
|
/*
|
|
|
|
* Name - init_iface()
|
1998-05-29 15:25:41 +00:00
|
|
|
* Purpose - Build up an array of the IP addresses supported on
|
|
|
|
* the network interfaces of this machine.
|
1997-05-03 19:18:21 +00:00
|
|
|
*/
|
|
|
|
static void
|
|
|
|
init_iface()
|
|
|
|
{
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2002-02-25 18:10:58 +00:00
|
|
|
INTERFACE_INFO InterfaceList[20];
|
|
|
|
unsigned long nBytesReturned;
|
2002-02-26 18:23:32 +00:00
|
|
|
int i, countActive, nNumInterfaces;
|
|
|
|
SOCKET desc = WSASocket(PF_INET, SOCK_RAW, AF_INET, 0, 0, 0);
|
2002-02-25 18:10:58 +00:00
|
|
|
|
2002-02-26 18:23:32 +00:00
|
|
|
if (desc == INVALID_SOCKET)
|
2002-02-25 18:10:58 +00:00
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Failed to get a socket. Error %d\n", WSAGetLastError());
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
2002-02-25 18:10:58 +00:00
|
|
|
}
|
|
|
|
|
2002-02-26 18:23:32 +00:00
|
|
|
memset((void*)InterfaceList, '\0', sizeof(InterfaceList));
|
|
|
|
if (WSAIoctl(desc, SIO_GET_INTERFACE_LIST, 0, 0, (void*)InterfaceList,
|
2002-02-25 18:10:58 +00:00
|
|
|
sizeof(InterfaceList), &nBytesReturned, 0, 0) == SOCKET_ERROR)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Failed WSAIoctl. Error %d\n", WSAGetLastError());
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
2002-02-25 18:10:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO);
|
|
|
|
|
2002-02-26 18:23:32 +00:00
|
|
|
/*
|
|
|
|
* See how many active entries there are.
|
|
|
|
*/
|
|
|
|
countActive = 0;
|
|
|
|
for (i = 0; i < nNumInterfaces; i++)
|
|
|
|
{
|
|
|
|
u_long nFlags = InterfaceList[i].iiFlags;
|
|
|
|
|
|
|
|
if ((nFlags & IFF_UP)
|
2002-11-13 15:12:39 +00:00
|
|
|
&& (InterfaceList[i].iiAddress.Address.sa_family == AF_INET))
|
2002-02-26 18:23:32 +00:00
|
|
|
{
|
|
|
|
countActive++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-02-25 18:10:58 +00:00
|
|
|
/*
|
|
|
|
* Allocate enough space for all interfaces.
|
|
|
|
*/
|
|
|
|
if (addr != 0) free(addr);
|
2002-02-26 18:23:32 +00:00
|
|
|
addr = (struct in_addr*)malloc((countActive+1)*IASIZE);
|
2002-02-25 18:10:58 +00:00
|
|
|
if (bcok != 0) free(bcok);
|
2012-08-27 09:26:00 +00:00
|
|
|
bcok = (unsigned char*)malloc((countActive+1)*sizeof(unsigned char));
|
2002-02-25 18:10:58 +00:00
|
|
|
if (bcst != 0) free(bcst);
|
2002-02-26 18:23:32 +00:00
|
|
|
bcst = (struct in_addr*)malloc((countActive+1)*IASIZE);
|
2002-02-25 18:10:58 +00:00
|
|
|
if (mask != 0) free(mask);
|
2002-02-26 18:23:32 +00:00
|
|
|
mask = (struct in_addr*)malloc((countActive+1)*IASIZE);
|
2002-02-25 18:10:58 +00:00
|
|
|
|
|
|
|
for (i = 0; i < nNumInterfaces; i++)
|
|
|
|
{
|
2002-02-25 20:44:41 +00:00
|
|
|
u_long nFlags = InterfaceList[i].iiFlags;
|
2002-02-25 18:10:58 +00:00
|
|
|
|
2002-02-26 18:23:32 +00:00
|
|
|
if ((nFlags & IFF_UP)
|
2002-11-13 15:12:39 +00:00
|
|
|
&& (InterfaceList[i].iiAddress.Address.sa_family == AF_INET))
|
2002-02-25 20:44:41 +00:00
|
|
|
{
|
2002-02-25 18:10:58 +00:00
|
|
|
int broadcast = 0;
|
|
|
|
int pointopoint = 0;
|
|
|
|
int loopback = 0;
|
|
|
|
|
|
|
|
if (nFlags & IFF_BROADCAST)
|
|
|
|
{
|
|
|
|
broadcast = 1;
|
|
|
|
}
|
|
|
|
if (nFlags & IFF_POINTTOPOINT)
|
|
|
|
{
|
|
|
|
pointopoint = 1;
|
|
|
|
}
|
|
|
|
if (nFlags & IFF_LOOPBACK)
|
|
|
|
{
|
|
|
|
loopback = 1;
|
|
|
|
}
|
2002-02-25 20:44:41 +00:00
|
|
|
addr[interfaces] = ((struct sockaddr_in*)
|
|
|
|
&(InterfaceList[i].iiAddress))->sin_addr;
|
|
|
|
mask[interfaces] = ((struct sockaddr_in*)
|
|
|
|
&(InterfaceList[i].iiNetmask))->sin_addr;
|
|
|
|
bcst[interfaces] = ((struct sockaddr_in*)
|
|
|
|
&(InterfaceList[i].iiBroadcastAddress))->sin_addr;
|
2002-02-25 18:10:58 +00:00
|
|
|
bcok[interfaces] = (broadcast | pointopoint);
|
2002-02-25 20:44:41 +00:00
|
|
|
|
|
|
|
if (addr[interfaces].s_addr == 0)
|
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
addr[interfaces].s_addr = htonl(0x8f000001);
|
2004-05-06 12:10:03 +00:00
|
|
|
fprintf(stderr, "Bad iface addr (0.0.0.0) guess (%s)\n",
|
2002-02-25 20:44:41 +00:00
|
|
|
inet_ntoa(addr[interfaces]));
|
|
|
|
}
|
|
|
|
if (mask[interfaces].s_addr == 0)
|
|
|
|
{
|
|
|
|
mask[interfaces].s_addr = htonl(0xffffff00);
|
|
|
|
fprintf(stderr, "Bad iface mask (0.0.0.0) guess (%s)\n",
|
|
|
|
inet_ntoa(mask[interfaces]));
|
|
|
|
}
|
|
|
|
if (bcst[interfaces].s_addr == 0)
|
|
|
|
{
|
|
|
|
u_long l = ntohl(addr[interfaces].s_addr);
|
2002-02-26 09:43:04 +00:00
|
|
|
bcst[interfaces].s_addr = htonl(l | 0xff);
|
2002-02-25 20:44:41 +00:00
|
|
|
fprintf(stderr, "Bad iface bcst (0.0.0.0) guess (%s)\n",
|
|
|
|
inet_ntoa(bcst[interfaces]));
|
|
|
|
}
|
2002-02-25 18:10:58 +00:00
|
|
|
interfaces++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
closesocket(desc);
|
|
|
|
#else
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(SIOCGIFCONF)
|
1998-10-29 16:20:53 +00:00
|
|
|
struct ifconf ifc;
|
|
|
|
struct ifreq ifreq;
|
2002-01-25 20:26:37 +00:00
|
|
|
void *final;
|
|
|
|
void *ifr_ptr;
|
1998-10-29 16:20:53 +00:00
|
|
|
char buf[MAX_IFACE * sizeof(struct ifreq)];
|
|
|
|
int desc;
|
|
|
|
|
|
|
|
if ((desc = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
|
|
|
{
|
|
|
|
perror("socket for init_iface");
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
2012-08-26 08:55:49 +00:00
|
|
|
// QNX seems to disagree about what it means to be SysV r4.
|
|
|
|
#if defined(__svr4__) && !defined(__QNXNTO__)
|
1998-05-29 15:25:41 +00:00
|
|
|
{
|
1998-10-29 16:20:53 +00:00
|
|
|
struct strioctl ioc;
|
1997-05-03 19:18:21 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
ioc.ic_cmd = SIOCGIFCONF;
|
|
|
|
ioc.ic_timout = 0;
|
|
|
|
ioc.ic_len = sizeof(buf);
|
|
|
|
ioc.ic_dp = buf;
|
|
|
|
if (ioctl(desc, I_STR, (char*)&ioc) < 0)
|
|
|
|
{
|
|
|
|
ioc.ic_len = 0;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
ifc.ifc_len = ioc.ic_len;
|
|
|
|
ifc.ifc_buf = ioc.ic_dp;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-05-29 15:25:41 +00:00
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
ifc.ifc_len = sizeof(buf);
|
|
|
|
ifc.ifc_buf = buf;
|
|
|
|
if (ioctl(desc, SIOCGIFCONF, (char*)&ifc) < 0)
|
|
|
|
{
|
|
|
|
ifc.ifc_len = 0;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-05-29 15:25:41 +00:00
|
|
|
#endif
|
1997-05-03 19:18:21 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* Find the IP address of each active network interface.
|
|
|
|
*/
|
2002-01-25 20:26:37 +00:00
|
|
|
if (ifc.ifc_len == 0)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
|
|
|
int res = errno;
|
1998-05-29 15:25:41 +00:00
|
|
|
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
2008-10-30 14:22:19 +00:00
|
|
|
"SIOCGIFCONF for init_iface found no active interfaces; %s", lastErr());
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
2002-02-24 18:28:40 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
if (res == EINVAL)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
2002-02-24 18:28:40 +00:00
|
|
|
"Either you have too many network interfaces on your machine (in which case\n"
|
|
|
|
"you need to change the 'MAX_IFACE' constant in gdomap.c and rebuild it), or\n"
|
|
|
|
"your system is buggy, and you need to use the '-a' command line flag for\n"
|
2008-10-30 14:22:19 +00:00
|
|
|
"gdomap to manually set the interface addresses and masks to be used.\n"
|
|
|
|
"Try 'gdomap -C' for more information.\n");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_INFO);
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
close(desc);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
2002-01-25 20:26:37 +00:00
|
|
|
/*
|
|
|
|
* We cannot know the number of interfaces in advance, thus we
|
|
|
|
* need to malloc to MAX_IFACE toensure sufficient space
|
|
|
|
*/
|
2000-02-22 08:32:04 +00:00
|
|
|
if (addr != 0) free(addr);
|
2002-01-25 20:26:37 +00:00
|
|
|
addr = (struct in_addr*)malloc((MAX_IFACE+1)*IASIZE);
|
2000-02-22 08:32:04 +00:00
|
|
|
if (bcok != 0) free(bcok);
|
2013-04-14 16:25:27 +00:00
|
|
|
bcok = (unsigned char*)malloc((MAX_IFACE+1)*sizeof(unsigned char));
|
2000-02-22 08:32:04 +00:00
|
|
|
if (bcst != 0) free(bcst);
|
2002-01-25 20:26:37 +00:00
|
|
|
bcst = (struct in_addr*)malloc((MAX_IFACE+1)*IASIZE);
|
2000-02-22 08:32:04 +00:00
|
|
|
if (mask != 0) free(mask);
|
2002-01-25 20:26:37 +00:00
|
|
|
mask = (struct in_addr*)malloc((MAX_IFACE+1)*IASIZE);
|
1998-10-29 16:20:53 +00:00
|
|
|
|
2002-01-25 20:26:37 +00:00
|
|
|
final = &ifc.ifc_buf[ifc.ifc_len];
|
|
|
|
for (ifr_ptr = ifc.ifc_req; ifr_ptr < final;)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2002-01-25 20:26:37 +00:00
|
|
|
ifreq = *(struct ifreq*)ifr_ptr;
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(HAVE_SA_LEN)
|
2012-08-26 08:55:49 +00:00
|
|
|
ifr_ptr += sizeof(ifreq) - sizeof(ifreq.ifr_addr)
|
2005-04-20 02:58:17 +00:00
|
|
|
+ ROUND(ifreq.ifr_addr.sa_len, sizeof(struct ifreq*));
|
2002-01-25 20:26:37 +00:00
|
|
|
#else
|
|
|
|
ifr_ptr += sizeof(ifreq);
|
|
|
|
#endif
|
|
|
|
|
2000-02-19 00:40:47 +00:00
|
|
|
if (ioctl(desc, SIOCGIFFLAGS, (char *)&ifreq) < 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "SIOCGIFFLAGS: %s", lastErr());
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
2000-02-19 00:40:47 +00:00
|
|
|
}
|
|
|
|
else if (ifreq.ifr_flags & IFF_UP)
|
|
|
|
{ /* interface is up */
|
2000-02-22 08:32:04 +00:00
|
|
|
int broadcast = 0;
|
|
|
|
int pointopoint = 0;
|
2002-01-25 20:26:37 +00:00
|
|
|
int loopback = 0;
|
2000-02-22 08:32:04 +00:00
|
|
|
|
|
|
|
if (ifreq.ifr_flags & IFF_BROADCAST)
|
|
|
|
{
|
|
|
|
broadcast = 1;
|
|
|
|
}
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(IFF_POINTOPOINT)
|
2000-02-22 08:32:04 +00:00
|
|
|
if (ifreq.ifr_flags & IFF_POINTOPOINT)
|
|
|
|
{
|
|
|
|
pointopoint = 1;
|
|
|
|
}
|
2002-01-25 20:26:37 +00:00
|
|
|
#endif
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(IFF_LOOPBACK)
|
2002-01-25 20:26:37 +00:00
|
|
|
if (ifreq.ifr_flags & IFF_LOOPBACK)
|
|
|
|
{
|
|
|
|
loopback = 1;
|
|
|
|
}
|
2000-06-13 14:50:40 +00:00
|
|
|
#endif
|
2000-02-19 00:40:47 +00:00
|
|
|
if (ioctl(desc, SIOCGIFADDR, (char *)&ifreq) < 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "SIOCGIFADDR: %s", lastErr());
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
2000-02-19 00:40:47 +00:00
|
|
|
}
|
|
|
|
else if (ifreq.ifr_addr.sa_family == AF_INET)
|
|
|
|
{ /* IP interface */
|
|
|
|
if (interfaces >= MAX_IFACE)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
1998-12-05 06:50:15 +00:00
|
|
|
"You have too many network interfaces on your machine (in which case you need\n"
|
|
|
|
"to change the 'MAX_IFACE' constant in gdomap.c and rebuild it), or your\n"
|
|
|
|
"system is buggy, and you need to use the '-a' command line flag for\n"
|
2008-10-30 14:22:19 +00:00
|
|
|
"gdomap to manually set the interface addresses and masks to be used.\n"
|
|
|
|
"Try 'gdomap -C' for more information.\n");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_INFO);
|
2000-07-18 11:34:30 +00:00
|
|
|
close(desc);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
2000-02-19 00:40:47 +00:00
|
|
|
}
|
|
|
|
addr[interfaces] =
|
|
|
|
((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
|
2000-02-22 08:32:04 +00:00
|
|
|
bcok[interfaces] = (broadcast | pointopoint);
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(IFF_POINTOPOINT)
|
2000-02-22 08:32:04 +00:00
|
|
|
if (pointopoint)
|
|
|
|
{
|
|
|
|
if (ioctl(desc, SIOCGIFDSTADDR, (char*)&ifreq) < 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"SIOCGIFADDR: %s", lastErr());
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
2000-02-22 08:32:04 +00:00
|
|
|
bcok[interfaces] = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bcst[interfaces]
|
|
|
|
= ((struct sockaddr_in *)&ifreq.ifr_dstaddr)->sin_addr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2000-06-13 14:50:40 +00:00
|
|
|
#endif
|
2000-02-22 08:32:04 +00:00
|
|
|
{
|
2008-10-30 14:22:19 +00:00
|
|
|
if (!loopback
|
|
|
|
&& ioctl(desc, SIOCGIFBRDADDR, (char*)&ifreq) < 0)
|
2000-02-22 08:32:04 +00:00
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"SIOCGIFBRDADDR: %s", lastErr());
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
2000-02-22 08:32:04 +00:00
|
|
|
bcok[interfaces] = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bcst[interfaces]
|
|
|
|
= ((struct sockaddr_in*)&ifreq.ifr_broadaddr)->sin_addr;
|
|
|
|
}
|
|
|
|
}
|
2000-02-19 00:40:47 +00:00
|
|
|
if (ioctl(desc, SIOCGIFNETMASK, (char *)&ifreq) < 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "SIOCGIFNETMASK: %s", lastErr());
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
2000-02-19 00:40:47 +00:00
|
|
|
/*
|
|
|
|
* If we can't get a netmask - assume a class-c
|
|
|
|
* network.
|
|
|
|
*/
|
|
|
|
mask[interfaces] = class_c_mask;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1998-02-26 17:55:42 +00:00
|
|
|
/*
|
|
|
|
* Some systems don't have ifr_netmask
|
|
|
|
*/
|
|
|
|
#ifdef ifr_netmask
|
2000-02-19 00:40:47 +00:00
|
|
|
mask[interfaces] =
|
|
|
|
((struct sockaddr_in *)&ifreq.ifr_netmask)->sin_addr;
|
1998-02-26 17:55:42 +00:00
|
|
|
#else
|
2000-02-19 00:40:47 +00:00
|
|
|
mask[interfaces] =
|
|
|
|
((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
|
1998-02-26 17:55:42 +00:00
|
|
|
#endif
|
2000-02-19 00:40:47 +00:00
|
|
|
}
|
|
|
|
interfaces++;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2002-02-25 18:10:58 +00:00
|
|
|
close(desc);
|
2002-02-25 20:44:41 +00:00
|
|
|
#endif /* SIOCGIFCONF */
|
|
|
|
#endif /* MINGW */
|
|
|
|
|
|
|
|
if (interfaces == 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"I can't find any network interfaces on this platform - "
|
2008-10-30 14:22:19 +00:00
|
|
|
"use the '-a' flag to load interface details from a file instead.\n"
|
|
|
|
"Try 'gdomap -C' for more information.\n");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
2002-02-25 20:44:41 +00:00
|
|
|
}
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Name - load_iface()
|
|
|
|
* Purpose - Read addresses and netmasks for interfaces on this
|
|
|
|
* machine from a file.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
load_iface(const char* from)
|
|
|
|
{
|
2010-05-05 09:23:01 +00:00
|
|
|
FILE *fptr;
|
1998-10-29 16:20:53 +00:00
|
|
|
char buf[128];
|
2010-05-03 20:28:23 +00:00
|
|
|
int line = 0;
|
1998-10-29 16:20:53 +00:00
|
|
|
int num_iface = 0;
|
1998-05-29 15:25:41 +00:00
|
|
|
|
2010-05-06 05:09:12 +00:00
|
|
|
in_config = 1;
|
2010-05-05 09:23:01 +00:00
|
|
|
if (access(from, R_OK) != 0)
|
|
|
|
{
|
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Unable to access address config - '%s'", from);
|
|
|
|
gdomap_log(LOG_CRIT);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
fptr = fopen(from, "rt");
|
1998-10-29 16:20:53 +00:00
|
|
|
if (fptr == 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Unable to open address config - '%s'", from);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while (fgets(buf, sizeof(buf), fptr) != 0)
|
|
|
|
{
|
|
|
|
char *ptr = buf;
|
|
|
|
|
2010-05-03 20:28:23 +00:00
|
|
|
line++;
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* Strip leading white space.
|
|
|
|
*/
|
|
|
|
while (isspace(*ptr))
|
|
|
|
{
|
|
|
|
ptr++;
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
if (ptr != buf)
|
|
|
|
{
|
|
|
|
strcpy(buf, ptr);
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* Strip comments.
|
|
|
|
*/
|
|
|
|
ptr = strchr(buf, '#');
|
|
|
|
if (ptr)
|
|
|
|
{
|
|
|
|
*ptr = '\0';
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* Strip trailing white space.
|
|
|
|
*/
|
|
|
|
ptr = buf;
|
|
|
|
while (*ptr)
|
|
|
|
{
|
|
|
|
ptr++;
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
while (ptr > buf && isspace(ptr[-1]))
|
|
|
|
{
|
|
|
|
ptr--;
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
*ptr = '\0';
|
|
|
|
/*
|
|
|
|
* Ignore blank lines.
|
|
|
|
*/
|
|
|
|
if (*buf == '\0')
|
|
|
|
{
|
|
|
|
continue;
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
2010-05-06 05:09:12 +00:00
|
|
|
if (num_iface++ > 1000)
|
|
|
|
{
|
|
|
|
snprintf(ebuf, sizeof(ebuf), "Too many network interfaces found");
|
|
|
|
gdomap_log(LOG_CRIT);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
fseek(fptr, 0, 0);
|
1998-05-29 15:25:41 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
if (num_iface == 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "No network interfaces found");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
2001-02-23 10:11:32 +00:00
|
|
|
num_iface++;
|
|
|
|
addr = (struct in_addr*)malloc((num_iface+1)*IASIZE);
|
|
|
|
mask = (struct in_addr*)malloc((num_iface+1)*IASIZE);
|
2013-04-14 16:25:27 +00:00
|
|
|
bcok = (unsigned char*)malloc((num_iface+1)*sizeof(unsigned char));
|
2001-02-23 10:11:32 +00:00
|
|
|
bcst = (struct in_addr*)malloc((num_iface+1)*IASIZE);
|
|
|
|
|
|
|
|
addr[interfaces].s_addr = inet_addr("127.0.0.1");
|
|
|
|
mask[interfaces].s_addr = inet_addr("255.255.255.0");
|
|
|
|
bcok[interfaces] = 0;
|
|
|
|
bcst[interfaces].s_addr = inet_addr("127.0.0.255");
|
|
|
|
interfaces++;
|
2002-02-26 09:43:04 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
while (fgets(buf, sizeof(buf), fptr) != 0)
|
|
|
|
{
|
|
|
|
char *ptr = buf;
|
2001-02-23 10:11:32 +00:00
|
|
|
char *msk;
|
1998-05-29 15:25:41 +00:00
|
|
|
|
2010-05-03 20:28:23 +00:00
|
|
|
line++;
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* Strip leading white space.
|
|
|
|
*/
|
|
|
|
while (isspace(*ptr))
|
|
|
|
{
|
|
|
|
ptr++;
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
if (ptr != buf)
|
|
|
|
{
|
|
|
|
strcpy(buf, ptr);
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* Strip comments.
|
|
|
|
*/
|
|
|
|
ptr = strchr(buf, '#');
|
|
|
|
if (ptr)
|
|
|
|
{
|
|
|
|
*ptr = '\0';
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* Strip trailing white space.
|
|
|
|
*/
|
|
|
|
ptr = buf;
|
|
|
|
while (*ptr)
|
|
|
|
{
|
|
|
|
ptr++;
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
while (ptr > buf && isspace(ptr[-1]))
|
|
|
|
{
|
|
|
|
ptr--;
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
*ptr = '\0';
|
|
|
|
/*
|
|
|
|
* Ignore blank lines.
|
|
|
|
*/
|
|
|
|
if (*buf == '\0')
|
|
|
|
{
|
|
|
|
continue;
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
ptr = buf;
|
2001-02-23 10:11:32 +00:00
|
|
|
while (*ptr && (isdigit(*ptr) || (*ptr == '.')))
|
|
|
|
{
|
|
|
|
ptr++;
|
|
|
|
}
|
|
|
|
while (isspace(*ptr))
|
|
|
|
{
|
|
|
|
*ptr++ = '\0';
|
|
|
|
}
|
|
|
|
msk = ptr;
|
1998-10-29 16:20:53 +00:00
|
|
|
while (*ptr && (isdigit(*ptr) || (*ptr == '.')))
|
|
|
|
{
|
|
|
|
ptr++;
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
while (isspace(*ptr))
|
|
|
|
{
|
|
|
|
*ptr++ = '\0';
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
addr[interfaces].s_addr = inet_addr(buf);
|
2001-02-23 10:11:32 +00:00
|
|
|
mask[interfaces].s_addr = inet_addr(msk);
|
|
|
|
if (isdigit(*ptr))
|
|
|
|
{
|
|
|
|
bcok[interfaces] = 1;
|
|
|
|
bcst[interfaces].s_addr = inet_addr(ptr);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bcok[interfaces] = 0;
|
|
|
|
bcst[interfaces].s_addr = inet_addr("0.0.0.0");
|
|
|
|
}
|
2006-01-10 10:29:11 +00:00
|
|
|
if (addr[interfaces].s_addr == (uint32_t)-1)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2010-05-06 05:09:12 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "line %d of '%s' bad address (%s)",
|
|
|
|
line, from, buf);
|
|
|
|
gdomap_log(LOG_CRIT);
|
|
|
|
exit(EXIT_FAILURE);
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
2006-01-10 10:29:11 +00:00
|
|
|
else if (mask[interfaces].s_addr == (uint32_t)-1)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2010-05-06 05:09:12 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "line %d of '%s' bad netmask (%s)",
|
|
|
|
line, from, ptr);
|
|
|
|
gdomap_log(LOG_CRIT);
|
|
|
|
exit(EXIT_FAILURE);
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
interfaces++;
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
fclose(fptr);
|
2010-05-06 05:09:12 +00:00
|
|
|
in_config = 0;
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Name - init_my_port()
|
|
|
|
* Purpose - Establish our well-known port (my_port).
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
init_my_port()
|
|
|
|
{
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* First we determine the port for the 'gdomap' service - ideally
|
|
|
|
* this should be the default port, since we should have registered
|
|
|
|
* this with the appropriate authority and have it reserved for us.
|
|
|
|
*/
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(GDOMAP_PORT_OVERRIDE)
|
1998-10-29 16:20:53 +00:00
|
|
|
my_port = htons(GDOMAP_PORT_OVERRIDE);
|
1998-05-29 15:25:41 +00:00
|
|
|
#else
|
2013-03-05 16:20:10 +00:00
|
|
|
struct servent *sp;
|
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
my_port = htons(GDOMAP_PORT);
|
|
|
|
if ((sp = getservbyname("gdomap", "tcp")) == 0)
|
|
|
|
{
|
2002-03-20 09:37:36 +00:00
|
|
|
if (debug)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Unable to find service 'gdomap'");
|
2002-03-20 09:37:36 +00:00
|
|
|
gdomap_log(LOG_WARNING);
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"On a unix host it should be in /etc/services "
|
2002-03-20 09:37:36 +00:00
|
|
|
"as 'gdomap %d/tcp' and 'gdomap %d/udp'\n",
|
|
|
|
GDOMAP_PORT, GDOMAP_PORT);
|
|
|
|
gdomap_log(LOG_INFO);
|
|
|
|
}
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
unsigned short tcp_port = sp->s_port;
|
1998-05-29 15:25:41 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
if ((sp = getservbyname("gdomap", "udp")) == 0)
|
|
|
|
{
|
2002-03-20 09:37:36 +00:00
|
|
|
if (debug)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Unable to find service 'gdomap'");
|
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"On a unix host it should be in /etc/services "
|
2002-03-20 09:37:36 +00:00
|
|
|
"as 'gdomap %d/tcp' and 'gdomap %d/udp'\n",
|
|
|
|
GDOMAP_PORT, GDOMAP_PORT);
|
|
|
|
gdomap_log(LOG_INFO);
|
|
|
|
}
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else if (sp->s_port != tcp_port)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
2002-02-24 19:58:31 +00:00
|
|
|
"UDP and TCP service entries differ. "
|
|
|
|
"Using the TCP entry for both!");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_WARNING);
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
if (tcp_port != my_port)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "gdomap not running on normal port");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_WARNING);
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
my_port = tcp_port;
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
|
|
|
#endif
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Name - init_ports()
|
|
|
|
* Purpose - Set up the ports for accepting incoming requests.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
init_ports()
|
|
|
|
{
|
1998-10-29 16:20:53 +00:00
|
|
|
int r;
|
|
|
|
struct sockaddr_in sa;
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
unsigned long dummy;
|
2010-03-19 12:10:11 +00:00
|
|
|
#endif /* __MINGW__ */
|
1998-10-29 16:20:53 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Now we set up the sockets to accept incoming connections and set
|
|
|
|
* options on it so that if this program is killed, we can restart
|
|
|
|
* immediately and not find the socket addresses hung.
|
|
|
|
*/
|
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
udp_desc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2002-02-26 09:43:04 +00:00
|
|
|
if (udp_desc == INVALID_SOCKET)
|
|
|
|
#else
|
|
|
|
if (udp_desc < 0)
|
|
|
|
#endif
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Unable to create UDP socket");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
2002-03-20 16:11:08 +00:00
|
|
|
else if (debug)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Opened UDP socket %d", udp_desc);
|
2002-03-20 16:11:08 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
|
|
|
}
|
2008-12-07 06:57:02 +00:00
|
|
|
#if 0 && defined(SO_EXCLUSIVEADDRUSE)
|
2008-12-07 06:50:14 +00:00
|
|
|
r = 1;
|
|
|
|
if ((setsockopt(udp_desc,SOL_SOCKET,SO_REUSEADDR,(char*)&r,sizeof(r)))<0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Unable to set 're-use' on UDP socket");
|
2008-12-07 06:50:14 +00:00
|
|
|
gdomap_log(LOG_WARNING);
|
|
|
|
}
|
|
|
|
r = 1;
|
|
|
|
if ((setsockopt
|
|
|
|
(udp_desc,SOL_SOCKET,SO_EXCLUSIVEADDRUSE,(char*)&r,sizeof(r)))<0)
|
|
|
|
{
|
2010-03-19 13:44:37 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Unable to set 'exclusive-use' on UDP socket");
|
2008-12-07 06:50:14 +00:00
|
|
|
gdomap_log(LOG_WARNING);
|
|
|
|
}
|
|
|
|
#endif
|
2002-04-16 18:54:01 +00:00
|
|
|
#ifndef BROKEN_SO_REUSEADDR
|
2002-03-20 12:03:30 +00:00
|
|
|
/*
|
2002-04-16 18:54:01 +00:00
|
|
|
* Under decent systems, SO_REUSEADDR means that the port can be reused
|
|
|
|
* immediately that this process exits. Under some it means
|
|
|
|
* that multiple processes can serve the same port simultaneously.
|
|
|
|
* We don't want that broken behavior!
|
2002-03-20 12:03:30 +00:00
|
|
|
*/
|
1998-10-29 16:20:53 +00:00
|
|
|
r = 1;
|
|
|
|
if ((setsockopt(udp_desc,SOL_SOCKET,SO_REUSEADDR,(char*)&r,sizeof(r)))<0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Unable to set 're-use' on UDP socket");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_WARNING);
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
2002-03-20 12:03:30 +00:00
|
|
|
#endif
|
2000-02-22 08:32:04 +00:00
|
|
|
if (nobcst == 0)
|
|
|
|
{
|
|
|
|
r = 1;
|
|
|
|
if ((setsockopt(udp_desc,SOL_SOCKET,SO_BROADCAST,(char*)&r,sizeof(r)))<0)
|
|
|
|
{
|
|
|
|
nobcst++;
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Unable to use 'broadcast' for probes");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_WARNING);
|
2000-02-22 08:32:04 +00:00
|
|
|
}
|
|
|
|
}
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
dummy = 1;
|
|
|
|
if (ioctlsocket(udp_desc, FIONBIO, &dummy) < 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Unable to handle UDP socket non-blocking");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
2000-07-18 11:34:30 +00:00
|
|
|
}
|
2010-03-19 12:10:11 +00:00
|
|
|
#else /* !__MINGW__ */
|
1998-10-29 16:20:53 +00:00
|
|
|
if ((r = fcntl(udp_desc, F_GETFL, 0)) >= 0)
|
|
|
|
{
|
|
|
|
r |= NBLK_OPT;
|
|
|
|
if (fcntl(udp_desc, F_SETFL, r) < 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Unable to set UDP socket non-blocking");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Unable to handle UDP socket non-blocking");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
|
|
|
/*
|
1998-10-29 16:20:53 +00:00
|
|
|
* Now we bind our address to the socket and prepare to accept incoming
|
|
|
|
* connections by listening on it.
|
|
|
|
*/
|
2002-02-27 13:37:42 +00:00
|
|
|
memset(&sa, '\0', sizeof(sa));
|
1998-10-29 16:20:53 +00:00
|
|
|
sa.sin_family = AF_INET;
|
|
|
|
sa.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
|
|
sa.sin_port = my_port;
|
|
|
|
if (bind(udp_desc, (void*)&sa, sizeof(sa)) < 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
2002-03-20 12:03:30 +00:00
|
|
|
"Unable to bind address to UDP socket. Perhaps gdomap is already running");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
1999-10-04 10:35:57 +00:00
|
|
|
if (errno == EACCES)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
2002-03-20 09:37:36 +00:00
|
|
|
"You probably need to run gdomap as root/system administrator (recommended),\n"
|
|
|
|
"or run the nameserver on a non-standard port that does not require root\n"
|
|
|
|
"privilege (poor option and last resort!!!)");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_INFO);
|
1999-10-04 10:35:57 +00:00
|
|
|
}
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now we do the TCP socket.
|
|
|
|
*/
|
2002-02-26 09:43:04 +00:00
|
|
|
tcp_desc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2002-02-26 09:43:04 +00:00
|
|
|
if (tcp_desc == INVALID_SOCKET)
|
|
|
|
#else
|
|
|
|
if (tcp_desc < 0)
|
|
|
|
#endif
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Unable to create TCP socket");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
2002-03-20 16:11:08 +00:00
|
|
|
else if (debug)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Opened TDP socket %d", tcp_desc);
|
2002-03-20 16:11:08 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
|
|
|
}
|
2008-12-07 06:57:02 +00:00
|
|
|
#if 0 && defined(SO_EXCLUSIVEADDRUSE)
|
2008-12-07 06:50:14 +00:00
|
|
|
r = 1;
|
|
|
|
if ((setsockopt(tcp_desc,SOL_SOCKET,SO_REUSEADDR,(char*)&r,sizeof(r)))<0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Unable to set 're-use' on TCP socket");
|
2008-12-07 06:50:14 +00:00
|
|
|
gdomap_log(LOG_WARNING);
|
|
|
|
}
|
|
|
|
r = 1;
|
|
|
|
if ((setsockopt
|
|
|
|
(tcp_desc,SOL_SOCKET,SO_EXCLUSIVEADDRUSE,(char*)&r,sizeof(r)))<0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Unable to set 'exclusive-use' on TCP socket");
|
2008-12-07 06:50:14 +00:00
|
|
|
gdomap_log(LOG_WARNING);
|
|
|
|
}
|
|
|
|
#endif
|
2002-04-16 18:54:01 +00:00
|
|
|
#ifndef BROKEN_SO_REUSEADDR
|
2002-03-20 12:03:30 +00:00
|
|
|
/*
|
2002-04-16 18:54:01 +00:00
|
|
|
* Under decent systems, SO_REUSEADDR means that the port can be reused
|
|
|
|
* immediately that this process exits. Under some it means
|
|
|
|
* that multiple processes can serve the same port simultaneously.
|
|
|
|
* We don't want that broken behavior!
|
2002-03-20 12:03:30 +00:00
|
|
|
*/
|
1998-10-29 16:20:53 +00:00
|
|
|
r = 1;
|
|
|
|
if ((setsockopt(tcp_desc,SOL_SOCKET,SO_REUSEADDR,(char*)&r,sizeof(r)))<0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Unable to set 're-use' on TCP socket");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_WARNING);
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
2002-03-20 12:03:30 +00:00
|
|
|
#endif
|
|
|
|
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
dummy = 1;
|
|
|
|
if (ioctlsocket(tcp_desc, FIONBIO, &dummy) < 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Unable to handle TCP socket non-blocking");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
2000-07-18 11:34:30 +00:00
|
|
|
}
|
2010-03-19 12:10:11 +00:00
|
|
|
#else /* !__MINGW__ */
|
1998-10-29 16:20:53 +00:00
|
|
|
if ((r = fcntl(tcp_desc, F_GETFL, 0)) >= 0)
|
|
|
|
{
|
|
|
|
r |= NBLK_OPT;
|
|
|
|
if (fcntl(tcp_desc, F_SETFL, r) < 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Unable to set TCP socket non-blocking");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Unable to handle TCP socket non-blocking");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
2010-03-19 12:10:11 +00:00
|
|
|
#endif /* __MINGW__ */
|
2000-07-18 11:34:30 +00:00
|
|
|
|
2002-02-27 13:37:42 +00:00
|
|
|
memset(&sa, '\0', sizeof(sa));
|
1998-10-29 16:20:53 +00:00
|
|
|
sa.sin_family = AF_INET;
|
|
|
|
sa.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
|
|
sa.sin_port = my_port;
|
|
|
|
if (bind(tcp_desc, (void*)&sa, sizeof(sa)) < 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
2002-03-20 12:03:30 +00:00
|
|
|
"Unable to bind address to TCP socket. Perhaps gdomap is already running");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
1999-10-04 10:35:57 +00:00
|
|
|
if (errno == EACCES)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
2002-03-20 09:37:36 +00:00
|
|
|
"You probably need to run gdomap as root/system administrator (recommended),\n"
|
|
|
|
"or run the nameserver on a non-standard port that does not require root\n"
|
|
|
|
"privilege (poor option and last resort!!!)");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_INFO);
|
1999-10-04 10:35:57 +00:00
|
|
|
}
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
|
|
|
if (listen(tcp_desc, QUEBACKLOG) < 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Unable to listen for connections on TCP socket");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up masks to say we are interested in these descriptors.
|
|
|
|
*/
|
1999-02-17 14:35:49 +00:00
|
|
|
memset(&read_fds, '\0', sizeof(read_fds));
|
|
|
|
memset(&write_fds, '\0', sizeof(write_fds));
|
2000-07-18 11:34:30 +00:00
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
getRInfo(tcp_desc, 1);
|
|
|
|
getRInfo(udp_desc, 1);
|
2000-07-18 11:34:30 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
FD_SET(tcp_desc, &read_fds);
|
|
|
|
FD_SET(udp_desc, &read_fds);
|
|
|
|
|
2010-03-19 12:10:11 +00:00
|
|
|
#ifndef __MINGW__
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* Turn off pipe signals so we don't get interrupted if we attempt
|
|
|
|
* to write a response to a process which has died.
|
|
|
|
*/
|
|
|
|
signal(SIGPIPE, SIG_IGN);
|
2000-07-24 12:03:14 +00:00
|
|
|
/*
|
|
|
|
* Enable table dumping to /tmp/gdomap.dump
|
|
|
|
*/
|
|
|
|
signal(SIGUSR1, dump_tables);
|
2010-03-19 12:10:11 +00:00
|
|
|
#endif /* !__MINGW__ */
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
|
1998-02-26 17:55:42 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
other_addresses_on_net(struct in_addr old, struct in_addr **extra)
|
|
|
|
{
|
1998-10-29 16:20:53 +00:00
|
|
|
int numExtra = 0;
|
|
|
|
int iface;
|
1998-02-26 17:55:42 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
for (iface = 0; iface < interfaces; iface++)
|
|
|
|
{
|
|
|
|
if (addr[iface].s_addr == old.s_addr)
|
|
|
|
{
|
|
|
|
continue;
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
if ((addr[iface].s_addr & mask[iface].s_addr) ==
|
1998-10-29 16:20:53 +00:00
|
|
|
(old.s_addr & mask[iface].s_addr))
|
|
|
|
{
|
|
|
|
numExtra++;
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
if (numExtra > 0)
|
|
|
|
{
|
|
|
|
struct in_addr *addrs;
|
1998-02-26 17:55:42 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
addrs = (struct in_addr*)malloc(sizeof(struct in_addr)*numExtra);
|
|
|
|
*extra = addrs;
|
|
|
|
numExtra = 0;
|
1998-02-26 17:55:42 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
for (iface = 0; iface < interfaces; iface++)
|
|
|
|
{
|
|
|
|
if (addr[iface].s_addr == old.s_addr)
|
|
|
|
{
|
|
|
|
continue;
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
if ((addr[iface].s_addr & mask[iface].s_addr) ==
|
1998-10-29 16:20:53 +00:00
|
|
|
(old.s_addr & mask[iface].s_addr))
|
|
|
|
{
|
|
|
|
addrs[numExtra].s_addr = addr[iface].s_addr;
|
|
|
|
numExtra++;
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
return numExtra;
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1997-05-03 19:18:21 +00:00
|
|
|
/*
|
|
|
|
* Name - init_probe()
|
|
|
|
* Purpose - Send a request to all hosts on the local network
|
|
|
|
* to see if there is a name server running on them.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
init_probe()
|
|
|
|
{
|
1998-10-29 16:20:53 +00:00
|
|
|
unsigned long nlist[interfaces];
|
|
|
|
int nlist_size = 0;
|
|
|
|
int iface;
|
|
|
|
int i;
|
1997-05-03 19:18:21 +00:00
|
|
|
|
2000-02-22 08:32:04 +00:00
|
|
|
if (noprobe > 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
if (debug > 2)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Initiating probe requests.");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1997-05-03 19:18:21 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* Make a list of the different networks to which we must send.
|
|
|
|
*/
|
|
|
|
for (iface = 0; iface < interfaces; iface++)
|
|
|
|
{
|
|
|
|
unsigned long net = (addr[iface].s_addr & mask[iface].s_addr);
|
1997-05-03 19:18:21 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
if (addr[iface].s_addr == loopback.s_addr)
|
|
|
|
{
|
|
|
|
continue; /* Skip loopback */
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
for (i = 0; i < nlist_size; i++)
|
|
|
|
{
|
|
|
|
if (net == nlist[i])
|
|
|
|
{
|
|
|
|
break;
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
if (i == nlist_size)
|
|
|
|
{
|
|
|
|
nlist[i] = net;
|
|
|
|
nlist_size++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < nlist_size; i++)
|
|
|
|
{
|
2000-02-22 08:32:04 +00:00
|
|
|
int broadcast = 0;
|
|
|
|
int elen = 0;
|
2011-02-10 10:52:54 +00:00
|
|
|
struct in_addr *other = 0;
|
2013-07-06 07:16:29 +00:00
|
|
|
struct in_addr sin = { 0 };
|
2010-08-10 10:38:50 +00:00
|
|
|
int high = 0;
|
|
|
|
int low = 0;
|
|
|
|
unsigned long net = 0;
|
1998-10-29 16:20:53 +00:00
|
|
|
int j;
|
2000-02-22 08:32:04 +00:00
|
|
|
struct in_addr b;
|
1998-10-29 16:20:53 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Build up a list of addresses that we serve on this network.
|
|
|
|
*/
|
|
|
|
for (iface = 0; iface < interfaces; iface++)
|
|
|
|
{
|
|
|
|
if ((addr[iface].s_addr & mask[iface].s_addr) == nlist[i])
|
|
|
|
{
|
2000-04-05 07:59:55 +00:00
|
|
|
sin = addr[iface];
|
2000-02-22 08:32:04 +00:00
|
|
|
if (bcok[iface])
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Simple broadcast for this address.
|
|
|
|
*/
|
|
|
|
b.s_addr = bcst[iface].s_addr;
|
|
|
|
broadcast = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unsigned long ha; /* full host address. */
|
|
|
|
unsigned long hm; /* full netmask. */
|
1998-10-29 16:20:53 +00:00
|
|
|
|
2000-02-22 08:32:04 +00:00
|
|
|
ha = ntohl(addr[iface].s_addr);
|
|
|
|
hm = ntohl(mask[iface].s_addr);
|
1998-10-29 16:20:53 +00:00
|
|
|
|
2000-02-22 08:32:04 +00:00
|
|
|
/*
|
|
|
|
* Make sure that our netmasks are restricted
|
|
|
|
* to class-c networks and subnets of those
|
|
|
|
* networks - we don't want to be probing
|
|
|
|
* more than a couple of hundred hosts!
|
|
|
|
*/
|
|
|
|
if ((mask[iface].s_addr | class_c_mask.s_addr)
|
|
|
|
!= mask[iface].s_addr)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "netmask %s will be "
|
2002-02-26 09:43:04 +00:00
|
|
|
"treated as 255.255.255.0 for ",
|
|
|
|
inet_ntoa(mask[iface]));
|
|
|
|
strcat(ebuf, inet_ntoa(addr[iface]));
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_WARNING);
|
2000-02-22 08:32:04 +00:00
|
|
|
hm |= ~255;
|
|
|
|
}
|
|
|
|
net = ha & hm & ~255; /* class-c net number. */
|
|
|
|
low = ha & hm & 255; /* low end of subnet. */
|
|
|
|
high = low | (255 & ~hm); /* high end of subnet. */
|
|
|
|
elen = other_addresses_on_net(sin, &other);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
break;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
if (plist)
|
|
|
|
{
|
|
|
|
plentry *p;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* Now start probes for servers on machines in our probe config
|
|
|
|
* list for which we have a direct connection.
|
|
|
|
*/
|
|
|
|
for (p = plist; p != 0; p = p->next)
|
|
|
|
{
|
|
|
|
if ((p->addr.s_addr & mask[iface].s_addr) ==
|
|
|
|
(addr[iface].s_addr & mask[iface].s_addr))
|
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
unsigned int len = elen;
|
1998-10-29 16:20:53 +00:00
|
|
|
|
|
|
|
p->direct = 1;
|
|
|
|
/* Kick off probe. */
|
|
|
|
if (is_local_host(p->addr))
|
|
|
|
{
|
|
|
|
continue; /* Don't probe self. */
|
1998-03-10 19:01:24 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
while (len > MAX_EXTRA)
|
|
|
|
{
|
|
|
|
len -= MAX_EXTRA;
|
|
|
|
queue_probe(&p->addr, &sin, MAX_EXTRA, &other[len], 0);
|
1998-03-10 19:01:24 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
queue_probe(&p->addr, &sin, len, other, 0);
|
1998-03-10 19:01:24 +00:00
|
|
|
}
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-03-10 19:01:24 +00:00
|
|
|
}
|
2000-02-22 08:32:04 +00:00
|
|
|
else if (broadcast)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Now broadcast probe on this network.
|
|
|
|
*/
|
|
|
|
queue_probe(&b, &sin, 0, 0, 0);
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Now start probes for servers on machines which may be on
|
|
|
|
* any network for which we have an interface.
|
|
|
|
*
|
|
|
|
* Assume 'low' and 'high' are not valid host addresses as 'low'
|
|
|
|
* is the network address and 'high' is the broadcast address.
|
|
|
|
*/
|
|
|
|
for (j = low + 1; j < high; j++)
|
|
|
|
{
|
|
|
|
struct in_addr a;
|
2003-01-03 20:14:47 +00:00
|
|
|
unsigned int len = elen;
|
1998-10-29 16:20:53 +00:00
|
|
|
|
|
|
|
a.s_addr = htonl(net + j);
|
|
|
|
if (is_local_host(a))
|
|
|
|
{
|
|
|
|
continue; /* Don't probe self - that's silly. */
|
1998-03-10 19:01:24 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
/* Kick off probe. */
|
|
|
|
while (len > MAX_EXTRA)
|
|
|
|
{
|
|
|
|
len -= MAX_EXTRA;
|
|
|
|
queue_probe(&a, &sin, MAX_EXTRA, &other[len], 0);
|
1998-03-10 19:01:24 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
queue_probe(&a, &sin, len, other, 0);
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
|
|
|
}
|
1998-03-10 19:01:24 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
if (elen > 0)
|
|
|
|
{
|
|
|
|
free(other);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
1998-03-10 19:01:24 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
if (plist)
|
|
|
|
{
|
|
|
|
plentry *p;
|
|
|
|
int indirect = 0;
|
1998-03-10 19:01:24 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* Are there any hosts for which we do not have a direct
|
|
|
|
* network connection, and to which we have therefore not
|
|
|
|
* queued a probe?
|
|
|
|
*/
|
|
|
|
for (p = plist; p != 0; p = p->next)
|
|
|
|
{
|
|
|
|
if (p->direct == 0)
|
|
|
|
{
|
|
|
|
indirect = 1;
|
1998-03-10 19:01:24 +00:00
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
if (indirect)
|
|
|
|
{
|
2013-04-14 16:25:27 +00:00
|
|
|
struct in_addr *other = 0;
|
1998-10-29 16:20:53 +00:00
|
|
|
int elen;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Queue probes for indirect connections to hosts from our
|
|
|
|
* primary interface and let the routing system handle it.
|
|
|
|
*/
|
|
|
|
elen = other_addresses_on_net(addr[0], &other);
|
|
|
|
for (p = plist; p != 0; p = p->next)
|
|
|
|
{
|
|
|
|
if (p->direct == 0)
|
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
unsigned int len = elen;
|
1998-03-10 19:01:24 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
if (is_local_host(p->addr))
|
|
|
|
{
|
|
|
|
continue; /* Don't probe self. */
|
1998-03-10 19:01:24 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
/* Kick off probe. */
|
|
|
|
while (len > MAX_EXTRA)
|
|
|
|
{
|
|
|
|
len -= MAX_EXTRA;
|
|
|
|
queue_probe(&p->addr, addr, MAX_EXTRA, &other[len], 0);
|
1998-03-10 19:01:24 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
queue_probe(&p->addr, addr, len, other, 0);
|
1998-03-10 19:01:24 +00:00
|
|
|
}
|
|
|
|
}
|
2013-04-14 16:25:27 +00:00
|
|
|
if (0 != other)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
|
|
|
free(other);
|
1998-03-10 19:01:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
if (debug > 2)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Probe requests initiated.");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
last_probe = time(0);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Name - handle_accept()
|
|
|
|
* Purpose - Handle an incoming connection, setting up resources
|
|
|
|
* for the request. Ensure that the channel is in
|
|
|
|
* non-blocking mode so that we can't hang.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
handle_accept()
|
|
|
|
{
|
1998-10-29 16:20:53 +00:00
|
|
|
struct sockaddr_in sa;
|
2010-03-16 15:08:20 +00:00
|
|
|
socklen_t len = sizeof(sa);
|
2002-02-26 09:43:04 +00:00
|
|
|
int desc;
|
1997-05-03 19:18:21 +00:00
|
|
|
|
2013-04-14 09:04:40 +00:00
|
|
|
memset(&sa, '\0', len);
|
1998-10-29 16:20:53 +00:00
|
|
|
desc = accept(tcp_desc, (void*)&sa, &len);
|
|
|
|
if (desc >= 0)
|
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
RInfo *ri;
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2002-02-26 09:43:04 +00:00
|
|
|
unsigned long dummy = 1;
|
|
|
|
#else
|
|
|
|
int r;
|
2010-03-19 12:10:11 +00:00
|
|
|
#endif /* !__MINGW__ */
|
1997-05-03 19:18:21 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
FD_SET(desc, &read_fds);
|
2002-02-26 09:43:04 +00:00
|
|
|
ri = getRInfo(desc, 1);
|
|
|
|
ri->pos = 0;
|
2002-02-27 13:37:42 +00:00
|
|
|
memcpy((char*)&ri->addr, (char*)&sa, sizeof(sa));
|
1997-05-03 19:18:21 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
if (debug)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "accept from %s(%d) to chan %d",
|
2002-02-24 19:58:31 +00:00
|
|
|
inet_ntoa(sa.sin_addr), ntohs(sa.sin_port), desc);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* Ensure that the connection is non-blocking.
|
|
|
|
*/
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
if (ioctlsocket(desc, FIONBIO, &dummy) < 0)
|
|
|
|
{
|
|
|
|
if (debug)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"failed to set chan %d non-blocking", desc);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
2000-07-18 11:34:30 +00:00
|
|
|
}
|
|
|
|
clear_chan(desc);
|
|
|
|
}
|
2010-03-19 12:10:11 +00:00
|
|
|
#else /* !__MINGW__ */
|
1998-10-29 16:20:53 +00:00
|
|
|
if ((r = fcntl(desc, F_GETFL, 0)) >= 0)
|
|
|
|
{
|
|
|
|
r |= NBLK_OPT;
|
|
|
|
if (fcntl(desc, F_SETFL, r) < 0)
|
|
|
|
{
|
|
|
|
if (debug)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"failed to set chan %d non-blocking", desc);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
clear_chan(desc);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (debug)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"failed to set chan %d non-blocking", desc);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
clear_chan(desc);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
2010-03-19 12:10:11 +00:00
|
|
|
#endif /* __MINGW__ */
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else if (debug)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "accept failed - errno %d",
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2002-02-24 19:58:31 +00:00
|
|
|
WSAGetLastError());
|
2000-07-18 11:34:30 +00:00
|
|
|
#else
|
2002-02-24 19:58:31 +00:00
|
|
|
errno);
|
2010-03-19 12:10:11 +00:00
|
|
|
#endif /* __MINGW__ */
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Name - handle_io()
|
|
|
|
* Purpose - Main loop to handle I/O on multiple simultaneous
|
|
|
|
* connections. All non-blocking stuff.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
handle_io()
|
|
|
|
{
|
1998-10-29 16:20:53 +00:00
|
|
|
struct timeval timeout;
|
|
|
|
void *to;
|
|
|
|
int rval = 0;
|
|
|
|
int i;
|
|
|
|
fd_set rfds;
|
|
|
|
fd_set wfds;
|
|
|
|
|
|
|
|
while (rval >= 0)
|
|
|
|
{
|
|
|
|
rfds = read_fds;
|
|
|
|
wfds = write_fds;
|
|
|
|
to = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If there is anything waiting to be sent on the UDP socket
|
|
|
|
* we must check to see if it is writable.
|
|
|
|
*/
|
|
|
|
if (u_queue != 0)
|
|
|
|
{
|
|
|
|
FD_SET(udp_desc, &wfds);
|
|
|
|
}
|
|
|
|
|
|
|
|
timeout.tv_sec = 10;
|
|
|
|
timeout.tv_usec = 0;
|
|
|
|
to = &timeout;
|
2000-07-24 12:03:14 +00:00
|
|
|
soft_int = 0;
|
1998-10-29 16:20:53 +00:00
|
|
|
rval = select(FD_SETSIZE, &rfds, &wfds, 0, to);
|
|
|
|
|
|
|
|
if (rval < 0)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Let's handle any error return.
|
|
|
|
*/
|
|
|
|
if (errno == EBADF)
|
|
|
|
{
|
|
|
|
fd_set efds;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Almost certainly lost a connection - try each
|
|
|
|
* descriptor in turn to see which one it is.
|
|
|
|
* Remove descriptor from bitmask and close it.
|
|
|
|
* If the error is on the listener socket we die.
|
|
|
|
*/
|
1999-02-17 14:35:49 +00:00
|
|
|
memset(&efds, '\0', sizeof(efds));
|
1998-10-29 16:20:53 +00:00
|
|
|
for (i = 0; i < FD_SETSIZE; i++)
|
|
|
|
{
|
|
|
|
if (FD_ISSET(i, &rfds) || FD_ISSET(i, &wfds))
|
|
|
|
{
|
|
|
|
FD_SET(i, &efds);
|
|
|
|
timeout.tv_sec = 0;
|
|
|
|
timeout.tv_usec = 0;
|
|
|
|
to = &timeout;
|
|
|
|
rval = select(FD_SETSIZE, &efds, 0, 0, to);
|
|
|
|
FD_CLR(i, &efds);
|
|
|
|
if (rval < 0 && errno == EBADF)
|
|
|
|
{
|
|
|
|
clear_chan(i);
|
2010-06-26 15:22:38 +00:00
|
|
|
if (i == tcp_desc || i == udp_desc)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Fatal error on socket.");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
rval = 0;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
2000-07-24 12:03:14 +00:00
|
|
|
else if (soft_int > 0)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* We were interrupted - but it was one we were expecting.
|
|
|
|
*/
|
|
|
|
rval = 0;
|
|
|
|
}
|
2004-05-22 03:16:01 +00:00
|
|
|
else if (errno == EINTR)
|
|
|
|
{
|
|
|
|
rval = 0;
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Interrupted in select: %s",strerror(errno));
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else if (rval == 0)
|
|
|
|
{
|
|
|
|
long now = time(0);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Let's handle a timeout.
|
|
|
|
*/
|
|
|
|
prb_tim(now); /* Remove dead servers */
|
|
|
|
if (udp_pending == 0 && (now - last_probe) >= interval)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If there is no output pending on the udp channel and
|
|
|
|
* it is at least five minutes since we sent out a probe
|
|
|
|
* we can re-probe the network for other name servers.
|
|
|
|
*/
|
|
|
|
init_probe();
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Got some descriptor activity - deal with it.
|
|
|
|
*/
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
/* read file descriptors */
|
|
|
|
for (i = 0; i < rfds.fd_count; i++)
|
|
|
|
{
|
|
|
|
if (rfds.fd_array[i] == tcp_desc)
|
|
|
|
{
|
|
|
|
handle_accept();
|
|
|
|
}
|
|
|
|
else if (rfds.fd_array[i] == udp_desc)
|
|
|
|
{
|
|
|
|
handle_recv();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
handle_read(rfds.fd_array[i]);
|
|
|
|
}
|
|
|
|
if (debug > 2)
|
|
|
|
{
|
|
|
|
dump_stats();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (i = 0; i < wfds.fd_count; i++)
|
|
|
|
{
|
|
|
|
if (wfds.fd_array[i] == udp_desc)
|
|
|
|
{
|
|
|
|
handle_send();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
handle_write(wfds.fd_array[i]);
|
|
|
|
}
|
|
|
|
}
|
2010-03-19 12:10:11 +00:00
|
|
|
#else /* !__MINGW__ */
|
1998-10-29 16:20:53 +00:00
|
|
|
for (i = 0; i < FD_SETSIZE; i++)
|
|
|
|
{
|
|
|
|
if (FD_ISSET(i, &rfds))
|
|
|
|
{
|
|
|
|
if (i == tcp_desc)
|
|
|
|
{
|
|
|
|
handle_accept();
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else if (i == udp_desc)
|
|
|
|
{
|
|
|
|
handle_recv();
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
handle_read(i);
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
if (debug > 2)
|
|
|
|
{
|
|
|
|
dump_stats();
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
if (FD_ISSET(i, &wfds))
|
|
|
|
{
|
|
|
|
if (i == udp_desc)
|
|
|
|
{
|
|
|
|
handle_send();
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
handle_write(i);
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
2010-03-19 12:10:11 +00:00
|
|
|
#endif /* __MINGW__ */
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Name - handle_read()
|
|
|
|
* Purpose - Read a request from a channel. This may be called in
|
|
|
|
* many stages if the read is blocking.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
handle_read(int desc)
|
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
RInfo *ri;
|
2000-07-18 11:34:30 +00:00
|
|
|
uptr ptr;
|
1998-10-29 16:20:53 +00:00
|
|
|
int nothingRead = 1;
|
|
|
|
int done = 0;
|
|
|
|
int r;
|
1997-05-03 19:18:21 +00:00
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
ri = getRInfo(desc, 0);
|
2013-07-06 07:14:45 +00:00
|
|
|
if (0 == ri)
|
|
|
|
{
|
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"request not found on descriptor %d", desc);
|
|
|
|
gdomap_log(LOG_DEBUG);
|
|
|
|
return;
|
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
ptr = ri->buf.b;
|
2000-07-18 11:34:30 +00:00
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
while (ri->pos < GDO_REQ_SIZE && done == 0)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
|
|
|
r = recv(desc, (char *)&ptr[ri->pos], GDO_REQ_SIZE - ri->pos, 0);
|
2000-07-18 11:34:30 +00:00
|
|
|
#else
|
2010-03-19 13:44:37 +00:00
|
|
|
r = read(desc, &ptr[ri->pos], GDO_REQ_SIZE - ri->pos);
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
1998-10-29 16:20:53 +00:00
|
|
|
if (r > 0)
|
|
|
|
{
|
|
|
|
nothingRead = 0;
|
2002-02-26 09:43:04 +00:00
|
|
|
ri->pos += r;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
done = 1;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
if (ri->pos == GDO_REQ_SIZE)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
|
|
|
tcp_read++;
|
|
|
|
handle_request(desc);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
else if (WSAGetLastError() != WSAEWOULDBLOCK || nothingRead == 1)
|
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
else if (errno != EWOULDBLOCK || nothingRead == 1)
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If there is an error or end-of-file on the descriptor then
|
|
|
|
* we must close it down.
|
|
|
|
*/
|
|
|
|
clear_chan(desc);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Name - handle_recv()
|
|
|
|
* Purpose - Read a request from the UDP socket.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
handle_recv()
|
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
RInfo *ri;
|
2000-07-18 11:34:30 +00:00
|
|
|
uptr ptr;
|
|
|
|
struct sockaddr_in* addr;
|
2010-03-16 15:08:20 +00:00
|
|
|
socklen_t len = sizeof(struct sockaddr_in);
|
1998-10-29 16:20:53 +00:00
|
|
|
int r;
|
1997-05-03 19:18:21 +00:00
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
ri = getRInfo(udp_desc, 0);
|
2013-07-06 07:14:45 +00:00
|
|
|
if (0 == ri)
|
|
|
|
{
|
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"request not found on descriptor %d", udp_desc);
|
|
|
|
gdomap_log(LOG_DEBUG);
|
|
|
|
return;
|
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
addr = &(ri->addr);
|
|
|
|
ptr = ri->buf.b;
|
2000-07-18 11:34:30 +00:00
|
|
|
|
2010-03-16 15:08:20 +00:00
|
|
|
r = recvfrom(udp_desc, (char *)ptr, GDO_REQ_SIZE, 0, (void*)addr, &len);
|
1998-10-29 16:20:53 +00:00
|
|
|
if (r == GDO_REQ_SIZE)
|
|
|
|
{
|
|
|
|
udp_read++;
|
2002-02-26 09:43:04 +00:00
|
|
|
ri->pos = GDO_REQ_SIZE;
|
1998-10-29 16:20:53 +00:00
|
|
|
if (debug)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"recvfrom %s", inet_ntoa(addr->sin_addr));
|
2010-07-12 10:22:49 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
2000-02-22 08:32:04 +00:00
|
|
|
if (is_local_host(addr->sin_addr) == 1)
|
|
|
|
{
|
2000-02-23 06:45:18 +00:00
|
|
|
if (debug)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"recvfrom packet from self discarded");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
2000-02-23 06:45:18 +00:00
|
|
|
}
|
2000-02-22 08:32:04 +00:00
|
|
|
return;
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
handle_request(udp_desc);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (debug)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"recvfrom returned %d - %s", r, lastErr());
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
clear_chan(udp_desc);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Name - handle_request()
|
|
|
|
* Purpose - Once we have read a full request, we come here
|
|
|
|
* to take action depending on the request type.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
handle_request(int desc)
|
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
RInfo *ri;
|
|
|
|
WInfo *wi;
|
|
|
|
unsigned char type;
|
|
|
|
unsigned char size;
|
|
|
|
unsigned char ptype;
|
|
|
|
unsigned long port;
|
|
|
|
unsigned char *buf;
|
|
|
|
map_ent *m;
|
|
|
|
|
|
|
|
ri = getRInfo(desc, 0);
|
2013-04-14 16:25:27 +00:00
|
|
|
if (0 == ri)
|
|
|
|
{
|
|
|
|
snprintf(ebuf, sizeof(ebuf), "request not found on descriptor %d", desc);
|
|
|
|
gdomap_log(LOG_DEBUG);
|
|
|
|
return;
|
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
type = ri->buf.r.rtype;
|
|
|
|
size = ri->buf.r.nsize;
|
|
|
|
ptype = ri->buf.r.ptype;
|
|
|
|
port = ntohl(ri->buf.r.port);
|
2005-07-08 11:48:37 +00:00
|
|
|
buf = (unsigned char*)ri->buf.r.name;
|
2000-07-18 11:34:30 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
FD_CLR(desc, &read_fds);
|
|
|
|
FD_SET(desc, &write_fds);
|
2000-07-18 11:34:30 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
if (debug > 1)
|
|
|
|
{
|
|
|
|
if (desc == udp_desc)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "request type '%c' on UDP chan", type);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"request type '%c' from chan %d", type, desc);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
2000-07-18 15:50:36 +00:00
|
|
|
if (type == GDO_PROBE || type == GDO_PREPLY || type == GDO_SERVERS
|
|
|
|
|| type == GDO_NAMES)
|
2000-04-05 08:11:52 +00:00
|
|
|
{
|
2002-02-24 18:28:40 +00:00
|
|
|
/* fprintf(stderr, "\n"); */
|
2000-04-05 08:11:52 +00:00
|
|
|
}
|
|
|
|
else
|
2000-04-05 08:05:45 +00:00
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
" name: '%.*s' port: %ld", size, buf, port);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
2000-04-05 08:05:45 +00:00
|
|
|
}
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
wi = getWInfo(desc, 1);
|
|
|
|
wi->pos = 0;
|
|
|
|
|
2000-07-18 11:34:30 +00:00
|
|
|
if (ptype != GDO_TCP_GDO && ptype != GDO_TCP_FOREIGN
|
|
|
|
&& ptype != GDO_UDP_GDO && ptype != GDO_UDP_FOREIGN)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2000-07-18 15:50:36 +00:00
|
|
|
if (ptype != 0 || (type != GDO_PROBE && type != GDO_PREPLY
|
|
|
|
&& type != GDO_SERVERS && type != GDO_NAMES))
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
|
|
|
if (debug)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Illegal port type in request");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
clear_chan(desc);
|
|
|
|
return;
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* The default return value is a four byte number set to zero.
|
|
|
|
* We assume that malloc returns data aligned on a 4 byte boundary.
|
|
|
|
*/
|
2002-02-26 09:43:04 +00:00
|
|
|
wi->len = 4;
|
|
|
|
wi->buf = (char*)malloc(4);
|
|
|
|
wi->buf[0] = 0;
|
|
|
|
wi->buf[1] = 0;
|
|
|
|
wi->buf[2] = 0;
|
|
|
|
wi->buf[3] = 0;
|
1998-10-29 16:20:53 +00:00
|
|
|
|
|
|
|
if (type == GDO_REGISTER)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* See if this is a request from a local process.
|
|
|
|
*/
|
2002-02-26 09:43:04 +00:00
|
|
|
if (is_local_host(ri->addr.sin_addr) == 0)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Illegal attempt to register!");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
1998-10-29 16:20:53 +00:00
|
|
|
clear_chan(desc); /* Only local progs may register. */
|
|
|
|
return;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1997-10-28 14:34:49 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* What should we do if we already have the name registered?
|
|
|
|
* Simple algorithm -
|
|
|
|
* We check to see if we can bind to the old port,
|
|
|
|
* and if we can we assume that the original process
|
|
|
|
* has gone away and permit a new registration for the
|
|
|
|
* same name.
|
|
|
|
* This is not foolproof - if the machine has more
|
|
|
|
* than one IP address, we could bind to the port on
|
|
|
|
* one address even though the server is using it on
|
|
|
|
* another.
|
|
|
|
* Also - the operating system is not guaranteed to
|
|
|
|
* let us bind to the port if another process has only
|
|
|
|
* recently stopped using it.
|
|
|
|
* Also - what if an old server used the port that the
|
|
|
|
* new one is using? In this case the registration
|
|
|
|
* attempt will be refused even though it shouldn't be!
|
|
|
|
* On the other hand - the occasional registration
|
|
|
|
* failure MUST be better than permitting a process to
|
|
|
|
* grab a name already in use! If a server fails to
|
|
|
|
* register a name/port combination, it can always be
|
|
|
|
* coded to retry on a different port.
|
|
|
|
*/
|
|
|
|
m = map_by_name(buf, size);
|
|
|
|
if (m != 0 && port == m->port)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Special case - we already have this name registered for this
|
|
|
|
* port - so everything is already ok.
|
|
|
|
*/
|
2010-07-12 10:22:49 +00:00
|
|
|
if (debug)
|
|
|
|
{
|
|
|
|
snprintf(ebuf, sizeof(ebuf), "Already registered ... success");
|
|
|
|
gdomap_log(LOG_DEBUG);
|
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
*(unsigned long*)wi->buf = htonl(port);
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
|
|
|
else if (m != 0)
|
|
|
|
{
|
|
|
|
int sock = -1;
|
|
|
|
|
|
|
|
if ((ptype & GDO_NET_MASK) == GDO_NET_TCP)
|
|
|
|
{
|
|
|
|
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else if ((ptype & GDO_NET_MASK) == GDO_NET_UDP)
|
|
|
|
{
|
|
|
|
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1997-05-03 19:18:21 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
if (sock < 0)
|
|
|
|
{
|
|
|
|
perror("unable to create new socket");
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
2002-04-16 18:54:01 +00:00
|
|
|
#ifndef BROKEN_SO_REUSEADDR
|
1998-10-29 16:20:53 +00:00
|
|
|
int r = 1;
|
2002-03-20 12:03:30 +00:00
|
|
|
|
|
|
|
/*
|
2002-04-16 18:54:01 +00:00
|
|
|
* Under decent systems, SO_REUSEADDR means that the port can
|
|
|
|
* be reused immediately that this process exits. Under some
|
|
|
|
* it means that multiple processes can serve the same port
|
|
|
|
* simultaneously.
|
|
|
|
* We don't want that broken behavior!
|
2002-03-20 12:03:30 +00:00
|
|
|
*/
|
1998-10-29 16:20:53 +00:00
|
|
|
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
|
2002-04-16 18:54:01 +00:00
|
|
|
(char*)&r, sizeof(r)) < 0)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
|
|
|
perror("unable to set socket options");
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
2002-03-20 12:03:30 +00:00
|
|
|
#endif
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
|
|
|
struct sockaddr_in sa;
|
|
|
|
int result;
|
|
|
|
short p = m->port;
|
|
|
|
|
2002-02-27 13:37:42 +00:00
|
|
|
memset(&sa, '\0', sizeof(sa));
|
1998-10-29 16:20:53 +00:00
|
|
|
sa.sin_family = AF_INET;
|
|
|
|
sa.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
|
|
sa.sin_port = htons(p);
|
|
|
|
result = bind(sock, (void*)&sa, sizeof(sa));
|
|
|
|
if (result == 0)
|
|
|
|
{
|
|
|
|
if (debug > 1)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"re-register from %d to %ld",
|
2002-02-24 19:58:31 +00:00
|
|
|
m->port, port);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
m->port = port;
|
|
|
|
m->net = (ptype & GDO_NET_MASK);
|
|
|
|
m->svc = (ptype & GDO_SVC_MASK);
|
|
|
|
port = htonl(m->port);
|
2002-02-26 09:43:04 +00:00
|
|
|
*(unsigned long*)wi->buf = port;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2002-02-26 09:43:04 +00:00
|
|
|
/* closesocket(sock); */
|
2000-07-18 11:34:30 +00:00
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
close(sock);
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
2010-07-12 10:22:49 +00:00
|
|
|
else if (port == 0)
|
1998-10-29 16:20:53 +00:00
|
|
|
{ /* Port not provided! */
|
2010-07-12 10:22:49 +00:00
|
|
|
if (debug)
|
|
|
|
{
|
|
|
|
snprintf(ebuf, sizeof(ebuf), "Port not provided in request!");
|
|
|
|
gdomap_log(LOG_DEBUG);
|
|
|
|
}
|
2010-06-26 15:22:38 +00:00
|
|
|
*(unsigned long*)wi->buf = 0;
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{ /* Use port provided in request. */
|
2010-07-12 10:22:49 +00:00
|
|
|
if (debug)
|
|
|
|
{
|
|
|
|
snprintf(ebuf, sizeof(ebuf), "Registered on port %lu", port);
|
|
|
|
gdomap_log(LOG_DEBUG);
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
m = map_add(buf, size, port, ptype);
|
|
|
|
port = htonl(m->port);
|
2002-02-26 09:43:04 +00:00
|
|
|
*(unsigned long*)wi->buf = port;
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else if (type == GDO_LOOKUP)
|
|
|
|
{
|
|
|
|
m = map_by_name(buf, size);
|
|
|
|
if (m != 0 && (m->net | m->svc) != ptype)
|
|
|
|
{
|
|
|
|
if (debug > 1)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"requested service is of wrong type");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
m = 0; /* Name exists but is of wrong type. */
|
|
|
|
}
|
|
|
|
if (m)
|
|
|
|
{
|
|
|
|
int sock = -1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We check to see if we can bind to the old port, and if we can
|
|
|
|
* we assume that the process has gone away and remove it from
|
|
|
|
* the map.
|
|
|
|
* This is not foolproof - if the machine has more
|
|
|
|
* than one IP address, we could bind to the port on
|
|
|
|
* one address even though the server is using it on
|
|
|
|
* another.
|
|
|
|
*/
|
|
|
|
if ((ptype & GDO_NET_MASK) == GDO_NET_TCP)
|
|
|
|
{
|
|
|
|
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else if ((ptype & GDO_NET_MASK) == GDO_NET_UDP)
|
|
|
|
{
|
|
|
|
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1997-05-03 19:18:21 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
if (sock < 0)
|
|
|
|
{
|
|
|
|
perror("unable to create new socket");
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
2002-04-16 18:54:01 +00:00
|
|
|
#ifndef BROKEN_SO_REUSEADDR
|
1998-10-29 16:20:53 +00:00
|
|
|
int r = 1;
|
2002-03-20 12:03:30 +00:00
|
|
|
|
|
|
|
/*
|
2002-04-16 18:54:01 +00:00
|
|
|
* Under decent systems, SO_REUSEADDR means that the port can
|
|
|
|
* be reused immediately that this process exits. Under some
|
|
|
|
* it means that multiple processes can serve the same port
|
|
|
|
* simultaneously.
|
|
|
|
* We don't want that broken behavior!
|
2002-03-20 12:03:30 +00:00
|
|
|
*/
|
1998-10-29 16:20:53 +00:00
|
|
|
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
|
2000-07-18 15:50:36 +00:00
|
|
|
(char*)&r, sizeof(r)) < 0)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
|
|
|
perror("unable to set socket options");
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
|
|
|
struct sockaddr_in sa;
|
|
|
|
int result;
|
|
|
|
unsigned short p = (unsigned short)m->port;
|
|
|
|
|
2002-02-27 13:37:42 +00:00
|
|
|
memset(&sa, '\0', sizeof(sa));
|
1998-10-29 16:20:53 +00:00
|
|
|
sa.sin_family = AF_INET;
|
2005-11-11 15:06:07 +00:00
|
|
|
|
2010-03-19 12:10:11 +00:00
|
|
|
#if defined(__MINGW__)
|
2005-11-11 15:06:07 +00:00
|
|
|
/* COMMENT: (3 Nov 2004 by Wim Oudshoorn):
|
|
|
|
The comment below might be true. But
|
|
|
|
using addr[0].s_addr has on windows 2003 server
|
|
|
|
(and some other versions of windows.)
|
|
|
|
exactly the same sympton as it tries to avoid.
|
|
|
|
The funny thing is that the original line, just
|
|
|
|
using INADDR_ANY seems to work on windows.
|
|
|
|
However, I assume the FIXME below was put there
|
|
|
|
for a reason. But for now I just revert it because
|
|
|
|
the platform independent code seems to work.
|
|
|
|
*/
|
|
|
|
/* FIXME: This must not be INADDR_ANY on Win,
|
|
|
|
otherwise the system will try to bind on any of
|
|
|
|
the local addresses (including 127.0.0.1), which
|
|
|
|
works. - bjoern */
|
|
|
|
/* sa.sin_addr.s_addr = addr[0].s_addr; */
|
1998-10-29 16:20:53 +00:00
|
|
|
sa.sin_addr.s_addr = htonl(INADDR_ANY);
|
2005-11-11 15:06:07 +00:00
|
|
|
#else
|
|
|
|
sa.sin_addr.s_addr = htonl(INADDR_ANY);
|
2010-03-19 12:10:11 +00:00
|
|
|
#endif /* __MINGW__ */
|
1998-10-29 16:20:53 +00:00
|
|
|
sa.sin_port = htons(p);
|
|
|
|
result = bind(sock, (void*)&sa, sizeof(sa));
|
|
|
|
if (result == 0)
|
|
|
|
{
|
|
|
|
map_del(m);
|
|
|
|
m = 0;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
closesocket(sock);
|
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
close(sock);
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
if (m)
|
|
|
|
{ /* Lookup found live server. */
|
2002-02-26 09:43:04 +00:00
|
|
|
*(unsigned long*)wi->buf = htonl(m->port);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{ /* Not found. */
|
|
|
|
if (debug > 1)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "requested service not found");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
*(unsigned short*)wi->buf = 0;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else if (type == GDO_UNREG)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* See if this is a request from a local process.
|
|
|
|
*/
|
2002-02-26 09:43:04 +00:00
|
|
|
if (is_local_host(ri->addr.sin_addr) == 0)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Illegal attempt to un-register!");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
1998-10-29 16:20:53 +00:00
|
|
|
clear_chan(desc);
|
|
|
|
return;
|
|
|
|
}
|
1998-11-02 11:48:42 +00:00
|
|
|
if (port == 0 || size > 0)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
1998-11-02 11:48:42 +00:00
|
|
|
m = map_by_name(buf, size);
|
|
|
|
if (m)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
1998-11-02 11:48:42 +00:00
|
|
|
if ((m->net | m->svc) != ptype)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
1998-11-02 11:48:42 +00:00
|
|
|
if (debug)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Attempted unregister with wrong type");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1998-11-02 11:48:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
*(unsigned long*)wi->buf = htonl(m->port);
|
1998-11-02 11:48:42 +00:00
|
|
|
map_del(m);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
1998-11-02 11:48:42 +00:00
|
|
|
if (debug > 1)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "requested service not found");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1998-11-02 11:48:42 +00:00
|
|
|
}
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
*(unsigned long*)wi->buf = 0;
|
2000-07-18 11:34:30 +00:00
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
while ((m = map_by_port(port, ptype)) != 0)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
*(unsigned long*)wi->buf = htonl(m->port);
|
1998-11-02 11:48:42 +00:00
|
|
|
map_del(m);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else if (type == GDO_SERVERS)
|
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
unsigned int i;
|
|
|
|
unsigned int j;
|
1997-05-03 19:18:21 +00:00
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
free(wi->buf);
|
2013-04-14 16:25:27 +00:00
|
|
|
wi->buf = (char*)calloc(sizeof(unsigned long)
|
|
|
|
+ (prb_used+1)*IASIZE, 1);
|
2002-02-26 09:43:04 +00:00
|
|
|
*(unsigned long*)wi->buf = htonl(prb_used+1);
|
2002-02-27 13:37:42 +00:00
|
|
|
memcpy(&wi->buf[4], &ri->addr.sin_addr, IASIZE);
|
1999-08-21 05:29:10 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy the addresses of the hosts we have probed into the buffer.
|
|
|
|
* During the copy, reverse the order of the addresses so that the
|
|
|
|
* address we have contacted most recently is first. This should
|
|
|
|
* ensure that the client process will attempt to contact live
|
|
|
|
* hosts before dead ones.
|
|
|
|
*/
|
|
|
|
for (i = 0, j = prb_used; i < prb_used; i++)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2002-02-27 13:37:42 +00:00
|
|
|
memcpy(&wi->buf[4+(i+1)*IASIZE], &prb[--j]->sin, IASIZE);
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
wi->len = 4 + (prb_used+1)*IASIZE;
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
2000-07-18 15:50:36 +00:00
|
|
|
else if (type == GDO_NAMES)
|
|
|
|
{
|
|
|
|
int bytes = 0;
|
|
|
|
uptr ptr;
|
|
|
|
int i;
|
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
free(wi->buf);
|
2000-07-18 15:50:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Size buffer for names.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < map_used; i++)
|
|
|
|
{
|
2000-07-24 12:03:14 +00:00
|
|
|
bytes += 2 + map[i]->size;
|
2000-07-18 15:50:36 +00:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Allocate with space for number of names and set it up.
|
|
|
|
*/
|
2002-02-26 09:43:04 +00:00
|
|
|
wi->buf = (char*)malloc(4 + bytes);
|
|
|
|
*(unsigned long*)wi->buf = htonl(bytes);
|
|
|
|
ptr = (uptr)wi->buf;
|
2000-07-18 15:50:36 +00:00
|
|
|
ptr += 4;
|
|
|
|
for (i = 0; i < map_used; i++)
|
|
|
|
{
|
2000-07-24 12:03:14 +00:00
|
|
|
ptr[0] = (unsigned char)map[i]->size;
|
2000-07-18 15:50:36 +00:00
|
|
|
ptr[1] = (unsigned char)(map[i]->net | map[i]->svc);
|
|
|
|
memcpy(&ptr[2], map[i]->name, ptr[0]);
|
|
|
|
ptr += 2 + ptr[0];
|
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
wi->len = 4 + bytes;
|
2000-07-18 15:50:36 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else if (type == GDO_PROBE)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If the client is a name server, we add it to the list.
|
|
|
|
*/
|
2002-02-26 09:43:04 +00:00
|
|
|
if (ri->addr.sin_port == my_port)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
|
|
|
struct in_addr sin;
|
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
memcpy(&sin, ri->buf.r.name, IASIZE);
|
1998-10-29 16:20:53 +00:00
|
|
|
if (debug > 2)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Probe from '%s'", inet_ntoa(sin));
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
2011-10-25 08:02:38 +00:00
|
|
|
prb_add(&sin);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Irrespective of what we are told to do - we also add the
|
|
|
|
* interface from which this packet arrived so we have a
|
|
|
|
* route we KNOW we can use.
|
|
|
|
*/
|
|
|
|
prb_add(&ri->addr.sin_addr);
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
{
|
|
|
|
struct in_addr *ptr;
|
|
|
|
unsigned long net;
|
|
|
|
int c;
|
|
|
|
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
if (IN_CLASSA(sin.s_addr))
|
|
|
|
{
|
|
|
|
net = sin.s_addr & IN_CLASSA_NET;
|
|
|
|
}
|
|
|
|
else if (IN_CLASSB(sin.s_addr))
|
|
|
|
{
|
|
|
|
net = sin.s_addr & IN_CLASSB_NET;
|
|
|
|
}
|
|
|
|
else if (IN_CLASSC(sin.s_addr))
|
|
|
|
{
|
|
|
|
net = sin.s_addr & IN_CLASSC_NET;
|
|
|
|
}
|
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
net = inet_netof(sin);
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
2002-02-26 09:43:04 +00:00
|
|
|
ptr = (struct in_addr*)&ri->buf.r.name[2*IASIZE];
|
|
|
|
c = (ri->buf.r.nsize - 2*IASIZE)/IASIZE;
|
1998-10-29 16:20:53 +00:00
|
|
|
while (c-- > 0)
|
|
|
|
{
|
|
|
|
if (debug > 2)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Add server '%s'", inet_ntoa(*ptr));
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
2000-07-24 12:03:14 +00:00
|
|
|
prb_add(ptr);
|
1998-10-29 16:20:53 +00:00
|
|
|
ptr++;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
2011-10-25 08:02:38 +00:00
|
|
|
}
|
2000-07-24 12:03:14 +00:00
|
|
|
#endif
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* For a UDP request from another name server, we send a reply
|
|
|
|
* packet. We shouldn't be getting probes from anywhere else,
|
|
|
|
* but just to be nice, we send back our port number anyway.
|
|
|
|
*/
|
2002-02-26 09:43:04 +00:00
|
|
|
if (desc == udp_desc && ri->addr.sin_port == my_port)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
|
|
|
struct in_addr laddr;
|
|
|
|
struct in_addr raddr;
|
2013-04-14 16:25:27 +00:00
|
|
|
struct in_addr *other = 0;
|
2003-01-03 20:14:47 +00:00
|
|
|
unsigned int elen;
|
2002-02-26 09:43:04 +00:00
|
|
|
void *rbuf = ri->buf.r.name;
|
1998-10-29 16:20:53 +00:00
|
|
|
void *wbuf;
|
|
|
|
int i;
|
|
|
|
gdo_req *r;
|
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
free(wi->buf);
|
2013-04-14 16:25:27 +00:00
|
|
|
r = (gdo_req*)calloc(GDO_REQ_SIZE, 1);
|
|
|
|
wi->buf = (char*)r;
|
1998-10-29 16:20:53 +00:00
|
|
|
wbuf = r->name;
|
|
|
|
r->rtype = GDO_PREPLY;
|
|
|
|
r->nsize = IASIZE*2;
|
|
|
|
|
2002-02-27 13:37:42 +00:00
|
|
|
memcpy(&raddr, rbuf, IASIZE);
|
|
|
|
memcpy(&laddr, rbuf+IASIZE, IASIZE);
|
2000-07-05 16:56:06 +00:00
|
|
|
if (debug > 2)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Probe sent remote '%s'", inet_ntoa(raddr));
|
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Probe sent local '%s'", inet_ntoa(laddr));
|
2000-07-05 16:56:06 +00:00
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
|
2002-02-27 13:37:42 +00:00
|
|
|
memcpy(wbuf+IASIZE, &raddr, IASIZE);
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* If the other end did not tell us which of our addresses it was
|
|
|
|
* probing, try to select one on the same network to send back.
|
|
|
|
* otherwise, respond with the address it was probing.
|
|
|
|
*/
|
2000-04-20 14:41:05 +00:00
|
|
|
if (is_local_host(laddr) == 0
|
|
|
|
|| laddr.s_addr == loopback.s_addr)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
|
|
|
for (i = 0; i < interfaces; i++)
|
|
|
|
{
|
2000-04-20 14:41:05 +00:00
|
|
|
if (addr[i].s_addr == loopback.s_addr)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
if ((mask[i].s_addr && addr[i].s_addr) ==
|
2002-02-26 09:43:04 +00:00
|
|
|
(mask[i].s_addr && ri->addr.sin_addr.s_addr))
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
|
|
|
laddr = addr[i];
|
2002-02-27 13:37:42 +00:00
|
|
|
memcpy(wbuf, &laddr, IASIZE);
|
1998-10-29 16:20:53 +00:00
|
|
|
break;
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
2002-02-27 13:37:42 +00:00
|
|
|
memcpy(wbuf, &laddr, IASIZE);
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
wi->len = GDO_REQ_SIZE;
|
1998-02-26 17:55:42 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
elen = other_addresses_on_net(laddr, &other);
|
|
|
|
if (elen > 0)
|
|
|
|
{
|
|
|
|
while (elen > MAX_EXTRA)
|
|
|
|
{
|
|
|
|
elen -= MAX_EXTRA;
|
|
|
|
queue_probe(&raddr, &laddr, MAX_EXTRA, &other[elen], 1);
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
queue_probe(&raddr, &laddr, elen, other, 1);
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
2013-04-14 16:25:27 +00:00
|
|
|
if (0 != other)
|
|
|
|
{
|
|
|
|
free(other);
|
|
|
|
}
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
port = my_port;
|
2002-02-26 09:43:04 +00:00
|
|
|
*(unsigned long*)wi->buf = htonl(port);
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (type == GDO_PREPLY)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* This should really be a reply by UDP to a probe we sent
|
|
|
|
* out earlier. We should add the name server to our list.
|
|
|
|
*/
|
2002-02-26 09:43:04 +00:00
|
|
|
if (ri->addr.sin_port == my_port)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
|
|
|
struct in_addr sin;
|
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
memcpy(&sin, &ri->buf.r.name, IASIZE);
|
1998-10-29 16:20:53 +00:00
|
|
|
if (debug > 2)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Probe reply from '%s'", inet_ntoa(sin));
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
prb_add(&sin);
|
|
|
|
/*
|
|
|
|
* Irrespective of what we are told to do - we also add the
|
|
|
|
* interface from which this packet arrived so we have a
|
|
|
|
* route we KNOW we can use.
|
|
|
|
*/
|
2002-02-26 09:43:04 +00:00
|
|
|
prb_add(&ri->addr.sin_addr);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* Because this is really a reply to us, we don't want to reply
|
|
|
|
* to it or we would get a feedback loop.
|
|
|
|
*/
|
|
|
|
clear_chan(desc);
|
|
|
|
return;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Illegal operation code received!");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
1998-10-29 16:20:53 +00:00
|
|
|
clear_chan(desc);
|
|
|
|
return;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* If the request was via UDP, we send a response back by queuing
|
|
|
|
* rather than letting the normal 'write_handler()' function do it.
|
|
|
|
*/
|
|
|
|
if (desc == udp_desc)
|
|
|
|
{
|
2005-07-08 11:48:37 +00:00
|
|
|
queue_msg(&ri->addr, (unsigned char*)wi->buf, wi->len);
|
1998-10-29 16:20:53 +00:00
|
|
|
clear_chan(desc);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
/*
|
|
|
|
* Name - handle_send()
|
|
|
|
* Purpose - Send any pending message on UDP socket.
|
|
|
|
* The code is designed to send the message in parts if
|
|
|
|
* the 'sendto()' function returns a positive integer
|
|
|
|
* indicating that only part of the message has been
|
|
|
|
* written. This should never happen - but I coded it
|
|
|
|
* this way in case we have to run on a system which
|
|
|
|
* implements sendto() badly (I used such a system
|
|
|
|
* many years ago).
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
handle_send()
|
|
|
|
{
|
1998-10-29 16:20:53 +00:00
|
|
|
struct u_data* entry = u_queue;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
if (entry)
|
|
|
|
{
|
|
|
|
int r;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
2012-08-26 08:55:49 +00:00
|
|
|
r = sendto(udp_desc, (const char *)&entry->dat[entry->pos],
|
2010-03-16 15:08:20 +00:00
|
|
|
entry->len - entry->pos, 0, (void*)&entry->addr, sizeof(entry->addr));
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* 'r' is the number of bytes sent. This should be the number
|
|
|
|
* of bytes we asked to send, or -1 to indicate failure.
|
|
|
|
*/
|
|
|
|
if (r > 0)
|
|
|
|
{
|
|
|
|
entry->pos += r;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we haven't written all the data, it should have been
|
|
|
|
* because we blocked. Anything else is a major problem
|
|
|
|
* so we remove the message from the queue.
|
|
|
|
*/
|
|
|
|
if (entry->pos != entry->len)
|
|
|
|
{
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
if (WSAGetLastError() != WSAEWOULDBLOCK)
|
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
if (errno != EWOULDBLOCK)
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
|
|
|
if (debug)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"failed sendto on %d for %s - %s",
|
2002-03-20 16:11:08 +00:00
|
|
|
udp_desc, inet_ntoa(entry->addr.sin_addr), strerror(errno));
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1999-08-21 05:29:10 +00:00
|
|
|
queue_pop();
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
udp_sent++;
|
|
|
|
if (debug > 1)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "performed sendto for %s",
|
2002-02-24 19:58:31 +00:00
|
|
|
inet_ntoa(entry->addr.sin_addr));
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* If we have sent the entire message - remove it from queue.
|
|
|
|
*/
|
|
|
|
if (entry->pos == entry->len)
|
|
|
|
{
|
|
|
|
queue_pop();
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1997-05-03 19:18:21 +00:00
|
|
|
/*
|
|
|
|
* Name - handle_write()
|
|
|
|
* Purpose - Write data to a channel. When all writing for the
|
|
|
|
* channel is complete, close the channel down.
|
|
|
|
*
|
|
|
|
* This is all probably totally paranoid - the reply
|
|
|
|
* to any request is so short that the write operation
|
|
|
|
* should not block so there shouldn't be any need to
|
|
|
|
* handle non-blocking I/O.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
handle_write(int desc)
|
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
WInfo *wi;
|
2000-07-18 11:34:30 +00:00
|
|
|
char *ptr;
|
|
|
|
int len;
|
1998-10-29 16:20:53 +00:00
|
|
|
int r;
|
|
|
|
|
2002-02-26 09:43:04 +00:00
|
|
|
wi = getWInfo(desc, 0);
|
|
|
|
if (wi == 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"handle_write for unknown descriptor (%d)", desc);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
2002-02-26 09:43:04 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
ptr = wi->buf;
|
|
|
|
len = wi->len;
|
|
|
|
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2002-02-26 09:43:04 +00:00
|
|
|
r = send(desc, &ptr[wi->pos], len - wi->pos, 0);
|
2000-07-18 11:34:30 +00:00
|
|
|
#else
|
2002-02-26 09:43:04 +00:00
|
|
|
r = write(desc, &ptr[wi->pos], len - wi->pos);
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
1998-10-29 16:20:53 +00:00
|
|
|
if (r < 0)
|
|
|
|
{
|
|
|
|
if (debug > 1)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Failed write on chan %d - closing", desc);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
/*
|
1998-10-29 16:20:53 +00:00
|
|
|
* Failure - close connection silently.
|
|
|
|
*/
|
|
|
|
clear_chan(desc);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-02-26 09:43:04 +00:00
|
|
|
wi->pos += r;
|
|
|
|
if (wi->pos >= len)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
|
|
|
tcp_sent++;
|
|
|
|
if (debug > 1)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Completed write on chan %d - closing", desc);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
/*
|
1998-10-29 16:20:53 +00:00
|
|
|
* Success - written all information.
|
|
|
|
*/
|
|
|
|
clear_chan(desc);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-10-27 20:58:22 +00:00
|
|
|
/*
|
|
|
|
* Name - tryRead()
|
|
|
|
* Purpose - Attempt to read from a non blocking channel.
|
|
|
|
* Time out in specified time.
|
|
|
|
* If length of data is zero then just wait for
|
|
|
|
* descriptor to be readable.
|
|
|
|
* If the length is negative then attempt to
|
|
|
|
* read the absolute value of length but return
|
|
|
|
* as soon as anything is read.
|
|
|
|
*
|
|
|
|
* Return -1 on failure
|
|
|
|
* Return -2 on timeout
|
|
|
|
* Return number of bytes read
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
tryRead(int desc, int tim, unsigned char* dat, int len)
|
|
|
|
{
|
|
|
|
struct timeval timeout;
|
|
|
|
fd_set fds;
|
|
|
|
void *to;
|
|
|
|
int rval;
|
|
|
|
int pos = 0;
|
|
|
|
time_t when = 0;
|
|
|
|
int neg = 0;
|
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
if (len < 0)
|
|
|
|
{
|
|
|
|
neg = 1;
|
|
|
|
len = -len;
|
|
|
|
}
|
1998-10-27 20:58:22 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* First time round we do a select with an instant timeout to see
|
|
|
|
* if the descriptor is already readable.
|
|
|
|
*/
|
|
|
|
timeout.tv_sec = 0;
|
|
|
|
timeout.tv_usec = 0;
|
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
to = &timeout;
|
1999-02-17 14:35:49 +00:00
|
|
|
memset(&fds, '\0', sizeof(fds));
|
1998-10-29 16:20:53 +00:00
|
|
|
FD_SET(desc, &fds);
|
|
|
|
|
|
|
|
rval = select(FD_SETSIZE, &fds, 0, 0, to);
|
|
|
|
if (rval == 0)
|
|
|
|
{
|
|
|
|
time_t now = time(0);
|
|
|
|
|
|
|
|
if (when == 0)
|
|
|
|
{
|
|
|
|
when = now;
|
|
|
|
}
|
|
|
|
else if (now - when >= tim)
|
|
|
|
{
|
1998-12-05 06:50:15 +00:00
|
|
|
return -2; /* Timed out. */
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Set the timeout for a new call to select next time
|
|
|
|
* round the loop.
|
|
|
|
*/
|
|
|
|
timeout.tv_sec = tim - (now - when);
|
|
|
|
timeout.tv_usec = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (rval < 0)
|
|
|
|
{
|
1998-12-05 06:50:15 +00:00
|
|
|
return -1; /* Error in select. */
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
|
|
|
else if (len > 0)
|
|
|
|
{
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2010-03-16 15:08:20 +00:00
|
|
|
rval = recv(desc, (char *)&dat[pos], len - pos, 0);
|
2000-07-18 11:34:30 +00:00
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
rval = read(desc, &dat[pos], len - pos);
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
1998-10-29 16:20:53 +00:00
|
|
|
if (rval < 0)
|
|
|
|
{
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
if (WSAGetLastError() != WSAEWOULDBLOCK)
|
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
if (errno != EWOULDBLOCK)
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
1998-12-05 06:50:15 +00:00
|
|
|
return -1; /* Error in read. */
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (rval == 0)
|
|
|
|
{
|
1998-12-05 06:50:15 +00:00
|
|
|
return -1; /* End of file. */
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pos += rval;
|
|
|
|
if (pos == len || neg == 1)
|
|
|
|
{
|
1998-12-05 06:50:15 +00:00
|
|
|
return pos; /* Read as needed. */
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1998-12-05 06:50:15 +00:00
|
|
|
return 0; /* Not actually asked to read. */
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Name - tryWrite()
|
|
|
|
* Purpose - Attempt to write to a non blocking channel.
|
|
|
|
* Time out in specified time.
|
|
|
|
* If length of data is zero then just wait for
|
|
|
|
* descriptor to be writable.
|
|
|
|
* If the length is negative then attempt to
|
|
|
|
* write the absolute value of length but return
|
|
|
|
* as soon as anything is written.
|
|
|
|
*
|
|
|
|
* Return -1 on failure
|
|
|
|
* Return -2 on timeout
|
|
|
|
* Return number of bytes written
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
tryWrite(int desc, int tim, unsigned char* dat, int len)
|
|
|
|
{
|
|
|
|
struct timeval timeout;
|
|
|
|
fd_set fds;
|
|
|
|
void *to;
|
|
|
|
int rval;
|
|
|
|
int pos = 0;
|
|
|
|
time_t when = 0;
|
|
|
|
int neg = 0;
|
|
|
|
|
|
|
|
if (len < 0) {
|
|
|
|
neg = 1;
|
|
|
|
len = -len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* First time round we do a select with an instant timeout to see
|
|
|
|
* if the descriptor is already writable.
|
|
|
|
*/
|
|
|
|
timeout.tv_sec = 0;
|
|
|
|
timeout.tv_usec = 0;
|
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
to = &timeout;
|
1999-02-17 14:35:49 +00:00
|
|
|
memset(&fds, '\0', sizeof(fds));
|
1998-10-29 16:20:53 +00:00
|
|
|
FD_SET(desc, &fds);
|
|
|
|
|
|
|
|
rval = select(FD_SETSIZE, 0, &fds, 0, to);
|
|
|
|
if (rval == 0)
|
|
|
|
{
|
|
|
|
time_t now = time(0);
|
|
|
|
|
|
|
|
if (when == 0)
|
|
|
|
{
|
|
|
|
when = now;
|
|
|
|
}
|
|
|
|
else if (now - when >= tim)
|
|
|
|
{
|
1998-12-05 06:50:15 +00:00
|
|
|
return -2; /* Timed out. */
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Set the timeout for a new call to select next time round
|
|
|
|
* the loop. */
|
|
|
|
timeout.tv_sec = tim - (now - when);
|
|
|
|
timeout.tv_usec = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (rval < 0)
|
|
|
|
{
|
1998-12-05 06:50:15 +00:00
|
|
|
return -1; /* Error in select. */
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
|
|
|
else if (len > 0)
|
|
|
|
{
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__) /* FIXME: Is this correct? */
|
2010-03-16 15:08:20 +00:00
|
|
|
rval = send(desc, (const char*)&dat[pos], len - pos, 0);
|
2000-07-18 11:34:30 +00:00
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
void (*ifun)();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Should be able to write this short a message immediately, but
|
|
|
|
* if the connection is lost we will get a signal we must trap.
|
|
|
|
*/
|
|
|
|
ifun = signal(SIGPIPE, (void(*)(int))SIG_IGN);
|
|
|
|
rval = write(desc, &dat[pos], len - pos);
|
|
|
|
signal(SIGPIPE, ifun);
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
1998-10-29 16:20:53 +00:00
|
|
|
|
|
|
|
if (rval <= 0)
|
|
|
|
{
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
if (WSAGetLastError() != WSAEWOULDBLOCK)
|
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
if (errno != EWOULDBLOCK)
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
1998-12-05 06:50:15 +00:00
|
|
|
return -1; /* Error in write. */
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pos += rval;
|
|
|
|
if (pos == len || neg == 1)
|
|
|
|
{
|
1998-12-05 06:50:15 +00:00
|
|
|
return pos; /* Written as needed. */
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1998-12-05 06:50:15 +00:00
|
|
|
return 0; /* Not actually asked to write. */
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Name - tryHost()
|
|
|
|
* Purpose - Perform a name server operation with a given
|
|
|
|
* request packet to a server at specified address.
|
|
|
|
* On error - return non-zero with reason in 'errno'
|
|
|
|
*/
|
|
|
|
static int
|
2013-07-06 07:14:45 +00:00
|
|
|
tryHost(unsigned char op, unsigned char len, const unsigned char *name,
|
|
|
|
int ptype, struct sockaddr_in *addr, unsigned short *p, uptr *v)
|
1998-10-27 20:58:22 +00:00
|
|
|
{
|
1998-10-29 16:20:53 +00:00
|
|
|
int desc = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
|
int e = 0;
|
|
|
|
unsigned long port = *p;
|
|
|
|
gdo_req msg;
|
|
|
|
struct sockaddr_in sin;
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
unsigned long dummy;
|
2010-03-19 12:10:11 +00:00
|
|
|
#endif /* __MINGW__ */
|
1998-10-29 16:20:53 +00:00
|
|
|
|
|
|
|
*p = 0;
|
|
|
|
if (desc < 0)
|
|
|
|
{
|
2002-02-25 20:44:41 +00:00
|
|
|
return 1; /* Couldn't create socket. */
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
|
|
|
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
dummy = 1;
|
|
|
|
if (ioctlsocket(desc, FIONBIO, &dummy) < 0)
|
|
|
|
{
|
|
|
|
e = WSAGetLastError();
|
|
|
|
closesocket(desc);
|
|
|
|
WSASetLastError(e);
|
|
|
|
return 2; /* Couldn't set non-blocking. */
|
|
|
|
}
|
2010-03-19 12:10:11 +00:00
|
|
|
#else /* !__MINGW__ */
|
1998-10-29 16:20:53 +00:00
|
|
|
if ((e = fcntl(desc, F_GETFL, 0)) >= 0)
|
|
|
|
{
|
|
|
|
e |= NBLK_OPT;
|
|
|
|
if (fcntl(desc, F_SETFL, e) < 0)
|
|
|
|
{
|
|
|
|
e = errno;
|
|
|
|
close(desc);
|
|
|
|
errno = e;
|
1998-12-05 06:50:15 +00:00
|
|
|
return 2; /* Couldn't set non-blocking. */
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
e = errno;
|
|
|
|
close(desc);
|
|
|
|
errno = e;
|
1998-12-05 06:50:15 +00:00
|
|
|
return 2; /* Couldn't set non-blocking. */
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
2010-03-19 12:10:11 +00:00
|
|
|
#endif /* __MINGW__ */
|
2002-02-26 09:43:04 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
memcpy(&sin, addr, sizeof(sin));
|
|
|
|
if (connect(desc, (struct sockaddr*)&sin, sizeof(sin)) != 0)
|
|
|
|
{
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2002-02-25 20:44:41 +00:00
|
|
|
if (WSAGetLastError() == WSAEWOULDBLOCK)
|
2000-07-18 11:34:30 +00:00
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
if (errno == EINPROGRESS)
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
|
|
|
e = tryWrite(desc, 10, 0, 0);
|
|
|
|
if (e == -2)
|
|
|
|
{
|
|
|
|
e = errno;
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
closesocket(desc);
|
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
close(desc);
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
1998-10-29 16:20:53 +00:00
|
|
|
errno = e;
|
1998-12-05 06:50:15 +00:00
|
|
|
return 3; /* Connect timed out. */
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else if (e == -1)
|
|
|
|
{
|
|
|
|
e = errno;
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
closesocket(desc);
|
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
close(desc);
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
1998-10-29 16:20:53 +00:00
|
|
|
errno = e;
|
1998-12-05 06:50:15 +00:00
|
|
|
return 3; /* Select failed. */
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
e = errno;
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
closesocket(desc);
|
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
close(desc);
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
1998-10-29 16:20:53 +00:00
|
|
|
errno = e;
|
1998-12-05 06:50:15 +00:00
|
|
|
return 3; /* Failed connect. */
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
memset((char*)&msg, '\0', GDO_REQ_SIZE);
|
|
|
|
msg.rtype = op;
|
|
|
|
msg.nsize = len;
|
|
|
|
msg.ptype = ptype;
|
|
|
|
if (op != GDO_REGISTER)
|
|
|
|
{
|
|
|
|
port = 0;
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
msg.port = htonl(port);
|
2013-04-14 16:25:27 +00:00
|
|
|
if (name && len)
|
|
|
|
{
|
|
|
|
memcpy(msg.name, name, len);
|
|
|
|
}
|
1998-10-27 20:58:22 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
e = tryWrite(desc, 10, (uptr)&msg, GDO_REQ_SIZE);
|
|
|
|
if (e != GDO_REQ_SIZE)
|
|
|
|
{
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
e = WSAGetLastError();
|
|
|
|
closesocket(desc);
|
|
|
|
WSASetLastError(e);
|
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
e = errno;
|
|
|
|
close(desc);
|
|
|
|
errno = e;
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
1998-12-05 06:50:15 +00:00
|
|
|
return 4;
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
e = tryRead(desc, 3, (uptr)&port, 4);
|
|
|
|
if (e != 4)
|
|
|
|
{
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
e = WSAGetLastError();
|
|
|
|
closesocket(desc);
|
|
|
|
WSASetLastError(e);
|
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
e = errno;
|
|
|
|
close(desc);
|
|
|
|
errno = e;
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
1998-12-05 06:50:15 +00:00
|
|
|
return 5; /* Read timed out. */
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
port = ntohl(port);
|
1998-10-27 20:58:22 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* Special case for GDO_SERVERS - allocate buffer and read list.
|
|
|
|
*/
|
|
|
|
if (op == GDO_SERVERS)
|
|
|
|
{
|
|
|
|
int len = port * sizeof(struct in_addr);
|
|
|
|
uptr b;
|
1998-10-27 20:58:22 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
b = (uptr)malloc(len);
|
|
|
|
if (tryRead(desc, 3, b, len) != len)
|
|
|
|
{
|
|
|
|
free(b);
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
e = WSAGetLastError();
|
|
|
|
closesocket(desc);
|
|
|
|
WSASetLastError(e);
|
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
e = errno;
|
|
|
|
close(desc);
|
|
|
|
errno = e;
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
1998-12-05 06:50:15 +00:00
|
|
|
return 5;
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
2013-07-06 07:14:45 +00:00
|
|
|
if (0 != v)
|
|
|
|
{
|
|
|
|
*v = b;
|
|
|
|
}
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
2000-07-18 15:50:36 +00:00
|
|
|
/*
|
|
|
|
* Special case for GDO_NAMES - allocate buffer and read list.
|
|
|
|
*/
|
|
|
|
else if (op == GDO_NAMES)
|
|
|
|
{
|
|
|
|
int len = port;
|
|
|
|
uptr ptr;
|
|
|
|
uptr b;
|
|
|
|
|
|
|
|
b = (uptr)malloc(len);
|
|
|
|
if (tryRead(desc, 3, b, len) != len)
|
|
|
|
{
|
|
|
|
free(b);
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 15:50:36 +00:00
|
|
|
e = WSAGetLastError();
|
|
|
|
closesocket(desc);
|
|
|
|
WSASetLastError(e);
|
|
|
|
#else
|
|
|
|
e = errno;
|
|
|
|
close(desc);
|
|
|
|
errno = e;
|
|
|
|
#endif
|
|
|
|
return 5;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Count the number of registered names and return them.
|
|
|
|
*/
|
|
|
|
ptr = b;
|
|
|
|
port = 0;
|
|
|
|
while (ptr < &b[len])
|
|
|
|
{
|
|
|
|
ptr += 2 + ptr[0];
|
|
|
|
port++;
|
|
|
|
}
|
|
|
|
if ((port & 0xffff) != port)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Insanely large number of registered names");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
2000-07-18 15:50:36 +00:00
|
|
|
port = 0;
|
|
|
|
}
|
2013-04-14 16:25:27 +00:00
|
|
|
if (0 != v)
|
|
|
|
{
|
|
|
|
*v = b;
|
|
|
|
}
|
2000-07-18 15:50:36 +00:00
|
|
|
}
|
1998-10-27 20:58:22 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
*p = (unsigned short)port;
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
closesocket(desc);
|
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
close(desc);
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
1998-10-29 16:20:53 +00:00
|
|
|
errno = 0;
|
1998-12-05 06:50:15 +00:00
|
|
|
return 0;
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Name - nameFail()
|
|
|
|
* Purpose - If given a failure status from tryHost()
|
|
|
|
* raise an appropriate exception.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
nameFail(int why)
|
|
|
|
{
|
1998-10-29 16:20:53 +00:00
|
|
|
switch (why)
|
|
|
|
{
|
|
|
|
case 0: break;
|
|
|
|
case 1:
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"failed to contact name server - socket - %s",
|
2000-07-18 15:50:36 +00:00
|
|
|
strerror(errno));
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
1998-10-29 16:20:53 +00:00
|
|
|
case 2:
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"failed to contact name server - socket - %s",
|
2000-07-18 15:50:36 +00:00
|
|
|
strerror(errno));
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
1998-10-29 16:20:53 +00:00
|
|
|
case 3:
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"failed to contact name server - socket - %s",
|
2000-07-18 15:50:36 +00:00
|
|
|
strerror(errno));
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
1998-10-29 16:20:53 +00:00
|
|
|
case 4:
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"failed to contact name server - socket - %s",
|
2002-02-24 19:58:31 +00:00
|
|
|
strerror(errno));
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Name - nameServer()
|
|
|
|
* Purpose - Perform name server lookup or registration.
|
|
|
|
* Return success/failure status and set up an
|
|
|
|
* address structure for use in bind or connect.
|
|
|
|
* Restrictions - 0xffff byte name limit
|
|
|
|
* Uses old style host lookup - only handles the
|
|
|
|
* primary network interface for each host!
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
nameServer(const char* name, const char* host, int op, int ptype, struct sockaddr_in* addr, int pnum, int max)
|
|
|
|
{
|
1998-10-29 16:20:53 +00:00
|
|
|
struct sockaddr_in sin;
|
|
|
|
struct hostent* hp;
|
2013-04-14 16:25:27 +00:00
|
|
|
unsigned short p;
|
1998-10-29 16:20:53 +00:00
|
|
|
unsigned short port = 0;
|
|
|
|
int len = strlen(name);
|
|
|
|
int multi = 0;
|
|
|
|
int found = 0;
|
|
|
|
int rval;
|
2004-09-15 09:29:06 +00:00
|
|
|
char *first_dot = 0;
|
1998-10-29 16:20:53 +00:00
|
|
|
|
|
|
|
if (len == 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "no name specified.");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
1998-10-29 16:20:53 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (len > 0xffff)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "name length to large.");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
1998-10-29 16:20:53 +00:00
|
|
|
return -1;
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if GDOMAP_PORT_OVERRIDE
|
1998-10-29 16:20:53 +00:00
|
|
|
p = htons(GDOMAP_PORT_OVERRIDE);
|
1998-10-27 20:58:22 +00:00
|
|
|
#else
|
2013-03-05 16:20:10 +00:00
|
|
|
{
|
|
|
|
struct servent* sp;
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* Ensure we have port number to connect to name server.
|
|
|
|
* The TCP service name 'gdomap' overrides the default port.
|
|
|
|
*/
|
|
|
|
if ((sp = getservbyname("gdomap", "tcp")) != 0)
|
|
|
|
{
|
|
|
|
p = sp->s_port; /* Network byte order. */
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
2013-04-14 16:25:27 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
p = htons(GDOMAP_PORT);
|
|
|
|
}
|
2013-03-05 16:20:10 +00:00
|
|
|
}
|
1998-10-27 20:58:22 +00:00
|
|
|
#endif
|
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* The host name '*' matches any host on the local network.
|
|
|
|
*/
|
|
|
|
if (host && host[0] == '*' && host[1] == '\0')
|
|
|
|
{
|
2010-06-28 14:35:44 +00:00
|
|
|
multi = 1;
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* If no host name is given, we use the name of the local host.
|
|
|
|
* NB. This should always be the case for operations other than lookup.
|
|
|
|
*/
|
|
|
|
if (multi || host == 0 || *host == '\0')
|
|
|
|
{
|
|
|
|
first_dot = strchr(local_hostname, '.');
|
|
|
|
if (first_dot)
|
|
|
|
{
|
|
|
|
*first_dot = '\0';
|
|
|
|
}
|
|
|
|
host = local_hostname;
|
|
|
|
}
|
2004-09-15 09:29:06 +00:00
|
|
|
if ((hp = gethostbyname(host)) == 0 && first_dot != 0)
|
|
|
|
{
|
|
|
|
*first_dot = '.';
|
|
|
|
hp = gethostbyname(host);
|
|
|
|
}
|
|
|
|
if (hp == 0)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"gethostbyname('%s') failed: %s", host, strerror(errno));
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
1998-10-29 16:20:53 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (hp->h_addrtype != AF_INET)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"non-internet network not supported for %s", host);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
1998-10-29 16:20:53 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset((char*)&sin, '\0', sizeof(sin));
|
|
|
|
sin.sin_family = AF_INET;
|
|
|
|
sin.sin_port = p;
|
2000-07-18 11:34:30 +00:00
|
|
|
memcpy(&sin.sin_addr, hp->h_addr, hp->h_length);
|
1998-10-29 16:20:53 +00:00
|
|
|
|
|
|
|
if (multi)
|
|
|
|
{
|
|
|
|
unsigned short num;
|
2013-07-06 07:14:45 +00:00
|
|
|
struct in_addr *b;
|
1998-10-29 16:20:53 +00:00
|
|
|
|
|
|
|
/*
|
2002-02-25 20:44:41 +00:00
|
|
|
* A host name of '*' is a special case which should do lookup on
|
2002-02-26 09:43:04 +00:00
|
|
|
* all machines on the local network until one is found which has
|
2002-02-25 20:44:41 +00:00
|
|
|
* the specified server on it.
|
1998-10-29 16:20:53 +00:00
|
|
|
*/
|
|
|
|
rval = tryHost(GDO_SERVERS, 0, 0, ptype, &sin, &num, (uptr*)&b);
|
2011-03-09 10:24:18 +00:00
|
|
|
if (rval != 0)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"failed to contact gdomap on %s(%s) - %s",
|
2002-10-05 17:47:54 +00:00
|
|
|
local_hostname, inet_ntoa(sin.sin_addr), strerror(errno));
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
1998-10-29 16:20:53 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (rval == 0)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; found == 0 && i < num; i++)
|
|
|
|
{
|
|
|
|
memset((char*)&sin, '\0', sizeof(sin));
|
|
|
|
sin.sin_family = AF_INET;
|
|
|
|
sin.sin_port = p;
|
2000-07-18 11:34:30 +00:00
|
|
|
memcpy(&sin.sin_addr, &b[i], sizeof(struct in_addr));
|
1998-10-29 16:20:53 +00:00
|
|
|
if (sin.sin_addr.s_addr == 0)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2005-07-08 11:48:37 +00:00
|
|
|
if (tryHost(GDO_LOOKUP, len, (unsigned char*)name,
|
|
|
|
ptype, &sin, &port, 0)==0)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
|
|
|
if (port != 0)
|
|
|
|
{
|
|
|
|
memset((char*)&addr[found], '\0', sizeof(*addr));
|
2000-07-18 11:34:30 +00:00
|
|
|
memcpy(&addr[found].sin_addr, &sin.sin_addr,
|
2002-02-25 20:44:41 +00:00
|
|
|
sizeof(sin.sin_addr));
|
1998-10-29 16:20:53 +00:00
|
|
|
addr[found].sin_family = AF_INET;
|
|
|
|
addr[found].sin_port = htons(port);
|
|
|
|
found++;
|
|
|
|
if (found == max)
|
|
|
|
{
|
|
|
|
break;
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
free(b);
|
1998-12-05 06:50:15 +00:00
|
|
|
return found;
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
nameFail(rval);
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (op == GDO_REGISTER)
|
|
|
|
{
|
|
|
|
port = (unsigned short)pnum;
|
2010-06-28 14:35:44 +00:00
|
|
|
if (port == 0 || htons(port) == p)
|
2010-06-26 15:22:38 +00:00
|
|
|
{
|
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
2010-06-28 14:35:44 +00:00
|
|
|
"attempted registration with bad port (%d).", port);
|
2010-06-26 15:22:38 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
|
|
|
return -1;
|
|
|
|
}
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
2005-07-08 11:48:37 +00:00
|
|
|
rval = tryHost(op, len, (unsigned char*)name, ptype, &sin, &port, 0);
|
2013-04-14 16:25:27 +00:00
|
|
|
if (rval != 0)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"failed to contact gdomap on %s(%s) - %s",
|
2002-10-05 17:47:54 +00:00
|
|
|
local_hostname, inet_ntoa(sin.sin_addr), strerror(errno));
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
1998-10-29 16:20:53 +00:00
|
|
|
return -1;
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
nameFail(rval);
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
if (op == GDO_REGISTER)
|
|
|
|
{
|
|
|
|
if (port == 0 || (pnum != 0 && port != pnum))
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"service already registered.");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
1998-10-29 16:20:53 +00:00
|
|
|
return -1;
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
if (port == 0)
|
|
|
|
{
|
|
|
|
return 0;
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
memset((char*)addr, '\0', sizeof(*addr));
|
2000-07-18 11:34:30 +00:00
|
|
|
memcpy(&addr->sin_addr, &sin.sin_addr, sizeof(sin.sin_addr));
|
1998-10-29 16:20:53 +00:00
|
|
|
addr->sin_family = AF_INET;
|
|
|
|
addr->sin_port = htons(port);
|
|
|
|
return 1;
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
lookup(const char *name, const char *host, int ptype)
|
|
|
|
{
|
|
|
|
struct sockaddr_in sin[100];
|
|
|
|
int found;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
found = nameServer(name, host, GDO_LOOKUP, ptype, sin, 0, 100);
|
|
|
|
for (i = 0; i < found; i++)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Found %s on '%s' port %d", name,
|
2002-02-24 19:58:31 +00:00
|
|
|
inet_ntoa(sin[i].sin_addr), ntohs(sin[i].sin_port));
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_INFO);
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
|
|
|
if (found == 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Unable to find %s.", name);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_INFO);
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-07-18 15:50:36 +00:00
|
|
|
static void
|
2002-10-05 17:47:54 +00:00
|
|
|
donames(const char *host)
|
2000-07-18 15:50:36 +00:00
|
|
|
{
|
|
|
|
struct sockaddr_in sin;
|
|
|
|
struct hostent* hp;
|
2013-04-14 16:25:27 +00:00
|
|
|
unsigned short p;
|
2000-07-18 15:50:36 +00:00
|
|
|
unsigned short num = 0;
|
|
|
|
int rval;
|
|
|
|
uptr b;
|
2004-09-14 15:31:13 +00:00
|
|
|
char *first_dot = 0;
|
2000-07-18 15:50:36 +00:00
|
|
|
|
|
|
|
#if GDOMAP_PORT_OVERRIDE
|
|
|
|
p = htons(GDOMAP_PORT_OVERRIDE);
|
|
|
|
#else
|
2013-03-05 16:20:10 +00:00
|
|
|
{
|
|
|
|
struct servent* sp;
|
2000-07-18 15:50:36 +00:00
|
|
|
/*
|
|
|
|
* Ensure we have port number to connect to name server.
|
|
|
|
* The TCP service name 'gdomap' overrides the default port.
|
|
|
|
*/
|
|
|
|
if ((sp = getservbyname("gdomap", "tcp")) != 0)
|
|
|
|
{
|
|
|
|
p = sp->s_port; /* Network byte order. */
|
|
|
|
}
|
2013-04-14 16:25:27 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
p = htons(GDOMAP_PORT);
|
|
|
|
}
|
2013-03-05 16:20:10 +00:00
|
|
|
}
|
2000-07-18 15:50:36 +00:00
|
|
|
#endif
|
|
|
|
|
2002-10-05 17:47:54 +00:00
|
|
|
if (host == 0 || *host == '\0')
|
2000-07-18 15:50:36 +00:00
|
|
|
{
|
2002-10-05 17:47:54 +00:00
|
|
|
/*
|
|
|
|
* If no host name is given, we use the name of the local host.
|
|
|
|
*/
|
|
|
|
first_dot = strchr(local_hostname, '.');
|
|
|
|
if (first_dot)
|
|
|
|
{
|
|
|
|
*first_dot = '\0';
|
|
|
|
}
|
|
|
|
host = local_hostname;
|
2000-07-18 15:50:36 +00:00
|
|
|
}
|
2004-09-14 15:31:13 +00:00
|
|
|
if ((hp = gethostbyname(host)) == 0 && first_dot != 0)
|
2000-07-18 15:50:36 +00:00
|
|
|
{
|
2004-09-14 15:31:13 +00:00
|
|
|
*first_dot = '.';
|
|
|
|
hp = gethostbyname(host);
|
|
|
|
}
|
|
|
|
if (hp == 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"gethostbyname('%s') failed: %s", host, strerror(errno));
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
2000-07-18 15:50:36 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (hp->h_addrtype != AF_INET)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"non-internet network not supported for %s", host);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
2000-07-18 15:50:36 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset((char*)&sin, '\0', sizeof(sin));
|
|
|
|
sin.sin_family = AF_INET;
|
|
|
|
sin.sin_port = p;
|
|
|
|
memcpy(&sin.sin_addr, hp->h_addr, hp->h_length);
|
|
|
|
|
|
|
|
rval = tryHost(GDO_NAMES, 0, 0, 0, &sin, &num, (uptr*)&b);
|
|
|
|
if (rval != 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "failed to contact gdomap on %s(%s) - %s",
|
2002-10-05 17:47:54 +00:00
|
|
|
local_hostname, inet_ntoa(sin.sin_addr), strerror(errno));
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
2000-07-18 15:50:36 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (num == 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "No names currently registered with gdomap");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_INFO);
|
2000-07-18 15:50:36 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2000-07-24 13:28:01 +00:00
|
|
|
uptr p = b;
|
|
|
|
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Registered names are -");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_INFO);
|
2000-07-18 15:50:36 +00:00
|
|
|
while (num-- > 0)
|
|
|
|
{
|
|
|
|
char buf[256];
|
|
|
|
|
2000-07-24 13:28:01 +00:00
|
|
|
memcpy(buf, &p[2], p[0]);
|
|
|
|
buf[p[0]] = '\0';
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), " %s", buf);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_INFO);
|
2000-07-24 13:28:01 +00:00
|
|
|
p += 2 + p[0];
|
2000-07-18 15:50:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
free(b);
|
|
|
|
}
|
|
|
|
|
1998-10-27 20:58:22 +00:00
|
|
|
static void
|
|
|
|
doregister(const char *name, int port, int ptype)
|
|
|
|
{
|
|
|
|
struct sockaddr_in sin;
|
|
|
|
int found;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
found = nameServer(name, 0, GDO_REGISTER, ptype, &sin, port, 1);
|
|
|
|
for (i = 0; i < found; i++)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Registered %s on '%s' port %d", name,
|
2002-02-24 19:58:31 +00:00
|
|
|
inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_INFO);
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
|
|
|
if (found == 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Unable to register %s on port %d.", name, port);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1998-11-02 11:48:42 +00:00
|
|
|
unregister(const char *name, int port, int ptype)
|
1998-10-27 20:58:22 +00:00
|
|
|
{
|
|
|
|
struct sockaddr_in sin;
|
|
|
|
int found;
|
|
|
|
int i;
|
|
|
|
|
1998-11-02 11:48:42 +00:00
|
|
|
found = nameServer(name, 0, GDO_UNREG, ptype, &sin, port, 1);
|
1998-10-27 20:58:22 +00:00
|
|
|
for (i = 0; i < found; i++)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Unregistered %s on '%s' port %d", name,
|
2002-02-24 19:58:31 +00:00
|
|
|
inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_INFO);
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
|
|
|
if (found == 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Unable to unregister %s.", name);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_INFO);
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
|
|
|
}
|
1997-05-03 19:18:21 +00:00
|
|
|
|
2004-11-25 09:00:07 +00:00
|
|
|
static void do_help(int argc, char **argv, char *options)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Where argc > 0 we check to see if there is a '--help' argument
|
|
|
|
* and do nothing if there isn't.
|
|
|
|
*/
|
|
|
|
if (argc > 0)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 1; i < argc; i++)
|
|
|
|
{
|
|
|
|
if (strcmp(argv[i], "--help") == 0)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i == argc)
|
|
|
|
{
|
2012-08-26 08:55:49 +00:00
|
|
|
return; // --help not found ...
|
2004-11-25 09:00:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
printf("%s -[%s]\n", argv[0], options);
|
|
|
|
printf("GNU Distributed Objects name server\n");
|
2008-10-30 14:22:19 +00:00
|
|
|
printf("-C help about interfaces and configuration\n");
|
2004-11-25 09:00:07 +00:00
|
|
|
printf("-H general help\n");
|
|
|
|
printf("-I pid file to write pid\n");
|
|
|
|
printf("-L name perform lookup for name then quit.\n");
|
|
|
|
printf("-M name machine name for -L and -N\n");
|
|
|
|
printf("-N list all names registered on host\n");
|
|
|
|
printf("-P number port number required for R option.\n");
|
|
|
|
printf("-R name register name locally then quit.\n");
|
|
|
|
printf("-T type port type for L, R and U options -\n");
|
|
|
|
printf(" tcp_gdo, udp_gdo,\n");
|
|
|
|
printf(" tcp_foreign, udp_foreign.\n");
|
|
|
|
printf("-U name unregister name locally then quit.\n");
|
|
|
|
printf("-a file use config file for interface list.\n");
|
|
|
|
printf("-c file use config file for probe.\n");
|
|
|
|
printf("-d extra debug logging (normally via syslog).\n");
|
|
|
|
printf("-f avoid fork() to make debugging easy\n");
|
|
|
|
printf("-i seconds re-probe at this interval (roughly), min 60\n");
|
2014-07-25 12:47:18 +00:00
|
|
|
#if !defined(__MINGW__)
|
|
|
|
printf("-j path specify a jail directory the process is to\n");
|
|
|
|
printf(" run in (if omitted, /tmp is used).\n");
|
|
|
|
#endif
|
2004-11-25 09:00:07 +00:00
|
|
|
printf("-p disable probing for other servers\n");
|
|
|
|
printf("\n");
|
|
|
|
printf("Kill with SIGUSR1 to obtain a dump of all known peers\n");
|
|
|
|
printf("in /tmp/gdomap.dump\n");
|
|
|
|
printf("\n");
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2005-02-14 14:39:22 +00:00
|
|
|
static char*
|
|
|
|
quoteArg(const char *arg)
|
|
|
|
{
|
|
|
|
int len = strlen(arg);
|
|
|
|
int in;
|
|
|
|
int out = 0;
|
|
|
|
int quote = 0;
|
2005-02-14 14:56:31 +00:00
|
|
|
char *ptr = malloc(len*2+3);
|
2005-02-14 14:39:22 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Check for white space ... if present, must quote argument.
|
|
|
|
*/
|
|
|
|
for (in = 0; in < len; in++)
|
|
|
|
{
|
|
|
|
if (isspace(arg[in]))
|
|
|
|
{
|
|
|
|
quote = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (quote)
|
|
|
|
{
|
|
|
|
ptr[out++] = '"';
|
|
|
|
}
|
|
|
|
|
|
|
|
for (in = 0; in < len; in++)
|
|
|
|
{
|
|
|
|
if (arg[in] == '\\')
|
|
|
|
{
|
|
|
|
int pos = in + 1;
|
|
|
|
|
|
|
|
// Step past any backslashes
|
|
|
|
while (pos < len && ptr[pos] == '\\')
|
|
|
|
{
|
|
|
|
pos++;
|
|
|
|
}
|
|
|
|
// If backslashes precede a quote ... double them.
|
|
|
|
if (pos < len && ptr[pos] == '"')
|
|
|
|
{
|
|
|
|
int num = pos - in;
|
|
|
|
|
|
|
|
while (num-- > 0)
|
|
|
|
{
|
|
|
|
ptr[out++] = '\\';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Copy the original backslashes
|
|
|
|
while (in < pos)
|
|
|
|
{
|
2005-02-14 14:56:31 +00:00
|
|
|
ptr[out++] = arg[in++];
|
2005-02-14 14:39:22 +00:00
|
|
|
}
|
|
|
|
// Copy the character after the backslashes
|
2005-02-14 14:56:31 +00:00
|
|
|
if (in < len)
|
2005-02-14 14:39:22 +00:00
|
|
|
{
|
|
|
|
ptr[out++] = arg[in];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (arg[in] == '"')
|
|
|
|
{
|
|
|
|
ptr[out++] = '\\'; // Escape the quote.
|
|
|
|
ptr[out++] = arg[in];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ptr[out++] = arg[in];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (quote)
|
|
|
|
{
|
|
|
|
ptr[out++] = '"';
|
|
|
|
}
|
|
|
|
|
2005-02-14 14:56:31 +00:00
|
|
|
ptr[out] = '\0';
|
2005-02-14 14:39:22 +00:00
|
|
|
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2004-09-14 02:13:59 +00:00
|
|
|
/**
|
|
|
|
* (A dummy comment to help autogsdoc realize this is a command-line tool.)
|
|
|
|
*/
|
2008-10-19 10:42:35 +00:00
|
|
|
#if GS_FAKE_MAIN
|
|
|
|
/* Since we don't link gnustep-base, the main function below has to be
|
|
|
|
* the real main function. */
|
|
|
|
#undef main
|
|
|
|
#endif
|
1997-05-03 19:18:21 +00:00
|
|
|
int
|
|
|
|
main(int argc, char** argv)
|
|
|
|
{
|
1998-10-29 16:20:53 +00:00
|
|
|
extern char *optarg;
|
2014-07-25 12:47:18 +00:00
|
|
|
#if defined(__MINGW__)
|
2002-10-05 17:47:54 +00:00
|
|
|
char *options = "-CHI:L:M:NP:R:T:U:a:bc:dfi:p";
|
2014-07-25 12:47:18 +00:00
|
|
|
#else
|
|
|
|
char *options = "-CHI:L:M:NP:R:T:U:a:bc:dfi:j:p";
|
|
|
|
const char *jail = 0;
|
|
|
|
#endif
|
1998-10-29 16:20:53 +00:00
|
|
|
int c;
|
|
|
|
int ptype = GDO_TCP_GDO;
|
|
|
|
int port = 0;
|
|
|
|
const char *machine = 0;
|
2002-10-05 17:47:54 +00:00
|
|
|
const char *lookupf = 0;
|
|
|
|
int donamesf = 0;
|
2002-02-24 18:28:40 +00:00
|
|
|
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
WORD wVersionRequested;
|
|
|
|
WSADATA wsaData;
|
|
|
|
|
2002-02-26 18:23:32 +00:00
|
|
|
wVersionRequested = MAKEWORD(2, 2);
|
2000-07-18 11:34:30 +00:00
|
|
|
WSAStartup(wVersionRequested, &wsaData);
|
2014-05-08 06:47:42 +00:00
|
|
|
#else
|
|
|
|
int forked = 0;
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
2002-02-26 09:43:04 +00:00
|
|
|
|
2013-04-14 16:25:27 +00:00
|
|
|
local_hostname = xgethostname();
|
|
|
|
if (!local_hostname)
|
|
|
|
{
|
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"gethostname() failed: %s", strerror(errno));
|
|
|
|
gdomap_log(LOG_CRIT);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* Would use inet_aton(), but older systems don't have it.
|
|
|
|
*/
|
|
|
|
loopback.s_addr = inet_addr("127.0.0.1");
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__)
|
2000-07-18 11:34:30 +00:00
|
|
|
class_a_net = IN_CLASSA_NET;
|
|
|
|
class_a_mask.s_addr = class_a_net;
|
|
|
|
class_b_net = IN_CLASSB_NET;
|
|
|
|
class_b_mask.s_addr = class_b_net;
|
|
|
|
class_c_net = IN_CLASSC_NET;
|
|
|
|
class_c_mask.s_addr = class_c_net;
|
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
class_a_net = inet_network("255.0.0.0");
|
|
|
|
class_a_mask = inet_makeaddr(class_a_net, 0);
|
|
|
|
class_b_net = inet_network("255.255.0.0");
|
|
|
|
class_b_mask = inet_makeaddr(class_b_net, 0);
|
|
|
|
class_c_net = inet_network("255.255.255.0");
|
|
|
|
class_c_mask = inet_makeaddr(class_c_net, 0);
|
2000-07-18 11:34:30 +00:00
|
|
|
#endif
|
1998-10-29 16:20:53 +00:00
|
|
|
|
2004-11-25 09:00:07 +00:00
|
|
|
do_help(argc, argv, options);
|
1998-10-29 16:20:53 +00:00
|
|
|
while ((c = getopt(argc, argv, options)) != -1)
|
|
|
|
{
|
|
|
|
switch(c)
|
|
|
|
{
|
|
|
|
case 'H':
|
2004-11-25 09:00:07 +00:00
|
|
|
do_help(0, argv, options);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_SUCCESS);
|
1998-10-29 16:20:53 +00:00
|
|
|
|
|
|
|
case 'C':
|
|
|
|
printf("\n");
|
|
|
|
printf(
|
1998-03-10 19:01:24 +00:00
|
|
|
"Gdomap normally probes every machine on the local network to see if there\n"
|
|
|
|
"is a copy of gdomap running on it. This is done for class-C networks and\n"
|
|
|
|
"subnets of class-C networks. If your host is on a class-B or class-A net\n"
|
|
|
|
"then the default behaviour is to treat it as a class-C net and probe only\n"
|
|
|
|
"the hosts that would be expected on a class-C network of the same number.\n");
|
1998-10-29 16:20:53 +00:00
|
|
|
printf("\n");
|
|
|
|
printf(
|
1998-03-10 19:01:24 +00:00
|
|
|
"If you are running on a class-A or class-B network, or if your net has a\n"
|
|
|
|
"large number of hosts which will not have gdomap on them - you may want to\n"
|
|
|
|
"supply a configuration file listing the hosts to be probed explicitly,\n"
|
|
|
|
"rather than getting gdomap to probe all hosts on the local net.\n");
|
1998-10-29 16:20:53 +00:00
|
|
|
printf("\n");
|
|
|
|
printf(
|
1998-03-10 19:01:24 +00:00
|
|
|
"You may also want to supply the configuration file so that hosts which are\n"
|
|
|
|
"not actually on your local network can still be found when your code tries\n"
|
|
|
|
"to connect to a host using @\"*\" as the host name. NB. this functionality\n"
|
|
|
|
"does not exist in OpenStep.\n");
|
1998-10-29 16:20:53 +00:00
|
|
|
printf("\n");
|
|
|
|
printf(
|
1998-03-10 19:01:24 +00:00
|
|
|
"A configuration file consists of a list of IP addresses to be probed.\n"
|
2000-02-21 22:01:08 +00:00
|
|
|
"The IP addresses should be in standard 'dot' notation, one per line.\n"
|
1998-03-10 19:01:24 +00:00
|
|
|
"Empty lines are permitted in the configuration file.\n"
|
|
|
|
"Anything on a line after a hash ('#') is ignored.\n"
|
|
|
|
"You tell gdomap about the config file with the '-c' command line option.\n");
|
1998-10-29 16:20:53 +00:00
|
|
|
printf("\n");
|
|
|
|
printf("\n");
|
1998-05-29 15:25:41 +00:00
|
|
|
printf(
|
|
|
|
"gdomap uses the SIOCGIFCONF ioctl to build a list of IP addresses and\n"
|
|
|
|
"netmasks for the network interface cards on your machine. On some operating\n"
|
|
|
|
"systems, this facility is not available (or is broken), so you must tell\n"
|
|
|
|
"gdomap the addresses and masks of the interfaces using the '-a' command line\n"
|
|
|
|
"option. The file named with '-a' should contain a series of lines with\n"
|
2008-10-30 14:22:19 +00:00
|
|
|
"space separated pairs of addresses and masks in 'dot' notation, eg.\n"
|
|
|
|
"192.168.1.2 255.255.255.0\n"
|
1998-05-29 15:25:41 +00:00
|
|
|
"You must NOT include loopback interfaces in this list.\n"
|
2001-02-23 10:11:32 +00:00
|
|
|
"If you want to support broadcasting of probe information on a network,\n"
|
2008-10-30 14:22:19 +00:00
|
|
|
"you may supply the broadcast address as a third item on the line, eg.\n"
|
|
|
|
"192.168.1.9 255.255.255.0 192.168.1.255\n"
|
1998-05-29 15:25:41 +00:00
|
|
|
"If your operating system has some other method of giving you a list of\n"
|
|
|
|
"network interfaces and masks, please send me example code so that I can\n"
|
|
|
|
"implement it in gdomap.\n");
|
1998-10-29 16:20:53 +00:00
|
|
|
printf("\n");
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_SUCCESS);
|
1998-10-29 16:20:53 +00:00
|
|
|
|
|
|
|
case 'L':
|
2002-10-05 17:47:54 +00:00
|
|
|
lookupf = optarg;
|
|
|
|
break;
|
1998-10-29 16:20:53 +00:00
|
|
|
|
|
|
|
case 'M':
|
|
|
|
machine = optarg;
|
|
|
|
break;
|
|
|
|
|
2000-07-18 15:50:36 +00:00
|
|
|
case 'N':
|
2002-10-05 17:47:54 +00:00
|
|
|
donamesf = 1;
|
|
|
|
break;
|
2000-07-18 15:50:36 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
case 'P':
|
|
|
|
port = atoi(optarg);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'R':
|
|
|
|
if (machine && *machine)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "-M flag is ignored for registration.\n");
|
|
|
|
fprintf(stderr, "Registration will take place locally.\n");
|
|
|
|
}
|
|
|
|
doregister(optarg, port, ptype);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_SUCCESS);
|
1998-10-29 16:20:53 +00:00
|
|
|
|
|
|
|
case 'T':
|
|
|
|
if (strcmp(optarg, "tcp_gdo") == 0)
|
|
|
|
{
|
|
|
|
ptype = GDO_TCP_GDO;
|
|
|
|
}
|
|
|
|
else if (strcmp(optarg, "udp_gdo") == 0)
|
|
|
|
{
|
|
|
|
ptype = GDO_UDP_GDO;
|
|
|
|
}
|
|
|
|
else if (strcmp(optarg, "tcp_foreign") == 0)
|
|
|
|
{
|
|
|
|
ptype = GDO_TCP_FOREIGN;
|
|
|
|
}
|
|
|
|
else if (strcmp(optarg, "udp_foreign") == 0)
|
|
|
|
{
|
|
|
|
ptype = GDO_UDP_FOREIGN;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Warning - -P selected unknown type -");
|
|
|
|
fprintf(stderr, " using tcp_gdo.\n");
|
|
|
|
ptype = GDO_TCP_GDO;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'U':
|
|
|
|
if (machine && *machine)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "-M flag is ignored for unregistration.\n");
|
|
|
|
fprintf(stderr, "Operation will take place locally.\n");
|
|
|
|
}
|
1998-11-02 11:48:42 +00:00
|
|
|
unregister(optarg, port, ptype);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_SUCCESS);
|
1998-10-29 16:20:53 +00:00
|
|
|
|
|
|
|
case 'a':
|
|
|
|
load_iface(optarg);
|
|
|
|
break;
|
|
|
|
|
2000-02-22 08:32:04 +00:00
|
|
|
case 'b':
|
|
|
|
nobcst++;
|
|
|
|
break;
|
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
case 'c':
|
|
|
|
{
|
2010-05-05 09:23:01 +00:00
|
|
|
FILE *fptr;
|
2010-05-03 20:28:23 +00:00
|
|
|
int line = 0;
|
2010-05-06 05:09:12 +00:00
|
|
|
int count = 0;
|
1998-10-29 16:20:53 +00:00
|
|
|
char buf[128];
|
|
|
|
|
2010-05-06 05:09:12 +00:00
|
|
|
in_config = 1;
|
2010-05-05 09:23:01 +00:00
|
|
|
if (access(optarg, R_OK) != 0)
|
|
|
|
{
|
2010-05-06 05:09:12 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Unable to access probe config - '%s'\n",
|
2010-05-05 09:23:01 +00:00
|
|
|
optarg);
|
2010-05-06 05:09:12 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2010-05-05 09:23:01 +00:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
fptr = fopen(optarg, "rt");
|
1998-10-29 16:20:53 +00:00
|
|
|
if (fptr == 0)
|
|
|
|
{
|
2010-05-06 05:09:12 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Unable to open probe config - '%s'\n",
|
2010-05-03 20:28:23 +00:00
|
|
|
optarg);
|
2010-05-06 05:09:12 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
1998-10-27 20:58:22 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
while (fgets(buf, sizeof(buf), fptr) != 0)
|
1998-03-10 19:01:24 +00:00
|
|
|
{
|
2010-05-03 20:28:23 +00:00
|
|
|
char *ptr = buf;
|
1998-10-29 16:20:53 +00:00
|
|
|
plentry *prb;
|
|
|
|
|
2010-05-03 20:28:23 +00:00
|
|
|
line++;
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* Strip leading white space.
|
|
|
|
*/
|
|
|
|
while (isspace(*ptr))
|
|
|
|
{
|
|
|
|
ptr++;
|
|
|
|
}
|
|
|
|
if (ptr != buf)
|
|
|
|
{
|
|
|
|
strcpy(buf, ptr);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Strip comments.
|
|
|
|
*/
|
|
|
|
ptr = strchr(buf, '#');
|
|
|
|
if (ptr)
|
|
|
|
{
|
|
|
|
*ptr = '\0';
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Strip trailing white space.
|
|
|
|
*/
|
|
|
|
ptr = buf;
|
|
|
|
while (*ptr)
|
|
|
|
{
|
|
|
|
ptr++;
|
|
|
|
}
|
|
|
|
while (ptr > buf && isspace(ptr[-1]))
|
|
|
|
{
|
|
|
|
ptr--;
|
|
|
|
}
|
|
|
|
*ptr = '\0';
|
|
|
|
/*
|
|
|
|
* Ignore blank lines.
|
|
|
|
*/
|
|
|
|
if (*buf == '\0')
|
|
|
|
{
|
|
|
|
continue;
|
1998-03-10 19:01:24 +00:00
|
|
|
}
|
|
|
|
|
2010-05-06 05:09:12 +00:00
|
|
|
if (count++ > 1000)
|
|
|
|
{
|
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Too many probe configurations found");
|
|
|
|
gdomap_log(LOG_CRIT);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
prb = (plentry*)malloc(sizeof(plentry));
|
|
|
|
memset((char*)prb, '\0', sizeof(plentry));
|
|
|
|
prb->addr.s_addr = inet_addr(buf);
|
2006-01-10 10:29:11 +00:00
|
|
|
if (prb->addr.s_addr == (uint32_t)-1)
|
1998-10-29 16:20:53 +00:00
|
|
|
{
|
2010-05-06 05:09:12 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"line %d of '%s' (%s) is not a valid address\n",
|
|
|
|
line, optarg, buf);
|
1998-10-29 16:20:53 +00:00
|
|
|
free(prb);
|
2010-05-06 05:09:12 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
|
|
|
exit(EXIT_FAILURE);
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Add this address at the end of the list.
|
|
|
|
*/
|
|
|
|
if (plist == 0)
|
|
|
|
{
|
|
|
|
plist = prb;
|
1998-03-10 19:01:24 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
plentry *tmp = plist;
|
|
|
|
|
|
|
|
while (tmp->next)
|
|
|
|
{
|
|
|
|
if (tmp->addr.s_addr == prb->addr.s_addr)
|
|
|
|
{
|
2010-05-06 05:09:12 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"'%s' repeat in '%s'\n",
|
2010-05-03 20:28:23 +00:00
|
|
|
buf, optarg);
|
1998-10-29 16:20:53 +00:00
|
|
|
free(prb);
|
2010-05-06 05:09:12 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
|
|
|
exit(EXIT_FAILURE);
|
1998-10-29 16:20:53 +00:00
|
|
|
break;
|
1998-03-10 19:01:24 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
tmp = tmp->next;
|
|
|
|
}
|
|
|
|
if (tmp->next == 0)
|
|
|
|
{
|
|
|
|
tmp->next = prb;
|
1998-03-10 19:01:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
fclose(fptr);
|
2010-05-06 05:09:12 +00:00
|
|
|
in_config = 0;
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
|
|
|
break;
|
2000-02-21 22:01:08 +00:00
|
|
|
|
|
|
|
case 'I':
|
|
|
|
pidfile = optarg;
|
|
|
|
break;
|
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
case 'd':
|
|
|
|
debug++;
|
|
|
|
break;
|
1998-02-26 17:55:42 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
case 'f':
|
|
|
|
nofork++;
|
|
|
|
break;
|
1997-05-03 19:18:21 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
case 'i':
|
|
|
|
interval = atoi(optarg);
|
|
|
|
if (interval < 60)
|
|
|
|
{
|
|
|
|
interval = 60;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2014-07-25 12:47:18 +00:00
|
|
|
#if !defined(__MINGW__)
|
|
|
|
case 'j':
|
|
|
|
jail = optarg;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
case 'p':
|
|
|
|
noprobe++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
printf("%s - GNU Distributed Objects name server\n", argv[0]);
|
|
|
|
printf("-H for help\n");
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_SUCCESS);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
2002-10-05 17:47:54 +00:00
|
|
|
if (donamesf || lookupf)
|
|
|
|
{
|
|
|
|
if (donamesf)
|
|
|
|
{
|
|
|
|
donames(machine);
|
|
|
|
}
|
|
|
|
if (lookupf)
|
|
|
|
{
|
|
|
|
lookup(lookupf, machine, ptype);
|
|
|
|
}
|
|
|
|
exit (0);
|
|
|
|
}
|
1997-05-03 19:18:21 +00:00
|
|
|
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(__MINGW__) /* On Win32, we don't fork */
|
2002-03-20 12:03:30 +00:00
|
|
|
if (nofork == 0)
|
|
|
|
{
|
|
|
|
char **a = malloc((argc+2) * sizeof(char*));
|
2005-02-14 14:39:22 +00:00
|
|
|
int i;
|
2002-03-20 12:03:30 +00:00
|
|
|
|
2005-02-14 14:39:22 +00:00
|
|
|
for (i = 0; i < argc; i++)
|
|
|
|
{
|
|
|
|
a[i] = quoteArg(argv[i]);
|
|
|
|
}
|
2002-03-20 12:03:30 +00:00
|
|
|
a[argc] = "-f";
|
|
|
|
a[argc+1] = 0;
|
2005-02-21 14:44:18 +00:00
|
|
|
if (_spawnv(_P_NOWAIT, argv[0], (const char* const*)a) == -1)
|
2002-03-20 12:03:30 +00:00
|
|
|
{
|
2002-05-08 11:27:50 +00:00
|
|
|
fprintf(stderr, "gdomap - spawn '%s' failed - bye.\n", argv[0]);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
2002-03-20 12:03:30 +00:00
|
|
|
}
|
|
|
|
if (debug)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "initialisation complete.");
|
2002-03-20 12:03:30 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
|
|
|
}
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_SUCCESS);
|
2002-03-20 12:03:30 +00:00
|
|
|
}
|
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
if (nofork == 0)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Now fork off child process to run in background.
|
|
|
|
*/
|
|
|
|
switch (fork())
|
|
|
|
{
|
|
|
|
case -1:
|
|
|
|
fprintf(stderr, "gdomap - fork failed - bye.\n");
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
1997-05-03 19:18:21 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
case 0:
|
|
|
|
/*
|
|
|
|
* Try to run in background.
|
|
|
|
*/
|
2014-03-19 08:18:09 +00:00
|
|
|
forked = 1;
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(NeXT)
|
1998-10-29 16:20:53 +00:00
|
|
|
setpgrp(0, getpid());
|
1997-05-03 19:18:21 +00:00
|
|
|
#else
|
1998-10-29 16:20:53 +00:00
|
|
|
setsid();
|
1997-05-03 19:18:21 +00:00
|
|
|
#endif
|
1998-10-29 16:20:53 +00:00
|
|
|
break;
|
1997-05-03 19:18:21 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
default:
|
|
|
|
if (debug)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "initialisation complete.");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_SUCCESS);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
/*
|
|
|
|
* Ensure we don't have any open file descriptors which may refer
|
|
|
|
* to sockets bound to ports we may try to use.
|
|
|
|
*
|
1999-10-04 09:48:57 +00:00
|
|
|
* Use '/dev/null' for stdin and stdout. Assume stderr is ok.
|
1998-10-29 16:20:53 +00:00
|
|
|
*/
|
|
|
|
for (c = 0; c < FD_SETSIZE; c++)
|
|
|
|
{
|
2002-08-07 15:47:27 +00:00
|
|
|
if (is_daemon || (c != 2))
|
2002-03-20 12:03:30 +00:00
|
|
|
{
|
|
|
|
(void)close(c);
|
|
|
|
}
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
2002-03-20 16:11:08 +00:00
|
|
|
if (open("/dev/null", O_RDONLY) != 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"failed to open stdin from /dev/null (%s)\n", strerror(errno));
|
2002-08-07 15:47:27 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
2002-03-20 16:11:08 +00:00
|
|
|
}
|
|
|
|
if (open("/dev/null", O_WRONLY) != 1)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"failed to open stdout from /dev/null (%s)\n", strerror(errno));
|
2002-08-07 15:47:27 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
2002-08-07 15:47:27 +00:00
|
|
|
}
|
|
|
|
if (is_daemon && open("/dev/null", O_WRONLY) != 2)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"failed to open stderr from /dev/null (%s)\n", strerror(errno));
|
2002-08-07 15:47:27 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
2002-03-20 16:11:08 +00:00
|
|
|
}
|
|
|
|
if (debug)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Closed descriptors");
|
2002-03-20 16:11:08 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
|
|
|
}
|
1997-09-01 21:59:51 +00:00
|
|
|
|
2014-03-19 08:18:09 +00:00
|
|
|
if (forked)
|
|
|
|
{
|
|
|
|
is_daemon = 1;
|
|
|
|
#if defined(HAVE_SYSLOG)
|
|
|
|
#if defined(SYSLOG_4_2)
|
|
|
|
openlog ("gdomap", LOG_NDELAY);
|
|
|
|
log_priority = LOG_DAEMON;
|
|
|
|
#elif !defined(HAVE_SLOGF)
|
|
|
|
openlog ("gdomap", LOG_NDELAY, LOG_DAEMON);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-05-08 06:47:42 +00:00
|
|
|
#endif /* !__MINGW__ */
|
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
init_my_port(); /* Determine port to listen on. */
|
2002-03-20 12:03:30 +00:00
|
|
|
init_ports(); /* Create ports to handle requests. */
|
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
if (interfaces == 0)
|
|
|
|
{
|
|
|
|
init_iface(); /* Build up list of network interfaces. */
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
1998-12-05 06:50:15 +00:00
|
|
|
|
|
|
|
if (!is_local_host(loopback))
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"I can't find the loopback interface on this machine.");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_ERR);
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
2008-10-30 14:22:19 +00:00
|
|
|
"Perhaps you should correct your machine configuration or use the -a flag.\n"
|
|
|
|
"Try 'gdomap -C' for more information.\n");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_INFO);
|
1998-12-05 06:50:15 +00:00
|
|
|
if (interfaces < MAX_IFACE)
|
|
|
|
{
|
|
|
|
addr[interfaces].s_addr = loopback.s_addr;
|
|
|
|
mask[interfaces] = class_c_mask;
|
|
|
|
interfaces++;
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"I am assuming loopback interface on 127.0.0.1");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_INFO);
|
1998-12-05 06:50:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
2002-02-24 18:28:40 +00:00
|
|
|
"You have too many network interfaces to add the loopback interface on "
|
|
|
|
"127.0.0.1 - you need to change the 'MAX_IFACE' constant in gdomap.c and "
|
|
|
|
"rebuild it.");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
1998-12-05 06:50:15 +00:00
|
|
|
}
|
|
|
|
}
|
2000-03-18 17:29:32 +00:00
|
|
|
|
2002-07-29 19:37:40 +00:00
|
|
|
/* Write the pidfile, but only if the user is root. This allows us
|
|
|
|
to write to restricted directories without allowing normal users
|
2003-07-30 06:21:06 +00:00
|
|
|
to mess it up. Because we are writing as root, we must be careful
|
|
|
|
to create/open the file in exclusive mode */
|
2002-07-29 19:37:40 +00:00
|
|
|
if (pidfile)
|
|
|
|
{
|
|
|
|
FILE *fptr;
|
|
|
|
|
2010-03-19 12:10:11 +00:00
|
|
|
#ifndef __MINGW__
|
2002-07-29 19:37:40 +00:00
|
|
|
if (getuid () == 0)
|
2002-08-25 08:41:29 +00:00
|
|
|
#endif
|
2002-07-29 19:37:40 +00:00
|
|
|
{
|
2003-08-06 05:39:51 +00:00
|
|
|
int desc = open(pidfile, O_EXCL|O_CREAT|O_WRONLY, 0644);
|
2003-07-30 06:21:06 +00:00
|
|
|
fptr = fdopen(desc, "w");
|
2002-07-29 19:37:40 +00:00
|
|
|
|
|
|
|
if (fptr == 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Unable to create new pid file - '%s'", pidfile);
|
2002-07-29 19:37:40 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
2003-05-12 20:42:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
2002-07-29 19:37:40 +00:00
|
|
|
}
|
|
|
|
fprintf(fptr, "%d\n", (int) getpid());
|
|
|
|
fclose(fptr);
|
|
|
|
chmod(pidfile, 0644);
|
|
|
|
}
|
2010-03-19 12:10:11 +00:00
|
|
|
#ifndef __MINGW__
|
2002-07-29 19:37:40 +00:00
|
|
|
else
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Only root user can write to pid file\n");
|
2002-07-29 19:37:40 +00:00
|
|
|
gdomap_log(LOG_WARNING);
|
|
|
|
}
|
2002-08-25 08:41:29 +00:00
|
|
|
#endif
|
2002-07-29 19:37:40 +00:00
|
|
|
}
|
2003-10-08 08:41:10 +00:00
|
|
|
{
|
2010-03-19 12:10:11 +00:00
|
|
|
#ifndef __MINGW__
|
2015-03-21 15:22:20 +00:00
|
|
|
uid_t uid = -2;
|
|
|
|
gid_t gid = -2;
|
2005-02-21 14:44:18 +00:00
|
|
|
#endif
|
2003-10-08 08:41:10 +00:00
|
|
|
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(HAVE_PWD_H)
|
|
|
|
#if defined(HAVE_GETPWNAM)
|
2003-10-08 08:41:10 +00:00
|
|
|
struct passwd *pw = getpwnam("nobody");
|
|
|
|
|
|
|
|
if (pw != 0)
|
|
|
|
{
|
|
|
|
uid = pw->pw_uid;
|
|
|
|
gid = pw->pw_gid;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
2002-07-29 19:37:40 +00:00
|
|
|
|
2003-07-30 06:21:06 +00:00
|
|
|
#if !defined(__svr4__)
|
|
|
|
/*
|
2014-07-25 12:47:18 +00:00
|
|
|
* As another level of paranoia - jail this process to a directory
|
2003-07-30 06:21:06 +00:00
|
|
|
*/
|
2010-03-19 12:10:11 +00:00
|
|
|
#ifndef __MINGW__
|
2014-07-25 12:47:18 +00:00
|
|
|
if (0 == jail)
|
|
|
|
{
|
|
|
|
jail = "/tmp"; /* Not great, but better than nothing */
|
|
|
|
}
|
|
|
|
if (chdir(jail) < 0)
|
2003-07-30 06:21:06 +00:00
|
|
|
{
|
2014-07-25 12:47:18 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Unable to change directory to %s", jail);
|
2003-07-30 06:21:06 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2004-02-27 14:08:36 +00:00
|
|
|
|
2003-07-30 06:21:06 +00:00
|
|
|
if (geteuid() == 0)
|
|
|
|
{
|
2014-07-25 12:47:18 +00:00
|
|
|
if (chroot(jail) < 0)
|
2003-07-30 06:21:06 +00:00
|
|
|
{
|
2014-07-25 12:47:18 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "Unable to change root to %s", jail);
|
2003-07-30 06:21:06 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
chdir("/");
|
|
|
|
}
|
2010-03-19 12:10:11 +00:00
|
|
|
#endif /* __MINGW__ */
|
2003-07-30 06:21:06 +00:00
|
|
|
#endif /* __svr4__ */
|
|
|
|
|
2010-03-19 12:10:11 +00:00
|
|
|
#ifndef __MINGW__
|
2000-03-18 17:29:32 +00:00
|
|
|
/*
|
|
|
|
* Try to become a 'safe' user now that we have
|
|
|
|
* done everything that needs root priv.
|
2003-10-08 08:41:10 +00:00
|
|
|
*
|
|
|
|
* Try to be the user who launched us ... so they can kill us too.
|
|
|
|
* Otherwise default to user nobody.
|
2002-02-26 09:43:04 +00:00
|
|
|
*/
|
2000-03-18 17:29:32 +00:00
|
|
|
if (getuid () != 0)
|
|
|
|
{
|
2003-10-08 08:41:10 +00:00
|
|
|
uid = getuid();
|
|
|
|
gid = getgid();
|
2000-03-18 17:29:32 +00:00
|
|
|
}
|
2015-03-21 15:22:20 +00:00
|
|
|
/* The call to setgroups may fail if we don't have that capability ...
|
|
|
|
* but in that case we aren't too bothered anyway.
|
|
|
|
*/
|
|
|
|
setgroups (1, &gid);
|
2003-10-08 08:41:10 +00:00
|
|
|
if (setgid (gid) < 0)
|
2000-03-18 17:29:32 +00:00
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Failed setgid(%d) - %s", gid, strerror(errno));
|
2003-10-08 08:41:10 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
|
|
|
exit(EXIT_FAILURE);
|
2000-03-18 17:29:32 +00:00
|
|
|
}
|
2003-10-08 08:41:10 +00:00
|
|
|
if (setuid (uid) < 0)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Failed setuid(%d) - %s", uid, strerror(errno));
|
2003-10-08 08:41:10 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
if (getuid () == 0)
|
2003-07-30 06:21:06 +00:00
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Still running as root after trying to change");
|
2003-07-30 06:21:06 +00:00
|
|
|
gdomap_log(LOG_CRIT);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2010-03-19 12:10:11 +00:00
|
|
|
#endif /* __MINGW__ */
|
2003-10-08 08:41:10 +00:00
|
|
|
}
|
2003-09-02 02:45:03 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
init_probe(); /* Probe other name servers on net. */
|
2002-02-26 09:43:04 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
if (debug)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), "entering main loop.\n");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
1997-09-01 21:59:51 +00:00
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
handle_io();
|
1998-12-05 06:50:15 +00:00
|
|
|
return 0;
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-01 21:59:51 +00:00
|
|
|
* Name - queue_probe()
|
1997-05-03 19:18:21 +00:00
|
|
|
* Purpose - Send a probe request to a specified host so we
|
|
|
|
* can see if a name server is running on it.
|
|
|
|
* We don't bother to check to see if it worked.
|
|
|
|
*/
|
|
|
|
static void
|
1998-02-26 17:55:42 +00:00
|
|
|
queue_probe(struct in_addr* to, struct in_addr* from, int l, struct in_addr* e, int f)
|
1997-05-03 19:18:21 +00:00
|
|
|
{
|
1998-10-29 16:20:53 +00:00
|
|
|
struct sockaddr_in sin;
|
|
|
|
gdo_req msg;
|
|
|
|
|
|
|
|
if (debug > 2)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
"Probing for server on '%s' from '", inet_ntoa(*to));
|
2002-02-26 09:43:04 +00:00
|
|
|
strcat(ebuf, inet_ntoa(*from));
|
|
|
|
strcat(ebuf, "'");
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
2000-04-05 07:44:18 +00:00
|
|
|
if (l > 0)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
|
|
|
" %d additional local addresses sent -", l);
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
2000-04-05 07:44:18 +00:00
|
|
|
for (i = 0; i < l; i++)
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
snprintf(ebuf, sizeof(ebuf), " '%s'", inet_ntoa(e[i]));
|
2002-03-14 06:54:44 +00:00
|
|
|
gdomap_log(LOG_DEBUG);
|
2000-04-05 07:44:18 +00:00
|
|
|
}
|
|
|
|
}
|
1998-10-29 16:20:53 +00:00
|
|
|
}
|
2002-02-27 13:37:42 +00:00
|
|
|
memset(&sin, '\0', sizeof(sin));
|
1998-10-29 16:20:53 +00:00
|
|
|
sin.sin_family = AF_INET;
|
2002-02-27 13:37:42 +00:00
|
|
|
memcpy(&sin.sin_addr, to, sizeof(*to));
|
1998-10-29 16:20:53 +00:00
|
|
|
sin.sin_port = my_port;
|
|
|
|
|
2002-02-27 13:37:42 +00:00
|
|
|
memset((char*)&msg, '\0', GDO_REQ_SIZE);
|
1998-10-29 16:20:53 +00:00
|
|
|
if (f)
|
|
|
|
{
|
|
|
|
msg.rtype = GDO_PREPLY;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
msg.rtype = GDO_PROBE;
|
|
|
|
}
|
|
|
|
msg.nsize = 2*IASIZE;
|
|
|
|
msg.ptype = 0;
|
|
|
|
msg.dummy = 0;
|
|
|
|
msg.port = 0;
|
2002-02-27 13:37:42 +00:00
|
|
|
memcpy(msg.name, from, IASIZE);
|
|
|
|
memcpy(&msg.name[IASIZE], to, IASIZE);
|
1998-10-29 16:20:53 +00:00
|
|
|
if (l > 0)
|
|
|
|
{
|
|
|
|
memcpy(&msg.name[msg.nsize], e, l*IASIZE);
|
|
|
|
msg.nsize += l*IASIZE;
|
1998-02-26 17:55:42 +00:00
|
|
|
}
|
2002-02-26 09:43:04 +00:00
|
|
|
|
1998-10-29 16:20:53 +00:00
|
|
|
queue_msg(&sin, (uptr)&msg, GDO_REQ_SIZE);
|
1997-05-03 19:18:21 +00:00
|
|
|
}
|
2004-05-22 03:16:01 +00:00
|
|
|
|
|
|
|
/* Copyright (c) 2001 Neal H Walfield <neal@cs.uml.edu>.
|
2012-08-26 08:55:49 +00:00
|
|
|
|
2004-05-22 03:16:01 +00:00
|
|
|
This file is placed into the public domain. Its distribution
|
|
|
|
is unlimited.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
|
|
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
|
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
|
|
|
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
|
|
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
|
|
|
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
|
|
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
|
|
|
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* NAME
|
|
|
|
|
|
|
|
xgethostname - get the host name.
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
|
|
|
|
char *xgethostname (void);
|
|
|
|
|
|
|
|
DESCRIPTION
|
|
|
|
|
|
|
|
The xhostname function is intended to replace gethostname(2), a
|
|
|
|
function used to access the host name. The old interface is
|
|
|
|
inflexable given that it assumes the existance of the
|
|
|
|
MAXHOSTNAMELEN macro, which neither POSIX nor the proposed
|
|
|
|
Single Unix Specification version 3 guarantee to be defined.
|
|
|
|
|
|
|
|
RETURN VALUE
|
|
|
|
|
|
|
|
On success, a malloced, null terminated (possibly truncated)
|
|
|
|
string containing the host name is returned. On failure,
|
|
|
|
NULL is returned and errno is set.
|
|
|
|
*/
|
|
|
|
|
|
|
|
char *
|
|
|
|
xgethostname (void)
|
|
|
|
{
|
|
|
|
int size = 0;
|
|
|
|
int addnull = 0;
|
|
|
|
char *buf;
|
|
|
|
int err;
|
|
|
|
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(MAXHOSTNAMELEN)
|
2004-05-22 03:16:01 +00:00
|
|
|
size = MAXHOSTNAMELEN;
|
|
|
|
addnull = 1;
|
|
|
|
#else /* MAXHOSTNAMELEN */
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(_SC_HOST_NAME_MAX)
|
2004-05-22 03:16:01 +00:00
|
|
|
size = sysconf (_SC_HOST_NAME_MAX);
|
|
|
|
addnull = 1;
|
|
|
|
#endif /* _SC_HOST_NAME_MAX */
|
2010-03-19 13:44:37 +00:00
|
|
|
#if defined(INTERNET_MAX_HOST_NAME_LENGTH)
|
2004-06-19 03:22:11 +00:00
|
|
|
size = INTERNET_MAX_HOST_NAME_LENGTH;
|
2004-05-22 03:16:01 +00:00
|
|
|
addnull = 1;
|
|
|
|
#endif
|
|
|
|
if (size <= 0)
|
|
|
|
size = 256;
|
|
|
|
#endif /* MAXHOSTNAMELEN */
|
|
|
|
|
|
|
|
buf = malloc (size + addnull);
|
|
|
|
if (! buf)
|
|
|
|
{
|
|
|
|
errno = ENOMEM;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = gethostname (buf, size);
|
|
|
|
while (err == -1 && errno == ENAMETOOLONG)
|
|
|
|
{
|
|
|
|
free (buf);
|
|
|
|
|
|
|
|
size *= 2;
|
|
|
|
buf = malloc (size + addnull);
|
|
|
|
if (! buf)
|
|
|
|
{
|
|
|
|
errno = ENOMEM;
|
|
|
|
return NULL;
|
|
|
|
}
|
2012-08-26 08:55:49 +00:00
|
|
|
|
2004-05-22 03:16:01 +00:00
|
|
|
err = gethostname (buf, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
if (buf)
|
|
|
|
free (buf);
|
|
|
|
errno = err;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (addnull)
|
|
|
|
buf[size] = '\0';
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|