if_pflog.c revision 126258
1/* $OpenBSD: if_pflog.c,v 1.9 2003/05/14 08:42:00 canacar Exp $ */ 2/* 3 * The authors of this code are John Ioannidis (ji@tla.org), 4 * Angelos D. Keromytis (kermit@csd.uch.gr) and 5 * Niels Provos (provos@physnet.uni-hamburg.de). 6 * 7 * This code was written by John Ioannidis for BSD/OS in Athens, Greece, 8 * in November 1995. 9 * 10 * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, 11 * by Angelos D. Keromytis. 12 * 13 * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis 14 * and Niels Provos. 15 * 16 * Copyright (C) 1995, 1996, 1997, 1998 by John Ioannidis, Angelos D. Keromytis 17 * and Niels Provos. 18 * Copyright (c) 2001, Angelos D. Keromytis, Niels Provos. 19 * 20 * Permission to use, copy, and modify this software with or without fee 21 * is hereby granted, provided that this entire notice is included in 22 * all copies of any software which is or includes a copy or 23 * modification of this software. 24 * You may use this code under the GNU public license if you so wish. Please 25 * contribute changes back to the authors under this freer than GPL license 26 * so that we may further the use of strong encryption without limitations to 27 * all. 28 * 29 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR 30 * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY 31 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE 32 * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR 33 * PURPOSE. 34 */ 35 36#include "bpfilter.h" 37#include "pflog.h" 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/mbuf.h> 42#include <sys/socket.h> 43#include <sys/ioctl.h> 44 45#include <net/if.h> 46#include <net/if_types.h> 47#include <net/route.h> 48#include <net/bpf.h> 49 50#ifdef INET 51#include <netinet/in.h> 52#include <netinet/in_var.h> 53#include <netinet/in_systm.h> 54#include <netinet/ip.h> 55#endif 56 57#ifdef INET6 58#ifndef INET 59#include <netinet/in.h> 60#endif 61#include <netinet6/nd6.h> 62#endif /* INET6 */ 63 64#include <net/pfvar.h> 65#include <net/if_pflog.h> 66 67#define PFLOGMTU (32768 + MHLEN + MLEN) 68 69#ifdef PFLOGDEBUG 70#define DPRINTF(x) do { if (pflogdebug) printf x ; } while (0) 71#else 72#define DPRINTF(x) 73#endif 74 75struct pflog_softc pflogif[NPFLOG]; 76 77void pflogattach(int); 78int pflogoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 79 struct rtentry *); 80int pflogioctl(struct ifnet *, u_long, caddr_t); 81void pflogrtrequest(int, struct rtentry *, struct sockaddr *); 82void pflogstart(struct ifnet *); 83 84extern int ifqmaxlen; 85 86void 87pflogattach(int npflog) 88{ 89 struct ifnet *ifp; 90 int i; 91 92 bzero(pflogif, sizeof(pflogif)); 93 94 for (i = 0; i < NPFLOG; i++) { 95 ifp = &pflogif[i].sc_if; 96 snprintf(ifp->if_xname, sizeof ifp->if_xname, "pflog%d", i); 97 ifp->if_softc = &pflogif[i]; 98 ifp->if_mtu = PFLOGMTU; 99 ifp->if_ioctl = pflogioctl; 100 ifp->if_output = pflogoutput; 101 ifp->if_start = pflogstart; 102 ifp->if_type = IFT_PFLOG; 103 ifp->if_snd.ifq_maxlen = ifqmaxlen; 104 ifp->if_hdrlen = PFLOG_HDRLEN; 105 if_attach(ifp); 106 if_alloc_sadl(ifp); 107 108#if NBPFILTER > 0 109 bpfattach(&pflogif[i].sc_if.if_bpf, ifp, DLT_PFLOG, 110 PFLOG_HDRLEN); 111#endif 112 } 113} 114 115/* 116 * Start output on the pflog interface. 117 */ 118void 119pflogstart(struct ifnet *ifp) 120{ 121 struct mbuf *m; 122 int s; 123 124 for (;;) { 125 s = splimp(); 126 IF_DROP(&ifp->if_snd); 127 IF_DEQUEUE(&ifp->if_snd, m); 128 splx(s); 129 130 if (m == NULL) 131 return; 132 else 133 m_freem(m); 134 } 135} 136 137int 138pflogoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 139 struct rtentry *rt) 140{ 141 m_freem(m); 142 return (0); 143} 144 145/* ARGSUSED */ 146void 147pflogrtrequest(int cmd, struct rtentry *rt, struct sockaddr *sa) 148{ 149 if (rt) 150 rt->rt_rmx.rmx_mtu = PFLOGMTU; 151} 152 153/* ARGSUSED */ 154int 155pflogioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 156{ 157 switch (cmd) { 158 case SIOCSIFADDR: 159 case SIOCAIFADDR: 160 case SIOCSIFDSTADDR: 161 case SIOCSIFFLAGS: 162 if (ifp->if_flags & IFF_UP) 163 ifp->if_flags |= IFF_RUNNING; 164 else 165 ifp->if_flags &= ~IFF_RUNNING; 166 break; 167 default: 168 return (EINVAL); 169 } 170 171 return (0); 172} 173 174int 175pflog_packet(struct ifnet *ifp, struct mbuf *m, sa_family_t af, u_int8_t dir, 176 u_int8_t reason, struct pf_rule *rm, struct pf_rule *am, 177 struct pf_ruleset *ruleset) 178{ 179#if NBPFILTER > 0 180 struct ifnet *ifn; 181 struct pfloghdr hdr; 182 struct mbuf m1; 183 184 if (ifp == NULL || m == NULL || rm == NULL) 185 return (-1); 186 187 hdr.length = PFLOG_REAL_HDRLEN; 188 hdr.af = af; 189 hdr.action = rm->action; 190 hdr.reason = reason; 191 memcpy(hdr.ifname, ifp->if_xname, sizeof(hdr.ifname)); 192 193 if (am == NULL) { 194 hdr.rulenr = htonl(rm->nr); 195 hdr.subrulenr = -1; 196 bzero(hdr.ruleset, sizeof(hdr.ruleset)); 197 } else { 198 hdr.rulenr = htonl(am->nr); 199 hdr.subrulenr = htonl(rm->nr); 200 if (ruleset == NULL) 201 bzero(hdr.ruleset, sizeof(hdr.ruleset)); 202 else 203 memcpy(hdr.ruleset, ruleset->name, 204 sizeof(hdr.ruleset)); 205 206 207 } 208 hdr.dir = dir; 209 210#ifdef INET 211 if (af == AF_INET && dir == PF_OUT) { 212 struct ip *ip; 213 214 ip = mtod(m, struct ip *); 215 ip->ip_sum = 0; 216 ip->ip_sum = in_cksum(m, ip->ip_hl << 2); 217 } 218#endif /* INET */ 219 220 m1.m_next = m; 221 m1.m_len = PFLOG_HDRLEN; 222 m1.m_data = (char *) &hdr; 223 224 ifn = &(pflogif[0].sc_if); 225 226 if (ifn->if_bpf) 227 bpf_mtap(ifn->if_bpf, &m1); 228#endif 229 230 return (0); 231} 232