/* $Cambridge: hermes/src/prayer/accountd/ipaddr.c,v 1.1.1.1 2003/04/15 13:00:02 dpc22 Exp $ */
/************************************************
 *    Prayer - a Webmail Interface              *
 ************************************************/

/* Copyright (c) University of Cambridge 2000 - 2002 */
/* See the file NOTICE for conditions of use and distribution. */

#include "accountd.h"

/* Class for recording and comparing IP addresses. At the moment IPv4
 * only. Shouldn't be to hard to expand to IPv6 as well I hope */

/* ipaddr_create() *******************************************************
 *
 * Create a fresh ipaddr structure.
 ************************************************************************/

struct ipaddr *ipaddr_create(struct pool *pool)
{
    struct ipaddr *result = pool_alloc(pool, sizeof(struct ipaddr));

    return (result);
}

/* ipaddr_copy() *********************************************************
 *
 * Copy ip address.
 *     dst: Target
 *     src: Source
 ************************************************************************/

BOOL ipaddr_copy(struct ipaddr * dst, struct ipaddr * src)
{
    dst->version = src->version;
    dst->addr[0] = src->addr[0];
    dst->addr[1] = src->addr[1];
    dst->addr[2] = src->addr[2];
    dst->addr[3] = src->addr[3];

    return (T);
}

/* ipaddr_compare() ******************************************************
 *
 * Compare two ipaddr structures
 *    addr1: First ipaddr
 *    addr2: Second ipaddr
 *
 * Returns: T if ipaddrs match
 ************************************************************************/

BOOL ipaddr_compare(struct ipaddr * addr1, struct ipaddr * addr2)
{
    if (addr1->version != addr2->version)
        return (NIL);

    if (addr1->addr[0] != addr2->addr[0])
        return (NIL);

    if (addr1->addr[1] != addr2->addr[1])
        return (NIL);

    if (addr1->addr[2] != addr2->addr[2])
        return (NIL);

    if (addr1->addr[3] != addr2->addr[3])
        return (NIL);

    return (T);
}

/* ====================================================================== */

/* ipaddr_text() *********************************************************
 *
 * Convert ipaddr to text representation using static buffer
 ************************************************************************/

char *ipaddr_text(struct ipaddr *addr)
{
    static char buf[64];

    sprintf(buf, "%d.%d.%d.%d",
            addr->addr[0], addr->addr[1], addr->addr[2], addr->addr[3]);

    return (buf);
}

/* ====================================================================== */

/* ipaddr_parse() ********************************************************
 *
 * Parse text representation of IP address
 *     addr: Target ipaddr
 *     text: Text to parse
 *
 * Returns: T if text parsed as correct IP address.
 ************************************************************************/

BOOL ipaddr_parse(struct ipaddr * addr, char *text)
{
    char *next;

    if (text == NIL)
        return (NIL);

    /* IPv4 only for the moment */
    addr->version = 4;

    /* Parse first number */
    if (!(next = strchr(text, '.')))
        return (NIL);
    addr->addr[0] = atoi(text);
    text = next + 1;

    /* Parse second number */
    if (!(next = strchr(text, '.')))
        return (NIL);
    addr->addr[1] = atoi(text);
    text = next + 1;

    /* Parse third number */
    if (!(next = strchr(text, '.')))
        return (NIL);
    addr->addr[2] = atoi(text);
    text = next + 1;

    /* Parse forth number */
    if ((next = strchr(text, '.')))
        return (NIL);
    addr->addr[3] = atoi(text);

    /* Looks good */
    return (T);
}

/* ====================================================================== */

/* ipaddr_send_iostream() ************************************************
 *
 * Send contents an raw ip address into iostream
 *    addr: Address to send
 *  stream: Target stream
 ************************************************************************/

void ipaddr_send_iostream(struct ipaddr *addr, struct iostream *stream)
{
    ioputc(addr->version, stream);
    ioputc(addr->addr[0], stream);
    ioputc(addr->addr[1], stream);
    ioputc(addr->addr[2], stream);
    ioputc(addr->addr[3], stream);
}

/* ====================================================================== */

/* ipaddr_fetch_iostream() ***********************************************
 *
 * Parse raw ipaddr from iostream.
 ************************************************************************/

BOOL ipaddr_fetch_iostream(struct ipaddr *addr, struct iostream *stream)
{
    BOOL rc = T;
    int i, c;

    if ((c = iogetc(stream)) != EOF) {
        addr->version = (unsigned char) c;
        for (i = 0; i < 4; i++) {
            if ((c = iogetc(stream)) == EOF) {
                rc = NIL;
                break;
            }

            addr->addr[i] = (unsigned char) c;
        }
    }

    if (c == EOF) {
        log_panic
            ("Unexpected disconnect receiving IP address from frontend");
        rc = NIL;
    }

    return (rc);
}

/* ====================================================================== */

/* ipaddr_set() **********************************************************
 *
 * Set IP address in ipaddr structure
 *    ipaddr: Target ipaddr structure
 *    ipvers: IP version
 *      addr: Address string
 ************************************************************************/

void
ipaddr_set(struct ipaddr *ipaddr,
           unsigned long version, unsigned char *addr)
{
    if (version != 4)
        log_fatal("ipaddr_set(): IPv4 only supported at the moment!");

    ipaddr->version = 4;
    memcpy(ipaddr->addr, addr, 4);
}


syntax highlighted by Code2HTML, v. 0.9.1