/*
 *  GRUB  --  GRand Unified Bootloader
 *  Copyright (C) 2010,2011  Free Software Foundation, Inc.
 *
 *  GRUB is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  GRUB is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/env.h>
#include <grub/net/ethernet.h>
#include <grub/net/ip.h>
#include <grub/net/arp.h>
#include <grub/net/netbuff.h>
#include <grub/net.h>
#include <grub/time.h>
#include <grub/net/arp.h>

#define LLCADDRMASK 0x7f

struct etherhdr
{
  grub_uint8_t dst[6];
  grub_uint8_t src[6];
  grub_uint16_t type;
} GRUB_PACKED;

struct llchdr
{
  grub_uint8_t dsap;
  grub_uint8_t ssap;
  grub_uint8_t ctrl;
} GRUB_PACKED;

struct snaphdr
{
  grub_uint8_t oui[3]; 
  grub_uint16_t type;
} GRUB_PACKED;

grub_err_t
send_ethernet_packet (struct grub_net_network_level_interface *inf,
		      struct grub_net_buff *nb,
		      grub_net_link_level_address_t target_addr,
		      grub_net_ethertype_t ethertype)
{
  struct etherhdr *eth;
  grub_err_t err;
  grub_uint8_t etherhdr_size;
  grub_uint16_t vlantag_id = VLANTAG_IDENTIFIER;

  etherhdr_size = sizeof (*eth);
  COMPILE_TIME_ASSERT (sizeof (*eth) + 4 < GRUB_NET_MAX_LINK_HEADER_SIZE);

  /* Increase ethernet header in case of vlantag */
  if (inf->vlantag != 0)
    etherhdr_size += 4;

  err = grub_netbuff_push (nb, etherhdr_size);
  if (err)
    return err;
  eth = (struct etherhdr *) nb->data;
  grub_memcpy (eth->dst, target_addr.mac, 6);
  grub_memcpy (eth->src, inf->hwaddress.mac, 6);

  eth->type = grub_cpu_to_be16 (ethertype);
  if (!inf->card->opened)
    {
      err = GRUB_ERR_NONE;
      if (inf->card->driver->open)
	err = inf->card->driver->open (inf->card);
      if (err)
	return err;
      inf->card->opened = 1;
    }

  /* Check and add a vlan-tag if needed. */
  if (inf->vlantag != 0)
    {
      /* Move eth type to the right */
      grub_memcpy ((char *) nb->data + etherhdr_size - 2,
                   (char *) nb->data + etherhdr_size - 6, 2);

      /* Add the tag in the middle */
      grub_memcpy ((char *) nb->data + etherhdr_size - 6, &vlantag_id, 2);
      grub_memcpy ((char *) nb->data + etherhdr_size - 4, (char *) &(inf->vlantag), 2);
    }

  return inf->card->driver->send (inf->card, nb);
}

grub_err_t
grub_net_recv_ethernet_packet (struct grub_net_buff *nb,
			       struct grub_net_card *card)
{
  struct etherhdr *eth;
  struct llchdr *llch;
  struct snaphdr *snaph;
  grub_net_ethertype_t type;
  grub_net_link_level_address_t hwaddress;
  grub_net_link_level_address_t src_hwaddress;
  grub_err_t err;
  grub_uint8_t etherhdr_size = sizeof (*eth);
  grub_uint16_t vlantag = 0;


  /* Check if a vlan-tag is present. If so, the ethernet header is 4 bytes */
  /* longer than the original one. The vlantag id is extracted and the header */
  /* is reseted to the original size. */
  if (grub_get_unaligned16 (nb->data + etherhdr_size - 2) == VLANTAG_IDENTIFIER)
    {
      vlantag = grub_get_unaligned16 (nb->data + etherhdr_size);
      etherhdr_size += 4;
      /* Move eth type to the original position */
      grub_memcpy((char *) nb->data + etherhdr_size - 6,
                  (char *) nb->data + etherhdr_size - 2, 2);
    }

  eth = (struct etherhdr *) nb->data;
  type = grub_be_to_cpu16 (eth->type);
  err = grub_netbuff_pull (nb, etherhdr_size);
  if (err)
    return err;

  if (type <= 1500)
    {
      llch = (struct llchdr *) nb->data;
      type = llch->dsap & LLCADDRMASK;

      if (llch->dsap == 0xaa && llch->ssap == 0xaa && llch->ctrl == 0x3)
	{
	  err = grub_netbuff_pull (nb, sizeof (*llch));
	  if (err)
	    return err;
	  snaph = (struct snaphdr *) nb->data;
	  type = snaph->type;
	}
    }

  hwaddress.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
  grub_memcpy (hwaddress.mac, eth->dst, sizeof (hwaddress.mac));
  src_hwaddress.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
  grub_memcpy (src_hwaddress.mac, eth->src, sizeof (src_hwaddress.mac));

  switch (type)
    {
      /* ARP packet. */
    case GRUB_NET_ETHERTYPE_ARP:
      grub_net_arp_receive (nb, card, &vlantag);
      grub_netbuff_free (nb);
      return GRUB_ERR_NONE;
      /* IP packet.  */
    case GRUB_NET_ETHERTYPE_IP:
    case GRUB_NET_ETHERTYPE_IP6:
      return grub_net_recv_ip_packets (nb, card, &hwaddress, &src_hwaddress,
                                       &vlantag);
    }
  grub_netbuff_free (nb);
  return GRUB_ERR_NONE;
}
