/* ipaddr.c */

/* Copyright 1997-1999 by Eberhard Mattes <em-gw@windhager.de>
   Donated to the public domain.  No warranty.

   1997-10-21 Initial version */

#include <stdlib.h>
#include <string.h>
#include "libemfw.h"

/* Parse the string pointed to by SRC as IP address.  Store the 4
   octets of the IP address to the array pointed to by DST (most
   significant octet first).  Store a mask of significant bits of the
   IP address (0=ignore, 1=significant) to the array pointed to by
   MASK.  Wildcards are accepted if FLAGS includes IAP_WILDCARD ("*"
   matches any octet).  Return 0 on success, -1 on failure. */

#define OCTETS	4

int ipaddr_parsen (const octet *src, size_t len, octet *dst, octet *mask,
		   unsigned flags)
{
  int i;

  const octet *end = src + len;
  for (i = 0; i < OCTETS; ++i)
    {
      if (src == end)
	return -1;
      if (*src == '*' && (flags & IAP_WILDCARD))
	{
	  dst[i] = 0;		/* Doesn't matter */
	  mask[i] = 0;		/* Ignore all bits of this octet */
	  ++src;
	}
      else if (*src >= '0' && *src <= '9')
	{
	  unsigned x = 0;
	  while (src != end && *src >= '0' && *src <= '9')
	    {
	      x = x * 10 + *src++ - '0';
	      if (x > 255)
		return -1;
	    }
	  dst[i] = (octet)x;
	  mask[i] = 0xff;	/* All bits of this octet are significant */
	}
      else
	return -1;		/* Syntax error */
      if (i != OCTETS - 1 && (src == end || *src++ != '.'))
	return -1;
    }
  if (src != end)
    return -1;
  return 0;
}

/* Ditto, for null-terminated string. */

int ipaddr_parsez (const octet *src, octet *dst, octet *mask,
		   unsigned flags)
{
  return ipaddr_parsen (src, strlen ((const char*) src), dst, mask, flags);
}

/* Compare two IP addresses parsed by ipaddr_parse().  PAT points to
   the 4 octets of the pattern, MASK points to the mask of significant
   bits, and VAL points to the 4 octets of the value to be tested.
   Return 0 if VAL matches PAT under MASK, return 1 otherwise. */

int ipaddr_compare (const octet *pat, const octet *mask, const octet *val)
{
  int i;

  for (i = 0; i < OCTETS; ++i)
    if ((pat[i] ^ val[i]) & mask[i])
      return 1;
  return 0;
}
