/*
* $Id: telnet.c,v 1.23 2002/10/17 20:02:31 ljb Exp $
* originally Id: telnet.c,v 1.59 1998/08/03 17:29:10 gerald Exp
*/
/* Most of this code was taken from the MRT user.c library. I'm not sure what
* all -- shrug, even most -- of the code does. Ask Masaki. Seems to work.
*/
#include <stdio.h>
#include <string.h>
#include "mrt.h"
#include "select.h"
#include "trace.h"
#include <time.h>
#include <ctype.h>
#include <signal.h>
#ifndef NT
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#endif /* NT */
#include <stdarg.h>
#include "config_file.h"
#include <sys/types.h>
#include "irrd.h"
#include <fcntl.h>
#ifndef NT
#ifndef SETPGRP_VOID
#include <sys/termios.h>
#endif
#endif /* NT */
#include "config_file.h"
extern int IPV4;
extern trace_t *default_trace;
extern irr_t IRR;
static int irr_read_command (irr_connection_t * irr);
/* local yokel's */
void irr_write_answer (char *, char **, int *, irr_answer_t *, irr_connection_t *);
void long_fields_output (irr_connection_t *, char *, char **);
#ifndef HAVE_LIBPTHREAD
static int irr_read_command_schedule (irr_connection_t *irr);
#endif /* HAVE_LIBPTHREAD */
void *start_irr_connection (irr_connection_t * irr_connection) {
fd_set read_fds;
struct timeval tv;
int ret;
#ifdef HAVE_LIBPTHREAD
#ifndef NT
sigset_t set;
sigemptyset (&set);
sigaddset (&set, SIGALRM);
sigaddset (&set, SIGHUP);
pthread_sigmask (SIG_BLOCK, &set, NULL);
#endif /* NT */
#endif /* HAVE_LIBPTHREAD */
irr_connection->cp = irr_connection->buffer;
irr_connection->end = irr_connection->buffer;
irr_connection->end[0] = '\0';
trace (NORM, default_trace, "IRR connection from %s:%d\n",
prefix_toa (irr_connection->from), irr_connection->sockfd);
#ifndef HAVE_LIBPTHREAD
select_add_fd (irr_connection->sockfd, SELECT_READ,
(void *) irr_read_command_schedule, irr_connection);
return NULL;
#endif /* HAVE_LIBPTHREAD */
FD_ZERO(&read_fds);
FD_SET(irr_connection->sockfd, &read_fds);
while (1) {
/* set connection timeout */
tv.tv_sec = irr_connection->timeout;
tv.tv_usec = 0;
ret = select (irr_connection->sockfd + 1, &read_fds, 0, 0, &tv);
if (ret <= 0) {
if (ret == 0)
trace (NORM, default_trace, "-- IRR Connection Timeout -- \n");
trace (NORM, default_trace,
"ERROR on IRR select (before read). Closing connection (%s)\n",
strerror (errno));
irr_destroy_connection (irr_connection);
return NULL;
}
ret = irr_read_command (irr_connection);
if (ret < 0) {
trace (NORM, default_trace, "IRR Connection Aborted\n");
return NULL;
}
if (((ret == 1) && (irr_connection->stay_open == 0)) ||
(irr_connection->scheduled_for_deletion == 1)) {
/*trace (NORM, default_trace,
"Closing connection. stay_open set to close.\n");*/
irr_destroy_connection (irr_connection);
return NULL;
}
}
}
int irr_accept_connection (int fd) {
int sockfd;
int len, family;
prefix_t *prefix;
struct sockaddr_in addr;
irr_connection_t *irr_connection;
u_int one = 1;
char tmp[BUFSIZE];
irr_database_t *database;
len = sizeof (addr);
memset ((struct sockaddr *) &addr, 0, len);
if ((sockfd = accept (fd, (struct sockaddr *) &addr, &len)) < 0) {
trace (ERROR, default_trace, "ERROR -- IRR Accept failed (%s)\n",
strerror (errno));
select_enable_fd (fd);
return (-1);
}
select_enable_fd (fd);
if (setsockopt (sockfd, IPPROTO_TCP, TCP_NODELAY, (char *) &one,
sizeof (one)) < 0) {
trace (NORM | INFO, default_trace, "IRR setsockoptfailed\n");
return (-1);
}
if ((family = addr.sin_family) == AF_INET) {
struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
prefix = New_Prefix (AF_INET, &sin->sin_addr, 32);
}
else {
trace (ERROR, default_trace, "IRR ERROR unknown connection family = %d\n",
family);
close (sockfd);
return (-1);
}
/* check load */
if (IRR.connections > IRR.max_connections) {
trace (INFO, default_trace, "Too many connections -- REJECTING %s\n",
prefix_toa (prefix));
Deref_Prefix (prefix);
close (sockfd);
return (-1);
}
/* Apply access list (if one exists) */
if (IRR.irr_port_access > 0) {
if (!apply_access_list (IRR.irr_port_access, prefix)) {
trace (NORM, default_trace, "IRR connection DENIED from %s\n",
prefix_toa (prefix));
Deref_Prefix (prefix);
close (sockfd);
return (-1);
}
}
trace (TRACE, default_trace, "IRR accepting connection from %s\n",
prefix_toa (prefix));
IRR.connections++;
irr_connection = New (irr_connection_t);
#ifndef HAVE_LIBPTHREAD
irr_connection->schedule = New_Schedule ("irr_connection", default_trace);
#else
irr_connection->schedule = NULL;
#endif
irr_connection->sockfd = sockfd;
irr_connection->from = prefix;
irr_connection->ll_database = LL_Create (0);
irr_connection->timeout = 60; /* *5; default timeout of five minutes */
irr_connection->full_obj = 1;
irr_connection->end = irr_connection->buffer;
irr_connection->start = time (NULL);
irr_connection->ENCODING = strdup("gzip"); /* be sure to free this */
if (pthread_mutex_lock (&IRR.connections_mutex_lock) != 0)
trace (NORM, default_trace, "Error locking -- connection_mutex_lock--: %s\n",
strerror (errno));
LL_Add (IRR.ll_connections, irr_connection);
if (pthread_mutex_unlock (&IRR.connections_mutex_lock) != 0)
trace (NORM, default_trace, "Error unlocking -- connection_mutex_lock--: %s\n",
strerror (errno));
/* by default, use all databases in order appear IRRd config file */
LL_Iterate (IRR.ll_database, database) {
/* Apply access list (if one exists) */
if ((database->access_list > 0) &&
(!apply_access_list (database->access_list, prefix))) {
trace (NORM, default_trace, "Access to %s denied for %s...\n",
database->name, prefix_toa (prefix));
}
else {
if (! (database->flags & IRR_NODEFAULT))
LL_Add (irr_connection->ll_database, database);
}
}
sprintf (tmp, "IRR %s", prefix_toa (prefix));
mrt_thread_create (tmp, irr_connection->schedule,
(thread_fn_t) start_irr_connection, irr_connection);
return (1);
}
/*
* begin listening for connections on a well known port
*/
int
listen_telnet (u_short port) {
struct sockaddr_in serv_addr;
struct sockaddr *sa;
int len, optval = 1;
int sockfd;
/* this port has not been configured */
if (port <= 0) return (0);
memset (&serv_addr, 0, sizeof (serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons (port);
sa = (struct sockaddr *) &serv_addr;
len = sizeof (serv_addr);
if ((sockfd = socket (sa->sa_family, SOCK_STREAM, 0)) < 0) {
trace (ERROR, default_trace,
"IRR ERROR -- Could not get socket (%s)\n",
strerror (errno));
return (-1);
}
if (setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR,
(const char *) &optval, sizeof (optval)) < 0) {
trace (ERROR, default_trace, "IRR ERROR -- Could setsocket (%s)\n",
strerror (errno));
}
if (bind (sockfd, sa, len) < 0) {
trace (ERROR, default_trace,
"IRR ERROR -- Could not bind to port %d (%s)\n",
port, strerror(errno));
return (-1);
}
listen (sockfd, 5);
trace (NORM, default_trace,
"IRR listening for connections on port %d (socket %d)\n",
port, sockfd);
select_add_fd (sockfd, 1, (void_fn_t) irr_accept_connection, (void *) sockfd);
return (sockfd);
}
#ifndef HAVE_LIBPTHREAD
static int irr_read_command_schedule (irr_connection_t *irr) {
schedule_event (irr->schedule, (void *) irr_read_command, 1, irr);
return (1);
}
#endif /* HAVE_LIBPTHREAD */
/*
* irr_read_command
* A misnamed routine -- actually read command input into buffer and
* and process the buffer. We may, or may not have a command...
* If we have not processed a command, return 0 (1 otherwise)
*/
static int irr_read_command (irr_connection_t * irr) {
int n, i, state;
char *cp, *newline;
int command_found = 0;
#ifdef NT
if ((n = recv (irr->sockfd, irr->end, BUFSIZE - (irr->end - irr->buffer) - 2,0)) <= 0) {
#else
if ((n = read (irr->sockfd, irr->end, BUFSIZE - (irr->end - irr->buffer) - 2)) <= 0) {
/*if((n = read_socket_line(default_trace, irr->sockfd, irr->buffer, BUFSIZE)) <= 0) {*/
#endif /* NT */
trace (NORM, default_trace, "IRR read failed\n",
strerror (errno));
irr_destroy_connection (irr);
return (-1);
}
irr->end += n;
*(irr->end) = '\0'; /* necessary for IRR_MODE_LOAD_UPDATE case */
state = irr->state;
/* we should probably have this in a loop... */
while ((newline = strchr (irr->buffer, '\r')) != NULL) {
memmove (newline, newline + 1, irr->end - newline);
irr->end--;
n--;
}
while ((newline = strchr (irr->buffer, '\n')) != NULL ||
state == IRR_MODE_LOAD_UPDATE) {
if (newline != NULL) {
if (state == IRR_MODE_LOAD_UPDATE) {
i = newline - irr->buffer + 1;
memcpy (irr->tmp, irr->buffer, i);
*(irr->tmp + i) = '\0';
}
else
*newline = '\0';
}
else
strcpy (irr->tmp, irr->buffer);
command_found = 1;
if (state != IRR_MODE_LOAD_UPDATE) {
strcpy (irr->tmp, irr->buffer);
/* remove tailing spaces */
cp = irr->tmp + strlen (irr->tmp) - 1;
while (cp >= (irr->tmp) && isspace ((int) *cp)) {
*cp = '\0';
cp--;
}
/* remove heading spaces */
cp = irr->tmp;
while (*cp && isspace ((int) *cp)) {
cp++;
}
if (irr->tmp != cp)
strcpy (irr->tmp, cp);
}
irr->cp = irr->tmp;
irr_process_command (irr);
/* user has quit or we've unexpetdly terminated */
if (irr->stay_open == 0) {
#ifndef HAVE_LIBPTHREAD
irr_destroy_connection (irr);
#endif /* HAVE_LIBPTHREAD */
return (1);
}
/* IRR_MODE_LOAD_UPDATE case:
* there may not be a newline, so
* process all 'n' chars in buffer
*/
if (state == IRR_MODE_LOAD_UPDATE) {
n -= strlen (irr->tmp);
if (n <= 0) {
irr->end = irr->buffer;
break;
}
}
newline++;
if ((irr->end - newline) > 0)
memmove (irr->buffer, newline, irr->end - newline);
irr->end = irr->buffer + (irr->end - newline);
*(irr->end) = '\0';
}
#ifndef HAVE_LIBPTHREAD
select_enable_fd (irr->sockfd);
#endif /* HAVE_LIBPTHREAD */
return (command_found);
}
int irr_destroy_connection (irr_connection_t * connection) {
#if 0
int n;
n = close (connection->sockfd);
n = WSAGetLastError();
#endif
#ifndef HAVE_LIBPTHREAD
select_delete_fd (connection->sockfd);
#else
close (connection->sockfd);
#endif /* HAVE_LIBPTHREAD */
#if 0
n = close (connection->sockfd);
n = WSAGetLastError();
#endif
trace (NORM, default_trace,
"IRR Closing a connection from %s:%d (%d connections)\n",
prefix_toa (connection->from),
connection->sockfd,
IRR.connections);
/*LL_RemoveFn (IRR.ll_irr_connections, connection, 0);*/
Deref_Prefix (connection->from);
if (connection->ENCODING != NULL)
free(connection->ENCODING);
#ifndef HAVE_LIBPTHREAD
if(connection->schedule->is_running > 0)
/* if we running as a scheduled event, can't destroy schedule yet */
delete_schedule (connection->schedule);
else
/* it's safe to destroy the schedule */
destroy_schedule (connection->schedule);
#endif
LL_Destroy (connection->ll_database);
if (pthread_mutex_lock (&IRR.connections_mutex_lock) != 0)
trace (NORM, default_trace, "Error locking -- connection_mutex_lock--: %s\n",
strerror (errno));
LL_Remove (IRR.ll_connections, connection);
if (pthread_mutex_unlock (&IRR.connections_mutex_lock) != 0)
trace (NORM, default_trace, "Error locking -- connection_mutex_lock--: %s\n",
strerror (errno));
if (connection->answer != NULL)
Delete (connection->answer);
Delete (connection);
IRR.connections--;
#ifndef NT
mrt_thread_exit ();
#endif /* NT */
/* NOTREACHED */
return(-1);
}
int irr_add_answer (irr_connection_t *irr, char *format, ...) {
va_list args;
int len;
char buffer[BUFSIZE];
if (irr->answer == NULL) {
/* If this is first time, create a linked list and malloc a buffer */
irr->ll_answer = LL_Create (LL_DestroyFunction, free, 0);
irr->answer = malloc (IRR_OUTPUT_BUFFER_SIZE);
irr->answer_len = 0;
}
if (irr->answer_len >= (IRR_OUTPUT_BUFFER_SIZE - BUFSIZE)) {
/* buffer too big, add answer to linked list and malloc more space */
irr_build_answer(irr, NULL, NO_FIELD, 0, irr->answer_len, irr->answer, RAWHOISD_MODE);
irr->answer = malloc (IRR_OUTPUT_BUFFER_SIZE);
irr->answer_len = 0;
}
va_start (args, format);
vsprintf (buffer, format, args);
len = strlen (buffer);
strcpy(irr->answer + irr->answer_len, buffer);
irr->answer_len += len;
return (1);
}
/*
* Send answer built up by irr_add_answer
*
*/
void irr_send_answer (irr_connection_t * irr) {
irr_answer_t *irr_answer;
char *cp;
if (irr->answer != NULL) {
/* add a terminating newline if not already present */
cp = irr->answer + irr->answer_len - 1;
if (*cp++ != '\n') {
*cp++ = '\n';
*cp = 0;
irr->answer_len++;
}
/* Add buffered data to the linked list */
irr_build_answer(irr, NULL, NO_FIELD, 0, irr->answer_len, irr->answer, RAWHOISD_MODE);
} else /* no data to send, create an empty list */
irr->ll_answer = LL_Create (LL_DestroyFunction, free, 0);
send_dbobjs_answer (irr, MEM_INDEX, RAWHOISD_MODE);
LL_ContIterate (irr->ll_answer, irr_answer) {
free (irr_answer->blob); /* free our malloc'ed memory */
}
irr_write_buffer_flush (irr);
LL_Destroy(irr->ll_answer);
irr->answer = NULL;
}
/* irr_flush_final_answer
* Called after we're done itterating through the database building up an answer.
* This routine actually writes out to the socket, feeding it final_answer
* structures built during irr_write
*/
void irr_write_buffer_flush (irr_connection_t *irr) {
int n, ret;
int fd = irr->sockfd;
u_char *ptr;
fd_set write_fds;
struct timeval tv;
final_answer_t *final_answer;
/* something happened to the socket at some point -- delete before read */
if (irr->scheduled_for_deletion)
return;
FD_ZERO(&write_fds);
FD_SET(fd, &write_fds);
if (irr->ll_final_answer == NULL) return;
/* iterate through all of our linked answers */
LL_Iterate (irr->ll_final_answer, final_answer) {
ptr = final_answer->buf;
/* len = final_answer->ptr - final_answer->buf; */
while (ptr < final_answer->ptr) {
tv.tv_sec = 30; /* 30 second timeout on trying to write to socket */
tv.tv_usec = 0;
ret = select (fd + 1, 0, &write_fds, 0, &tv);
if (ret <= 0) {
trace (NORM, default_trace, "-- IRR Connection Timeout -- \n");
trace (NORM, default_trace,
"ERROR on IRR select (before buffered write). Closing connection (%s)\n",
strerror (errno));
LL_Destroy (irr->ll_final_answer);
irr->scheduled_for_deletion = 1;
return;
}
#ifdef NT
if ((n = send (fd, ptr, final_answer->ptr - ptr,0 )) < 0) {
#else
if ((n = write (fd, ptr, final_answer->ptr - ptr)) < 0) {
#endif /* NT */
irr->scheduled_for_deletion = 1;
trace (NORM, default_trace, "Write error %s \n", strerror (errno));
/* free ll_final_answer structs!!!! */
LL_Destroy (irr->ll_final_answer);
return;
}
ptr += n;
}
}
/* free ll_final_answer structs!!!! Need to write a destroy routine */
LL_Destroy (irr->ll_final_answer);
irr->ll_final_answer = NULL;
return;
}
void irr_write_nobuffer (irr_connection_t *irr, char *buf, int len) {
int n, ret;
int fd = irr->sockfd;
char *ptr;
fd_set write_fds;
struct timeval tv;
ptr = buf;
/* something happened to the socket at some point -- delete before read */
if (irr->scheduled_for_deletion)
return;
FD_ZERO(&write_fds);
FD_SET(fd, &write_fds);
while ((ptr - buf) < len) {
tv.tv_sec = 20; /* 20 second timeout on trying to write to socket */
tv.tv_usec = 0;
/* select call with timeout --- add me !!!!!!! */
ret = select (fd + 1, 0, &write_fds, 0, &tv);
if (ret <= 0) {
trace (NORM, default_trace, "-- IRR Connection Timeout -- \n");
trace (NORM, default_trace,
"ERROR on IRR select (before write). Closing connection (%s)\n",
strerror (errno));
irr->scheduled_for_deletion = 1;
return;
}
#ifdef NT
if ((n = send (fd, buf, len - (ptr-buf),0)) < 0) {
#else
if ((n = write (fd, buf, len - (ptr-buf))) < 0) {
#endif /* NT */
irr->scheduled_for_deletion = 1;
trace (NORM, default_trace, "Write error %s \n", strerror (errno));
return;
}
ptr += n;
}
return;
}
void delete_final_answer (final_answer_t *tmp) {
Destroy (tmp->buf);
Destroy (tmp);
}
/* irr_write_buffer
* Just copy buf answer to memory buffers in a linked_list hung off the
* irr_connection structure.
* We later call irr_answer_flush after we finish gathering answer and releasing
* all the locks
*/
/* JMH TODO - n was throwing warnings due to being uninitialized. Based
on the way this is written, its not certain n is guaranteed to be set
to a useful value. For now, n is set to 0 and later we need to audit
the code to see if we're guaranteed to get a useful value in here. */
void irr_write (irr_connection_t *irr, char *buf, int len) {
int bytes, n = 0;
char *ptr;
final_answer_t *final_answer;
ptr = buf;
/* something happened to the socket at some point -- delete before read */
if (irr->scheduled_for_deletion)
return;
/* fill in final_answer structures */
while ((ptr - buf) < len) {
/* oops, first time */
if (irr->ll_final_answer == NULL) {
irr->ll_final_answer = LL_Create (LL_DestroyFunction, delete_final_answer, 0);
final_answer = New (final_answer_t);
final_answer->buf = final_answer->ptr = malloc (4096);
LL_Add (irr->ll_final_answer, final_answer);
}
/* see if there is room in the last entry */
final_answer = NULL;
if ((final_answer = LL_GetTail (irr->ll_final_answer)) != NULL)
n = 4096 - (final_answer->ptr - final_answer->buf);
/* no room, we need to add another one */
if ((final_answer == NULL) || n == 0) {
final_answer = New (final_answer_t);
final_answer->buf = final_answer->ptr = malloc (4096);
LL_Add (irr->ll_final_answer, final_answer);
n = 4096;
}
/* write either all thats left, or as much room as left in buffer */
if (n < (len- (ptr-buf)))
bytes = n;
else
bytes = len - (ptr-buf);
memcpy (final_answer->ptr, ptr, bytes);
ptr += bytes;
final_answer->ptr += bytes;
}
return;
}
void irr_send_okay (irr_connection_t * irr) {
char tmp[20];
sprintf (tmp, "C\n");
irr_write_nobuffer (irr, tmp, strlen (tmp));
}
void irr_send_error (irr_connection_t * irr, char *msg) {
char tmp[256];
if (msg != NULL)
sprintf (tmp, "F%s\n", msg);
else
sprintf (tmp, "F\n");
irr_write_nobuffer (irr, tmp, strlen (tmp));
trace (NORM, default_trace, "Returned error: %s\n", tmp);
}
void send_dbobjs_answer (irr_connection_t *irr, enum INDEX_T index, int mode) {
char *cp;
char buffer[BUFSIZE];
irr_answer_t *irr_answer;
u_long answer_size = 0;
int first = 1, space_left;
enum DB_SYNTAX db_syntax = RIPE181;
/* compute answer size */
LL_ContIterate (irr->ll_answer, irr_answer) {
if (first != 1 && index == DISK_INDEX)
answer_size += 1; /* need to add '\n' between disk obj's for blank line */
answer_size += (u_long) irr_answer->len;
first = 0;
db_syntax = irr_answer->db_syntax;
}
/* return "D" empty answer return code */
if (answer_size == 0) {
/* JW
* if (irr->stay_open)
*/
if (mode == RAWHOISD_MODE)
sprintf (buffer, "D\n");
else /* later read this string from configs, ie make it customizable */
sprintf (buffer, "%% No entries found for the selected source(s).\n");
irr_write (irr, buffer, strlen (buffer));
trace (NORM, default_trace, "Returned D -- no entries found\n");
return;
}
/* JW
* if (irr->stay_open) {
*/
if (mode == RAWHOISD_MODE) {
/* # of bytes in answer */
sprintf (buffer, "A%d\n", (int) answer_size);
/* write the answer to the socket buffer */
cp = buffer + strlen(buffer);
space_left = BUFSIZE - strlen(buffer) - 1;
}
else {
cp = buffer;
space_left = BUFSIZE - 1;
}
if (index == DISK_INDEX) {
first = 1;
LL_ContIterate (irr->ll_answer, irr_answer) {
if (first != 1) {
sprintf (cp, "\n");
cp++;
space_left -= 1;
}
irr_write_answer (buffer, &cp, &space_left, irr_answer, irr);
first = 0;
}
} else { /* MEM_INDEX */
if (cp != buffer) /* flush answer length */
irr_write (irr, buffer, cp - buffer);
cp = buffer;
LL_ContIterate (irr->ll_answer, irr_answer) {
irr_write (irr, irr_answer->blob, irr_answer->len);
}
}
/* add "C" return code */
/* JW
* if (irr->stay_open) {
*/
if (mode == RAWHOISD_MODE) {
if (space_left < 2) {
irr_write (irr, buffer, cp - buffer);
cp = buffer;
}
sprintf (cp, "C\n");
cp += 2;
}
/* flush anything left in the buffer */
if (irr->short_fields || db_syntax == RPSL)
irr_write (irr, buffer, cp - buffer);
else
long_fields_output (irr, buffer, &cp);
trace (NORM, default_trace, "Sent %d bytes\n", answer_size);
} /* end send_dbobjs_answer() */
void irr_write_answer (char *buf, char **cp, int *space_left,
irr_answer_t *irr_answer, irr_connection_t *irr) {
int bytes_to_read;
if (fseek (irr_answer->fp, irr_answer->offset, SEEK_SET) < 0)
trace (NORM, default_trace, "** Error ** fseek failed in irr_write_answer");
while (irr_answer->len > 0) {
if (*space_left >= irr_answer->len)
bytes_to_read = irr_answer->len;
else
bytes_to_read = *space_left;
fread(*cp, 1, bytes_to_read, irr_answer->fp);
*cp += bytes_to_read;
*space_left -= bytes_to_read;
if (*space_left < 3) { /* calling routine assumes space for newline */
if (irr->short_fields || irr_answer->db_syntax == RPSL)
irr_write (irr, buf, *cp - buf);
else
long_fields_output (irr, buf, cp);
*cp = buf;
*space_left = BUFSIZE - 1;
}
irr_answer->len -= bytes_to_read;
}
} /* end irr_write_answer() */
void irr_build_answer (irr_connection_t *irr, FILE *fp, enum IRR_OBJECTS type,
u_long offset, u_long len, char *blob, enum DB_SYNTAX syntax) {
irr_answer_t *irr_answer;
irr_answer = New (irr_answer_t);
irr_answer->fp = fp;
irr_answer->type = type;
irr_answer->offset = offset;
irr_answer->len = len;
irr_answer->blob = blob;
irr_answer->db_syntax = syntax;
LL_Add (irr->ll_answer, irr_answer);
} /* end irr_build_answer() */
void irr_build_key_answer (irr_connection_t *irr, FILE *fp, char *dbname,
enum IRR_OBJECTS type, u_long offset,
u_short origin) {
char buffer[BUFSIZE], str_orig[10];
irr_answer_t *irr_answer;
strcpy (buffer, dbname);
strcat (buffer, " ");
if (get_prefix_from_disk (fp, offset, buffer) < 0)
return;
strcat (buffer, "-AS");
sprintf (str_orig, "%d", origin);
strcat (buffer, str_orig);
strcat (buffer, "\n");
irr_answer = New (irr_answer_t);
irr_answer->len = strlen (buffer);
irr_answer->blob = malloc (irr_answer->len);
strcpy (irr_answer->blob, buffer);
LL_Add (irr->ll_answer, irr_answer);
} /* end irr_build_key_answer() */
void long_fields_output (irr_connection_t * irr, char *buffer, char **cp) {
char *p, *q;
char *rt = "route: ";
char *cm = "community: ";
char *au = "authority: ";
char *de = "descr: ";
char *so = "source: ";
char *or = "origin: ";
char *mt = "mntner: ";
char *ch = "changed: ";
char *mb = "mnt-by: ";
char *ny = "notify: ";
char *mn = "mnt-nfy: ";
char *dt = "upd-to: ";
char *at = "auth: ";
char *ai = "as-in: ";
char *an = "aut-num: ";
char *ao = "as-out: ";
char *tc = "tech-c: ";
char *ac = "admin-c: ";
char *av = "advisory: ";
char *rm = "remark: ";
char *aa = "as-name: ";
char *gd = "guardian: ";
char *am = "as-macro: ";
char *al = "as-list: ";
char *pn = "person: ";
char *ad = "address: ";
char *ph = "phone: ";
char *fx = "fax-no: ";
char *nh = "nic-hdl: ";
char *em = "e-mail: ";
char *df = "default: ";
char *ir = "inet-rtr: ";
char *la = "localas: ";
char *if2 = "ifaddr: ";
char *pe = "peer: ";
char *ri = "rs-in: ";
char *rx = "rs-out: ";
char *cp2 = "contact-proc: ";
char *ne = "noc-email: ";
char *np = "noc-phone: ";
char *rc = "rtr-loc: ";
char *rr = "rtr-ver: ";
char *ry = "rtr-type: ";
char *cs = "comm-str: ";
char *cl = "comm-list: ";
char *wd = "withdrawn: ";
for (p = q = buffer; p < *cp; p = q + 1) {
q = strchr (p, '\n');
if (!strncasecmp (p, "*rt:", 4)) {
irr_write (irr, rt, strlen (rt));
p +=4;
}
else if (!strncasecmp (p, "*de:", 4)) {
irr_write (irr, de, strlen (de));
p +=4;
}
else if (!strncasecmp (p, "*so:", 4)) {
irr_write (irr, so, strlen (so));
p +=4;
}
else if (!strncasecmp (p, "*ch:", 4)) {
irr_write (irr, ch, strlen (ch));
p +=4;
}
else if (!strncasecmp (p, "*mt:", 4)) {
irr_write (irr, mt, strlen (mt));
p +=4;
}
else if (!strncasecmp (p, "*or:", 4)) {
irr_write (irr, or, strlen (or));
p +=4;
}
else if (!strncasecmp (p, "*ai:", 4)) {
irr_write (irr, ai, strlen (ai));
p +=4;
}
else if (!strncasecmp (p, "*ao:", 4)) {
irr_write (irr, ao, strlen (ao));
p +=4;
}
else if (!strncasecmp (p, "*an:", 4)) {
irr_write (irr, an, strlen (an));
p +=4;
}
else if (!strncasecmp (p, "*tc:", 4)) {
irr_write (irr, tc, strlen (tc));
p +=4;
}
else if (!strncasecmp (p, "*ac:", 4)) {
irr_write (irr, ac, strlen (ac));
p +=4;
}
else if (!strncasecmp (p, "*ny:", 4)) {
irr_write (irr, ny, strlen (ny));
p +=4;
}
else if (!strncasecmp (p, "*at:", 4)) {
irr_write (irr, at, strlen (at));
p +=4;
}
else if (!strncasecmp (p, "*dt:", 4)) {
irr_write (irr, dt, strlen (dt));
p +=4;
}
else if (!strncasecmp (p, "*mn:", 4)) {
irr_write (irr, mn, strlen (mn));
p +=4;
}
else if (!strncasecmp (p, "*mb:", 4)) {
irr_write (irr, mb, strlen (mb));
p +=4;
}
else if (!strncasecmp (p, "*av:", 4)) {
irr_write (irr, av, strlen (av));
p +=4;
}
else if (!strncasecmp (p, "*rm:", 4)) {
irr_write (irr, rm, strlen (rm));
p +=4;
}
else if (!strncasecmp (p, "*aa:", 4)) {
irr_write (irr, aa, strlen (aa));
p +=4;
}
else if (!strncasecmp (p, "*gd:", 4)) {
irr_write (irr, gd, strlen (gd));
p +=4;
}
else if (!strncasecmp (p, "*am:", 4)) {
irr_write (irr, am, strlen (am));
p +=4;
}
else if (!strncasecmp (p, "*al:", 4)) {
irr_write (irr, al, strlen (al));
p +=4;
}
else if (!strncasecmp (p, "*pn:", 4)) {
irr_write (irr, pn, strlen (pn));
p +=4;
}
else if (!strncasecmp (p, "*ad:", 4)) {
irr_write (irr, ad, strlen (ad));
p+=4;
}
else if (!strncasecmp (p, "*ph:", 4)) {
irr_write (irr, ph, strlen (ph));
p+=4;
}
else if (!strncasecmp (p, "*fx:", 4)) {
irr_write (irr, fx, strlen (fx));
p+=4;
}
else if (!strncasecmp (p, "*nh:", 4)) {
irr_write (irr, nh, strlen (nh));
p+=4;
}
else if (!strncasecmp (p, "*em:", 4)) {
irr_write (irr, em, strlen (em));
p+=4;
}
else if (!strncasecmp (p, "*df:", 4)) {
irr_write (irr, df, strlen (df));
p+=4;
}
else if (!strncasecmp (p, "*ir:", 4)) {
irr_write (irr, ir, strlen (ir));
p+=4;
}
else if (!strncasecmp (p, "*la:", 4)) {
irr_write (irr, la, strlen (la));
p+=4;
}
else if (!strncasecmp (p, "*if:", 4)) {
irr_write (irr, if2, strlen (if2));
p+=4;
}
else if (!strncasecmp (p, "*pe:", 4)) {
irr_write (irr, pe, strlen (pe));
p+=4;
}
else if (!strncasecmp (p, "*ri:", 4)) {
irr_write (irr, ri, strlen (ri));
p+=4;
}
else if (!strncasecmp (p, "*rx:", 4)) {
irr_write (irr, rx, strlen (rx));
p+=4;
}
else if (!strncasecmp (p, "*cp:", 4)) {
irr_write (irr, cp2, strlen (cp2));
p+=4;
}
else if (!strncasecmp (p, "*ne:", 4)) {
irr_write (irr, ne, strlen (ne));
p+=4;
}
else if (!strncasecmp (p, "*np:", 4)) {
irr_write (irr, np, strlen (np));
p+=4;
}
else if (!strncasecmp (p, "*rc:", 4)) {
irr_write (irr, rc, strlen (rc));
p+=4;
}
else if (!strncasecmp (p, "*rr:", 4)) {
irr_write (irr, rr, strlen (rr));
p+=4;
}
else if (!strncasecmp (p, "*ry:", 4)) {
irr_write (irr, ry, strlen (ry));
p+=4;
}
else if (!strncasecmp (p, "*cs:", 4)) {
irr_write (irr, cs, strlen (cs));
p+=4;
}
else if (!strncasecmp (p, "*cm:", 4)) {
irr_write (irr, cm, strlen (cm));
p+=4;
}
else if (!strncasecmp (p, "*cl:", 4)) {
irr_write (irr, cl, strlen (cl));
p+=4;
}
else if (!strncasecmp (p, "*au:", 4)) {
irr_write (irr, au, strlen (au));
p+=4;
}
else if (!strncasecmp (p, "*wd:", 4)) {
irr_write (irr, wd, strlen (wd));
p+=4;
}
if (q == NULL) { /* flush rest of buffer and exit */
irr_write (irr, p, *cp - p);
break;
}
else
irr_write (irr, p, q - p + 1);
}
}
/* show_connections
* List current RAWhoisd TCP connections to UII
*/
void show_connections (uii_connection_t *uii) {
irr_connection_t *connection;
int i = 1;
uii_add_bulk_output (uii, "Currently %d connection(s) [MAX %d]\r\n\r\n",
IRR.connections, IRR.max_connections);
if (pthread_mutex_lock (&IRR.connections_mutex_lock) != 0)
trace (NORM, default_trace, "Error locking -- connection_mutex_lock--: %s\n",
strerror (errno));
LL_Iterate (IRR.ll_connections, connection) {
uii_add_bulk_output (uii, " %d %s (fd=%d) Age=%d\r\n",
i++, prefix_toa (connection->from),
connection->sockfd,
time (NULL) - connection->start);
}
if (pthread_mutex_unlock (&IRR.connections_mutex_lock) != 0)
trace (NORM, default_trace, "Error locking -- connection_mutex_lock--: %s\n",
strerror (errno));
uii_send_bulk_data (uii);
return;
}
syntax highlighted by Code2HTML, v. 0.9.1