pfil.c revision 109623
190075Sobrien/* $FreeBSD: head/sys/net/pfil.c 109623 2003-01-21 08:56:16Z alfred $ */ 290075Sobrien 390075Sobrien/* 490075Sobrien * Copyright (c) 1996 Matthew R. Green 5132718Skan * All rights reserved. 690075Sobrien * 7132718Skan * Redistribution and use in source and binary forms, with or without 890075Sobrien * modification, are permitted provided that the following conditions 990075Sobrien * are met: 1090075Sobrien * 1. Redistributions of source code must retain the above copyright 1190075Sobrien * notice, this list of conditions and the following disclaimer. 12132718Skan * 2. Redistributions in binary form must reproduce the above copyright 1390075Sobrien * notice, this list of conditions and the following disclaimer in the 1490075Sobrien * documentation and/or other materials provided with the distribution. 1590075Sobrien * 3. The name of the author may not be used to endorse or promote products 1690075Sobrien * derived from this software without specific prior written permission. 1790075Sobrien * 18132718Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19169689Skan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20169689Skan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2190075Sobrien * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22215841Sdim * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23215841Sdim * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24215841Sdim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25215841Sdim * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26215841Sdim * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27215841Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28215841Sdim * SUCH DAMAGE. 2990075Sobrien */ 3090075Sobrien 3190075Sobrien#include <sys/param.h> 3290075Sobrien#include <sys/errno.h> 3390075Sobrien#include <sys/malloc.h> 3490075Sobrien#include <sys/socket.h> 3590075Sobrien#include <sys/socketvar.h> 3690075Sobrien#include <sys/systm.h> 3790075Sobrien#include <sys/queue.h> 38146895Skan 39215841Sdim#include <net/if.h> 40#include <net/pfil.h> 41 42static void pfil_init(struct pfil_head *); 43static int pfil_list_add(pfil_list_t *, 44 int (*)(void *, int, struct ifnet *, int, struct mbuf **), int); 45static int pfil_list_remove(pfil_list_t *, 46 int (*)(void *, int, struct ifnet *, int, struct mbuf **)); 47 48static void 49pfil_init(ph) 50 struct pfil_head *ph; 51{ 52 53 TAILQ_INIT(&ph->ph_in); 54 TAILQ_INIT(&ph->ph_out); 55 ph->ph_init = 1; 56} 57 58/* 59 * pfil_add_hook() adds a function to the packet filter hook. the 60 * flags are: 61 * PFIL_IN call me on incoming packets 62 * PFIL_OUT call me on outgoing packets 63 * PFIL_ALL call me on all of the above 64 * PFIL_WAITOK OK to call malloc with 0. 65 */ 66int 67pfil_add_hook(func, flags, ph) 68 int (*func)(void *, int, struct ifnet *, int, struct mbuf **); 69 int flags; 70 struct pfil_head *ph; 71{ 72 int err = 0; 73 74 if (ph->ph_init == 0) 75 pfil_init(ph); 76 77 if (flags & PFIL_IN) 78 err = pfil_list_add(&ph->ph_in, func, flags & ~PFIL_OUT); 79 if (err) 80 return err; 81 if (flags & PFIL_OUT) 82 err = pfil_list_add(&ph->ph_out, func, flags & ~PFIL_IN); 83 if (err) { 84 if (flags & PFIL_IN) 85 pfil_list_remove(&ph->ph_in, func); 86 return err; 87 } 88 return 0; 89} 90 91static int 92pfil_list_add(list, func, flags) 93 pfil_list_t *list; 94 int (*func)(void *, int, struct ifnet *, int, struct mbuf **); 95 int flags; 96{ 97 struct packet_filter_hook *pfh; 98 99 pfh = (struct packet_filter_hook *)malloc(sizeof(*pfh), M_IFADDR, 100 flags & PFIL_WAITOK ? 0 : M_NOWAIT); 101 if (pfh == NULL) 102 return ENOMEM; 103 pfh->pfil_func = func; 104 /* 105 * insert the input list in reverse order of the output list 106 * so that the same path is followed in or out of the kernel. 107 */ 108 109 if (flags & PFIL_IN) 110 TAILQ_INSERT_HEAD(list, pfh, pfil_link); 111 else 112 TAILQ_INSERT_TAIL(list, pfh, pfil_link); 113 return 0; 114} 115 116/* 117 * pfil_remove_hook removes a specific function from the packet filter 118 * hook list. 119 */ 120int 121pfil_remove_hook(func, flags, ph) 122 int (*func)(void *, int, struct ifnet *, int, struct mbuf **); 123 int flags; 124 struct pfil_head *ph; 125{ 126 int err = 0; 127 128 if (ph->ph_init == 0) 129 pfil_init(ph); 130 131 if (flags & PFIL_IN) 132 err = pfil_list_remove(&ph->ph_in, func); 133 if ((err == 0) && (flags & PFIL_OUT)) 134 err = pfil_list_remove(&ph->ph_out, func); 135 return err; 136} 137 138/* 139 * pfil_list_remove is an internal function that takes a function off the 140 * specified list. 141 */ 142static int 143pfil_list_remove(list, func) 144 pfil_list_t *list; 145 int (*func)(void *, int, struct ifnet *, int, struct mbuf **); 146{ 147 struct packet_filter_hook *pfh; 148 149 TAILQ_FOREACH(pfh, list, pfil_link) 150 if (pfh->pfil_func == func) { 151 TAILQ_REMOVE(list, pfh, pfil_link); 152 free(pfh, M_IFADDR); 153 return 0; 154 } 155 return ENOENT; 156} 157 158struct packet_filter_hook * 159pfil_hook_get(flag, ph) 160 int flag; 161 struct pfil_head *ph; 162{ 163 if (ph->ph_init != 0) 164 switch (flag) { 165 case PFIL_IN: 166 return (TAILQ_FIRST(&ph->ph_in)); 167 case PFIL_OUT: 168 return (TAILQ_FIRST(&ph->ph_out)); 169 } 170 return NULL; 171} 172