1 /* $OpenBSD: if_pflog.c,v 1.10 2003/10/01 21:21:35 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 75 struct pflog_softc pflogif[NPFLOG]; 76 77 void pflogattach(int); 78 int pflogoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 79 struct rtentry *); 80 int pflogioctl(struct ifnet *, u_long, caddr_t); 81 void pflogrtrequest(int, struct rtentry *, struct sockaddr *); 82 void pflogstart(struct ifnet *); 83 84 extern int ifqmaxlen; 85 86 void 87 pflogattach(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 */ 118 void 119 pflogstart(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 137 int 138 pflogoutput(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 */ 146 void 147 pflogrtrequest(int cmd, struct rtentry *rt, struct sockaddr *sa) 148 { 149 if (rt) 150 rt->rt_rmx.rmx_mtu = PFLOGMTU; 151 } 152 153 /* ARGSUSED */ 154 int 155 pflogioctl(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 174 int 175 pflog_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 bzero(&hdr, sizeof(hdr)); 188 hdr.length = PFLOG_REAL_HDRLEN; 189 hdr.af = af; 190 hdr.action = rm->action; 191 hdr.reason = reason; 192 memcpy(hdr.ifname, ifp->if_xname, sizeof(hdr.ifname)); 193 194 if (am == NULL) { 195 hdr.rulenr = htonl(rm->nr); 196 hdr.subrulenr = -1; 197 } else { 198 hdr.rulenr = htonl(am->nr); 199 hdr.subrulenr = htonl(rm->nr); 200 if (ruleset != NULL) 201 memcpy(hdr.ruleset, ruleset->name, 202 sizeof(hdr.ruleset)); 203 204 205 } 206 hdr.dir = dir; 207 208 #ifdef INET 209 if (af == AF_INET && dir == PF_OUT) { 210 struct ip *ip; 211 212 ip = mtod(m, struct ip *); 213 ip->ip_sum = 0; 214 ip->ip_sum = in_cksum(m, ip->ip_hl << 2); 215 } 216 #endif /* INET */ 217 218 m1.m_next = m; 219 m1.m_len = PFLOG_HDRLEN; 220 m1.m_data = (char *) &hdr; 221 222 ifn = &(pflogif[0].sc_if); 223 224 if (ifn->if_bpf) 225 bpf_mtap(ifn->if_bpf, &m1); 226 #endif 227 228 return (0); 229 } 230