/*-
 * 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.
 */
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <err.h>

#ifndef lint
static const char rcsid[] =
        "@(#) $Header: /usr/cvs/ipex/bstream.c,v 1.6 2005/03/02 04:27:09 modulus Exp $";
#endif
#if (!defined(MAX))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif

struct bin {
	u_char *b_pattern;
	u_long b_len;
	struct bin *b_next;
};
static struct bin *header = NULL;

void 
strip(char *from, char *to, int max)
{
	int counter = 0;

	while (*from) {
		if (counter >= max)
			break;
		if (*from != ' ')
			*to++ = *from++;
		else
			from++;
		counter++;
	}
	*to = '\0';
}

unsigned char 
hex2binary(char *digits)
{
	unsigned char result = 0;
   
	if (!isxdigit(digits[0]) || !isxdigit(digits[1]))
		errx(1, "string non hex characters at `%s'", digits);
	result = ((digits[0] >= 'A' && digits[0] <= 'F') ? 
	    (digits[0] & 7) + 9 : digits[0] - '0') << 4;
	result += (digits[1] >= 'A' && digits[1] <= 'F') ? 
	    (digits[1] & 7) + 9 : digits[1] - '0';
	return (result);
}

char *
upcase(char *str)
{
	char *ptr, *hptr;

	ptr = malloc(strlen(str)+1);
	hptr = ptr;
	while (*str != '\0')
		*ptr++ = toupper(*str++);
	*ptr = '\0';
	return (hptr);
}

int
ln_pattern(char *hexspec)
{
	struct bin *b;
	int I, L, L2;

	L = strlen(hexspec);
	I = 0;
	strip(hexspec, hexspec, L);
	hexspec = upcase(hexspec);
	L = strlen(hexspec);
	if (L % 2 != 0)
		errx(1,
		    "padding required. I.E. '02' instead of '2' for octet value.");
	L2 = L / 2;
	if ((b = malloc(sizeof(*b))) == 0)
		errx(1, "malloc failed.");
	b->b_next = header;
	b->b_len = L2;
	b->b_pattern = malloc(b->b_len);
	memset(b->b_pattern, 0, b->b_len);
	header = b;
	while (*hexspec) {
		b->b_pattern[I] = hex2binary(hexspec);
		hexspec += 2;
		I++;
	}
	return (0);
}

static int
bmatch(u_char *pld, size_t pldlen, u_char *pt, size_t ptlen)
{
	int i;
	short match;

	match = 0;
	for (i = 0; i < pldlen; i++)
		if (pld[i] == *pt)
			if (memcmp(pld + i, pt, ptlen) == 0) {
				match = 1;
				break;
			}
	return (match ? 0 : -1);
}

int
detectpattern(u_char *p, size_t len)
{
	struct bin *b;
	int match;

	for (b = header; b != '\0'; b = b->b_next) {
		match = bmatch(p, len, b->b_pattern, b->b_len);
		if (match == 0)
			return (1);
	}
	return (0);
}


syntax highlighted by Code2HTML, v. 0.9.1