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.
@ -48,7 +48,7 @@
*/
#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_inet.h"
@ -439,7 +439,7 @@ gre_thread1(struct gre_softc *sc, struct lwp *l)
}
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",
__func__);
ifp->if_ierrors++;
@ -502,7 +502,7 @@ gre_thread(void *arg)
}
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)
{
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_ibytes += m->m_pkthdr.len;
switch (proto) {
case IPPROTO_GRE:
hlen += sizeof(struct gre_h);
hlen += sizeof(struct gre_h);
/* process GRE flags as packet can be of variable len */
flags = ntohs(gh->flags);
/* process GRE flags as packet can be of variable len */
flags = ntohs(gh->flags);
/* Checksum & Offset are present */
if ((flags & GRE_CP) | (flags & GRE_RP))
hlen += 4;
/* We don't support routing fields (variable length) */
if (flags & GRE_RP)
return 0;
if (flags & GRE_KP)
hlen += 4;
if (flags & GRE_SP)
hlen += 4;
/* Checksum & Offset are present */
if ((flags & GRE_CP) | (flags & GRE_RP))
hlen += 4;
/* We don't support routing fields (variable length) */
if (flags & GRE_RP) {
sc->sc_if.if_ierrors++;
return 0;
}
if (flags & GRE_KP)
hlen += 4;
if (flags & GRE_SP)
hlen += 4;
switch (ntohs(gh->ptype)) { /* ethertypes */
case ETHERTYPE_IP: /* shouldn't need a schednetisr(), as */
ifq = &ipintrq; /* we are in ip_input */
isr = NETISR_IP;
break;
switch (ntohs(gh->ptype)) { /* ethertypes */
case ETHERTYPE_IP: /* shouldn't need a schednetisr(), as */
ifq = &ipintrq; /* we are in ip_input */
isr = NETISR_IP;
break;
#ifdef NETATALK
case ETHERTYPE_ATALK:
ifq = &atintrq1;
isr = NETISR_ATALK;
case ETHERTYPE_ATALK:
ifq = &atintrq1;
isr = NETISR_ATALK;
#if NBPFILTER > 0
af = AF_APPLETALK;
af = AF_APPLETALK;
#endif
break;
break;
#endif
#ifdef INET6
case ETHERTYPE_IPV6:
GRE_DPRINTF(sc, "%s: IPv6 packet\n", __func__);
ifq = &ip6intrq;
isr = NETISR_IPV6;
case ETHERTYPE_IPV6:
GRE_DPRINTF(sc, "%s: IPv6 packet\n", __func__);
ifq = &ip6intrq;
isr = NETISR_IPV6;
#if NBPFILTER > 0
af = AF_INET6;
af = AF_INET6;
#endif
break;
#endif
default: /* others not yet supported */
printf("%s: unhandled ethertype 0x%04x\n", __func__,
ntohs(gh->ptype));
return 0;
}
break;
default:
/* others not yet supported */
#endif
default: /* others not yet supported */
printf("%s: unhandled ethertype 0x%04x\n", __func__,
ntohs(gh->ptype));
sc->sc_if.if_noproto++;
return 0;
}
@ -604,7 +600,7 @@ static int
gre_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
struct rtentry *rt)
{
int error = 0, hlen;
int error = 0, hlen, msiz;
struct gre_softc *sc = ifp->if_softc;
struct greip *gi;
struct gre_h *gh;
@ -632,56 +628,54 @@ gre_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
switch (sc->sc_proto) {
case IPPROTO_MOBILE:
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 (dst->sa_family != AF_INET) {
IF_DROP(&ifp->if_snd);
m_freem(m);
error = EINVAL;
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;
case IPPROTO_UDP:
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.
@ -163,8 +163,7 @@ LIST_HEAD(gre_softc_head, gre_softc);
extern struct gre_softc_head gre_softc_list;
u_int16_t gre_in_cksum(u_short *, u_int);
int gre_input3(struct gre_softc *, struct mbuf *, int, u_char,
const struct gre_h *);
int gre_input3(struct gre_softc *, struct mbuf *, int, const struct gre_h *);
#endif /* _KERNEL */
#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.
@ -45,7 +45,7 @@
*/
#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"
#if NGRE > 0
@ -156,7 +156,7 @@ gre_input2(struct mbuf *m, int hlen, u_char proto)
}
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);
}
/*