1 /* $NetBSD: pfil.c,v 1.4 1996/10/13 02:11:08 christos 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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Matthew R. Green for 18 * the NetBSD Project. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include <sys/param.h> 36 #include <sys/errno.h> 37 #include <sys/malloc.h> 38 #include <sys/socket.h> 39 #include <sys/socketvar.h> 40 #include <sys/systm.h> 41 #include <sys/proc.h> 42 #include <sys/queue.h> 43 44 #include <net/if.h> 45 #include <net/pfil.h> 46 47 typedef LIST_HEAD(, packet_filter_hook) pfil_list_t; 48 pfil_list_t pfil_in_list; 49 pfil_list_t pfil_out_list; 50 pfil_list_t pfil_bad_list; 51 static int done_pfil_init; 52 53 void pfil_init __P((void)); 54 void pfil_list_add(pfil_list_t *, 55 int (*) __P((void *, int, struct ifnet *, int, struct mbuf **)), int); 56 void pfil_list_remove(struct packet_filter_hook *, 57 int (*) __P((void *, int, struct ifnet *, int, struct mbuf **))); 58 59 void 60 pfil_init() 61 { 62 LIST_INIT(&pfil_in_list); 63 LIST_INIT(&pfil_out_list); 64 LIST_INIT(&pfil_bad_list); 65 done_pfil_init = 1; 66 } 67 68 /* 69 * pfil_add_hook() adds a function to the packet filter hook. the 70 * flags are: 71 * PFIL_IN call me on incoming packets 72 * PFIL_OUT call me on outgoing packets 73 * PFIL_BAD call me when rejecting a packet (that was 74 * not already reject by in/out filters). 75 * PFIL_ALL call me on all of the above 76 * PFIL_WAITOK OK to call malloc with M_WAITOK. 77 */ 78 void 79 pfil_add_hook(func, flags) 80 int (*func) __P((void *, int, struct ifnet *, int, 81 struct mbuf **)); 82 int flags; 83 { 84 85 if (done_pfil_init == 0) 86 pfil_init(); 87 88 if (flags & PFIL_IN) 89 pfil_list_add(&pfil_in_list, func, flags); 90 if (flags & PFIL_OUT) 91 pfil_list_add(&pfil_out_list, func, flags); 92 if (flags & PFIL_BAD) 93 pfil_list_add(&pfil_bad_list, func, flags); 94 } 95 96 void 97 pfil_list_add(list, func, flags) 98 pfil_list_t *list; 99 int (*func) __P((void *, int, struct ifnet *, int, 100 struct mbuf **)); 101 int flags; 102 { 103 struct packet_filter_hook *pfh; 104 105 pfh = (struct packet_filter_hook *)malloc(sizeof(*pfh), M_IFADDR, 106 flags & PFIL_WAITOK ? M_WAITOK : M_NOWAIT); 107 if (pfh == NULL) 108 panic("no memory for packet filter hook"); 109 110 pfh->pfil_func = func; 111 LIST_INSERT_HEAD(list, pfh, pfil_link); 112 } 113 114 /* 115 * pfil_remove_hook removes a specific function from the packet filter 116 * hook list. 117 */ 118 void 119 pfil_remove_hook(func, flags) 120 int (*func) __P((void *, int, struct ifnet *, int, 121 struct mbuf **)); 122 int flags; 123 { 124 125 if (done_pfil_init == 0) 126 pfil_init(); 127 128 if (flags & PFIL_IN) 129 pfil_list_remove(pfil_in_list.lh_first, func); 130 if (flags & PFIL_OUT) 131 pfil_list_remove(pfil_out_list.lh_first, func); 132 if (flags & PFIL_BAD) 133 pfil_list_remove(pfil_bad_list.lh_first, func); 134 } 135 136 /* 137 * pfil_list_remove is an internal function that takes a function off the 138 * specified list. 139 */ 140 void 141 pfil_list_remove(list, func) 142 struct packet_filter_hook *list; 143 int (*func) __P((void *, int, struct ifnet *, int, 144 struct mbuf **)); 145 { 146 struct packet_filter_hook *pfh; 147 148 for (pfh = list; pfh; pfh = pfh->pfil_link.le_next) 149 if (pfh->pfil_func == func) { 150 LIST_REMOVE(pfh, pfil_link); 151 free(pfh, M_IFADDR); 152 return; 153 } 154 printf("pfil_list_remove: no function on list\n"); 155 #ifdef DIAGNOSTIC 156 panic("pfil_list_remove"); 157 #endif 158 } 159 160 struct packet_filter_hook * 161 pfil_hook_get(flag) 162 int flag; 163 { 164 if (done_pfil_init) 165 switch (flag) { 166 case PFIL_IN: 167 return (pfil_in_list.lh_first); 168 case PFIL_OUT: 169 return (pfil_out_list.lh_first); 170 case PFIL_BAD: 171 return (pfil_bad_list.lh_first); 172 } 173 return NULL; 174 } 175