/* * The IKE Scanner (ike-scan) is Copyright (C) 2003-2007 Roy Hills, * NTA Monitor Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library, and distribute linked combinations including the two. * * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. If you * do not wish to do so, delete this exception statement from your * version. * * If this license is unacceptable to you, I may be willing to negotiate * alternative licenses (contact ike-scan@nta-monitor.com). * * You are encouraged to send comments, improvements or suggestions to * me at ike-scan@nta-monitor.com. * * $Id: utils.c 9884 2007-01-14 19:05:39Z rsh $ * * Author: Roy Hills * Date: 5 April 2004 * * This file contains various utility functions used by ike-scan. * * These functions were originally in ike-scan.c, but were moved to utils.c * because ike-scan.c was getting rather large. */ #include "ike-scan.h" static char rcsid[] = "$Id: utils.c 9884 2007-01-14 19:05:39Z rsh $"; /* RCS ID for ident(1) */ /* * timeval_diff -- Calculates the difference between two timevals * and returns this difference in a third timeval. * * Inputs: * * a = First timeval * b = Second timeval * diff = Difference between timevals (a - b). * * Returns: * * None. */ void timeval_diff(const struct timeval *a, const struct timeval *b, struct timeval *diff) { struct timeval temp; temp.tv_sec = b->tv_sec; temp.tv_usec = b->tv_usec; /* Perform the carry for the later subtraction by updating b. */ if (a->tv_usec < temp.tv_usec) { int nsec = (temp.tv_usec - a->tv_usec) / 1000000 + 1; temp.tv_usec -= 1000000 * nsec; temp.tv_sec += nsec; } if (a->tv_usec - temp.tv_usec > 1000000) { int nsec = (a->tv_usec - temp.tv_usec) / 1000000; temp.tv_usec += 1000000 * nsec; temp.tv_sec -= nsec; } /* Compute the time difference tv_usec is certainly positive. */ diff->tv_sec = a->tv_sec - temp.tv_sec; diff->tv_usec = a->tv_usec - temp.tv_usec; } /* * times_close_enough -- Check if two times are less than fuzz ms apart * * Inputs: * * t1 First time value * t2 Second time value * fuzz Fuzz value * * Returns: * * 1 if t1 and t2 are within fuzz ms of each other. Otherwise 0. */ int times_close_enough(struct timeval *t1, struct timeval *t2, unsigned fuzz) { struct timeval diff; int diff_ms; timeval_diff(t1, t2, &diff); /* diff = t1 - t2 */ diff_ms = abs(1000*diff.tv_sec + diff.tv_usec/1000); if (diff_ms <= fuzz) { return 1; } else { return 0; } } /* * hstr_i -- Convert two-digit hex string to unsigned integer * * Inputs: * * cptr Two-digit hex string * * Returns: * * Number corresponding to input hex value. * * An input of "0A" or "0a" would return 10. * Note that this function does no sanity checking, it's up to the * caller to ensure that *cptr points to at least two hex digits. * * This function is a modified version of hstr_i at www.snippets.org. */ unsigned int hstr_i(const char *cptr) { unsigned int i; unsigned int j = 0; int k; for (k=0; k<2; k++) { i = *cptr++ - '0'; if (9 < i) i -= 7; j <<= 4; j |= (i & 0x0f); } return j; } /* * hex2data -- Convert hex string to binary data * * Inputs: * * string The string to convert * data_len (output) The length of the resultant binary data * * Returns: * * Pointer to the binary data. * * The returned pointer points to malloc'ed storage which should be * free'ed by the caller when it's no longer needed. If the length of * the input string is not even, the function will return NULL and * set data_len to 0. */ unsigned char * hex2data(const char *string, size_t *data_len) { unsigned char *data; unsigned char *cp; unsigned i; size_t len; if (strlen(string) %2 ) { /* Length is odd */ *data_len = 0; return NULL; } len = strlen(string) / 2; data = Malloc(len); cp = data; for (i=0; i Input is in hex format * string Input is in string format * * The returned pointer points to malloc'ed storage which should be * free'ed by the caller when it's no longer needed. If the length of * the inputs string is not even, the function will return NULL and * set data_len to 0. */ unsigned char * hex_or_str(const char *string, size_t *data_len) { if (strlen(string) < 1) { /* Input string too short */ *data_len = 0; return NULL; } if (string[0] == '0' && string[1] == 'x') { /* Hex input format */ return hex2data((string+2), data_len); } else { /* Assume string input format */ unsigned char *data; size_t len; len = strlen(string); data = Malloc(len); memcpy(data, string, len); *data_len = len; return data; } } /* * hex_or_num -- Convert hex or number to binary data * * Inputs: * * string The hex or string to convert * data_len (output) The length of the resultant binary data * * Returns: * * Pointer to the binary data, or NULL if an error occurred. * * The input string must be in one of the following two formats: * * 0x Input is in hex format * decimal number Input is in numeric format * * For numeric input, the binary data will be a 32-bit value in * big endian format. * * The returned pointer points to malloc'ed storage which should be * free'ed by the caller when it's no longer needed. If the length of * the inputs string is not even, the function will return NULL and * set data_len to 0. */ unsigned char * hex_or_num(const char *string, size_t *data_len) { if (strlen(string) < 1) { /* Input string too short */ *data_len = 0; return NULL; } if (string[0] == '0' && string[1] == 'x') { /* Hex input format */ return hex2data((string+2), data_len); } else { /* Assume number input format */ unsigned char *data; size_t len = 4; /* 32-bit value */ unsigned long value; unsigned long value_be; value = Strtoul(string, 10); value_be = htonl(value); data = Malloc(len); memcpy(data, &value_be, len); *data_len = len; return data; } } /* * make_message -- allocate a sufficiently large string and print into it. * * Inputs: * * Format and variable number of arguments. * * Outputs: * * Pointer to the string, * * The code for this function is from the Debian Linux "woody" sprintf man * page. Modified slightly to use wrapper functions for malloc and realloc. */ char * make_message(const char *fmt, ...) { int n; /* Guess we need no more than 100 bytes. */ size_t size = 100; char *p; va_list ap; p = Malloc (size); while (1) { /* Try to print in the allocated space. */ va_start(ap, fmt); n = vsnprintf (p, size, fmt, ap); va_end(ap); /* If that worked, return the string. */ if (n > -1 && n < size) return p; /* Else try again with more space. */ if (n > -1) /* glibc 2.1 */ size = n+1; /* precisely what is needed */ else /* glibc 2.0 */ size *= 2; /* twice the old size */ p = Realloc (p, size); } } /* * numstr -- Convert an unsigned integer to a string * * Inputs: * * num The number to convert * * Returns: * * Pointer to the string representation of the number. * * I'm surprised that there is not a standard library function to do this. */ char * numstr(unsigned num) { static char buf[21]; /* Large enough for biggest 64-bit integer */ snprintf(buf, sizeof(buf), "%d", num); return buf; } /* * printable -- Convert string to printable form using C-style escapes * * Inputs: * * string Pointer to input string. * size Size of input string. 0 means that string is null-terminated. * * Returns: * * Pointer to the printable string. * * Any non-printable characters are replaced by C-Style escapes, e.g. * "\n" for newline. As a result, the returned string may be longer than * the one supplied. * * This function makes two passes through the input string: one to * determine the required output length, then a second to perform the * conversion. * * The pointer returned points to malloc'ed storage which should be * free'ed by the caller when it's no longer needed. */ char * printable(const unsigned char *string, size_t size) { char *result; char *r; const unsigned char *cp; size_t outlen; unsigned i; /* * If the input string is NULL, return an empty string. */ if (string == NULL) { result = Malloc(1); result[0] = '\0'; return result; } /* * Determine required size of output string. */ if (!size) size = strlen((const char *) string); outlen = size; cp = string; for (i=0; i 1) { sum += *ptr++; nbytes -= 2; } /* mop up an odd byte, if necessary */ if (nbytes == 1) { oddbyte = 0; /* make sure top half is zero */ *((u_char *) &oddbyte) = *(u_char *)ptr; /* one byte only */ sum += oddbyte; } /* * Add back carry outs from top 16 bits to low 16 bits. */ sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* ones-complement, then truncate to 16 bits */ return(answer); } /* * random_byte -- Return a random byte in range 0..255 * * Inputs: None * * Returns: The random byte */ uint8_t random_byte(void) { static union { uint32_t longword; uint8_t byte[4]; } random_data; static int num_bytes = 0; /* Number of bytes available */ if (num_bytes == 0) { uint32_t random_value; random_value = genrand_int32(); random_data.longword = htonl(random_value); num_bytes = 4; } return random_data.byte[--num_bytes]; } /* * random_ip -- Return a random IP address * * Imputs: None * Returns: A random IP address * * This returns a random IP address as a 32-bit value in host byte * order. * * It will not return the following IP address ranges, because they * are invalid: * * 0/8, 1/8 or 2/8 - IANA reserved * 127/8 - Localhost * Class D (Multicast) * Class E (Reserved) */ uint32_t random_ip(void) { uint32_t random_value; int acceptable; do { random_value = genrand_int32(); if ((random_value & 0xff000000) == 0x7f000000 || /* 127.x.x.x */ random_value > 0xefffffff || /* Class D or E */ random_value < 0x03000000) { /* 0/8, 1/8 or 2/8 */ acceptable = 0; } else { acceptable = 1; } } while (!acceptable); return random_value; } /* * str_ccmp -- Case-blind string comparison * * Inputs: * * s1 -- The first input string * s2 -- The second input string * * Returns: * * An integer indicating whether s1 is less than (-1), the same as (0), * or greater than (1) s2. * * This function performs the same function, and takes the same arguments * as the common library function strcasecmp. This function is used * instead because strcasecmp is not portable. */ int str_ccmp( const char *s1, const char *s2 ) { int c1, c2; for( ; ; s1++, s2++ ){ c1 = tolower( (unsigned char) *s1 ); c2 = tolower( (unsigned char) *s2 ); if( c1 > c2 ) return 1; if( c1 < c2 ) return -1; if( c1 == 0 && c2 == 0 ) return 0; } } /* * name_or_number -- Calculate the numeric value of a string containing * either a name from a map, or a number. * * Inputs: * * string The input string * map The ID/name map */ unsigned name_or_number(const char *string, const id_name_map map[]) { int result; char *endptr; result=strtoul(string, &endptr, 0); if (endptr != string) /* Successful conversion */ return result; result=name_to_id(string, map); if (result == -1) err_msg("Invalid value: %s", string); return result; } void utils_use_rcsid(void) { fprintf(stderr, "%s\n", rcsid); /* Use rcsid to stop compiler optimising away */ }