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:
dyoung 2007-03-21 01:56:05 +00:00
parent bbcca898c4
commit 271d77fa58
3 changed files with 88 additions and 95 deletions

View File

@ -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:

View File

@ -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_ */

View File

@ -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);
} }
/* /*