/*
 * esp.{cc,hh} -- element implements IPsec encapsulation (RFC 2406)
 * Alex Snoeren, Benjie Chen
 *
 * Copyright (c) 1999-2000 Massachusetts Institute of Technology
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, subject to the conditions
 * listed in the Click LICENSE file. These conditions include: you must
 * preserve this copyright notice, and you cannot mention the copyright
 * holders in advertising related to the Software without their permission.
 * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
 * notice is a summary of the Click LICENSE file; the license in that file is
 * legally binding.
 */

#include <click/config.h>
#ifndef HAVE_IPSEC
# error "Must #define HAVE_IPSEC in config.h"
#endif
#include "esp.hh"
#include <click/ipaddress.hh>
#include <click/confparse.hh>
#include <clicknet/ip.h>
#include <click/error.hh>
#include <click/glue.hh>
CLICK_DECLS

IPsecESPEncap::IPsecESPEncap()
  : _spi(-1)
{
}

IPsecESPEncap::IPsecESPEncap(int spi)
{
  _spi = spi;
}

IPsecESPEncap::~IPsecESPEncap()
{
}

int
IPsecESPEncap::configure(Vector<String> &conf, ErrorHandler *errh)
{
  unsigned int spi_uc;

  if (cp_va_parse(conf, this, errh,
		  cpUnsigned, "Security Parameter Index", &spi_uc, cpEnd) < 0)
    return -1;
  _spi = spi_uc;
  return 0;
}

int
IPsecESPEncap::initialize(ErrorHandler *errh)
{
  if (_spi < 0)
    return errh->error("not configured");
  _rpl = 0;
  return 0;
}


Packet *
IPsecESPEncap::simple_action(Packet *p)
{
  int i;

  // extract protocol header
  const click_ip *ip = p->ip_header();
  u_char ip_p = ip->ip_p;
  
  // make room for ESP header and padding
  int plen = p->length();
  int padding = ((BLKS - ((plen + 2) % BLKS)) % BLKS) + 2;
  
  WritablePacket *q = p->push(sizeof(esp_new));
  q = q->put(padding);

  struct esp_new *esp = (struct esp_new *) q->data();  
  u_char *pad = ((u_char *) q->data()) + sizeof(esp_new) + plen;

  // copy in ESP header
  esp->esp_spi = htonl(_spi);
  _rpl++;
  int rpl = _rpl;
  esp->esp_rpl = htonl(rpl);
  i = random() >> 2;
  memmove(&esp->esp_iv[0], &i, 4);
  i = random() >> 2;
  memmove(&esp->esp_iv[4], &i, 4);
  memmove(q->data(), esp, sizeof(struct esp_new));

  // default padding specified by RFC 2406
  for (i = 0; i < padding - 2; i++)
    pad[i] = i + 1;
  pad[padding - 2] = padding - 2;
  
  // next header = ip protocol number
  pad[padding - 1] = ip_p;

  return(q);
}

CLICK_ENDDECLS
EXPORT_ELEMENT(IPsecESPEncap)
ELEMENT_MT_SAFE(IPsecESPEncap)


syntax highlighted by Code2HTML, v. 0.9.1