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