/*
  
  sshinetencode.c       

  Author:
        Santeri Paavolainen <santtu@ssh.fi>

  Copyright:
        Copyright (c) 1999 SSH Communications Security, Finland
        All rights reserved

*/

#include "sshincludes.h"
#include "sshencode.h"
#include "sshinetencode.h"

size_t ssh_encode_ipaddr_array (unsigned char * buf, size_t bufsize, const SshIpAddr * ip)
{
  size_t got;

  if ((got = ssh_encode_array(buf, bufsize,
                              SSH_FORMAT_CHAR, ip->type,
                              SSH_FORMAT_UINT32, ip->mask_len,
                              SSH_FORMAT_DATA, ip->addr_data, SSH_IP_ADDR_LEN(ip),
                              SSH_FORMAT_END)) !=
      (1 + 4 + SSH_IP_ADDR_LEN(ip)))
    return 0;

  return got;
}

size_t ssh_encode_ipaddr_array_alloc (unsigned char ** buf_return, const SshIpAddr * ip)
{
  size_t req, got;

  req = 1 + 4 + SSH_IP_ADDR_LEN(ip);

  if (buf_return == NULL)
    return req;

  *buf_return = ssh_xmalloc(req);

  if ((got = ssh_encode_array(*buf_return, req,
                              SSH_FORMAT_CHAR, ip->type,
                              SSH_FORMAT_UINT32, ip->mask_len,
                              SSH_FORMAT_DATA, ip->addr_data, SSH_IP_ADDR_LEN(ip),
                              SSH_FORMAT_END)) != req) {
    ssh_xfree(*buf_return);
    *buf_return = NULL;
    return 0;
  }

  return got;
}

size_t ssh_decode_ipaddr_array (const unsigned char * buf,
                                size_t len,
                                SshIpAddr * ip)
{
  size_t        point, got;

  point = 0;

  if ((got = ssh_decode_array(buf + point, len - point,
                              SSH_FORMAT_CHAR, &ip->type,
                              SSH_FORMAT_UINT32, &ip->mask_len,
                              SSH_FORMAT_END)) != 5)
      return 0;

  point += got;

  if ((got = ssh_decode_array(buf + point, len - point,
                              SSH_FORMAT_DATA, ip->addr_data, SSH_IP_ADDR_LEN(ip),
                              SSH_FORMAT_END)) != SSH_IP_ADDR_LEN(ip))
      return 0;

  point += got;

  /* Sanity check */
  if (!SSH_IP_IS4(ip) && !SSH_IP_IS6(ip))
    return 0;

  return point;
}

#ifndef _KERNEL
size_t ssh_encode_ipaddr_buffer (SshBuffer * buffer, const SshIpAddr * ip)
{
  size_t got;
  unsigned char tmpbuf[1 + 4 + 16];

  if ((got = ssh_encode_ipaddr_array(tmpbuf, sizeof(tmpbuf), ip)) == 0)
      return FALSE;

  ssh_buffer_append(buffer, tmpbuf, got);

  return TRUE;
}

size_t ssh_ipaddr_decode_buffer (SshBuffer * buffer, SshIpAddr * ip)
{
  size_t got;

  if ((got = ssh_decode_ipaddr_array(ssh_buffer_ptr(buffer), 
                                     ssh_buffer_len(buffer),
                                     ip)) == 0)
    return 0;

  ssh_buffer_consume(buffer, got);

  return got;
}
#endif
