if_pflog.c revision 193900
1171168Smlaier/* $OpenBSD: if_pflog.c,v 1.22 2006/12/15 09:31:20 otto Exp $ */ 2126258Smlaier/* 3126258Smlaier * The authors of this code are John Ioannidis (ji@tla.org), 4126258Smlaier * Angelos D. Keromytis (kermit@csd.uch.gr) and 5126258Smlaier * Niels Provos (provos@physnet.uni-hamburg.de). 6126258Smlaier * 7126258Smlaier * This code was written by John Ioannidis for BSD/OS in Athens, Greece, 8126258Smlaier * in November 1995. 9126258Smlaier * 10126258Smlaier * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, 11126258Smlaier * by Angelos D. Keromytis. 12126258Smlaier * 13126258Smlaier * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis 14126258Smlaier * and Niels Provos. 15126258Smlaier * 16126258Smlaier * Copyright (C) 1995, 1996, 1997, 1998 by John Ioannidis, Angelos D. Keromytis 17126258Smlaier * and Niels Provos. 18126258Smlaier * Copyright (c) 2001, Angelos D. Keromytis, Niels Provos. 19126258Smlaier * 20126258Smlaier * Permission to use, copy, and modify this software with or without fee 21126258Smlaier * is hereby granted, provided that this entire notice is included in 22126258Smlaier * all copies of any software which is or includes a copy or 23126258Smlaier * modification of this software. 24126258Smlaier * You may use this code under the GNU public license if you so wish. Please 25126258Smlaier * contribute changes back to the authors under this freer than GPL license 26126258Smlaier * so that we may further the use of strong encryption without limitations to 27126258Smlaier * all. 28126258Smlaier * 29126258Smlaier * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR 30126258Smlaier * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY 31126258Smlaier * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE 32126258Smlaier * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR 33126258Smlaier * PURPOSE. 34126258Smlaier */ 35126258Smlaier 36127145Smlaier#ifdef __FreeBSD__ 37126261Smlaier#include "opt_inet.h" 38126261Smlaier#include "opt_inet6.h" 39126261Smlaier#include "opt_bpf.h" 40126261Smlaier#include "opt_pf.h" 41153110Sru 42171168Smlaier#include <sys/cdefs.h> 43171168Smlaier__FBSDID("$FreeBSD: head/sys/contrib/pf/net/if_pflog.c 193900 2009-06-10 11:19:34Z bz $"); 44171168Smlaier 45153110Sru#ifdef DEV_BPF 46127145Smlaier#define NBPFILTER DEV_BPF 47153110Sru#else 48153110Sru#define NBPFILTER 0 49153110Sru#endif 50153110Sru 51153110Sru#ifdef DEV_PFLOG 52127145Smlaier#define NPFLOG DEV_PFLOG 53153110Sru#else 54153110Sru#define NPFLOG 0 55126261Smlaier#endif 56126258Smlaier 57171168Smlaier#else /* ! __FreeBSD__ */ 58171168Smlaier#include "bpfilter.h" 59171168Smlaier#include "pflog.h" 60171168Smlaier#endif /* __FreeBSD__ */ 61153110Sru 62126258Smlaier#include <sys/param.h> 63126258Smlaier#include <sys/systm.h> 64126258Smlaier#include <sys/mbuf.h> 65171168Smlaier#include <sys/proc.h> 66126258Smlaier#include <sys/socket.h> 67127145Smlaier#ifdef __FreeBSD__ 68126261Smlaier#include <sys/kernel.h> 69171168Smlaier#include <sys/limits.h> 70126261Smlaier#include <sys/malloc.h> 71129907Smlaier#include <sys/module.h> 72126261Smlaier#include <sys/sockio.h> 73126261Smlaier#else 74126258Smlaier#include <sys/ioctl.h> 75126261Smlaier#endif 76126258Smlaier 77126258Smlaier#include <net/if.h> 78171168Smlaier#ifdef __FreeBSD__ 79130933Sbrooks#include <net/if_clone.h> 80130933Sbrooks#endif 81126258Smlaier#include <net/if_types.h> 82126258Smlaier#include <net/route.h> 83126258Smlaier#include <net/bpf.h> 84126258Smlaier 85126258Smlaier#ifdef INET 86126258Smlaier#include <netinet/in.h> 87126258Smlaier#include <netinet/in_var.h> 88126258Smlaier#include <netinet/in_systm.h> 89126258Smlaier#include <netinet/ip.h> 90126258Smlaier#endif 91126258Smlaier 92126258Smlaier#ifdef INET6 93126258Smlaier#ifndef INET 94126258Smlaier#include <netinet/in.h> 95126258Smlaier#endif 96126258Smlaier#include <netinet6/nd6.h> 97126258Smlaier#endif /* INET6 */ 98126258Smlaier 99126258Smlaier#include <net/pfvar.h> 100126258Smlaier#include <net/if_pflog.h> 101126258Smlaier 102193900Sbz#ifdef INET 103127145Smlaier#ifdef __FreeBSD__ 104171168Smlaier#include <machine/in_cksum.h> 105126261Smlaier#endif 106193900Sbz#endif 107126261Smlaier 108126258Smlaier#define PFLOGMTU (32768 + MHLEN + MLEN) 109126258Smlaier 110126258Smlaier#ifdef PFLOGDEBUG 111126258Smlaier#define DPRINTF(x) do { if (pflogdebug) printf x ; } while (0) 112126258Smlaier#else 113126258Smlaier#define DPRINTF(x) 114126258Smlaier#endif 115126258Smlaier 116126258Smlaiervoid pflogattach(int); 117126258Smlaierint pflogoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 118191148Skmacy struct route *); 119126258Smlaierint pflogioctl(struct ifnet *, u_long, caddr_t); 120126258Smlaiervoid pflogstart(struct ifnet *); 121171168Smlaier#ifdef __FreeBSD__ 122171168Smlaierstatic int pflog_clone_create(struct if_clone *, int, caddr_t); 123171168Smlaierstatic void pflog_clone_destroy(struct ifnet *); 124171168Smlaier#else 125171168Smlaierint pflog_clone_create(struct if_clone *, int); 126171168Smlaierint pflog_clone_destroy(struct ifnet *); 127171168Smlaier#endif 128126258Smlaier 129171168SmlaierLIST_HEAD(, pflog_softc) pflogif_list; 130171168Smlaier#ifdef __FreeBSD__ 131171168SmlaierIFC_SIMPLE_DECLARE(pflog, 1); 132171168Smlaier#else 133171168Smlaierstruct if_clone pflog_cloner = 134171168Smlaier IF_CLONE_INITIALIZER("pflog", pflog_clone_create, pflog_clone_destroy); 135171168Smlaier#endif 136171168Smlaier 137171168Smlaierstruct ifnet *pflogifs[PFLOGIFS_MAX]; /* for fast access */ 138171168Smlaier 139127145Smlaier#ifndef __FreeBSD__ 140126258Smlaierextern int ifqmaxlen; 141126261Smlaier#endif 142126258Smlaier 143171168Smlaiervoid 144171168Smlaierpflogattach(int npflog) 145126261Smlaier{ 146171168Smlaier int i; 147171168Smlaier LIST_INIT(&pflogif_list); 148171168Smlaier for (i = 0; i < PFLOGIFS_MAX; i++) 149171168Smlaier pflogifs[i] = NULL; 150171168Smlaier#ifndef __FreeBSD__ 151171168Smlaier (void) pflog_clone_create(&pflog_cloner, 0); 152171168Smlaier#endif 153171168Smlaier if_clone_attach(&pflog_cloner); 154126261Smlaier} 155126261Smlaier 156171168Smlaier#ifdef __FreeBSD__ 157128209Sbrooksstatic int 158171168Smlaierpflog_clone_create(struct if_clone *ifc, int unit, caddr_t param) 159160195Ssam#else 160171168Smlaierint 161126261Smlaierpflog_clone_create(struct if_clone *ifc, int unit) 162160195Ssam#endif 163126261Smlaier{ 164141584Smlaier struct ifnet *ifp; 165171168Smlaier struct pflog_softc *pflogif; 166171168Smlaier int s; 167126261Smlaier 168171168Smlaier if (unit >= PFLOGIFS_MAX) 169171168Smlaier return (EINVAL); 170171168Smlaier 171171168Smlaier if ((pflogif = malloc(sizeof(*pflogif), M_DEVBUF, M_NOWAIT)) == NULL) 172171168Smlaier return (ENOMEM); 173171168Smlaier bzero(pflogif, sizeof(*pflogif)); 174171168Smlaier 175171168Smlaier pflogif->sc_unit = unit; 176171168Smlaier#ifdef __FreeBSD__ 177171168Smlaier ifp = pflogif->sc_ifp = if_alloc(IFT_PFLOG); 178147256Sbrooks if (ifp == NULL) { 179171168Smlaier free(pflogif, M_DEVBUF); 180147256Sbrooks return (ENOSPC); 181147256Sbrooks } 182141584Smlaier if_initname(ifp, ifc->ifc_name, unit); 183171168Smlaier#else 184171168Smlaier ifp = &pflogif->sc_if; 185171168Smlaier snprintf(ifp->if_xname, sizeof ifp->if_xname, "pflog%d", unit); 186171168Smlaier#endif 187171168Smlaier ifp->if_softc = pflogif; 188141584Smlaier ifp->if_mtu = PFLOGMTU; 189141584Smlaier ifp->if_ioctl = pflogioctl; 190141584Smlaier ifp->if_output = pflogoutput; 191141584Smlaier ifp->if_start = pflogstart; 192171168Smlaier#ifndef __FreeBSD__ 193171168Smlaier ifp->if_type = IFT_PFLOG; 194171168Smlaier#endif 195141584Smlaier ifp->if_snd.ifq_maxlen = ifqmaxlen; 196141584Smlaier ifp->if_hdrlen = PFLOG_HDRLEN; 197141584Smlaier if_attach(ifp); 198171168Smlaier#ifndef __FreeBSD__ 199171168Smlaier if_alloc_sadl(ifp); 200171168Smlaier#endif 201126261Smlaier 202126261Smlaier#if NBPFILTER > 0 203171168Smlaier#ifdef __FreeBSD__ 204141584Smlaier bpfattach(ifp, DLT_PFLOG, PFLOG_HDRLEN); 205171168Smlaier#else 206171168Smlaier bpfattach(&pflogif->sc_if.if_bpf, ifp, DLT_PFLOG, PFLOG_HDRLEN); 207126261Smlaier#endif 208171168Smlaier#endif 209126261Smlaier 210171168Smlaier s = splnet(); 211171168Smlaier#ifdef __FreeBSD__ 212171168Smlaier PF_LOCK(); 213171168Smlaier#endif 214171168Smlaier LIST_INSERT_HEAD(&pflogif_list, pflogif, sc_list); 215171168Smlaier pflogifs[unit] = ifp; 216171168Smlaier#ifdef __FreeBSD__ 217171168Smlaier PF_UNLOCK(); 218171168Smlaier#endif 219171168Smlaier splx(s); 220171168Smlaier 221141584Smlaier return (0); 222126261Smlaier} 223171168Smlaier 224171168Smlaier#ifdef __FreeBSD__ 225171168Smlaierstatic void 226171168Smlaierpflog_clone_destroy(struct ifnet *ifp) 227171168Smlaier#else 228171168Smlaierint 229171168Smlaierpflog_clone_destroy(struct ifnet *ifp) 230171168Smlaier#endif 231126258Smlaier{ 232171168Smlaier struct pflog_softc *pflogif = ifp->if_softc; 233171168Smlaier int s; 234126258Smlaier 235171168Smlaier s = splnet(); 236171168Smlaier#ifdef __FreeBSD__ 237171168Smlaier PF_LOCK(); 238171168Smlaier#endif 239171168Smlaier pflogifs[pflogif->sc_unit] = NULL; 240171168Smlaier LIST_REMOVE(pflogif, sc_list); 241171168Smlaier#ifdef __FreeBSD__ 242171168Smlaier PF_UNLOCK(); 243171168Smlaier#endif 244171168Smlaier splx(s); 245126258Smlaier 246126258Smlaier#if NBPFILTER > 0 247171168Smlaier bpfdetach(ifp); 248126258Smlaier#endif 249171168Smlaier if_detach(ifp); 250171168Smlaier#ifdef __FreeBSD__ 251171168Smlaier if_free(ifp); 252171168Smlaier#endif 253171168Smlaier free(pflogif, M_DEVBUF); 254171168Smlaier#ifndef __FreeBSD__ 255171168Smlaier return (0); 256171168Smlaier#endif 257126258Smlaier} 258126258Smlaier 259126258Smlaier/* 260126258Smlaier * Start output on the pflog interface. 261126258Smlaier */ 262126258Smlaiervoid 263126258Smlaierpflogstart(struct ifnet *ifp) 264126258Smlaier{ 265126258Smlaier struct mbuf *m; 266130613Smlaier#ifndef __FreeBSD__ 267126258Smlaier int s; 268130613Smlaier#endif 269126258Smlaier 270126258Smlaier for (;;) { 271127145Smlaier#ifdef __FreeBSD__ 272130475Smlaier IF_LOCK(&ifp->if_snd); 273130475Smlaier _IF_DROP(&ifp->if_snd); 274130475Smlaier _IF_DEQUEUE(&ifp->if_snd, m); 275171168Smlaier IF_UNLOCK(&ifp->if_snd); 276126261Smlaier#else 277171168Smlaier s = splnet(); 278126258Smlaier IF_DROP(&ifp->if_snd); 279126258Smlaier IF_DEQUEUE(&ifp->if_snd, m); 280126258Smlaier splx(s); 281171168Smlaier#endif 282171168Smlaier 283126258Smlaier if (m == NULL) 284126258Smlaier return; 285126258Smlaier else 286126258Smlaier m_freem(m); 287126258Smlaier } 288126258Smlaier} 289126258Smlaier 290126258Smlaierint 291126258Smlaierpflogoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 292191148Skmacy struct route *ro) 293126258Smlaier{ 294126258Smlaier m_freem(m); 295126258Smlaier return (0); 296126258Smlaier} 297126258Smlaier 298126258Smlaier/* ARGSUSED */ 299126258Smlaierint 300126258Smlaierpflogioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 301126258Smlaier{ 302126258Smlaier switch (cmd) { 303126258Smlaier case SIOCSIFADDR: 304126258Smlaier case SIOCAIFADDR: 305126258Smlaier case SIOCSIFDSTADDR: 306126258Smlaier case SIOCSIFFLAGS: 307148891Smlaier#ifdef __FreeBSD__ 308126258Smlaier if (ifp->if_flags & IFF_UP) 309148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 310126258Smlaier else 311148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 312148891Smlaier#else 313148891Smlaier if (ifp->if_flags & IFF_UP) 314148891Smlaier ifp->if_flags |= IFF_RUNNING; 315148891Smlaier else 316148891Smlaier ifp->if_flags &= ~IFF_RUNNING; 317148891Smlaier#endif 318126258Smlaier break; 319126258Smlaier default: 320126258Smlaier return (EINVAL); 321126258Smlaier } 322126258Smlaier 323126258Smlaier return (0); 324126258Smlaier} 325126258Smlaier 326126258Smlaierint 327130613Smlaierpflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir, 328126258Smlaier u_int8_t reason, struct pf_rule *rm, struct pf_rule *am, 329171168Smlaier struct pf_ruleset *ruleset, struct pf_pdesc *pd) 330126258Smlaier{ 331126258Smlaier#if NBPFILTER > 0 332126258Smlaier struct ifnet *ifn; 333126258Smlaier struct pfloghdr hdr; 334126258Smlaier 335171168Smlaier if (kif == NULL || m == NULL || rm == NULL || pd == NULL) 336126258Smlaier return (-1); 337126258Smlaier 338171168Smlaier if ((ifn = pflogifs[rm->logif]) == NULL || !ifn->if_bpf) 339171168Smlaier return (0); 340171168Smlaier 341130613Smlaier bzero(&hdr, sizeof(hdr)); 342126258Smlaier hdr.length = PFLOG_REAL_HDRLEN; 343126258Smlaier hdr.af = af; 344126258Smlaier hdr.action = rm->action; 345126258Smlaier hdr.reason = reason; 346130613Smlaier memcpy(hdr.ifname, kif->pfik_name, sizeof(hdr.ifname)); 347126258Smlaier 348126258Smlaier if (am == NULL) { 349126258Smlaier hdr.rulenr = htonl(rm->nr); 350126258Smlaier hdr.subrulenr = -1; 351126258Smlaier } else { 352126258Smlaier hdr.rulenr = htonl(am->nr); 353126258Smlaier hdr.subrulenr = htonl(rm->nr); 354145836Smlaier if (ruleset != NULL && ruleset->anchor != NULL) 355145836Smlaier strlcpy(hdr.ruleset, ruleset->anchor->name, 356126258Smlaier sizeof(hdr.ruleset)); 357126258Smlaier } 358171168Smlaier if (rm->log & PF_LOG_SOCKET_LOOKUP && !pd->lookup.done) 359171168Smlaier#ifdef __FreeBSD__ 360171168Smlaier /* 361171168Smlaier * XXX: This should not happen as we force an early lookup 362171168Smlaier * via debug.pfugidhack 363171168Smlaier */ 364171168Smlaier ; /* empty */ 365171168Smlaier#else 366171168Smlaier pd->lookup.done = pf_socket_lookup(dir, pd); 367171168Smlaier#endif 368171168Smlaier if (pd->lookup.done > 0) { 369171168Smlaier hdr.uid = pd->lookup.uid; 370171168Smlaier hdr.pid = pd->lookup.pid; 371171168Smlaier } else { 372171168Smlaier hdr.uid = UID_MAX; 373171168Smlaier hdr.pid = NO_PID; 374171168Smlaier } 375171168Smlaier hdr.rule_uid = rm->cuid; 376171168Smlaier hdr.rule_pid = rm->cpid; 377126258Smlaier hdr.dir = dir; 378126258Smlaier 379126258Smlaier#ifdef INET 380126258Smlaier if (af == AF_INET && dir == PF_OUT) { 381126258Smlaier struct ip *ip; 382126258Smlaier 383126258Smlaier ip = mtod(m, struct ip *); 384126258Smlaier ip->ip_sum = 0; 385126258Smlaier ip->ip_sum = in_cksum(m, ip->ip_hl << 2); 386126258Smlaier } 387126258Smlaier#endif /* INET */ 388126258Smlaier 389171168Smlaier ifn->if_opackets++; 390171168Smlaier ifn->if_obytes += m->m_pkthdr.len; 391127145Smlaier#ifdef __FreeBSD__ 392171168Smlaier BPF_MTAP2(ifn, &hdr, PFLOG_HDRLEN, m); 393126261Smlaier#else 394171168Smlaier bpf_mtap_hdr(ifn->if_bpf, (char *)&hdr, PFLOG_HDRLEN, m, 395171168Smlaier BPF_DIRECTION_OUT); 396126258Smlaier#endif 397130613Smlaier#endif 398126258Smlaier 399126258Smlaier return (0); 400126258Smlaier} 401126261Smlaier 402127145Smlaier#ifdef __FreeBSD__ 403126261Smlaierstatic int 404126261Smlaierpflog_modevent(module_t mod, int type, void *data) 405126261Smlaier{ 406126261Smlaier int error = 0; 407126261Smlaier 408126261Smlaier switch (type) { 409126261Smlaier case MOD_LOAD: 410171168Smlaier pflogattach(1); 411155337Smlaier PF_LOCK(); 412155337Smlaier pflog_packet_ptr = pflog_packet; 413155337Smlaier PF_UNLOCK(); 414126261Smlaier break; 415126261Smlaier case MOD_UNLOAD: 416155337Smlaier PF_LOCK(); 417155337Smlaier pflog_packet_ptr = NULL; 418155337Smlaier PF_UNLOCK(); 419126261Smlaier if_clone_detach(&pflog_cloner); 420126261Smlaier break; 421126261Smlaier default: 422126261Smlaier error = EINVAL; 423126261Smlaier break; 424126261Smlaier } 425126261Smlaier 426126261Smlaier return error; 427126261Smlaier} 428126261Smlaier 429171168Smlaierstatic moduledata_t pflog_mod = { "pflog", pflog_modevent, 0 }; 430126261Smlaier 431126261Smlaier#define PFLOG_MODVER 1 432126261Smlaier 433135196SmlaierDECLARE_MODULE(pflog, pflog_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY); 434126261SmlaierMODULE_VERSION(pflog, PFLOG_MODVER); 435155337SmlaierMODULE_DEPEND(pflog, pf, PF_MODVER, PF_MODVER, PF_MODVER); 436126261Smlaier#endif /* __FreeBSD__ */ 437