This commit was generated by cvs2svn to compensate for changes in r126258,
which included commits to RCS files with non-trunk default branches.
This commit is contained in:
commit
3ef891af51
231
sys/contrib/pf/net/if_pflog.c
Normal file
231
sys/contrib/pf/net/if_pflog.c
Normal file
@ -0,0 +1,231 @@
|
||||
/* $OpenBSD: if_pflog.c,v 1.9 2003/05/14 08:42:00 canacar Exp $ */
|
||||
/*
|
||||
* The authors of this code are John Ioannidis (ji@tla.org),
|
||||
* Angelos D. Keromytis (kermit@csd.uch.gr) and
|
||||
* Niels Provos (provos@physnet.uni-hamburg.de).
|
||||
*
|
||||
* This code was written by John Ioannidis for BSD/OS in Athens, Greece,
|
||||
* in November 1995.
|
||||
*
|
||||
* Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
|
||||
* by Angelos D. Keromytis.
|
||||
*
|
||||
* Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
|
||||
* and Niels Provos.
|
||||
*
|
||||
* Copyright (C) 1995, 1996, 1997, 1998 by John Ioannidis, Angelos D. Keromytis
|
||||
* and Niels Provos.
|
||||
* Copyright (c) 2001, Angelos D. Keromytis, Niels Provos.
|
||||
*
|
||||
* Permission to use, copy, and modify this software with or without fee
|
||||
* is hereby granted, provided that this entire notice is included in
|
||||
* all copies of any software which is or includes a copy or
|
||||
* modification of this software.
|
||||
* You may use this code under the GNU public license if you so wish. Please
|
||||
* contribute changes back to the authors under this freer than GPL license
|
||||
* so that we may further the use of strong encryption without limitations to
|
||||
* all.
|
||||
*
|
||||
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
|
||||
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
|
||||
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
|
||||
* PURPOSE.
|
||||
*/
|
||||
|
||||
#include "bpfilter.h"
|
||||
#include "pflog.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/route.h>
|
||||
#include <net/bpf.h>
|
||||
|
||||
#ifdef INET
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#endif
|
||||
|
||||
#ifdef INET6
|
||||
#ifndef INET
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#include <netinet6/nd6.h>
|
||||
#endif /* INET6 */
|
||||
|
||||
#include <net/pfvar.h>
|
||||
#include <net/if_pflog.h>
|
||||
|
||||
#define PFLOGMTU (32768 + MHLEN + MLEN)
|
||||
|
||||
#ifdef PFLOGDEBUG
|
||||
#define DPRINTF(x) do { if (pflogdebug) printf x ; } while (0)
|
||||
#else
|
||||
#define DPRINTF(x)
|
||||
#endif
|
||||
|
||||
struct pflog_softc pflogif[NPFLOG];
|
||||
|
||||
void pflogattach(int);
|
||||
int pflogoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
|
||||
struct rtentry *);
|
||||
int pflogioctl(struct ifnet *, u_long, caddr_t);
|
||||
void pflogrtrequest(int, struct rtentry *, struct sockaddr *);
|
||||
void pflogstart(struct ifnet *);
|
||||
|
||||
extern int ifqmaxlen;
|
||||
|
||||
void
|
||||
pflogattach(int npflog)
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
int i;
|
||||
|
||||
bzero(pflogif, sizeof(pflogif));
|
||||
|
||||
for (i = 0; i < NPFLOG; i++) {
|
||||
ifp = &pflogif[i].sc_if;
|
||||
snprintf(ifp->if_xname, sizeof ifp->if_xname, "pflog%d", i);
|
||||
ifp->if_softc = &pflogif[i];
|
||||
ifp->if_mtu = PFLOGMTU;
|
||||
ifp->if_ioctl = pflogioctl;
|
||||
ifp->if_output = pflogoutput;
|
||||
ifp->if_start = pflogstart;
|
||||
ifp->if_type = IFT_PFLOG;
|
||||
ifp->if_snd.ifq_maxlen = ifqmaxlen;
|
||||
ifp->if_hdrlen = PFLOG_HDRLEN;
|
||||
if_attach(ifp);
|
||||
if_alloc_sadl(ifp);
|
||||
|
||||
#if NBPFILTER > 0
|
||||
bpfattach(&pflogif[i].sc_if.if_bpf, ifp, DLT_PFLOG,
|
||||
PFLOG_HDRLEN);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Start output on the pflog interface.
|
||||
*/
|
||||
void
|
||||
pflogstart(struct ifnet *ifp)
|
||||
{
|
||||
struct mbuf *m;
|
||||
int s;
|
||||
|
||||
for (;;) {
|
||||
s = splimp();
|
||||
IF_DROP(&ifp->if_snd);
|
||||
IF_DEQUEUE(&ifp->if_snd, m);
|
||||
splx(s);
|
||||
|
||||
if (m == NULL)
|
||||
return;
|
||||
else
|
||||
m_freem(m);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
pflogoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
|
||||
struct rtentry *rt)
|
||||
{
|
||||
m_freem(m);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
pflogrtrequest(int cmd, struct rtentry *rt, struct sockaddr *sa)
|
||||
{
|
||||
if (rt)
|
||||
rt->rt_rmx.rmx_mtu = PFLOGMTU;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
pflogioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
switch (cmd) {
|
||||
case SIOCSIFADDR:
|
||||
case SIOCAIFADDR:
|
||||
case SIOCSIFDSTADDR:
|
||||
case SIOCSIFFLAGS:
|
||||
if (ifp->if_flags & IFF_UP)
|
||||
ifp->if_flags |= IFF_RUNNING;
|
||||
else
|
||||
ifp->if_flags &= ~IFF_RUNNING;
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pflog_packet(struct ifnet *ifp, struct mbuf *m, sa_family_t af, u_int8_t dir,
|
||||
u_int8_t reason, struct pf_rule *rm, struct pf_rule *am,
|
||||
struct pf_ruleset *ruleset)
|
||||
{
|
||||
#if NBPFILTER > 0
|
||||
struct ifnet *ifn;
|
||||
struct pfloghdr hdr;
|
||||
struct mbuf m1;
|
||||
|
||||
if (ifp == NULL || m == NULL || rm == NULL)
|
||||
return (-1);
|
||||
|
||||
hdr.length = PFLOG_REAL_HDRLEN;
|
||||
hdr.af = af;
|
||||
hdr.action = rm->action;
|
||||
hdr.reason = reason;
|
||||
memcpy(hdr.ifname, ifp->if_xname, sizeof(hdr.ifname));
|
||||
|
||||
if (am == NULL) {
|
||||
hdr.rulenr = htonl(rm->nr);
|
||||
hdr.subrulenr = -1;
|
||||
bzero(hdr.ruleset, sizeof(hdr.ruleset));
|
||||
} else {
|
||||
hdr.rulenr = htonl(am->nr);
|
||||
hdr.subrulenr = htonl(rm->nr);
|
||||
if (ruleset == NULL)
|
||||
bzero(hdr.ruleset, sizeof(hdr.ruleset));
|
||||
else
|
||||
memcpy(hdr.ruleset, ruleset->name,
|
||||
sizeof(hdr.ruleset));
|
||||
|
||||
|
||||
}
|
||||
hdr.dir = dir;
|
||||
|
||||
#ifdef INET
|
||||
if (af == AF_INET && dir == PF_OUT) {
|
||||
struct ip *ip;
|
||||
|
||||
ip = mtod(m, struct ip *);
|
||||
ip->ip_sum = 0;
|
||||
ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
|
||||
}
|
||||
#endif /* INET */
|
||||
|
||||
m1.m_next = m;
|
||||
m1.m_len = PFLOG_HDRLEN;
|
||||
m1.m_data = (char *) &hdr;
|
||||
|
||||
ifn = &(pflogif[0].sc_if);
|
||||
|
||||
if (ifn->if_bpf)
|
||||
bpf_mtap(ifn->if_bpf, &m1);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
75
sys/contrib/pf/net/if_pflog.h
Normal file
75
sys/contrib/pf/net/if_pflog.h
Normal file
@ -0,0 +1,75 @@
|
||||
/* $OpenBSD: if_pflog.h,v 1.9 2003/07/15 20:27:27 dhartmei Exp $ */
|
||||
/*
|
||||
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
|
||||
* 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 ``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 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.
|
||||
*/
|
||||
|
||||
#ifndef _NET_IF_PFLOG_H_
|
||||
#define _NET_IF_PFLOG_H_
|
||||
|
||||
struct pflog_softc {
|
||||
struct ifnet sc_if; /* the interface */
|
||||
};
|
||||
|
||||
/* XXX keep in sync with pfvar.h */
|
||||
#ifndef PF_RULESET_NAME_SIZE
|
||||
#define PF_RULESET_NAME_SIZE 16
|
||||
#endif
|
||||
|
||||
struct pfloghdr {
|
||||
u_int8_t length;
|
||||
sa_family_t af;
|
||||
u_int8_t action;
|
||||
u_int8_t reason;
|
||||
char ifname[IFNAMSIZ];
|
||||
char ruleset[PF_RULESET_NAME_SIZE];
|
||||
u_int32_t rulenr;
|
||||
u_int32_t subrulenr;
|
||||
u_int8_t dir;
|
||||
u_int8_t pad[3];
|
||||
};
|
||||
|
||||
#define PFLOG_HDRLEN sizeof(struct pfloghdr)
|
||||
/* minus pad, also used as a signature */
|
||||
#define PFLOG_REAL_HDRLEN offsetof(struct pfloghdr, pad);
|
||||
|
||||
/* XXX remove later when old format logs are no longer needed */
|
||||
struct old_pfloghdr {
|
||||
u_int32_t af;
|
||||
char ifname[IFNAMSIZ];
|
||||
short rnr;
|
||||
u_short reason;
|
||||
u_short action;
|
||||
u_short dir;
|
||||
};
|
||||
#define OLD_PFLOG_HDRLEN sizeof(struct old_pfloghdr)
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#if NPFLOG > 0
|
||||
#define PFLOG_PACKET(i,x,a,b,c,d,e,f,g) pflog_packet(i,a,b,c,d,e,f,g)
|
||||
#else
|
||||
#define PFLOG_PACKET(i,x,a,b,c,d,e,f,g) ((void)0)
|
||||
#endif /* NPFLOG > 0 */
|
||||
#endif /* _KERNEL */
|
||||
#endif /* _NET_IF_PFLOG_H_ */
|
359
sys/contrib/pf/net/if_pfsync.c
Normal file
359
sys/contrib/pf/net/if_pfsync.c
Normal file
@ -0,0 +1,359 @@
|
||||
/* $OpenBSD: if_pfsync.c,v 1.6 2003/06/21 09:07:01 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002 Michael Shalayeff
|
||||
* 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 ``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 HIS RELATIVES 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 MIND, 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.
|
||||
*/
|
||||
|
||||
#include "bpfilter.h"
|
||||
#include "pfsync.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/timeout.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/route.h>
|
||||
#include <net/bpf.h>
|
||||
|
||||
#ifdef INET
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_var.h>
|
||||
#endif
|
||||
|
||||
#ifdef INET6
|
||||
#ifndef INET
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#include <netinet6/nd6.h>
|
||||
#endif /* INET6 */
|
||||
|
||||
#include <net/pfvar.h>
|
||||
#include <net/if_pfsync.h>
|
||||
|
||||
#define PFSYNC_MINMTU \
|
||||
(sizeof(struct pfsync_header) + sizeof(struct pf_state))
|
||||
|
||||
#ifdef PFSYNCDEBUG
|
||||
#define DPRINTF(x) do { if (pfsyncdebug) printf x ; } while (0)
|
||||
int pfsyncdebug;
|
||||
#else
|
||||
#define DPRINTF(x)
|
||||
#endif
|
||||
|
||||
struct pfsync_softc pfsyncif;
|
||||
|
||||
void pfsyncattach(int);
|
||||
void pfsync_setmtu(struct pfsync_softc *sc, int);
|
||||
int pfsyncoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
|
||||
struct rtentry *);
|
||||
int pfsyncioctl(struct ifnet *, u_long, caddr_t);
|
||||
void pfsyncstart(struct ifnet *);
|
||||
|
||||
struct mbuf *pfsync_get_mbuf(struct pfsync_softc *sc, u_int8_t action);
|
||||
int pfsync_sendout(struct pfsync_softc *sc);
|
||||
void pfsync_timeout(void *v);
|
||||
|
||||
extern int ifqmaxlen;
|
||||
|
||||
void
|
||||
pfsyncattach(int npfsync)
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
|
||||
pfsyncif.sc_mbuf = NULL;
|
||||
pfsyncif.sc_ptr = NULL;
|
||||
pfsyncif.sc_count = 8;
|
||||
ifp = &pfsyncif.sc_if;
|
||||
strlcpy(ifp->if_xname, "pfsync0", sizeof ifp->if_xname);
|
||||
ifp->if_softc = &pfsyncif;
|
||||
ifp->if_ioctl = pfsyncioctl;
|
||||
ifp->if_output = pfsyncoutput;
|
||||
ifp->if_start = pfsyncstart;
|
||||
ifp->if_type = IFT_PFSYNC;
|
||||
ifp->if_snd.ifq_maxlen = ifqmaxlen;
|
||||
ifp->if_hdrlen = PFSYNC_HDRLEN;
|
||||
ifp->if_baudrate = IF_Mbps(100);
|
||||
pfsync_setmtu(&pfsyncif, MCLBYTES);
|
||||
timeout_set(&pfsyncif.sc_tmo, pfsync_timeout, &pfsyncif);
|
||||
if_attach(ifp);
|
||||
if_alloc_sadl(ifp);
|
||||
|
||||
#if NBPFILTER > 0
|
||||
bpfattach(&pfsyncif.sc_if.if_bpf, ifp, DLT_PFSYNC, PFSYNC_HDRLEN);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Start output on the pfsync interface.
|
||||
*/
|
||||
void
|
||||
pfsyncstart(struct ifnet *ifp)
|
||||
{
|
||||
struct mbuf *m;
|
||||
int s;
|
||||
|
||||
for (;;) {
|
||||
s = splimp();
|
||||
IF_DROP(&ifp->if_snd);
|
||||
IF_DEQUEUE(&ifp->if_snd, m);
|
||||
splx(s);
|
||||
|
||||
if (m == NULL)
|
||||
return;
|
||||
else
|
||||
m_freem(m);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
pfsyncoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
|
||||
struct rtentry *rt)
|
||||
{
|
||||
m_freem(m);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
struct pfsync_softc *sc = ifp->if_softc;
|
||||
struct ifreq *ifr = (struct ifreq *)data;
|
||||
int s;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCSIFADDR:
|
||||
case SIOCAIFADDR:
|
||||
case SIOCSIFDSTADDR:
|
||||
case SIOCSIFFLAGS:
|
||||
if (ifp->if_flags & IFF_UP)
|
||||
ifp->if_flags |= IFF_RUNNING;
|
||||
else
|
||||
ifp->if_flags &= ~IFF_RUNNING;
|
||||
break;
|
||||
case SIOCSIFMTU:
|
||||
if (ifr->ifr_mtu < PFSYNC_MINMTU)
|
||||
return (EINVAL);
|
||||
if (ifr->ifr_mtu > MCLBYTES)
|
||||
ifr->ifr_mtu = MCLBYTES;
|
||||
s = splnet();
|
||||
if (ifr->ifr_mtu < ifp->if_mtu)
|
||||
pfsync_sendout(sc);
|
||||
pfsync_setmtu(sc, ifr->ifr_mtu);
|
||||
splx(s);
|
||||
break;
|
||||
default:
|
||||
return (ENOTTY);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
pfsync_setmtu(sc, mtu)
|
||||
struct pfsync_softc *sc;
|
||||
int mtu;
|
||||
{
|
||||
sc->sc_count = (mtu - sizeof(struct pfsync_header)) /
|
||||
sizeof(struct pf_state);
|
||||
sc->sc_if.if_mtu = sizeof(struct pfsync_header) +
|
||||
sc->sc_count * sizeof(struct pf_state);
|
||||
}
|
||||
|
||||
struct mbuf *
|
||||
pfsync_get_mbuf(sc, action)
|
||||
struct pfsync_softc *sc;
|
||||
u_int8_t action;
|
||||
{
|
||||
extern int hz;
|
||||
struct pfsync_header *h;
|
||||
struct mbuf *m;
|
||||
int len;
|
||||
|
||||
MGETHDR(m, M_DONTWAIT, MT_DATA);
|
||||
if (m == NULL) {
|
||||
sc->sc_if.if_oerrors++;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
len = sc->sc_if.if_mtu;
|
||||
if (len > MHLEN) {
|
||||
MCLGET(m, M_DONTWAIT);
|
||||
if ((m->m_flags & M_EXT) == 0) {
|
||||
m_free(m);
|
||||
sc->sc_if.if_oerrors++;
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
m->m_pkthdr.rcvif = NULL;
|
||||
m->m_pkthdr.len = m->m_len = len;
|
||||
|
||||
h = mtod(m, struct pfsync_header *);
|
||||
h->version = PFSYNC_VERSION;
|
||||
h->af = 0;
|
||||
h->count = 0;
|
||||
h->action = action;
|
||||
|
||||
sc->sc_mbuf = m;
|
||||
sc->sc_ptr = (struct pf_state *)((char *)h + PFSYNC_HDRLEN);
|
||||
timeout_add(&sc->sc_tmo, hz);
|
||||
|
||||
return (m);
|
||||
}
|
||||
|
||||
int
|
||||
pfsync_pack_state(action, st)
|
||||
u_int8_t action;
|
||||
struct pf_state *st;
|
||||
{
|
||||
extern struct timeval time;
|
||||
struct ifnet *ifp = &pfsyncif.sc_if;
|
||||
struct pfsync_softc *sc = ifp->if_softc;
|
||||
struct pfsync_header *h;
|
||||
struct pf_state *sp;
|
||||
struct pf_rule *r = st->rule.ptr;
|
||||
struct mbuf *m;
|
||||
u_long secs;
|
||||
int s, ret;
|
||||
|
||||
if (action >= PFSYNC_ACT_MAX)
|
||||
return (EINVAL);
|
||||
|
||||
s = splnet();
|
||||
m = sc->sc_mbuf;
|
||||
if (m == NULL) {
|
||||
if ((m = pfsync_get_mbuf(sc, action)) == NULL) {
|
||||
splx(s);
|
||||
return (ENOMEM);
|
||||
}
|
||||
h = mtod(m, struct pfsync_header *);
|
||||
} else {
|
||||
h = mtod(m, struct pfsync_header *);
|
||||
if (h->action != action) {
|
||||
pfsync_sendout(sc);
|
||||
if ((m = pfsync_get_mbuf(sc, action)) == NULL) {
|
||||
splx(s);
|
||||
return (ENOMEM);
|
||||
}
|
||||
h = mtod(m, struct pfsync_header *);
|
||||
}
|
||||
}
|
||||
|
||||
sp = sc->sc_ptr++;
|
||||
h->count++;
|
||||
bzero(sp, sizeof(*sp));
|
||||
|
||||
bcopy(&st->lan, &sp->lan, sizeof(sp->lan));
|
||||
bcopy(&st->gwy, &sp->gwy, sizeof(sp->gwy));
|
||||
bcopy(&st->ext, &sp->ext, sizeof(sp->ext));
|
||||
|
||||
pf_state_peer_hton(&st->src, &sp->src);
|
||||
pf_state_peer_hton(&st->dst, &sp->dst);
|
||||
|
||||
bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr));
|
||||
secs = time.tv_sec;
|
||||
sp->creation = htonl(secs - st->creation);
|
||||
if (st->expire <= secs)
|
||||
sp->expire = htonl(0);
|
||||
else
|
||||
sp->expire = htonl(st->expire - secs);
|
||||
sp->packets[0] = htonl(st->packets[0]);
|
||||
sp->packets[1] = htonl(st->packets[1]);
|
||||
sp->bytes[0] = htonl(st->bytes[0]);
|
||||
sp->bytes[1] = htonl(st->bytes[1]);
|
||||
if (r == NULL)
|
||||
sp->rule.nr = htonl(-1);
|
||||
else
|
||||
sp->rule.nr = htonl(r->nr);
|
||||
sp->af = st->af;
|
||||
sp->proto = st->proto;
|
||||
sp->direction = st->direction;
|
||||
sp->log = st->log;
|
||||
sp->allow_opts = st->allow_opts;
|
||||
|
||||
ret = 0;
|
||||
if (h->count == sc->sc_count)
|
||||
ret = pfsync_sendout(sc);
|
||||
|
||||
splx(s);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfsync_clear_state(st)
|
||||
struct pf_state *st;
|
||||
{
|
||||
struct ifnet *ifp = &pfsyncif.sc_if;
|
||||
struct pfsync_softc *sc = ifp->if_softc;
|
||||
struct mbuf *m = sc->sc_mbuf;
|
||||
int s, ret;
|
||||
|
||||
s = splnet();
|
||||
if (m == NULL && (m = pfsync_get_mbuf(sc, PFSYNC_ACT_CLR)) == NULL) {
|
||||
splx(s);
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
ret = (pfsync_sendout(sc));
|
||||
splx(s);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void
|
||||
pfsync_timeout(void *v)
|
||||
{
|
||||
struct pfsync_softc *sc = v;
|
||||
int s;
|
||||
|
||||
s = splnet();
|
||||
pfsync_sendout(sc);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
int
|
||||
pfsync_sendout(sc)
|
||||
struct pfsync_softc *sc;
|
||||
{
|
||||
struct ifnet *ifp = &sc->sc_if;
|
||||
struct mbuf *m = sc->sc_mbuf;
|
||||
|
||||
timeout_del(&sc->sc_tmo);
|
||||
sc->sc_mbuf = NULL;
|
||||
sc->sc_ptr = NULL;
|
||||
|
||||
#if NBPFILTER > 0
|
||||
if (ifp->if_bpf)
|
||||
bpf_mtap(ifp->if_bpf, m);
|
||||
#endif
|
||||
|
||||
m_freem(m);
|
||||
|
||||
return (0);
|
||||
}
|
84
sys/contrib/pf/net/if_pfsync.h
Normal file
84
sys/contrib/pf/net/if_pfsync.h
Normal file
@ -0,0 +1,84 @@
|
||||
/* $OpenBSD: if_pfsync.h,v 1.2 2002/12/11 18:31:26 mickey Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Michael Shalayeff
|
||||
* 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 ``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 HIS RELATIVES 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 MIND, 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.
|
||||
*/
|
||||
|
||||
#ifndef _NET_IF_PFSYNC_H_
|
||||
#define _NET_IF_PFSYNC_H_
|
||||
|
||||
#ifdef _KERNEL
|
||||
struct pfsync_softc {
|
||||
struct ifnet sc_if;
|
||||
|
||||
struct timeout sc_tmo;
|
||||
struct mbuf *sc_mbuf; /* current cummulative mbuf */
|
||||
struct pf_state *sc_ptr; /* current ongoing state */
|
||||
int sc_count; /* number of states in one mtu */
|
||||
};
|
||||
#endif
|
||||
|
||||
struct pfsync_header {
|
||||
u_int8_t version;
|
||||
#define PFSYNC_VERSION 1
|
||||
u_int8_t af;
|
||||
u_int8_t action;
|
||||
#define PFSYNC_ACT_CLR 0
|
||||
#define PFSYNC_ACT_INS 1
|
||||
#define PFSYNC_ACT_UPD 2
|
||||
#define PFSYNC_ACT_DEL 3
|
||||
#define PFSYNC_ACT_MAX 4
|
||||
u_int8_t count;
|
||||
};
|
||||
|
||||
#define PFSYNC_HDRLEN sizeof(struct pfsync_header)
|
||||
#define PFSYNC_ACTIONS \
|
||||
"CLR ST", "INS ST", "UPD ST", "DEL ST"
|
||||
|
||||
#define pf_state_peer_hton(s,d) do { \
|
||||
(d)->seqlo = htonl((s)->seqlo); \
|
||||
(d)->seqhi = htonl((s)->seqhi); \
|
||||
(d)->seqdiff = htonl((s)->seqdiff); \
|
||||
(d)->max_win = htons((s)->max_win); \
|
||||
(d)->state = (s)->state; \
|
||||
} while (0)
|
||||
|
||||
#define pf_state_peer_ntoh(s,d) do { \
|
||||
(d)->seqlo = ntohl((s)->seqlo); \
|
||||
(d)->seqhi = ntohl((s)->seqhi); \
|
||||
(d)->seqdiff = ntohl((s)->seqdiff); \
|
||||
(d)->max_win = ntohs((s)->max_win); \
|
||||
(d)->state = (s)->state; \
|
||||
} while (0)
|
||||
|
||||
#ifdef _KERNEL
|
||||
int pfsync_clear_state(struct pf_state *);
|
||||
int pfsync_pack_state(u_int8_t, struct pf_state *);
|
||||
#define pfsync_insert_state(st) pfsync_pack_state(PFSYNC_ACT_INS, (st))
|
||||
#define pfsync_update_state(st) pfsync_pack_state(PFSYNC_ACT_UPD, (st))
|
||||
#define pfsync_delete_state(st) pfsync_pack_state(PFSYNC_ACT_DEL, (st))
|
||||
#endif
|
||||
|
||||
#endif /* _NET_IF_PFSYNC_H_ */
|
5263
sys/contrib/pf/net/pf.c
Normal file
5263
sys/contrib/pf/net/pf.c
Normal file
File diff suppressed because it is too large
Load Diff
2158
sys/contrib/pf/net/pf_ioctl.c
Normal file
2158
sys/contrib/pf/net/pf_ioctl.c
Normal file
File diff suppressed because it is too large
Load Diff
1528
sys/contrib/pf/net/pf_norm.c
Normal file
1528
sys/contrib/pf/net/pf_norm.c
Normal file
File diff suppressed because it is too large
Load Diff
524
sys/contrib/pf/net/pf_osfp.c
Normal file
524
sys/contrib/pf/net/pf_osfp.c
Normal file
@ -0,0 +1,524 @@
|
||||
/* $OpenBSD: pf_osfp.c,v 1.3 2003/08/27 18:23:36 frantzen Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003 Mike Frantzen <frantzen@w4g.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#ifdef _KERNEL
|
||||
# include <sys/systm.h>
|
||||
#endif /* _KERNEL */
|
||||
#include <sys/mbuf.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/pfvar.h>
|
||||
|
||||
#ifdef INET6
|
||||
#include <netinet/ip6.h>
|
||||
#endif /* INET6 */
|
||||
|
||||
|
||||
#ifdef _KERNEL
|
||||
# define DPFPRINTF(format, x...) \
|
||||
if (pf_status.debug >= PF_DEBUG_NOISY) \
|
||||
printf(format , ##x)
|
||||
typedef struct pool pool_t;
|
||||
|
||||
#else
|
||||
/* Userland equivalents so we can lend code to tcpdump et al. */
|
||||
|
||||
# include <arpa/inet.h>
|
||||
# include <errno.h>
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# define pool_t int
|
||||
# define pool_get(pool, flags) malloc(*(pool))
|
||||
# define pool_put(pool, item) free(item)
|
||||
# define pool_init(pool, size, a, ao, f, m, p) (*(pool)) = (size)
|
||||
|
||||
# ifdef PFDEBUG
|
||||
# include <stdarg.h>
|
||||
# define DPFPRINTF(format, x...) fprintf(stderr, format , ##x)
|
||||
# else
|
||||
# define DPFPRINTF(format, x...) ((void)0)
|
||||
# endif /* PFDEBUG */
|
||||
#endif /* _KERNEL */
|
||||
|
||||
|
||||
SLIST_HEAD(pf_osfp_list, pf_os_fingerprint) pf_osfp_list;
|
||||
pool_t pf_osfp_entry_pl;
|
||||
pool_t pf_osfp_pl;
|
||||
|
||||
struct pf_os_fingerprint *pf_osfp_find(struct pf_osfp_list *,
|
||||
struct pf_os_fingerprint *, u_int8_t);
|
||||
struct pf_os_fingerprint *pf_osfp_find_exact(struct pf_osfp_list *,
|
||||
struct pf_os_fingerprint *);
|
||||
void pf_osfp_insert(struct pf_osfp_list *,
|
||||
struct pf_os_fingerprint *);
|
||||
|
||||
|
||||
#ifdef _KERNEL
|
||||
/*
|
||||
* Passively fingerprint the OS of the host (IPv4 TCP SYN packets only)
|
||||
* Returns the list of possible OSes.
|
||||
*/
|
||||
struct pf_osfp_enlist *
|
||||
pf_osfp_fingerprint(struct pf_pdesc *pd, struct mbuf *m, int off,
|
||||
const struct tcphdr *tcp)
|
||||
{
|
||||
struct ip *ip;
|
||||
char hdr[60];
|
||||
|
||||
/* XXX don't have a fingerprint database for IPv6 :-( */
|
||||
if (pd->af != PF_INET || pd->proto != IPPROTO_TCP || (tcp->th_off << 2)
|
||||
< sizeof(*tcp))
|
||||
return (NULL);
|
||||
|
||||
ip = mtod(m, struct ip *);
|
||||
if (!pf_pull_hdr(m, off, hdr, tcp->th_off << 2, NULL, NULL, pd->af))
|
||||
return (NULL);
|
||||
|
||||
return (pf_osfp_fingerprint_hdr(ip, (struct tcphdr *)hdr));
|
||||
}
|
||||
#endif /* _KERNEL */
|
||||
|
||||
struct pf_osfp_enlist *
|
||||
pf_osfp_fingerprint_hdr(const struct ip *ip, const struct tcphdr *tcp)
|
||||
{
|
||||
struct pf_os_fingerprint fp, *fpresult;
|
||||
int cnt, optlen = 0;
|
||||
u_int8_t *optp;
|
||||
|
||||
if ((tcp->th_flags & (TH_SYN|TH_ACK)) != TH_SYN || (ip->ip_off &
|
||||
htons(IP_OFFMASK)))
|
||||
return (NULL);
|
||||
|
||||
memset(&fp, 0, sizeof(fp));
|
||||
|
||||
fp.fp_psize = ntohs(ip->ip_len);
|
||||
fp.fp_ttl = ip->ip_ttl;
|
||||
if (ip->ip_off & htons(IP_DF))
|
||||
fp.fp_flags |= PF_OSFP_DF;
|
||||
fp.fp_wsize = ntohs(tcp->th_win);
|
||||
|
||||
|
||||
cnt = (tcp->th_off << 2) - sizeof(*tcp);
|
||||
optp = (caddr_t)tcp + sizeof(*tcp);
|
||||
for (; cnt > 0; cnt -= optlen, optp += optlen) {
|
||||
if (*optp == TCPOPT_EOL)
|
||||
break;
|
||||
|
||||
fp.fp_optcnt++;
|
||||
if (*optp == TCPOPT_NOP) {
|
||||
fp.fp_tcpopts = (fp.fp_tcpopts << PF_OSFP_TCPOPT_BITS) |
|
||||
PF_OSFP_TCPOPT_NOP;
|
||||
optlen = 1;
|
||||
} else {
|
||||
if (cnt < 2)
|
||||
return (NULL);
|
||||
optlen = optp[1];
|
||||
if (optlen > cnt || optlen < 2)
|
||||
return (NULL);
|
||||
switch (*optp) {
|
||||
case TCPOPT_MAXSEG:
|
||||
if (optlen >= TCPOLEN_MAXSEG)
|
||||
memcpy(&fp.fp_mss, &optp[2],
|
||||
sizeof(fp.fp_mss));
|
||||
fp.fp_tcpopts = (fp.fp_tcpopts <<
|
||||
PF_OSFP_TCPOPT_BITS) | PF_OSFP_TCPOPT_MSS;
|
||||
NTOHS(fp.fp_mss);
|
||||
break;
|
||||
case TCPOPT_WINDOW:
|
||||
if (optlen >= TCPOLEN_WINDOW)
|
||||
memcpy(&fp.fp_wscale, &optp[2],
|
||||
sizeof(fp.fp_wscale));
|
||||
NTOHS(fp.fp_wscale);
|
||||
fp.fp_tcpopts = (fp.fp_tcpopts <<
|
||||
PF_OSFP_TCPOPT_BITS) |
|
||||
PF_OSFP_TCPOPT_WSCALE;
|
||||
break;
|
||||
case TCPOPT_SACK_PERMITTED:
|
||||
fp.fp_tcpopts = (fp.fp_tcpopts <<
|
||||
PF_OSFP_TCPOPT_BITS) | PF_OSFP_TCPOPT_SACK;
|
||||
break;
|
||||
case TCPOPT_TIMESTAMP:
|
||||
if (optlen >= TCPOLEN_TIMESTAMP) {
|
||||
u_int32_t ts;
|
||||
memcpy(&ts, &optp[2], sizeof(ts));
|
||||
if (ts == 0)
|
||||
fp.fp_flags |= PF_OSFP_TS0;
|
||||
|
||||
}
|
||||
fp.fp_tcpopts = (fp.fp_tcpopts <<
|
||||
PF_OSFP_TCPOPT_BITS) | PF_OSFP_TCPOPT_TS;
|
||||
break;
|
||||
default:
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
optlen = MAX(optlen, 1); /* paranoia */
|
||||
}
|
||||
|
||||
DPFPRINTF("fingerprinted %s:%d %d:%d:%d:%d:%llx (%d) "
|
||||
"(TS=%s,M=%s%d,W=%s%d)\n",
|
||||
inet_ntoa(ip->ip_src), ntohs(tcp->th_sport),
|
||||
fp.fp_wsize, fp.fp_ttl, (fp.fp_flags & PF_OSFP_DF) != 0,
|
||||
fp.fp_psize, (long long int)fp.fp_tcpopts, fp.fp_optcnt,
|
||||
(fp.fp_flags & PF_OSFP_TS0) ? "0" : "",
|
||||
(fp.fp_flags & PF_OSFP_MSS_MOD) ? "%" :
|
||||
(fp.fp_flags & PF_OSFP_MSS_DC) ? "*" : "",
|
||||
fp.fp_mss,
|
||||
(fp.fp_flags & PF_OSFP_WSCALE_MOD) ? "%" :
|
||||
(fp.fp_flags & PF_OSFP_WSCALE_DC) ? "*" : "",
|
||||
fp.fp_wscale);
|
||||
|
||||
if ((fpresult = pf_osfp_find(&pf_osfp_list, &fp,
|
||||
PF_OSFP_MAXTTL_OFFSET)))
|
||||
return (&fpresult->fp_oses);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Match a fingerprint ID against a list of OSes */
|
||||
int
|
||||
pf_osfp_match(struct pf_osfp_enlist *list, pf_osfp_t os)
|
||||
{
|
||||
struct pf_osfp_entry *entry;
|
||||
int os_class, os_version, os_subtype;
|
||||
int en_class, en_version, en_subtype;
|
||||
|
||||
if (os == PF_OSFP_ANY)
|
||||
return (1);
|
||||
if (list == NULL) {
|
||||
DPFPRINTF("osfp no match against %x\n", os);
|
||||
return (os == PF_OSFP_UNKNOWN);
|
||||
}
|
||||
PF_OSFP_UNPACK(os, os_class, os_version, os_subtype);
|
||||
SLIST_FOREACH(entry, list, fp_entry) {
|
||||
PF_OSFP_UNPACK(entry->fp_os, en_class, en_version, en_subtype);
|
||||
if ((os_class == PF_OSFP_ANY || en_class == os_class) &&
|
||||
(os_version == PF_OSFP_ANY || en_version == os_version) &&
|
||||
(os_subtype == PF_OSFP_ANY || en_subtype == os_subtype)) {
|
||||
DPFPRINTF("osfp matched %s %s %s %x==%x\n",
|
||||
entry->fp_class_nm, entry->fp_version_nm,
|
||||
entry->fp_subtype_nm, os, entry->fp_os);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
DPFPRINTF("fingerprint 0x%x didn't match\n", os);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Initialize the OS fingerprint system */
|
||||
void
|
||||
pf_osfp_initialize(void)
|
||||
{
|
||||
pool_init(&pf_osfp_entry_pl, sizeof(struct pf_osfp_entry), 0, 0, 0,
|
||||
"pfosfpen", NULL);
|
||||
pool_init(&pf_osfp_pl, sizeof(struct pf_os_fingerprint), 0, 0, 0,
|
||||
"pfosfp", NULL);
|
||||
SLIST_INIT(&pf_osfp_list);
|
||||
}
|
||||
|
||||
/* Flush the fingerprint list */
|
||||
void
|
||||
pf_osfp_flush(void)
|
||||
{
|
||||
struct pf_os_fingerprint *fp;
|
||||
struct pf_osfp_entry *entry;
|
||||
|
||||
while ((fp = SLIST_FIRST(&pf_osfp_list))) {
|
||||
SLIST_REMOVE_HEAD(&pf_osfp_list, fp_next);
|
||||
while ((entry = SLIST_FIRST(&fp->fp_oses))) {
|
||||
SLIST_REMOVE_HEAD(&fp->fp_oses, fp_entry);
|
||||
pool_put(&pf_osfp_entry_pl, entry);
|
||||
}
|
||||
pool_put(&pf_osfp_pl, fp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Add a fingerprint */
|
||||
int
|
||||
pf_osfp_add(struct pf_osfp_ioctl *fpioc)
|
||||
{
|
||||
struct pf_os_fingerprint *fp, fpadd;
|
||||
struct pf_osfp_entry *entry;
|
||||
|
||||
memset(&fpadd, 0, sizeof(fpadd));
|
||||
fpadd.fp_tcpopts = fpioc->fp_tcpopts;
|
||||
fpadd.fp_wsize = fpioc->fp_wsize;
|
||||
fpadd.fp_psize = fpioc->fp_psize;
|
||||
fpadd.fp_mss = fpioc->fp_mss;
|
||||
fpadd.fp_flags = fpioc->fp_flags;
|
||||
fpadd.fp_optcnt = fpioc->fp_optcnt;
|
||||
fpadd.fp_wscale = fpioc->fp_wscale;
|
||||
fpadd.fp_ttl = fpioc->fp_ttl;
|
||||
|
||||
DPFPRINTF("adding osfp %s %s %s = %s%d:%d:%d:%s%d:0x%llx %d "
|
||||
"(TS=%s,M=%s%d,W=%s%d) %x\n",
|
||||
fpioc->fp_os.fp_class_nm, fpioc->fp_os.fp_version_nm,
|
||||
fpioc->fp_os.fp_subtype_nm,
|
||||
(fpadd.fp_flags & PF_OSFP_WSIZE_MOD) ? "%" :
|
||||
(fpadd.fp_flags & PF_OSFP_WSIZE_MSS) ? "S" :
|
||||
(fpadd.fp_flags & PF_OSFP_WSIZE_MTU) ? "T" :
|
||||
(fpadd.fp_flags & PF_OSFP_WSIZE_DC) ? "*" : "",
|
||||
fpadd.fp_wsize,
|
||||
fpadd.fp_ttl,
|
||||
(fpadd.fp_flags & PF_OSFP_DF) ? 1 : 0,
|
||||
(fpadd.fp_flags & PF_OSFP_PSIZE_MOD) ? "%" :
|
||||
(fpadd.fp_flags & PF_OSFP_PSIZE_DC) ? "*" : "",
|
||||
fpadd.fp_psize,
|
||||
(long long int)fpadd.fp_tcpopts, fpadd.fp_optcnt,
|
||||
(fpadd.fp_flags & PF_OSFP_TS0) ? "0" : "",
|
||||
(fpadd.fp_flags & PF_OSFP_MSS_MOD) ? "%" :
|
||||
(fpadd.fp_flags & PF_OSFP_MSS_DC) ? "*" : "",
|
||||
fpadd.fp_mss,
|
||||
(fpadd.fp_flags & PF_OSFP_WSCALE_MOD) ? "%" :
|
||||
(fpadd.fp_flags & PF_OSFP_WSCALE_DC) ? "*" : "",
|
||||
fpadd.fp_wscale,
|
||||
fpioc->fp_os.fp_os);
|
||||
|
||||
|
||||
if ((fp = pf_osfp_find_exact(&pf_osfp_list, &fpadd))) {
|
||||
SLIST_FOREACH(entry, &fp->fp_oses, fp_entry) {
|
||||
if (PF_OSFP_ENTRY_EQ(entry, &fpioc->fp_os))
|
||||
return (EEXIST);
|
||||
}
|
||||
if ((entry = pool_get(&pf_osfp_entry_pl, PR_NOWAIT)) == NULL)
|
||||
return (ENOMEM);
|
||||
} else {
|
||||
if ((fp = pool_get(&pf_osfp_pl, PR_NOWAIT)) == NULL)
|
||||
return (ENOMEM);
|
||||
memset(fp, 0, sizeof(*fp));
|
||||
fp->fp_tcpopts = fpioc->fp_tcpopts;
|
||||
fp->fp_wsize = fpioc->fp_wsize;
|
||||
fp->fp_psize = fpioc->fp_psize;
|
||||
fp->fp_mss = fpioc->fp_mss;
|
||||
fp->fp_flags = fpioc->fp_flags;
|
||||
fp->fp_optcnt = fpioc->fp_optcnt;
|
||||
fp->fp_wscale = fpioc->fp_wscale;
|
||||
fp->fp_ttl = fpioc->fp_ttl;
|
||||
SLIST_INIT(&fp->fp_oses);
|
||||
if ((entry = pool_get(&pf_osfp_entry_pl, PR_NOWAIT)) == NULL) {
|
||||
pool_put(&pf_osfp_pl, fp);
|
||||
return (ENOMEM);
|
||||
}
|
||||
pf_osfp_insert(&pf_osfp_list, fp);
|
||||
}
|
||||
memcpy(entry, &fpioc->fp_os, sizeof(*entry));
|
||||
|
||||
/* Make sure the strings are NUL terminated */
|
||||
entry->fp_class_nm[sizeof(entry->fp_class_nm)-1] = '\0';
|
||||
entry->fp_version_nm[sizeof(entry->fp_version_nm)-1] = '\0';
|
||||
entry->fp_subtype_nm[sizeof(entry->fp_subtype_nm)-1] = '\0';
|
||||
|
||||
SLIST_INSERT_HEAD(&fp->fp_oses, entry, fp_entry);
|
||||
|
||||
#ifdef PFDEBUG
|
||||
if ((fp = pf_osfp_validate()))
|
||||
printf("Invalid fingerprint list\n");
|
||||
#endif /* PFDEBUG */
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/* Find a fingerprint in the list */
|
||||
struct pf_os_fingerprint *
|
||||
pf_osfp_find(struct pf_osfp_list *list, struct pf_os_fingerprint *find,
|
||||
u_int8_t ttldiff)
|
||||
{
|
||||
struct pf_os_fingerprint *f;
|
||||
|
||||
#define MATCH_INT(_MOD, _DC, _field) \
|
||||
if ((f->fp_flags & _DC) == 0) { \
|
||||
if ((f->fp_flags & _MOD) == 0) { \
|
||||
if (f->_field != find->_field) \
|
||||
continue; \
|
||||
} else { \
|
||||
if (f->_field == 0 || find->_field % f->_field) \
|
||||
continue; \
|
||||
} \
|
||||
}
|
||||
|
||||
SLIST_FOREACH(f, list, fp_next) {
|
||||
if (f->fp_tcpopts != find->fp_tcpopts ||
|
||||
f->fp_optcnt != find->fp_optcnt ||
|
||||
f->fp_ttl < find->fp_ttl ||
|
||||
f->fp_ttl - find->fp_ttl > ttldiff ||
|
||||
(f->fp_flags & (PF_OSFP_DF|PF_OSFP_TS0)) !=
|
||||
(find->fp_flags & (PF_OSFP_DF|PF_OSFP_TS0)))
|
||||
continue;
|
||||
|
||||
MATCH_INT(PF_OSFP_PSIZE_MOD, PF_OSFP_PSIZE_DC, fp_psize)
|
||||
MATCH_INT(PF_OSFP_MSS_MOD, PF_OSFP_MSS_DC, fp_mss)
|
||||
MATCH_INT(PF_OSFP_WSCALE_MOD, PF_OSFP_WSCALE_DC, fp_wscale)
|
||||
if ((f->fp_flags & PF_OSFP_WSIZE_DC) == 0) {
|
||||
if (f->fp_flags & PF_OSFP_WSIZE_MSS) {
|
||||
if (find->fp_mss == 0)
|
||||
continue;
|
||||
|
||||
/* Some "smart" NAT devices and DSL routers will tweak the MSS size and
|
||||
* will set it to whatever is suitable for the link type.
|
||||
*/
|
||||
#define SMART_MSS 1460
|
||||
if ((find->fp_wsize % find->fp_mss ||
|
||||
find->fp_wsize / find->fp_mss !=
|
||||
f->fp_wsize) &&
|
||||
(find->fp_wsize % SMART_MSS ||
|
||||
find->fp_wsize / SMART_MSS !=
|
||||
f->fp_wsize))
|
||||
continue;
|
||||
} else if (f->fp_flags & PF_OSFP_WSIZE_MTU) {
|
||||
if (find->fp_mss == 0)
|
||||
continue;
|
||||
|
||||
#define MTUOFF (sizeof(struct ip) + sizeof(struct tcphdr))
|
||||
#define SMART_MTU (SMART_MSS + MTUOFF)
|
||||
if ((find->fp_wsize % (find->fp_mss + MTUOFF) ||
|
||||
find->fp_wsize / (find->fp_mss + MTUOFF) !=
|
||||
f->fp_wsize) &&
|
||||
(find->fp_wsize % SMART_MTU ||
|
||||
find->fp_wsize / SMART_MTU !=
|
||||
f->fp_wsize))
|
||||
continue;
|
||||
} else if (f->fp_flags & PF_OSFP_WSIZE_MOD) {
|
||||
if (f->fp_wsize == 0 || find->fp_wsize %
|
||||
f->fp_wsize)
|
||||
continue;
|
||||
} else {
|
||||
if (f->fp_wsize != find->fp_wsize)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return (f);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Find an exact fingerprint in the list */
|
||||
struct pf_os_fingerprint *
|
||||
pf_osfp_find_exact(struct pf_osfp_list *list, struct pf_os_fingerprint *find)
|
||||
{
|
||||
struct pf_os_fingerprint *f;
|
||||
|
||||
SLIST_FOREACH(f, list, fp_next) {
|
||||
if (f->fp_tcpopts == find->fp_tcpopts &&
|
||||
f->fp_wsize == find->fp_wsize &&
|
||||
f->fp_psize == find->fp_psize &&
|
||||
f->fp_mss == find->fp_mss &&
|
||||
f->fp_flags == find->fp_flags &&
|
||||
f->fp_optcnt == find->fp_optcnt &&
|
||||
f->fp_wscale == find->fp_wscale &&
|
||||
f->fp_ttl == find->fp_ttl)
|
||||
return (f);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Insert a fingerprint into the list */
|
||||
void
|
||||
pf_osfp_insert(struct pf_osfp_list *list, struct pf_os_fingerprint *ins)
|
||||
{
|
||||
struct pf_os_fingerprint *f, *prev = NULL;
|
||||
|
||||
/* XXX need to go semi tree based. can key on tcp options */
|
||||
|
||||
SLIST_FOREACH(f, list, fp_next)
|
||||
prev = f;
|
||||
if (prev)
|
||||
SLIST_INSERT_AFTER(prev, ins, fp_next);
|
||||
else
|
||||
SLIST_INSERT_HEAD(list, ins, fp_next);
|
||||
}
|
||||
|
||||
/* Fill a fingerprint by its number (from an ioctl) */
|
||||
int
|
||||
pf_osfp_get(struct pf_osfp_ioctl *fpioc)
|
||||
{
|
||||
struct pf_os_fingerprint *fp;
|
||||
struct pf_osfp_entry *entry;
|
||||
int num = fpioc->fp_getnum;
|
||||
int i = 0;
|
||||
|
||||
|
||||
memset(fpioc, 0, sizeof(*fpioc));
|
||||
SLIST_FOREACH(fp, &pf_osfp_list, fp_next) {
|
||||
SLIST_FOREACH(entry, &fp->fp_oses, fp_entry) {
|
||||
if (i++ == num) {
|
||||
fpioc->fp_mss = fp->fp_mss;
|
||||
fpioc->fp_wsize = fp->fp_wsize;
|
||||
fpioc->fp_flags = fp->fp_flags;
|
||||
fpioc->fp_psize = fp->fp_psize;
|
||||
fpioc->fp_ttl = fp->fp_ttl;
|
||||
fpioc->fp_wscale = fp->fp_wscale;
|
||||
fpioc->fp_getnum = num;
|
||||
memcpy(&fpioc->fp_os, entry,
|
||||
sizeof(fpioc->fp_os));
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (EBUSY);
|
||||
}
|
||||
|
||||
|
||||
/* Validate that each signature is reachable */
|
||||
struct pf_os_fingerprint *
|
||||
pf_osfp_validate(void)
|
||||
{
|
||||
struct pf_os_fingerprint *f, *f2, find;
|
||||
|
||||
SLIST_FOREACH(f, &pf_osfp_list, fp_next) {
|
||||
memcpy(&find, f, sizeof(find));
|
||||
|
||||
/* We do a few MSS/th_win percolations to make things unique */
|
||||
if (find.fp_mss == 0)
|
||||
find.fp_mss = 128;
|
||||
if (f->fp_flags & PF_OSFP_WSIZE_MSS)
|
||||
find.fp_wsize *= find.fp_mss, 1;
|
||||
else if (f->fp_flags & PF_OSFP_WSIZE_MTU)
|
||||
find.fp_wsize *= (find.fp_mss + 40);
|
||||
else if (f->fp_flags & PF_OSFP_WSIZE_MOD)
|
||||
find.fp_wsize *= 2;
|
||||
if (f != (f2 = pf_osfp_find(&pf_osfp_list, &find, 0))) {
|
||||
if (f2)
|
||||
printf("Found \"%s %s %s\" instead of "
|
||||
"\"%s %s %s\"\n",
|
||||
SLIST_FIRST(&f2->fp_oses)->fp_class_nm,
|
||||
SLIST_FIRST(&f2->fp_oses)->fp_version_nm,
|
||||
SLIST_FIRST(&f2->fp_oses)->fp_subtype_nm,
|
||||
SLIST_FIRST(&f->fp_oses)->fp_class_nm,
|
||||
SLIST_FIRST(&f->fp_oses)->fp_version_nm,
|
||||
SLIST_FIRST(&f->fp_oses)->fp_subtype_nm);
|
||||
else
|
||||
printf("Couldn't find \"%s %s %s\"\n",
|
||||
SLIST_FIRST(&f->fp_oses)->fp_class_nm,
|
||||
SLIST_FIRST(&f->fp_oses)->fp_version_nm,
|
||||
SLIST_FIRST(&f->fp_oses)->fp_subtype_nm);
|
||||
return (f);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
2018
sys/contrib/pf/net/pf_table.c
Normal file
2018
sys/contrib/pf/net/pf_table.c
Normal file
File diff suppressed because it is too large
Load Diff
1264
sys/contrib/pf/net/pfvar.h
Normal file
1264
sys/contrib/pf/net/pfvar.h
Normal file
File diff suppressed because it is too large
Load Diff
219
sys/contrib/pf/netinet/in4_cksum.c
Normal file
219
sys/contrib/pf/netinet/in4_cksum.c
Normal file
@ -0,0 +1,219 @@
|
||||
/* $OpenBSD: in4_cksum.c,v 1.7 2003/06/02 23:28:13 millert Exp $ */
|
||||
/* $KAME: in4_cksum.c,v 1.10 2001/11/30 10:06:15 itojun Exp $ */
|
||||
/* $NetBSD: in_cksum.c,v 1.13 1996/10/13 02:03:03 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1999 WIDE Project.
|
||||
* 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.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1992, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*
|
||||
* @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_var.h>
|
||||
|
||||
/*
|
||||
* Checksum routine for Internet Protocol family headers (Portable Version).
|
||||
* This is only for IPv4 pseudo header checksum.
|
||||
* No need to clear non-pseudo-header fields in IPv4 header.
|
||||
* len is for actual payload size, and does not include IPv4 header and
|
||||
* skipped header chain (off + len should be equal to the whole packet).
|
||||
*
|
||||
* This routine is very heavily used in the network
|
||||
* code and should be modified for each CPU to be as fast as possible.
|
||||
*/
|
||||
|
||||
#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
|
||||
#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
|
||||
|
||||
int
|
||||
in4_cksum(m, nxt, off, len)
|
||||
struct mbuf *m;
|
||||
u_int8_t nxt;
|
||||
int off, len;
|
||||
{
|
||||
u_int16_t *w;
|
||||
int sum = 0;
|
||||
int mlen = 0;
|
||||
int byte_swapped = 0;
|
||||
union {
|
||||
struct ipovly ipov;
|
||||
u_int16_t w[10];
|
||||
} u;
|
||||
union {
|
||||
u_int8_t c[2];
|
||||
u_int16_t s;
|
||||
} s_util;
|
||||
union {
|
||||
u_int16_t s[2];
|
||||
u_int32_t l;
|
||||
} l_util;
|
||||
|
||||
if (nxt != 0) {
|
||||
/* pseudo header */
|
||||
if (off < sizeof(struct ipovly))
|
||||
panic("in4_cksum: offset too short");
|
||||
if (m->m_len < sizeof(struct ip))
|
||||
panic("in4_cksum: bad mbuf chain");
|
||||
bzero(&u.ipov, sizeof(u.ipov));
|
||||
u.ipov.ih_len = htons(len);
|
||||
u.ipov.ih_pr = nxt;
|
||||
u.ipov.ih_src = mtod(m, struct ip *)->ip_src;
|
||||
u.ipov.ih_dst = mtod(m, struct ip *)->ip_dst;
|
||||
w = u.w;
|
||||
/* assumes sizeof(ipov) == 20 */
|
||||
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; sum += w[4];
|
||||
sum += w[5]; sum += w[6]; sum += w[7]; sum += w[8]; sum += w[9];
|
||||
}
|
||||
|
||||
/* skip unnecessary part */
|
||||
while (m && off > 0) {
|
||||
if (m->m_len > off)
|
||||
break;
|
||||
off -= m->m_len;
|
||||
m = m->m_next;
|
||||
}
|
||||
|
||||
for (;m && len; m = m->m_next) {
|
||||
if (m->m_len == 0)
|
||||
continue;
|
||||
w = (u_int16_t *)(mtod(m, caddr_t) + off);
|
||||
if (mlen == -1) {
|
||||
/*
|
||||
* The first byte of this mbuf is the continuation
|
||||
* of a word spanning between this mbuf and the
|
||||
* last mbuf.
|
||||
*
|
||||
* s_util.c[0] is already saved when scanning previous
|
||||
* mbuf.
|
||||
*/
|
||||
s_util.c[1] = *(u_int8_t *)w;
|
||||
sum += s_util.s;
|
||||
w = (u_int16_t *)((u_int8_t *)w + 1);
|
||||
mlen = m->m_len - off - 1;
|
||||
len--;
|
||||
} else
|
||||
mlen = m->m_len - off;
|
||||
off = 0;
|
||||
if (len < mlen)
|
||||
mlen = len;
|
||||
len -= mlen;
|
||||
/*
|
||||
* Force to even boundary.
|
||||
*/
|
||||
if ((1 & (long) w) && (mlen > 0)) {
|
||||
REDUCE;
|
||||
sum <<= 8;
|
||||
s_util.c[0] = *(u_int8_t *)w;
|
||||
w = (u_int16_t *)((int8_t *)w + 1);
|
||||
mlen--;
|
||||
byte_swapped = 1;
|
||||
}
|
||||
/*
|
||||
* Unroll the loop to make overhead from
|
||||
* branches &c small.
|
||||
*/
|
||||
while ((mlen -= 32) >= 0) {
|
||||
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
|
||||
sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
|
||||
sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
|
||||
sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
|
||||
w += 16;
|
||||
}
|
||||
mlen += 32;
|
||||
while ((mlen -= 8) >= 0) {
|
||||
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
|
||||
w += 4;
|
||||
}
|
||||
mlen += 8;
|
||||
if (mlen == 0 && byte_swapped == 0)
|
||||
continue;
|
||||
REDUCE;
|
||||
while ((mlen -= 2) >= 0) {
|
||||
sum += *w++;
|
||||
}
|
||||
if (byte_swapped) {
|
||||
REDUCE;
|
||||
sum <<= 8;
|
||||
byte_swapped = 0;
|
||||
if (mlen == -1) {
|
||||
s_util.c[1] = *(u_int8_t *)w;
|
||||
sum += s_util.s;
|
||||
mlen = 0;
|
||||
} else
|
||||
mlen = -1;
|
||||
} else if (mlen == -1)
|
||||
s_util.c[0] = *(u_int8_t *)w;
|
||||
}
|
||||
if (len)
|
||||
printf("cksum4: out of data\n");
|
||||
if (mlen == -1) {
|
||||
/* The last mbuf has odd # of bytes. Follow the
|
||||
standard (the odd byte may be shifted left by 8 bits
|
||||
or not as determined by endian-ness of the machine) */
|
||||
s_util.c[1] = 0;
|
||||
sum += s_util.s;
|
||||
}
|
||||
REDUCE;
|
||||
return (~sum & 0xffff);
|
||||
}
|
Loading…
Reference in New Issue
Block a user