if_pflog.c revision 240233
174429Sorion/* $OpenBSD: if_pflog.c,v 1.26 2007/10/18 21:58:18 mpf Exp $ */ 274429Sorion/* 374429Sorion * The authors of this code are John Ioannidis (ji@tla.org), 474429Sorion * Angelos D. Keromytis (kermit@csd.uch.gr) and 574429Sorion * Niels Provos (provos@physnet.uni-hamburg.de). 674429Sorion * 774429Sorion * This code was written by John Ioannidis for BSD/OS in Athens, Greece, 874429Sorion * in November 1995. 974429Sorion * 1074429Sorion * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, 1174429Sorion * by Angelos D. Keromytis. 1274429Sorion * 1374429Sorion * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis 1474429Sorion * and Niels Provos. 1574429Sorion * 1674429Sorion * Copyright (C) 1995, 1996, 1997, 1998 by John Ioannidis, Angelos D. Keromytis 1774429Sorion * and Niels Provos. 1874429Sorion * Copyright (c) 2001, Angelos D. Keromytis, Niels Provos. 1974429Sorion * 2074429Sorion * Permission to use, copy, and modify this software with or without fee 2174429Sorion * is hereby granted, provided that this entire notice is included in 2274429Sorion * all copies of any software which is or includes a copy or 2374429Sorion * modification of this software. 2474429Sorion * You may use this code under the GNU public license if you so wish. Please 2574429Sorion * contribute changes back to the authors under this freer than GPL license 2674429Sorion * so that we may further the use of strong encryption without limitations to 2774429Sorion * all. 2874429Sorion * 2974429Sorion * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR 3074429Sorion * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY 3174429Sorion * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE 3274429Sorion * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR 3374429Sorion * PURPOSE. 3474429Sorion */ 3574429Sorion 3674429Sorion#include <sys/cdefs.h> 3774429Sorion__FBSDID("$FreeBSD: head/sys/contrib/pf/net/if_pflog.c 240233 2012-09-08 06:41:54Z glebius $"); 3874429Sorion 3974429Sorion#include "opt_inet.h" 4074429Sorion#include "opt_inet6.h" 4174429Sorion#include "opt_bpf.h" 4274429Sorion#include "opt_pf.h" 4374429Sorion 4474429Sorion#include <sys/param.h> 4574429Sorion#include <sys/kernel.h> 4674429Sorion#include <sys/mbuf.h> 4774429Sorion#include <sys/module.h> 4874429Sorion#include <sys/proc.h> 4974429Sorion#include <sys/socket.h> 5074429Sorion#include <sys/sockio.h> 5174429Sorion 5274429Sorion#include <net/bpf.h> 5374429Sorion#include <net/if.h> 5474429Sorion#include <net/if_clone.h> 5574429Sorion#include <net/if_pflog.h> 5674429Sorion#include <net/if_types.h> 5774429Sorion#include <net/pfvar.h> 5874429Sorion 5974429Sorion#if defined(INET) || defined(INET6) 6074429Sorion#include <netinet/in.h> 6174429Sorion#endif 6274429Sorion#ifdef INET 6374429Sorion#include <netinet/in_var.h> 6474429Sorion#include <netinet/ip.h> 6574429Sorion#endif 6674429Sorion 6774429Sorion#ifdef INET6 6874429Sorion#include <netinet6/in6_var.h> 6974429Sorion#include <netinet6/nd6.h> 7074429Sorion#endif /* INET6 */ 7174429Sorion 7274429Sorion#ifdef INET 7374429Sorion#include <machine/in_cksum.h> 7474429Sorion#endif /* INET */ 7574429Sorion 7674429Sorion#define PFLOGMTU (32768 + MHLEN + MLEN) 7774429Sorion 7874429Sorion#ifdef PFLOGDEBUG 7974429Sorion#define DPRINTF(x) do { if (pflogdebug) printf x ; } while (0) 8074429Sorion#else 8174429Sorion#define DPRINTF(x) 8274429Sorion#endif 8374429Sorion 8474429Sorionstatic int pflogoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 8574429Sorion struct route *); 8674429Sorionstatic void pflogattach(int); 8774429Sorionstatic int pflogioctl(struct ifnet *, u_long, caddr_t); 8874429Sorionstatic void pflogstart(struct ifnet *); 8974429Sorionstatic int pflog_clone_create(struct if_clone *, int, caddr_t); 9074429Sorionstatic void pflog_clone_destroy(struct ifnet *); 9174429Sorion 9274429SorionIFC_SIMPLE_DECLARE(pflog, 1); 9374429Sorion 9474429Sorionstruct ifnet *pflogifs[PFLOGIFS_MAX]; /* for fast access */ 9574429Sorion 9674429Sorionstatic void 9774429Sorionpflogattach(int npflog) 9874429Sorion{ 9974429Sorion int i; 10074429Sorion for (i = 0; i < PFLOGIFS_MAX; i++) 10174429Sorion pflogifs[i] = NULL; 10274429Sorion if_clone_attach(&pflog_cloner); 10374429Sorion} 10474429Sorion 10574429Sorionstatic int 10674429Sorionpflog_clone_create(struct if_clone *ifc, int unit, caddr_t param) 10774429Sorion{ 10874429Sorion struct ifnet *ifp; 10974429Sorion 11074429Sorion if (unit >= PFLOGIFS_MAX) 11174429Sorion return (EINVAL); 11274429Sorion 11374429Sorion ifp = if_alloc(IFT_PFLOG); 11474429Sorion if (ifp == NULL) { 11574429Sorion return (ENOSPC); 11674429Sorion } 11774429Sorion if_initname(ifp, ifc->ifc_name, unit); 11874429Sorion ifp->if_mtu = PFLOGMTU; 11974429Sorion ifp->if_ioctl = pflogioctl; 12074429Sorion ifp->if_output = pflogoutput; 12174429Sorion ifp->if_start = pflogstart; 12274429Sorion ifp->if_snd.ifq_maxlen = ifqmaxlen; 12374429Sorion ifp->if_hdrlen = PFLOG_HDRLEN; 12474429Sorion if_attach(ifp); 12574429Sorion 12674429Sorion bpfattach(ifp, DLT_PFLOG, PFLOG_HDRLEN); 12774429Sorion 12874429Sorion pflogifs[unit] = ifp; 12974429Sorion 13074429Sorion return (0); 13174429Sorion} 13274429Sorion 13374429Sorionstatic void 13474429Sorionpflog_clone_destroy(struct ifnet *ifp) 13574429Sorion{ 13674429Sorion int i; 13774429Sorion 13874429Sorion for (i = 0; i < PFLOGIFS_MAX; i++) 13974429Sorion if (pflogifs[i] == ifp) 14074429Sorion pflogifs[i] = NULL; 14174429Sorion 14274429Sorion bpfdetach(ifp); 14374429Sorion if_detach(ifp); 14474429Sorion if_free(ifp); 14574429Sorion} 14674429Sorion 14774429Sorion/* 14874429Sorion * Start output on the pflog interface. 14974429Sorion */ 15074429Sorionstatic void 15174429Sorionpflogstart(struct ifnet *ifp) 15274429Sorion{ 15374429Sorion struct mbuf *m; 15474429Sorion 15574429Sorion for (;;) { 15674429Sorion IF_LOCK(&ifp->if_snd); 15774429Sorion _IF_DROP(&ifp->if_snd); 15874429Sorion _IF_DEQUEUE(&ifp->if_snd, m); 15974429Sorion IF_UNLOCK(&ifp->if_snd); 16074429Sorion 16174429Sorion if (m == NULL) 16274429Sorion return; 16374429Sorion else 16474429Sorion m_freem(m); 16574429Sorion } 16674429Sorion} 16774429Sorion 16874429Sorionstatic int 16974429Sorionpflogoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 17074429Sorion struct route *rt) 17174429Sorion{ 17274429Sorion m_freem(m); 17374429Sorion return (0); 17474429Sorion} 17574429Sorion 17674429Sorion/* ARGSUSED */ 17774429Sorionstatic int 17874429Sorionpflogioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 17974429Sorion{ 18074429Sorion switch (cmd) { 18174429Sorion case SIOCSIFFLAGS: 18274429Sorion if (ifp->if_flags & IFF_UP) 18374429Sorion ifp->if_drv_flags |= IFF_DRV_RUNNING; 18474429Sorion else 18574429Sorion ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 18674429Sorion break; 18774429Sorion default: 18874429Sorion return (ENOTTY); 18974429Sorion } 19074429Sorion 19174429Sorion return (0); 19274429Sorion} 19374429Sorion 19474429Sorionstatic int 19574429Sorionpflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir, 19674429Sorion u_int8_t reason, struct pf_rule *rm, struct pf_rule *am, 19774429Sorion struct pf_ruleset *ruleset, struct pf_pdesc *pd, int lookupsafe) 19874429Sorion{ 19974429Sorion struct ifnet *ifn; 20074429Sorion struct pfloghdr hdr; 20174429Sorion 20274429Sorion if (kif == NULL || m == NULL || rm == NULL || pd == NULL) 20374429Sorion return ( 1); 20474429Sorion 20574429Sorion if ((ifn = pflogifs[rm->logif]) == NULL || !ifn->if_bpf) 20674429Sorion return (0); 20774429Sorion 20874429Sorion bzero(&hdr, sizeof(hdr)); 20974429Sorion hdr.length = PFLOG_REAL_HDRLEN; 21074429Sorion hdr.af = af; 21174429Sorion hdr.action = rm->action; 21274429Sorion hdr.reason = reason; 21374429Sorion memcpy(hdr.ifname, kif->pfik_name, sizeof(hdr.ifname)); 21474429Sorion 21574429Sorion if (am == NULL) { 21674429Sorion hdr.rulenr = htonl(rm->nr); 21774429Sorion hdr.subrulenr = 1; 21874429Sorion } else { 21974429Sorion hdr.rulenr = htonl(am->nr); 22074429Sorion hdr.subrulenr = htonl(rm->nr); 22174429Sorion if (ruleset != NULL && ruleset->anchor != NULL) 22274429Sorion strlcpy(hdr.ruleset, ruleset->anchor->name, 22374429Sorion sizeof(hdr.ruleset)); 22474429Sorion } 22574429Sorion /* 22674429Sorion * XXXGL: we avoid pf_socket_lookup() when we are holding 22774429Sorion * state lock, since this leads to unsafe LOR. 22874429Sorion * These conditions are very very rare, however. 22974429Sorion */ 23074429Sorion if (rm->log & PF_LOG_SOCKET_LOOKUP && !pd->lookup.done && lookupsafe) 23174429Sorion pd->lookup.done = pf_socket_lookup(dir, pd, m); 23274429Sorion if (pd->lookup.done > 0) 23374429Sorion hdr.uid = pd->lookup.uid; 23474429Sorion else 23574429Sorion hdr.uid = UID_MAX; 23674429Sorion hdr.pid = NO_PID; 23774429Sorion hdr.rule_uid = rm->cuid; 23874429Sorion hdr.rule_pid = rm->cpid; 23974429Sorion hdr.dir = dir; 24074429Sorion 24174429Sorion#ifdef INET 24274429Sorion if (af == AF_INET && dir == PF_OUT) { 24374429Sorion struct ip *ip; 24474429Sorion 24574429Sorion ip = mtod(m, struct ip *); 24674429Sorion ip->ip_sum = 0; 24774429Sorion ip->ip_sum = in_cksum(m, ip->ip_hl << 2); 24874429Sorion } 24974429Sorion#endif /* INET */ 25074429Sorion 25174429Sorion ifn->if_opackets++; 25274429Sorion ifn->if_obytes += m->m_pkthdr.len; 25374429Sorion BPF_MTAP2(ifn, &hdr, PFLOG_HDRLEN, m); 25474429Sorion 25574429Sorion return (0); 25674429Sorion} 25774429Sorion 25874429Sorionstatic int 25974429Sorionpflog_modevent(module_t mod, int type, void *data) 26074429Sorion{ 26174429Sorion int error = 0; 26274429Sorion 26374429Sorion switch (type) { 26474429Sorion case MOD_LOAD: 26574429Sorion pflogattach(1); 26674429Sorion PF_RULES_WLOCK(); 26774429Sorion pflog_packet_ptr = pflog_packet; 26874429Sorion PF_RULES_WUNLOCK(); 26974429Sorion break; 27074429Sorion case MOD_UNLOAD: 27174429Sorion PF_RULES_WLOCK(); 27274429Sorion pflog_packet_ptr = NULL; 27374429Sorion PF_RULES_WUNLOCK(); 27474429Sorion if_clone_detach(&pflog_cloner); 27574429Sorion break; 27674429Sorion default: 27774429Sorion error = EINVAL; 27874429Sorion break; 27974429Sorion } 28074429Sorion 28174429Sorion return error; 28274429Sorion} 28374429Sorion 28474429Sorionstatic moduledata_t pflog_mod = { "pflog", pflog_modevent, 0 }; 28574429Sorion 28674429Sorion#define PFLOG_MODVER 1 28774429Sorion 28874429SorionDECLARE_MODULE(pflog, pflog_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 28974429SorionMODULE_VERSION(pflog, PFLOG_MODVER); 29074429SorionMODULE_DEPEND(pflog, pf, PF_MODVER, PF_MODVER, PF_MODVER); 29174429Sorion