If we do not recognize the protocol of a received packet, then
increase ifi_noproto. If the GRE header contains routing options, increase the input-error count, ifi_ierrors. While I am here, make some cosmetic changes: remove unnecessary 'proto' argument from gre_input3(). Shorten some staircases.
This commit is contained in:
parent
bbcca898c4
commit
271d77fa58
172
sys/net/if_gre.c
172
sys/net/if_gre.c
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: if_gre.c,v 1.88 2007/03/04 06:03:16 christos Exp $ */
|
/* $NetBSD: if_gre.c,v 1.89 2007/03/21 01:56:05 dyoung Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||||
|
@ -48,7 +48,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: if_gre.c,v 1.88 2007/03/04 06:03:16 christos Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: if_gre.c,v 1.89 2007/03/21 01:56:05 dyoung Exp $");
|
||||||
|
|
||||||
#include "opt_gre.h"
|
#include "opt_gre.h"
|
||||||
#include "opt_inet.h"
|
#include "opt_inet.h"
|
||||||
|
@ -439,7 +439,7 @@ gre_thread1(struct gre_softc *sc, struct lwp *l)
|
||||||
}
|
}
|
||||||
gh = mtod(m, const struct gre_h *);
|
gh = mtod(m, const struct gre_h *);
|
||||||
|
|
||||||
if (gre_input3(sc, m, 0, IPPROTO_GRE, gh) == 0) {
|
if (gre_input3(sc, m, 0, gh) == 0) {
|
||||||
GRE_DPRINTF(sc, "%s: dropping unsupported\n",
|
GRE_DPRINTF(sc, "%s: dropping unsupported\n",
|
||||||
__func__);
|
__func__);
|
||||||
ifp->if_ierrors++;
|
ifp->if_ierrors++;
|
||||||
|
@ -502,7 +502,7 @@ gre_thread(void *arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
gre_input3(struct gre_softc *sc, struct mbuf *m, int hlen, u_char proto,
|
gre_input3(struct gre_softc *sc, struct mbuf *m, int hlen,
|
||||||
const struct gre_h *gh)
|
const struct gre_h *gh)
|
||||||
{
|
{
|
||||||
u_int16_t flags;
|
u_int16_t flags;
|
||||||
|
@ -515,56 +515,52 @@ gre_input3(struct gre_softc *sc, struct mbuf *m, int hlen, u_char proto,
|
||||||
sc->sc_if.if_ipackets++;
|
sc->sc_if.if_ipackets++;
|
||||||
sc->sc_if.if_ibytes += m->m_pkthdr.len;
|
sc->sc_if.if_ibytes += m->m_pkthdr.len;
|
||||||
|
|
||||||
switch (proto) {
|
hlen += sizeof(struct gre_h);
|
||||||
case IPPROTO_GRE:
|
|
||||||
hlen += sizeof(struct gre_h);
|
|
||||||
|
|
||||||
/* process GRE flags as packet can be of variable len */
|
/* process GRE flags as packet can be of variable len */
|
||||||
flags = ntohs(gh->flags);
|
flags = ntohs(gh->flags);
|
||||||
|
|
||||||
/* Checksum & Offset are present */
|
/* Checksum & Offset are present */
|
||||||
if ((flags & GRE_CP) | (flags & GRE_RP))
|
if ((flags & GRE_CP) | (flags & GRE_RP))
|
||||||
hlen += 4;
|
hlen += 4;
|
||||||
/* We don't support routing fields (variable length) */
|
/* We don't support routing fields (variable length) */
|
||||||
if (flags & GRE_RP)
|
if (flags & GRE_RP) {
|
||||||
return 0;
|
sc->sc_if.if_ierrors++;
|
||||||
if (flags & GRE_KP)
|
return 0;
|
||||||
hlen += 4;
|
}
|
||||||
if (flags & GRE_SP)
|
if (flags & GRE_KP)
|
||||||
hlen += 4;
|
hlen += 4;
|
||||||
|
if (flags & GRE_SP)
|
||||||
|
hlen += 4;
|
||||||
|
|
||||||
switch (ntohs(gh->ptype)) { /* ethertypes */
|
switch (ntohs(gh->ptype)) { /* ethertypes */
|
||||||
case ETHERTYPE_IP: /* shouldn't need a schednetisr(), as */
|
case ETHERTYPE_IP: /* shouldn't need a schednetisr(), as */
|
||||||
ifq = &ipintrq; /* we are in ip_input */
|
ifq = &ipintrq; /* we are in ip_input */
|
||||||
isr = NETISR_IP;
|
isr = NETISR_IP;
|
||||||
break;
|
break;
|
||||||
#ifdef NETATALK
|
#ifdef NETATALK
|
||||||
case ETHERTYPE_ATALK:
|
case ETHERTYPE_ATALK:
|
||||||
ifq = &atintrq1;
|
ifq = &atintrq1;
|
||||||
isr = NETISR_ATALK;
|
isr = NETISR_ATALK;
|
||||||
#if NBPFILTER > 0
|
#if NBPFILTER > 0
|
||||||
af = AF_APPLETALK;
|
af = AF_APPLETALK;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
case ETHERTYPE_IPV6:
|
case ETHERTYPE_IPV6:
|
||||||
GRE_DPRINTF(sc, "%s: IPv6 packet\n", __func__);
|
GRE_DPRINTF(sc, "%s: IPv6 packet\n", __func__);
|
||||||
ifq = &ip6intrq;
|
ifq = &ip6intrq;
|
||||||
isr = NETISR_IPV6;
|
isr = NETISR_IPV6;
|
||||||
#if NBPFILTER > 0
|
#if NBPFILTER > 0
|
||||||
af = AF_INET6;
|
af = AF_INET6;
|
||||||
#endif
|
#endif
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default: /* others not yet supported */
|
|
||||||
printf("%s: unhandled ethertype 0x%04x\n", __func__,
|
|
||||||
ntohs(gh->ptype));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
#endif
|
||||||
/* others not yet supported */
|
default: /* others not yet supported */
|
||||||
|
printf("%s: unhandled ethertype 0x%04x\n", __func__,
|
||||||
|
ntohs(gh->ptype));
|
||||||
|
sc->sc_if.if_noproto++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -604,7 +600,7 @@ static int
|
||||||
gre_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
|
gre_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
|
||||||
struct rtentry *rt)
|
struct rtentry *rt)
|
||||||
{
|
{
|
||||||
int error = 0, hlen;
|
int error = 0, hlen, msiz;
|
||||||
struct gre_softc *sc = ifp->if_softc;
|
struct gre_softc *sc = ifp->if_softc;
|
||||||
struct greip *gi;
|
struct greip *gi;
|
||||||
struct gre_h *gh;
|
struct gre_h *gh;
|
||||||
|
@ -632,56 +628,54 @@ gre_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
|
||||||
|
|
||||||
switch (sc->sc_proto) {
|
switch (sc->sc_proto) {
|
||||||
case IPPROTO_MOBILE:
|
case IPPROTO_MOBILE:
|
||||||
if (dst->sa_family == AF_INET) {
|
if (dst->sa_family != AF_INET) {
|
||||||
int msiz;
|
|
||||||
|
|
||||||
if (M_UNWRITABLE(m, sizeof(*ip)) &&
|
|
||||||
(m = m_pullup(m, sizeof(*ip))) == NULL) {
|
|
||||||
error = ENOBUFS;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
ip = mtod(m, struct ip *);
|
|
||||||
|
|
||||||
memset(&mob_h, 0, MOB_H_SIZ_L);
|
|
||||||
mob_h.proto = (ip->ip_p) << 8;
|
|
||||||
mob_h.odst = ip->ip_dst.s_addr;
|
|
||||||
ip->ip_dst.s_addr = sc->g_dst.s_addr;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the packet comes from our host, we only change
|
|
||||||
* the destination address in the IP header.
|
|
||||||
* Else we also need to save and change the source
|
|
||||||
*/
|
|
||||||
if (in_hosteq(ip->ip_src, sc->g_src)) {
|
|
||||||
msiz = MOB_H_SIZ_S;
|
|
||||||
} else {
|
|
||||||
mob_h.proto |= MOB_H_SBIT;
|
|
||||||
mob_h.osrc = ip->ip_src.s_addr;
|
|
||||||
ip->ip_src.s_addr = sc->g_src.s_addr;
|
|
||||||
msiz = MOB_H_SIZ_L;
|
|
||||||
}
|
|
||||||
HTONS(mob_h.proto);
|
|
||||||
mob_h.hcrc = gre_in_cksum((u_int16_t *)&mob_h, msiz);
|
|
||||||
|
|
||||||
M_PREPEND(m, msiz, M_DONTWAIT);
|
|
||||||
if (m == NULL) {
|
|
||||||
error = ENOBUFS;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
/* XXX Assuming that ip does not dangle after
|
|
||||||
* M_PREPEND. In practice, that's true, but
|
|
||||||
* that's in M_PREPEND's contract.
|
|
||||||
*/
|
|
||||||
memmove(mtod(m, void *), ip, sizeof(*ip));
|
|
||||||
ip = mtod(m, struct ip *);
|
|
||||||
memcpy((void *)(ip + 1), &mob_h, (unsigned)msiz);
|
|
||||||
ip->ip_len = htons(ntohs(ip->ip_len) + msiz);
|
|
||||||
} else { /* AF_INET */
|
|
||||||
IF_DROP(&ifp->if_snd);
|
IF_DROP(&ifp->if_snd);
|
||||||
m_freem(m);
|
m_freem(m);
|
||||||
error = EINVAL;
|
error = EINVAL;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (M_UNWRITABLE(m, sizeof(*ip)) &&
|
||||||
|
(m = m_pullup(m, sizeof(*ip))) == NULL) {
|
||||||
|
error = ENOBUFS;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
ip = mtod(m, struct ip *);
|
||||||
|
|
||||||
|
memset(&mob_h, 0, MOB_H_SIZ_L);
|
||||||
|
mob_h.proto = (ip->ip_p) << 8;
|
||||||
|
mob_h.odst = ip->ip_dst.s_addr;
|
||||||
|
ip->ip_dst.s_addr = sc->g_dst.s_addr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the packet comes from our host, we only change
|
||||||
|
* the destination address in the IP header.
|
||||||
|
* Else we also need to save and change the source
|
||||||
|
*/
|
||||||
|
if (in_hosteq(ip->ip_src, sc->g_src)) {
|
||||||
|
msiz = MOB_H_SIZ_S;
|
||||||
|
} else {
|
||||||
|
mob_h.proto |= MOB_H_SBIT;
|
||||||
|
mob_h.osrc = ip->ip_src.s_addr;
|
||||||
|
ip->ip_src.s_addr = sc->g_src.s_addr;
|
||||||
|
msiz = MOB_H_SIZ_L;
|
||||||
|
}
|
||||||
|
HTONS(mob_h.proto);
|
||||||
|
mob_h.hcrc = gre_in_cksum((u_int16_t *)&mob_h, msiz);
|
||||||
|
|
||||||
|
M_PREPEND(m, msiz, M_DONTWAIT);
|
||||||
|
if (m == NULL) {
|
||||||
|
error = ENOBUFS;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
/* XXX Assuming that ip does not dangle after
|
||||||
|
* M_PREPEND. In practice, that's true, but
|
||||||
|
* that's in M_PREPEND's contract.
|
||||||
|
*/
|
||||||
|
memmove(mtod(m, void *), ip, sizeof(*ip));
|
||||||
|
ip = mtod(m, struct ip *);
|
||||||
|
memcpy((void *)(ip + 1), &mob_h, (unsigned)msiz);
|
||||||
|
ip->ip_len = htons(ntohs(ip->ip_len) + msiz);
|
||||||
break;
|
break;
|
||||||
case IPPROTO_UDP:
|
case IPPROTO_UDP:
|
||||||
case IPPROTO_GRE:
|
case IPPROTO_GRE:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: if_gre.h,v 1.20 2007/01/26 03:01:32 dyoung Exp $ */
|
/* $NetBSD: if_gre.h,v 1.21 2007/03/21 01:56:05 dyoung Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||||
|
@ -163,8 +163,7 @@ LIST_HEAD(gre_softc_head, gre_softc);
|
||||||
extern struct gre_softc_head gre_softc_list;
|
extern struct gre_softc_head gre_softc_list;
|
||||||
|
|
||||||
u_int16_t gre_in_cksum(u_short *, u_int);
|
u_int16_t gre_in_cksum(u_short *, u_int);
|
||||||
int gre_input3(struct gre_softc *, struct mbuf *, int, u_char,
|
int gre_input3(struct gre_softc *, struct mbuf *, int, const struct gre_h *);
|
||||||
const struct gre_h *);
|
|
||||||
#endif /* _KERNEL */
|
#endif /* _KERNEL */
|
||||||
|
|
||||||
#endif /* !_NET_IF_GRE_H_ */
|
#endif /* !_NET_IF_GRE_H_ */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: ip_gre.c,v 1.44 2006/11/16 22:54:14 dyoung Exp $ */
|
/* $NetBSD: ip_gre.c,v 1.45 2007/03/21 01:56:05 dyoung Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||||
|
@ -45,7 +45,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: ip_gre.c,v 1.44 2006/11/16 22:54:14 dyoung Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: ip_gre.c,v 1.45 2007/03/21 01:56:05 dyoung Exp $");
|
||||||
|
|
||||||
#include "gre.h"
|
#include "gre.h"
|
||||||
#if NGRE > 0
|
#if NGRE > 0
|
||||||
|
@ -156,7 +156,7 @@ gre_input2(struct mbuf *m, int hlen, u_char proto)
|
||||||
}
|
}
|
||||||
gip = mtod(m, const struct greip *);
|
gip = mtod(m, const struct greip *);
|
||||||
|
|
||||||
return gre_input3(sc, m, hlen, proto, &gip->gi_g);
|
return gre_input3(sc, m, hlen, &gip->gi_g);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue