/*-
 * Copyright (c) 2004 Robert N. M. Watson
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * [id for your version control system, if any]
 */

#include <sys/types.h>

#include <net/ethernet.h>

#include <netinet/in.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "arp.h"
#include "ip.h"
#include "stack.h"

u_char		my_ether_addr[ETHER_ADDR_LEN] = { 0x00, 0x04, 0x76, 0x42,
		    0xf0, 0xcb };
const u_char	broadcast_ether_addr[ETHER_ADDR_LEN] = {0xff, 0xff, 0xff,
		    0xff, 0xff, 0xff};

int
ether_setup(u_char *new_ether_addr)
{

	bcopy(new_ether_addr, my_ether_addr, ETHER_ADDR_LEN);
	return (0);
}

int
ether_output(u_char *packet, u_int packetlen)
{
	struct ether_header *eh;

	eh = (struct ether_header *)packet;
	bcopy(my_ether_addr, eh->ether_shost, ETHER_ADDR_LEN);
	return (stack_output(packet, packetlen));
}

static void
ether_print(u_char *addr)
{

	printf("%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2],
	    addr[3], addr[4], addr[5]);
}

void
ether_input(u_char *packet, u_int packetlen)
{
	struct ether_header *eh;

	eh = (struct ether_header *)packet;
	if (packetlen < sizeof(*eh))
		return;
	if (bcmp(my_ether_addr, eh->ether_dhost, ETHER_ADDR_LEN) != 0 &&
	    bcmp(broadcast_ether_addr, eh->ether_dhost, ETHER_ADDR_LEN) != 0)
		return;
	switch (ntohs(eh->ether_type)) {
	case ETHERTYPE_ARP:
		arp_input(eh, packet + sizeof(*eh), packetlen - sizeof(*eh));
		break;
	case ETHERTYPE_IP:
		ip_input(eh, packet + sizeof(*eh), packetlen - sizeof(*eh));
		break;
	default:
		fprintf(stderr, "ether_input: unknown type 0x%x\n",
		    ntohs(eh->ether_type));
	}
}
