/* $Id: utils.c,v 1.5 2006/03/03 17:27:38 bhockney Exp $ */ /* (C) 2004-2006 by Bob Hockney * * Based on fwlogwatch written by * * Boris Wesslowski * * * * utility routines for wfwl_syslog * * * * This code is distributed under the terms of GNU GPL */ #include #include #include #include #include #include #include #include #include #include #include #include #include "main.h" struct input_file *first_file = NULL; extern struct options opt; extern struct conn_data *first; /* xstrncpy() - similar to strncpy(3) but always terminates string * * with '\0' (if n > 0 and dest != NULL), doesn't do padding. */ char *xstrncpy(char *dest, const char *src, size_t n) { char *r = dest; if((n <= 0) || (dest == NULL)) { return dest; } if(src != NULL) { while ((--n != 0) && (*src != '\0')) { *dest++ = *src++; } } *dest = '\0'; return r; } /* Allocates memory; returns fatal error if allocation error. * * Like malloc, but returns fatal error if unsuccessful */ void *xmalloc(int size) { void *ptr; ptr = malloc(size); if (ptr == NULL) { fprintf(stderr, "\nMemory allocation error, exiting.\n"); exit(EXIT_FAILURE); } return ptr; } /* free report data memory when done */ void free_conn_data() { struct conn_data *this; this = first; while (this != NULL) { first = this; this = this->next; free(first); } first = NULL; } /* set initial values for parsed line */ void init_line() { opt.line->filename[0] = '\0'; opt.line->linenum = 0; opt.line->time = 0; opt.line->hostname[0] = '\0'; opt.line->log_label[0] = '\0'; opt.line->chainlabel[0] = '\0'; opt.line->branchname[0] = '\0'; opt.line->interface[0] = '\0'; opt.line->protocol = 0; opt.line->datalen = 0; opt.line->shost.s_addr = 0; opt.line->shostname[0] = '\0'; opt.line->sport = 0; opt.line->sservice[0] = '\0'; opt.line->dhost.s_addr = 0; opt.line->dhostname[0] = '\0'; opt.line->dport = 0; opt.line->dservice[0] = '\0'; opt.line->flags = 0; opt.line->count = 0; opt.line->raw_mac[0] = '\0'; opt.line->fwmark = 0; opt.line->inif[0] = '\0'; opt.line->outif[0] = '\0'; opt.line->tos = 0; opt.line->ttl = 0; opt.line->ihl = 0; opt.line->csum = 0; opt.line->ipid = 0; opt.line->fragoff = 0; opt.line->tcp_seq = 0; opt.line->tcp_ack_seq = 0; opt.line->tcp_window = 0; opt.line->tcp_urgp = 0; opt.line->udp_len = 0; opt.line->icmp_type = -1; opt.line->icmp_code = -1; opt.line->icmp_echoid = 0; opt.line->icmp_echoseq = 0; opt.line->icmp_gw.s_addr= 0; opt.line->icmp_mtu = 0; opt.line->ahesp_spi = 0; } /* Strip trailing newlines from msg */ /* Postresql does this for error messages */ char * strip_nl(char *msg) { char *nl; nl = strrchr(msg, '\n'); while (nl != NULL) { *nl = '\0'; nl = strrchr(msg, '\n'); } return msg; } /* set opt.line->time = specified time */ void build_time(char *smonth, int day, int hour, int minute, int second) { int month = 0, now, then; struct tm *t; time_t rr_now; rr_now = time(NULL); t = localtime(&rr_now); now = (int)mktime(t); if (strncmp(smonth, "Jan", 3) == 0) { month = 0; } else if (strncmp(smonth, "Feb", 3) == 0) { month = 1; } else if (strncmp(smonth, "Mar", 3) == 0) { month = 2; } else if (strncmp(smonth, "Apr", 3) == 0) { month = 3; } else if (strncmp(smonth, "May", 3) == 0) { month = 4; } else if (strncmp(smonth, "Jun", 3) == 0) { month = 5; } else if (strncmp(smonth, "Jul", 3) == 0) { month = 6; } else if (strncmp(smonth, "Aug", 3) == 0) { month = 7; } else if (strncmp(smonth, "Sep", 3) == 0) { month = 8; } else if (strncmp(smonth, "Oct", 3) == 0) { month = 9; } else if (strncmp(smonth, "Nov", 3) == 0) { month = 10; } else if (strncmp(smonth, "Dec", 3) == 0) { month = 11; } t->tm_mon = month; t->tm_mday = day; t->tm_hour = hour; t->tm_min = minute; t->tm_sec = second; t->tm_isdst = -1; then = (int)mktime(t); if (then > now) --t->tm_year; opt.line->time = mktime(t); } /* returns host name */ char * resolve_hostname(struct in_addr ip) { struct hostent *host; host = gethostbyaddr((void *)&ip.s_addr, sizeof(struct in_addr), AF_INET); if (host != NULL) { return ((char *)host->h_name); } else { return "-"; } } /* returns proto by name */ char * resolve_protocol(int proto) { struct protoent *protoent; protoent = getprotobynumber(proto); if (protoent != NULL) { return (protoent->p_name); } else { char *number; number = xmalloc(4); snprintf(number, 4, "%d", proto); return (number); } } /* returns service name for port and protocol */ char * get_service(unsigned int port, int proto) { struct servent *serv; serv = getservbyport(htons(port), resolve_protocol(proto)); if (serv != NULL) { return (serv->s_name); } else { return "-"; } } /* returns port number for service name and protocol */ long int get_port(char *service, int proto) { struct servent *serv; serv = getservbyname(service, resolve_protocol(proto)); if (serv != NULL) { return ntohs(serv->s_port); } else { return -1; } } /* returns OK if dotted-quad ip address is valid */ unsigned char convert_ip(char *ip, struct in_addr *addr) { #ifdef HAVE_INET_ATON int retval; retval = inet_aton(ip, addr); if (retval == 0) { #else #ifndef INADDR_NONE #define INADDR_NONE -1 #endif addr->s_addr = inet_addr(ip); if (addr->s_addr == INADDR_NONE) { #endif if (opt.verbose >= VERBOSE_INFO) fprintf(stderr, "IP address error: %s\n", ip); return IN_ADDR_ERROR; } return IN_ADDR_OK; } /* ICMP type and code tables to resolve and reverse resolve names. */ /* Lables are those used by ipfilter/ipmon to resolve names to numerical */ /* representations. */ static struct icmp_code icmp_unreach[] = { { 0, "net" }, { 1, "host" }, { 2, "protocol" }, { 3, "port" }, { 4, "needfrag" }, { 5, "srcfail" }, { 6, "net_unknown" }, { 7, "host_unknown" }, { 8, "isolated" }, { 9, "net_prohib" }, {10, "host_prohib" }, {11, "tosnet" }, {12, "toshost" }, {13, "admin_prohibit" } }; static struct icmp_code icmp_redirect[] = { { 0, "net" }, { 1, "host" }, { 2, "tosnet" }, { 3, "toshost" }, }; static struct icmp_code icmp_timeexceed[] = { { 0, "transit" }, { 1, "reassem" } }; static struct icmp_code icmp_parameter[] = { { 0, "errata_pointer" }, { 1, "optmissing" }, { 2, "length" }, }; static struct icmp_type icmp_types[] = { { 0, "echoreply", NULL, 0 }, { 3, "unreach", icmp_unreach, sizeof(icmp_unreach)/sizeof(struct icmp_code) }, { 4, "sourcequench", NULL, 0 }, { 5, "redirect", icmp_redirect, sizeof(icmp_redirect)/sizeof(struct icmp_code) }, { 8, "echo", NULL, 0 }, { 9, "routeradvert", NULL, 0 }, {10, "routersolicit", NULL, 0 }, {11, "timxceed", icmp_timeexceed, sizeof(icmp_timeexceed)/sizeof(struct icmp_code) }, {12, "paramprob", icmp_parameter, sizeof(icmp_parameter)/sizeof(struct icmp_code) }, {13, "timestamp", NULL, 0 }, {14, "timestampreply", NULL, 0 }, {15, "inforeq", NULL, 0 }, {16, "inforeply", NULL, 0 }, {17, "maskreq", NULL, 0 }, {18, "maskreply", NULL, 0 }, }; int numtypes = sizeof(icmp_types)/sizeof(struct icmp_type); int get_icmp_values(char *input) { int i, j; int type = -1, code = -1; char *type_name, *code_name; type_name = xmalloc(SHORTLEN); code_name = xmalloc(SHORTLEN); sscanf(input, "%[a-z0-9]/%[a-z0-9]", type_name, code_name); type = atoi(type_name); if (type == 0 && type_name[0] != '0') type = -1; for (i = 0; i < numtypes; i++) { if (icmp_types[i].name != NULL && (strncmp(type_name, icmp_types[i].name, strlen(icmp_types[i].name)) == 0 || icmp_types[i].type == type)) { type = icmp_types[i].type; code = atoi(code_name); if (icmp_types[i].codes != NULL) { for (j = 0; j < icmp_types[i].numcodes; j++) { if (strcmp(code_name, icmp_types[i].codes[j].name) == 0) { code = icmp_types[i].codes[j].code; break; } } } break; } } if (opt.verbose >= VERBOSE_WARNING) if (type == -1) fprintf(stderr, "Unrecognized Type %s, ignoring\n", type_name); if (opt.verbose >= VERBOSE_DEBUG) fprintf(stderr, "Type %s is %i; Code %s is %i\n", type_name, type, code_name, code); if (type != -1) { if (code == -1) code = 0; opt.line->icmp_type = type; opt.line->icmp_code = code; return PARSE_OK; } else { return PARSE_ERROR; } } /* adds input file to list of files to parse */ void add_input_file(char *name) { struct input_file *file, *ptr; if(!strncmp(name, "-", FILESIZE)) opt.std_in = 1; if (opt.std_in) { opt.filecount = 0; return; } file = xmalloc(sizeof(struct input_file)); file->name = xmalloc(strlen(name)+1); file->next = NULL; xstrncpy(file->name, name, strlen(name)+1); ptr = first_file; if (ptr == NULL) { first_file = file; } else { while (ptr->next != NULL) { ptr = ptr->next; } ptr->next = file; } opt.filecount++; } /* free memory for input files after parsing */ void free_input_file() { struct input_file *file; file = first_file; while (file != NULL) { free(file->name); first_file = file; file = file->next; free(first_file); } first_file = NULL; }