pfil.c revision 1.8
1/* $NetBSD: pfil.c,v 1.8 1999/06/18 05:59:20 mrg Exp $ */ 2 3/* 4 * Copyright (c) 1996 Matthew R. Green 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31#include <sys/param.h> 32#include <sys/errno.h> 33#include <sys/malloc.h> 34#include <sys/socket.h> 35#include <sys/socketvar.h> 36#include <sys/systm.h> 37#include <sys/proc.h> 38#include <sys/queue.h> 39 40#include <net/if.h> 41#include <net/pfil.h> 42 43typedef TAILQ_HEAD(, packet_filter_hook) pfil_list_t; 44pfil_list_t pfil_in_list; 45pfil_list_t pfil_out_list; 46static int done_pfil_init; 47 48static void pfil_init __P((void)); 49static void pfil_list_add(pfil_list_t *, 50 int (*) __P((void *, int, struct ifnet *, int, struct mbuf **)), int); 51static void pfil_list_remove(pfil_list_t, 52 int (*) __P((void *, int, struct ifnet *, int, struct mbuf **))); 53 54static void 55pfil_init() 56{ 57 58 TAILQ_INIT(&pfil_in_list); 59 TAILQ_INIT(&pfil_out_list); 60 done_pfil_init = 1; 61} 62 63/* 64 * pfil_add_hook() adds a function to the packet filter hook. the 65 * flags are: 66 * PFIL_IN call me on incoming packets 67 * PFIL_OUT call me on outgoing packets 68 * PFIL_ALL call me on all of the above 69 * PFIL_WAITOK OK to call malloc with M_WAITOK. 70 */ 71void 72pfil_add_hook(func, flags) 73 int (*func) __P((void *, int, struct ifnet *, int, 74 struct mbuf **)); 75 int flags; 76{ 77 78 if (done_pfil_init == 0) 79 pfil_init(); 80 81 if (flags & PFIL_IN) 82 pfil_list_add(&pfil_in_list, func, PFIL_IN); 83 if (flags & PFIL_OUT) 84 pfil_list_add(&pfil_out_list, func, PFIL_OUT); 85} 86 87static void 88pfil_list_add(list, func, flags) 89 pfil_list_t *list; 90 int (*func) __P((void *, int, struct ifnet *, int, 91 struct mbuf **)); 92 int flags; 93{ 94 struct packet_filter_hook *pfh; 95 96 pfh = (struct packet_filter_hook *)malloc(sizeof(*pfh), M_IFADDR, 97 flags & PFIL_WAITOK ? M_WAITOK : M_NOWAIT); 98 if (pfh == NULL) 99 panic("no memory for packet filter hook"); 100 101 pfh->pfil_func = func; 102 /* 103 * insert the input list in reverse order of the output list 104 * so that the same path is followed in or out of the kernel. 105 */ 106 if (flags & PFIL_IN) 107 TAILQ_INSERT_HEAD(list, pfh, pfil_link); 108 else 109 TAILQ_INSERT_TAIL(list, pfh, pfil_link); 110} 111 112/* 113 * pfil_remove_hook removes a specific function from the packet filter 114 * hook list. 115 */ 116void 117pfil_remove_hook(func, flags) 118 int (*func) __P((void *, int, struct ifnet *, int, 119 struct mbuf **)); 120 int flags; 121{ 122 123 if (done_pfil_init == 0) 124 pfil_init(); 125 126 if (flags & PFIL_IN) 127 pfil_list_remove(pfil_in_list, func); 128 if (flags & PFIL_OUT) 129 pfil_list_remove(pfil_out_list, func); 130} 131 132/* 133 * pfil_list_remove is an internal function that takes a function off the 134 * specified list. 135 */ 136static void 137pfil_list_remove(list, func) 138 pfil_list_t list; 139 int (*func) __P((void *, int, struct ifnet *, int, 140 struct mbuf **)); 141{ 142 struct packet_filter_hook *pfh; 143 144 for (pfh = list.tqh_first; pfh; pfh = pfh->pfil_link.tqe_next) 145 if (pfh->pfil_func == func) { 146 TAILQ_REMOVE(&list, pfh, pfil_link); 147 free(pfh, M_IFADDR); 148 return; 149 } 150 printf("pfil_list_remove: no function on list\n"); 151#ifdef DIAGNOSTIC 152 panic("pfil_list_remove"); 153#endif 154} 155 156struct packet_filter_hook * 157pfil_hook_get(flag) 158 int flag; 159{ 160 161 if (done_pfil_init) 162 switch (flag) { 163 case PFIL_IN: 164 return (pfil_in_list.tqh_first); 165 case PFIL_OUT: 166 return (pfil_out_list.tqh_first); 167 } 168 return NULL; 169} 170