/*-
* Copyright (c) 2001-2005 Christian S.J. Peron
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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.
*/
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /usr/cvs/ipex/util.c,v 1.21 2005/04/24 22:13:43 modulus Exp $";
#endif
#include "ipex_includes.h"
/*
* time_stamp() returns a pointer to
* a null terminated string. This
* string contains a timestamp of
* arbitary precision. (nice precision too ;))
*/
char *
time_stamp(const struct timeval *tvp, int32_t zone)
{
static char buf[32];
struct tm *tm;
char date[12];
int s;
tm = localtime((time_t *)&tvp->tv_sec);
strftime(date, sizeof(date), "%Y-%m-%d", tm);
s = (tvp->tv_sec + zone) % 86400;
snprintf(buf, sizeof(buf),
"%s %02d:%02d:%02d.%06u", date,
(s / 3600), ((s % 3600) / 60),
(s % 60), ((u_int32_t)tvp->tv_usec));
return (buf);
}
/*
* this gmt2local() was taken from the
* tcpdump(1) source code. thanks.
*/
int32_t
gmt2local(time_t t)
{
struct tm *gmt, *loc, sgmt;
int dt, dir;
if (t == 0)
t = time(0);
gmt = &sgmt;
*gmt = *gmtime(&t);
loc = localtime(&t);
dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 +
(loc->tm_min - gmt->tm_min) *60;
dir = loc->tm_year - gmt->tm_year;
if (dir == 0)
dir = loc->tm_yday - gmt->tm_yday;
dt += dir * 24 * 60 * 60;
return (dt);
}
/*
* text_dump() is the function wich is responsible
* for dumping the packet's contents in
* human readable form (where available).
* it was borrowed from ngrep(1). again. thanks.
*/
void
text_dump(char *data, int len, struct offset *off)
{
int pos;
if (len > 0) {
unsigned width = 70;
char c, *str = data;
int j, i = 0;
while (i < len) {
putchar(' ');
for(j = 0; j < width; j++) {
pos = i + j;
if (pos == off->base && opts.Eflag)
printf("\033[7m");
if (pos == (off->base + off->len) &&
opts.Eflag)
printf("\033[m");
if (pos < len) {
c = isprint(str[j]) ?
str[j] : ' ';
putchar(c);
} else
putchar(' ');
}
str += width;
i += j;
putchar('\n');
}
}
}
/*
* this function returns a pointer to a null terminated string.
* for the use of grep()'ing & dumping matched packets.
*/
void
rettext(char *buffer, int len)
{
int i;
for(i = 0; i < len; i++)
if (!isprint(buffer[i]))
buffer[i] = ' ';
}
int
grep(char *pattern, char *buf, struct offset *off)
{
static regex_t *rp, rd;
int match, flags, err;
const int nmatch = 1;
regmatch_t pmatch[1];
if (rp == NULL) {
flags = REG_EXTENDED | REG_ICASE;
if ((err = regcomp(&rd, pattern, flags)) != 0)
errx(1, "regular expression error");
rp = &rd;
}
match = regexec(rp, buf, nmatch, &pmatch[0], 0);
if (match == REG_NOMATCH)
return (0);
if (match != 0) {
warnx("regexec failed");
return (0);
}
off->base = (u_long)pmatch[0].rm_so;
off->len = (u_long)pmatch[0].rm_eo - (u_long)pmatch[0].rm_so;
return (1);
}
int
strtolower(string)
char *string;
{
char *c;
for (c = string; *c; c++)
if (!(*c = tolower (*c)))
return (0);
return (1);
}
int
strisdigit(string)
char *string;
{
while (*string) {
if (!isdigit(*string))
return (1);
string++;
}
return (0);
}
#define IGNORE 0x1
#define SPACE ' '
#if (!defined(IS_IGNORING))
#define IS_IGNORING(a) ((a & IGNORE) ? (1) : (0))
#endif
/*
* this function will return a null terminated
* string to the contents located in the file
* suppied by -f on the command line.
* we will however parse out any comments that
* may have been used in the file. Example
* of legal comments:
*
* this is a body of text ; this is ignored.
* this is also a body of text # this is ignored.
* standard C and C++ comments are also supported.
*/
void
logic_load(char *p, FILE *fp)
{
int flag = 0;
char nwchar, nwchar_temp, *op;
op = p;
while ((nwchar = getc(fp)) != EOF) {
switch(nwchar) {
case '#':
case ';':
flag |= IGNORE;
break;
case '/':
nwchar_temp = getc(fp);
if (nwchar_temp == '*') {
while ((nwchar = getc(fp)) != EOF &&
nwchar_temp == '*') {
if (nwchar == '*') {
nwchar = getc(fp);
if (nwchar == '/')
nwchar_temp = '0';
}
}
} else if (nwchar_temp != '/') {
*p = nwchar;
p++;
ungetc(nwchar_temp, fp);
} else if (nwchar_temp == '/')
flag |= IGNORE;
break;
case '\r':
break;
case '\n':
if (IS_IGNORING(flag)) {
flag &= ~IGNORE;
break;
}
*p = SPACE;
p++;
break;
default:
if (IS_IGNORING(flag))
break;
*p = nwchar;
p++;
break;
}
}
*p = 0;
}
void
prescan_pcap_expr(char *expr)
{
const char charset[]=
"1234567890abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
while (*expr) {
if (strchr(charset, *expr))
return;
expr++;
}
fprintf(stderr,"\n>> WARNING: NULL expr compiled: capturing ALL packets. <<\n\n");
}
char *
retrive_pcap_expr(char **argv)
{
char *p;
static char pcap_expr[1000];
if (*argv == NULL)
return (*argv);
while ((p = *argv++)) {
/* XXX size bug here */
strncat(pcap_expr, p, sizeof(pcap_expr));
strncat(pcap_expr, " ", 0x1);
}
return (pcap_expr);
}
/* XXX change out ns cache mechanism to use a radix tree
* instead of a home rolled tail queue.
*/
/*
* return a pointer to a null terminated string.
* this string will be in xxx.xxx.xxx.xxx or
* hostname form depending on the value of ``res''
*/
char *
hostname(int v, u_32_t *ip)
{
#define MAX_INETA 16
struct in_addr ipa;
char *ptr;
if (v == 4) {
ipa.s_addr = *ip;
if (opts.nflag)
ptr = inet_ntoa(ipa);
else
ptr = cache_ns_entry(ip);
return (ptr);
}
return ("ip6");
}
/*
* specify soft limit for cache
*/
#if (!defined(MAX_NS_CACHE))
#define MAX_NS_CACHE 524288 /* 1/2 Mb */
#endif
struct ns_entry {
char alpha_host[MAXHOSTNAMELEN + MAX_INETA + 3];
u_long ip_addr;
struct ns_entry *next;
struct ns_entry *prev;
};
static struct ns_entry *NsHead;
static struct ns_entry *NsTail;
static unsigned long cached_nodes;
char *
cache_ns_entry(u_32_t *ip)
{
struct ns_entry *new = NULL;
struct hostent *hp;
struct in_addr ipa;
if (cached_nodes * sizeof(struct ns_entry) > MAX_NS_CACHE)
return (inet_ntoa(ipa));
ipa.s_addr = *ip;
for(new = NsHead; new != NULL; new = new->next)
if (ipa.s_addr == new->ip_addr)
return (new->alpha_host);
new = NULL;
new = memalloc(sizeof(struct ns_entry));
if (new == NULL) {
fprintf(stderr,"fatal: exhausted memory.\n");
exit(1);
}
hp = gethostbyaddr((char *)ip, sizeof(ip), AF_INET);
if (!hp) {
new->ip_addr = ipa.s_addr;
strcpy(new->alpha_host, inet_ntoa(ipa));
goto arrange;
}
new->ip_addr = ipa.s_addr;
strcpy(new->alpha_host, hp->h_name);
arrange:
if (NsHead == NULL) {
NsHead = new;
new->prev = NULL;
} else {
NsTail->next = new;
new->prev = NsTail;
}
NsTail = new;
new->next = NULL;
cached_nodes++;
return (hp ? hp->h_name : new->alpha_host);
}
void
flush_ns_cache(void)
{
struct ns_entry *node;
struct ns_entry *next_node;
for (node = NsHead; node != NULL; node = next_node) {
next_node = node->next;
if (node->prev == NULL)
NsHead = node->next;
else
node->prev->next = node->next;
if (node->next == NULL)
NsTail = node->prev;
else
node->next->prev = node->prev;
free(node);
}
}
void *
memalloc(unsigned int n)
{
void *ret;
if (!(ret = malloc(n)))
errx(EX_UNAVAILABLE, "memory exhausted (failed to allocate" \
" %u bytes).", n);
else
return (ret);
}
void *
memrealloc(void *ptr, unsigned int n)
{
void *ret;
if (!(ret = realloc(ptr, n)))
errx(EX_UNAVAILABLE, "memory exhausted (failed to reallocate" \
" %u bytes).", n);
else
return (ret);
}
syntax highlighted by Code2HTML, v. 0.9.1