1be4f3cd0SPaolo Pisati /*- 2be4f3cd0SPaolo Pisati * Copyright (c) 2005 Paolo Pisati <piso@FreeBSD.org> 3be4f3cd0SPaolo Pisati * All rights reserved. 4be4f3cd0SPaolo Pisati * 5be4f3cd0SPaolo Pisati * Redistribution and use in source and binary forms, with or without 6be4f3cd0SPaolo Pisati * modification, are permitted provided that the following conditions 7be4f3cd0SPaolo Pisati * are met: 8be4f3cd0SPaolo Pisati * 1. Redistributions of source code must retain the above copyright 9be4f3cd0SPaolo Pisati * notice, this list of conditions and the following disclaimer. 10be4f3cd0SPaolo Pisati * 2. Redistributions in binary form must reproduce the above copyright 11be4f3cd0SPaolo Pisati * notice, this list of conditions and the following disclaimer in the 12be4f3cd0SPaolo Pisati * documentation and/or other materials provided with the distribution. 13be4f3cd0SPaolo Pisati * 14be4f3cd0SPaolo Pisati * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15be4f3cd0SPaolo Pisati * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16be4f3cd0SPaolo Pisati * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17be4f3cd0SPaolo Pisati * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18be4f3cd0SPaolo Pisati * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19be4f3cd0SPaolo Pisati * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20be4f3cd0SPaolo Pisati * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21be4f3cd0SPaolo Pisati * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22be4f3cd0SPaolo Pisati * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23be4f3cd0SPaolo Pisati * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24be4f3cd0SPaolo Pisati * SUCH DAMAGE. 25be4f3cd0SPaolo Pisati * 26be4f3cd0SPaolo Pisati */ 277c00cc76SPaolo Pisati #include <sys/cdefs.h> 28be4f3cd0SPaolo Pisati __FBSDID("$FreeBSD$"); 29be4f3cd0SPaolo Pisati 30be4f3cd0SPaolo Pisati #ifdef _KERNEL 31be4f3cd0SPaolo Pisati #include <sys/libkern.h> 32be4f3cd0SPaolo Pisati #include <sys/param.h> 33be4f3cd0SPaolo Pisati #include <sys/lock.h> 34be4f3cd0SPaolo Pisati #include <sys/rwlock.h> 35be4f3cd0SPaolo Pisati #else 36be4f3cd0SPaolo Pisati #include <stdio.h> 37be4f3cd0SPaolo Pisati #include <string.h> 38be4f3cd0SPaolo Pisati #include <sys/types.h> 39be4f3cd0SPaolo Pisati #include <errno.h> 40be4f3cd0SPaolo Pisati #endif 41be4f3cd0SPaolo Pisati 42be4f3cd0SPaolo Pisati #include <netinet/in_systm.h> 43be4f3cd0SPaolo Pisati #include <netinet/in.h> 44be4f3cd0SPaolo Pisati #include <netinet/ip.h> 45be4f3cd0SPaolo Pisati 46be4f3cd0SPaolo Pisati #ifdef _KERNEL 47be4f3cd0SPaolo Pisati #include <netinet/libalias/alias_local.h> 48be4f3cd0SPaolo Pisati #include <netinet/libalias/alias_mod.h> 49be4f3cd0SPaolo Pisati #else 50be4f3cd0SPaolo Pisati #include "alias_local.h" 51be4f3cd0SPaolo Pisati #include "alias_mod.h" 52be4f3cd0SPaolo Pisati #endif 53be4f3cd0SPaolo Pisati 54be4f3cd0SPaolo Pisati /* Protocol and userland module handlers chains. */ 55be4f3cd0SPaolo Pisati LIST_HEAD(handler_chain, proto_handler) handler_chain = LIST_HEAD_INITIALIZER(foo); 56be4f3cd0SPaolo Pisati #ifdef _KERNEL 57be4f3cd0SPaolo Pisati struct rwlock handler_rw; 58be4f3cd0SPaolo Pisati #endif 59be4f3cd0SPaolo Pisati SLIST_HEAD(dll_chain, dll) dll_chain = SLIST_HEAD_INITIALIZER(foo); 60be4f3cd0SPaolo Pisati 61be4f3cd0SPaolo Pisati #ifdef _KERNEL 62be4f3cd0SPaolo Pisati 63be4f3cd0SPaolo Pisati #define LIBALIAS_LOCK_INIT() \ 64be4f3cd0SPaolo Pisati rw_init(&handler_rw, "Libalias_modules_rwlock") 65be4f3cd0SPaolo Pisati #define LIBALIAS_LOCK_DESTROY() rw_destroy(&handler_rw) 66be4f3cd0SPaolo Pisati #define LIBALIAS_WLOCK_ASSERT() \ 67be4f3cd0SPaolo Pisati rw_assert(&handler_rw, RA_WLOCKED) 68be4f3cd0SPaolo Pisati 69be4f3cd0SPaolo Pisati static __inline void 70be4f3cd0SPaolo Pisati LIBALIAS_RLOCK(void) 71be4f3cd0SPaolo Pisati { 72be4f3cd0SPaolo Pisati rw_rlock(&handler_rw); 73be4f3cd0SPaolo Pisati } 74be4f3cd0SPaolo Pisati 75be4f3cd0SPaolo Pisati static __inline void 76be4f3cd0SPaolo Pisati LIBALIAS_RUNLOCK(void) 77be4f3cd0SPaolo Pisati { 78be4f3cd0SPaolo Pisati rw_runlock(&handler_rw); 79be4f3cd0SPaolo Pisati } 80be4f3cd0SPaolo Pisati 81be4f3cd0SPaolo Pisati static __inline void 82be4f3cd0SPaolo Pisati LIBALIAS_WLOCK(void) 83be4f3cd0SPaolo Pisati { 84be4f3cd0SPaolo Pisati rw_wlock(&handler_rw); 85be4f3cd0SPaolo Pisati } 86be4f3cd0SPaolo Pisati 87be4f3cd0SPaolo Pisati static __inline void 88be4f3cd0SPaolo Pisati LIBALIAS_WUNLOCK(void) 89be4f3cd0SPaolo Pisati { 90be4f3cd0SPaolo Pisati rw_wunlock(&handler_rw); 91be4f3cd0SPaolo Pisati } 92be4f3cd0SPaolo Pisati 93be4f3cd0SPaolo Pisati static void 94be4f3cd0SPaolo Pisati _handler_chain_init(void) 95be4f3cd0SPaolo Pisati { 96be4f3cd0SPaolo Pisati 97be4f3cd0SPaolo Pisati if (!rw_initialized(&handler_rw)) 98be4f3cd0SPaolo Pisati LIBALIAS_LOCK_INIT(); 99be4f3cd0SPaolo Pisati } 100be4f3cd0SPaolo Pisati 101be4f3cd0SPaolo Pisati static void 102be4f3cd0SPaolo Pisati _handler_chain_destroy(void) 103be4f3cd0SPaolo Pisati { 104be4f3cd0SPaolo Pisati 105be4f3cd0SPaolo Pisati if (rw_initialized(&handler_rw)) 106be4f3cd0SPaolo Pisati LIBALIAS_LOCK_DESTROY(); 107be4f3cd0SPaolo Pisati } 108be4f3cd0SPaolo Pisati 109be4f3cd0SPaolo Pisati #else 110be4f3cd0SPaolo Pisati #define LIBALIAS_LOCK_INIT() ; 111be4f3cd0SPaolo Pisati #define LIBALIAS_LOCK_DESTROY() ; 112be4f3cd0SPaolo Pisati #define LIBALIAS_WLOCK_ASSERT() ; 113be4f3cd0SPaolo Pisati #define LIBALIAS_RLOCK() ; 114be4f3cd0SPaolo Pisati #define LIBALIAS_RUNLOCK() ; 115be4f3cd0SPaolo Pisati #define LIBALIAS_WLOCK() ; 116be4f3cd0SPaolo Pisati #define LIBALIAS_WUNLOCK() ; 117be4f3cd0SPaolo Pisati #define _handler_chain_init() ; 118be4f3cd0SPaolo Pisati #define _handler_chain_destroy() ; 119be4f3cd0SPaolo Pisati #endif 120be4f3cd0SPaolo Pisati 121be4f3cd0SPaolo Pisati void 122be4f3cd0SPaolo Pisati handler_chain_init(void) 123be4f3cd0SPaolo Pisati { 124be4f3cd0SPaolo Pisati _handler_chain_init(); 125be4f3cd0SPaolo Pisati } 126be4f3cd0SPaolo Pisati 127be4f3cd0SPaolo Pisati void 128be4f3cd0SPaolo Pisati handler_chain_destroy(void) 129be4f3cd0SPaolo Pisati { 130be4f3cd0SPaolo Pisati _handler_chain_destroy(); 131be4f3cd0SPaolo Pisati } 132be4f3cd0SPaolo Pisati 133be4f3cd0SPaolo Pisati static int 134be4f3cd0SPaolo Pisati _attach_handler(struct proto_handler *p) 135be4f3cd0SPaolo Pisati { 136be4f3cd0SPaolo Pisati struct proto_handler *b = NULL; 137be4f3cd0SPaolo Pisati 138be4f3cd0SPaolo Pisati LIBALIAS_WLOCK_ASSERT(); 139be4f3cd0SPaolo Pisati LIST_FOREACH(b, &handler_chain, entries) { 140be4f3cd0SPaolo Pisati if ((b->pri == p->pri) && 141be4f3cd0SPaolo Pisati (b->dir == p->dir) && 142be4f3cd0SPaolo Pisati (b->proto == p->proto)) 143be4f3cd0SPaolo Pisati return (EEXIST); /* Priority conflict. */ 144be4f3cd0SPaolo Pisati if (b->pri > p->pri) { 145be4f3cd0SPaolo Pisati LIST_INSERT_BEFORE(b, p, entries); 146be4f3cd0SPaolo Pisati return (0); 147be4f3cd0SPaolo Pisati } 148be4f3cd0SPaolo Pisati } 149be4f3cd0SPaolo Pisati /* End of list or found right position, inserts here. */ 150be4f3cd0SPaolo Pisati if (b) 151be4f3cd0SPaolo Pisati LIST_INSERT_AFTER(b, p, entries); 152be4f3cd0SPaolo Pisati else 153be4f3cd0SPaolo Pisati LIST_INSERT_HEAD(&handler_chain, p, entries); 154be4f3cd0SPaolo Pisati return (0); 155be4f3cd0SPaolo Pisati } 156be4f3cd0SPaolo Pisati 157be4f3cd0SPaolo Pisati static int 158be4f3cd0SPaolo Pisati _detach_handler(struct proto_handler *p) 159be4f3cd0SPaolo Pisati { 160be4f3cd0SPaolo Pisati struct proto_handler *b, *b_tmp;; 161be4f3cd0SPaolo Pisati 162be4f3cd0SPaolo Pisati LIBALIAS_WLOCK_ASSERT(); 163be4f3cd0SPaolo Pisati LIST_FOREACH_SAFE(b, &handler_chain, entries, b_tmp) { 164be4f3cd0SPaolo Pisati if (b == p) { 165be4f3cd0SPaolo Pisati LIST_REMOVE(b, entries); 166be4f3cd0SPaolo Pisati return (0); 167be4f3cd0SPaolo Pisati } 168be4f3cd0SPaolo Pisati } 169be4f3cd0SPaolo Pisati return (ENOENT); /* Handler not found. */ 170be4f3cd0SPaolo Pisati } 171be4f3cd0SPaolo Pisati 172be4f3cd0SPaolo Pisati int 173be4f3cd0SPaolo Pisati LibAliasAttachHandlers(struct proto_handler *_p) 174be4f3cd0SPaolo Pisati { 175be4f3cd0SPaolo Pisati int i, error = -1; 176be4f3cd0SPaolo Pisati 177be4f3cd0SPaolo Pisati LIBALIAS_WLOCK(); 178be4f3cd0SPaolo Pisati for (i=0; 1; i++) { 179be4f3cd0SPaolo Pisati if (*((int *)&_p[i]) == EOH) 180be4f3cd0SPaolo Pisati break; 181be4f3cd0SPaolo Pisati error = _attach_handler(&_p[i]); 182be4f3cd0SPaolo Pisati if (error != 0) 183be4f3cd0SPaolo Pisati break; 184be4f3cd0SPaolo Pisati } 185be4f3cd0SPaolo Pisati LIBALIAS_WUNLOCK(); 186be4f3cd0SPaolo Pisati return (error); 187be4f3cd0SPaolo Pisati } 188be4f3cd0SPaolo Pisati 189be4f3cd0SPaolo Pisati int 190be4f3cd0SPaolo Pisati LibAliasDetachHandlers(struct proto_handler *_p) 191be4f3cd0SPaolo Pisati { 192be4f3cd0SPaolo Pisati int i, error = -1; 193be4f3cd0SPaolo Pisati 194be4f3cd0SPaolo Pisati LIBALIAS_WLOCK(); 195be4f3cd0SPaolo Pisati for (i=0; 1; i++) { 196be4f3cd0SPaolo Pisati if (*((int *)&_p[i]) == EOH) 197be4f3cd0SPaolo Pisati break; 198be4f3cd0SPaolo Pisati error = _detach_handler(&_p[i]); 199be4f3cd0SPaolo Pisati if (error != 0) 200be4f3cd0SPaolo Pisati break; 201be4f3cd0SPaolo Pisati } 202be4f3cd0SPaolo Pisati LIBALIAS_WUNLOCK(); 203be4f3cd0SPaolo Pisati return (error); 204be4f3cd0SPaolo Pisati } 205be4f3cd0SPaolo Pisati 206be4f3cd0SPaolo Pisati int 207be4f3cd0SPaolo Pisati detach_handler(struct proto_handler *_p) 208be4f3cd0SPaolo Pisati { 209be4f3cd0SPaolo Pisati int error = -1; 210be4f3cd0SPaolo Pisati 211be4f3cd0SPaolo Pisati LIBALIAS_WLOCK(); 212be4f3cd0SPaolo Pisati error = _detach_handler(_p); 213be4f3cd0SPaolo Pisati LIBALIAS_WUNLOCK(); 214be4f3cd0SPaolo Pisati return (error); 215be4f3cd0SPaolo Pisati } 216be4f3cd0SPaolo Pisati 217be4f3cd0SPaolo Pisati int 218be4f3cd0SPaolo Pisati find_handler(int8_t dir, int8_t proto, struct libalias *la, struct ip *pip, 219be4f3cd0SPaolo Pisati struct alias_data *ad) 220be4f3cd0SPaolo Pisati { 221be4f3cd0SPaolo Pisati struct proto_handler *p; 222be4f3cd0SPaolo Pisati int error = ENOENT; 223be4f3cd0SPaolo Pisati 224be4f3cd0SPaolo Pisati LIBALIAS_RLOCK(); 225be4f3cd0SPaolo Pisati 226be4f3cd0SPaolo Pisati LIST_FOREACH(p, &handler_chain, entries) { 227be4f3cd0SPaolo Pisati if ((p->dir & dir) && (p->proto & proto)) 228be4f3cd0SPaolo Pisati if (p->fingerprint(la, pip, ad) == 0) { 229be4f3cd0SPaolo Pisati error = p->protohandler(la, pip, ad); 230be4f3cd0SPaolo Pisati break; 231be4f3cd0SPaolo Pisati } 232be4f3cd0SPaolo Pisati } 233be4f3cd0SPaolo Pisati LIBALIAS_RUNLOCK(); 234be4f3cd0SPaolo Pisati return (error); 235be4f3cd0SPaolo Pisati } 236be4f3cd0SPaolo Pisati 237be4f3cd0SPaolo Pisati struct proto_handler * 238be4f3cd0SPaolo Pisati first_handler(void) 239be4f3cd0SPaolo Pisati { 240be4f3cd0SPaolo Pisati 241be4f3cd0SPaolo Pisati return (LIST_FIRST(&handler_chain)); 242be4f3cd0SPaolo Pisati } 243be4f3cd0SPaolo Pisati 244be4f3cd0SPaolo Pisati /* Dll manipulation code - this code is not thread safe... */ 245be4f3cd0SPaolo Pisati 246be4f3cd0SPaolo Pisati int 247be4f3cd0SPaolo Pisati attach_dll(struct dll *p) 248be4f3cd0SPaolo Pisati { 249be4f3cd0SPaolo Pisati struct dll *b; 250be4f3cd0SPaolo Pisati 251be4f3cd0SPaolo Pisati SLIST_FOREACH(b, &dll_chain, next) { 252be4f3cd0SPaolo Pisati if (!strncmp(b->name, p->name, DLL_LEN)) 253be4f3cd0SPaolo Pisati return (EEXIST); /* Dll name conflict. */ 254be4f3cd0SPaolo Pisati } 255be4f3cd0SPaolo Pisati SLIST_INSERT_HEAD(&dll_chain, p, next); 256be4f3cd0SPaolo Pisati return (0); 257be4f3cd0SPaolo Pisati } 258be4f3cd0SPaolo Pisati 259be4f3cd0SPaolo Pisati void * 260be4f3cd0SPaolo Pisati detach_dll(char *p) 261be4f3cd0SPaolo Pisati { 262be4f3cd0SPaolo Pisati struct dll *b = NULL, *b_tmp; 263be4f3cd0SPaolo Pisati void *error = NULL; 264be4f3cd0SPaolo Pisati 265be4f3cd0SPaolo Pisati SLIST_FOREACH_SAFE(b, &dll_chain, next, b_tmp) 266be4f3cd0SPaolo Pisati if (!strncmp(b->name, p, DLL_LEN)) { 267be4f3cd0SPaolo Pisati SLIST_REMOVE(&dll_chain, b, dll, next); 268be4f3cd0SPaolo Pisati error = b; 269be4f3cd0SPaolo Pisati break; 270be4f3cd0SPaolo Pisati } 271be4f3cd0SPaolo Pisati return (error); 272be4f3cd0SPaolo Pisati } 273be4f3cd0SPaolo Pisati 274be4f3cd0SPaolo Pisati struct dll * 275be4f3cd0SPaolo Pisati walk_dll_chain(void) 276be4f3cd0SPaolo Pisati { 277be4f3cd0SPaolo Pisati struct dll *t; 278be4f3cd0SPaolo Pisati 279be4f3cd0SPaolo Pisati t = SLIST_FIRST(&dll_chain); 280be4f3cd0SPaolo Pisati if (t == NULL) 281be4f3cd0SPaolo Pisati return (NULL); 282be4f3cd0SPaolo Pisati SLIST_REMOVE_HEAD(&dll_chain, next); 283be4f3cd0SPaolo Pisati return (t); 284be4f3cd0SPaolo Pisati } 285