/* * $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 #include #include "mrt.h" #include "select.h" #include "trace.h" #include #include #include #ifndef NT #include #include #include #include #endif /* NT */ #include #include "config_file.h" #include #include "irrd.h" #include #ifndef NT #ifndef SETPGRP_VOID #include #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; }