/*
 *    $Id: gre.c,v 1.3 2000/03/08 18:10:35 wessels Exp $
 *
 * Glenn Chisholm <glenn@ircache.net>
 * Duane Wessels <wessels@ircache.net>
 */

#include "opt_gre.h"

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/proc.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>

#include <vm/vm_zone.h>

#include <net/if.h>
#include <net/route.h>

#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/in_pcb.h>
#include <netinet/in_var.h>
#include <netinet/ip_var.h>
#include <netinet/ip_mroute.h>

#define GRE_PROTOCOL_TYPE 0x883E

struct gre {
    int type;
};

void
gre_input(m, iphlen)
     register struct mbuf *m;
     int iphlen;
{
    register struct ip *ip = mtod(m, struct ip *);
    register struct gre *gre;
    int len;

    len = iphlen + sizeof(struct gre);
    if (m->m_len < len) {
	if ((m = m_pullup(m, len)) == 0) {
	    printf("gre_input: m_pullup failed\n");
	    return;
	}
	ip = mtod(m, struct ip *);
    }
    gre = (struct gre *) ((caddr_t) ip + iphlen);
    if (ntohl(gre->type) != GRE_PROTOCOL_TYPE) {
	printf("gre_input: bad GRE type %x\n", gre->type);
	rip_input(m, iphlen);
	return;
    }
    if (m->m_len < len) {
	printf("gre_input: small packet?  len=%d, m_len=%d\n", len, m->m_len);
	m_freem(m);
	return;
    }
    /* drop IP and GRE headers */
    m_adj(m, len);
    ip_input(m);
}
