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. */ 5513e403fdSAntoine Brodin LIST_HEAD(handler_chain, proto_handler) handler_chain = LIST_HEAD_INITIALIZER(handler_chain); 56be4f3cd0SPaolo Pisati #ifdef _KERNEL 57be4f3cd0SPaolo Pisati struct rwlock handler_rw; 58be4f3cd0SPaolo Pisati #endif 5913e403fdSAntoine Brodin SLIST_HEAD(dll_chain, dll) dll_chain = SLIST_HEAD_INITIALIZER(dll_chain); 60be4f3cd0SPaolo Pisati 61be4f3cd0SPaolo Pisati #ifdef _KERNEL 62be4f3cd0SPaolo Pisati 63ccd57eeaSPaolo Pisati #define LIBALIAS_RWLOCK_INIT() \ 64be4f3cd0SPaolo Pisati rw_init(&handler_rw, "Libalias_modules_rwlock") 65ccd57eeaSPaolo Pisati #define LIBALIAS_RWLOCK_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)) 98ccd57eeaSPaolo Pisati LIBALIAS_RWLOCK_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)) 106ccd57eeaSPaolo Pisati LIBALIAS_RWLOCK_DESTROY(); 107be4f3cd0SPaolo Pisati } 108be4f3cd0SPaolo Pisati 109be4f3cd0SPaolo Pisati #else 110ccd57eeaSPaolo Pisati #define LIBALIAS_RWLOCK_INIT() ; 111ccd57eeaSPaolo Pisati #define LIBALIAS_RWLOCK_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 { 13643197d29SPaolo Pisati struct proto_handler *b; 137be4f3cd0SPaolo Pisati 138be4f3cd0SPaolo Pisati LIBALIAS_WLOCK_ASSERT(); 13943197d29SPaolo Pisati b = NULL; 140be4f3cd0SPaolo Pisati LIST_FOREACH(b, &handler_chain, entries) { 141be4f3cd0SPaolo Pisati if ((b->pri == p->pri) && 142be4f3cd0SPaolo Pisati (b->dir == p->dir) && 143be4f3cd0SPaolo Pisati (b->proto == p->proto)) 144be4f3cd0SPaolo Pisati return (EEXIST); /* Priority conflict. */ 145be4f3cd0SPaolo Pisati if (b->pri > p->pri) { 146be4f3cd0SPaolo Pisati LIST_INSERT_BEFORE(b, p, entries); 147be4f3cd0SPaolo Pisati return (0); 148be4f3cd0SPaolo Pisati } 149be4f3cd0SPaolo Pisati } 150be4f3cd0SPaolo Pisati /* End of list or found right position, inserts here. */ 151be4f3cd0SPaolo Pisati if (b) 152be4f3cd0SPaolo Pisati LIST_INSERT_AFTER(b, p, entries); 153be4f3cd0SPaolo Pisati else 154be4f3cd0SPaolo Pisati LIST_INSERT_HEAD(&handler_chain, p, entries); 155be4f3cd0SPaolo Pisati return (0); 156be4f3cd0SPaolo Pisati } 157be4f3cd0SPaolo Pisati 158be4f3cd0SPaolo Pisati static int 159be4f3cd0SPaolo Pisati _detach_handler(struct proto_handler *p) 160be4f3cd0SPaolo Pisati { 161c2ede4b3SMartin Blapp struct proto_handler *b, *b_tmp; 162be4f3cd0SPaolo Pisati 163be4f3cd0SPaolo Pisati LIBALIAS_WLOCK_ASSERT(); 164be4f3cd0SPaolo Pisati LIST_FOREACH_SAFE(b, &handler_chain, entries, b_tmp) { 165be4f3cd0SPaolo Pisati if (b == p) { 166be4f3cd0SPaolo Pisati LIST_REMOVE(b, entries); 167be4f3cd0SPaolo Pisati return (0); 168be4f3cd0SPaolo Pisati } 169be4f3cd0SPaolo Pisati } 170be4f3cd0SPaolo Pisati return (ENOENT); /* Handler not found. */ 171be4f3cd0SPaolo Pisati } 172be4f3cd0SPaolo Pisati 173be4f3cd0SPaolo Pisati int 174be4f3cd0SPaolo Pisati LibAliasAttachHandlers(struct proto_handler *_p) 175be4f3cd0SPaolo Pisati { 17643197d29SPaolo Pisati int i, error; 177be4f3cd0SPaolo Pisati 178be4f3cd0SPaolo Pisati LIBALIAS_WLOCK(); 17943197d29SPaolo Pisati error = -1; 180be4f3cd0SPaolo Pisati for (i = 0; 1; i++) { 181be4f3cd0SPaolo Pisati if (*((int *)&_p[i]) == EOH) 182be4f3cd0SPaolo Pisati break; 183be4f3cd0SPaolo Pisati error = _attach_handler(&_p[i]); 184be4f3cd0SPaolo Pisati if (error != 0) 185be4f3cd0SPaolo Pisati break; 186be4f3cd0SPaolo Pisati } 187be4f3cd0SPaolo Pisati LIBALIAS_WUNLOCK(); 188be4f3cd0SPaolo Pisati return (error); 189be4f3cd0SPaolo Pisati } 190be4f3cd0SPaolo Pisati 191be4f3cd0SPaolo Pisati int 192be4f3cd0SPaolo Pisati LibAliasDetachHandlers(struct proto_handler *_p) 193be4f3cd0SPaolo Pisati { 19443197d29SPaolo Pisati int i, error; 195be4f3cd0SPaolo Pisati 196be4f3cd0SPaolo Pisati LIBALIAS_WLOCK(); 19743197d29SPaolo Pisati error = -1; 198be4f3cd0SPaolo Pisati for (i = 0; 1; i++) { 199be4f3cd0SPaolo Pisati if (*((int *)&_p[i]) == EOH) 200be4f3cd0SPaolo Pisati break; 201be4f3cd0SPaolo Pisati error = _detach_handler(&_p[i]); 202be4f3cd0SPaolo Pisati if (error != 0) 203be4f3cd0SPaolo Pisati break; 204be4f3cd0SPaolo Pisati } 205be4f3cd0SPaolo Pisati LIBALIAS_WUNLOCK(); 206be4f3cd0SPaolo Pisati return (error); 207be4f3cd0SPaolo Pisati } 208be4f3cd0SPaolo Pisati 209be4f3cd0SPaolo Pisati int 210be4f3cd0SPaolo Pisati detach_handler(struct proto_handler *_p) 211be4f3cd0SPaolo Pisati { 21243197d29SPaolo Pisati int error; 213be4f3cd0SPaolo Pisati 214be4f3cd0SPaolo Pisati LIBALIAS_WLOCK(); 21543197d29SPaolo Pisati error = -1; 216be4f3cd0SPaolo Pisati error = _detach_handler(_p); 217be4f3cd0SPaolo Pisati LIBALIAS_WUNLOCK(); 218be4f3cd0SPaolo Pisati return (error); 219be4f3cd0SPaolo Pisati } 220be4f3cd0SPaolo Pisati 221be4f3cd0SPaolo Pisati int 22243197d29SPaolo Pisati find_handler(int8_t dir, int8_t proto, struct libalias *la, __unused struct ip *pip, 223be4f3cd0SPaolo Pisati struct alias_data *ad) 224be4f3cd0SPaolo Pisati { 225be4f3cd0SPaolo Pisati struct proto_handler *p; 22643197d29SPaolo Pisati int error; 227be4f3cd0SPaolo Pisati 228be4f3cd0SPaolo Pisati LIBALIAS_RLOCK(); 22943197d29SPaolo Pisati error = ENOENT; 230be4f3cd0SPaolo Pisati LIST_FOREACH(p, &handler_chain, entries) { 231be4f3cd0SPaolo Pisati if ((p->dir & dir) && (p->proto & proto)) 23243197d29SPaolo Pisati if (p->fingerprint(la, ad) == 0) { 233be4f3cd0SPaolo Pisati error = p->protohandler(la, pip, ad); 234be4f3cd0SPaolo Pisati break; 235be4f3cd0SPaolo Pisati } 236be4f3cd0SPaolo Pisati } 237be4f3cd0SPaolo Pisati LIBALIAS_RUNLOCK(); 238be4f3cd0SPaolo Pisati return (error); 239be4f3cd0SPaolo Pisati } 240be4f3cd0SPaolo Pisati 241be4f3cd0SPaolo Pisati struct proto_handler * 242be4f3cd0SPaolo Pisati first_handler(void) 243be4f3cd0SPaolo Pisati { 244be4f3cd0SPaolo Pisati 245be4f3cd0SPaolo Pisati return (LIST_FIRST(&handler_chain)); 246be4f3cd0SPaolo Pisati } 247be4f3cd0SPaolo Pisati 248*1019f603SGleb Smirnoff #ifndef _KERNEL 249be4f3cd0SPaolo Pisati /* Dll manipulation code - this code is not thread safe... */ 250be4f3cd0SPaolo Pisati int 251be4f3cd0SPaolo Pisati attach_dll(struct dll *p) 252be4f3cd0SPaolo Pisati { 253be4f3cd0SPaolo Pisati struct dll *b; 254be4f3cd0SPaolo Pisati 255be4f3cd0SPaolo Pisati SLIST_FOREACH(b, &dll_chain, next) { 256be4f3cd0SPaolo Pisati if (!strncmp(b->name, p->name, DLL_LEN)) 257be4f3cd0SPaolo Pisati return (EEXIST); /* Dll name conflict. */ 258be4f3cd0SPaolo Pisati } 259be4f3cd0SPaolo Pisati SLIST_INSERT_HEAD(&dll_chain, p, next); 260be4f3cd0SPaolo Pisati return (0); 261be4f3cd0SPaolo Pisati } 262be4f3cd0SPaolo Pisati 263be4f3cd0SPaolo Pisati void * 264be4f3cd0SPaolo Pisati detach_dll(char *p) 265be4f3cd0SPaolo Pisati { 26643197d29SPaolo Pisati struct dll *b, *b_tmp; 26743197d29SPaolo Pisati void *error; 268be4f3cd0SPaolo Pisati 26943197d29SPaolo Pisati b = NULL; 27043197d29SPaolo Pisati error = NULL; 271be4f3cd0SPaolo Pisati SLIST_FOREACH_SAFE(b, &dll_chain, next, b_tmp) 272be4f3cd0SPaolo Pisati if (!strncmp(b->name, p, DLL_LEN)) { 273be4f3cd0SPaolo Pisati SLIST_REMOVE(&dll_chain, b, dll, next); 274be4f3cd0SPaolo Pisati error = b; 275be4f3cd0SPaolo Pisati break; 276be4f3cd0SPaolo Pisati } 277be4f3cd0SPaolo Pisati return (error); 278be4f3cd0SPaolo Pisati } 279be4f3cd0SPaolo Pisati 280be4f3cd0SPaolo Pisati struct dll * 281be4f3cd0SPaolo Pisati walk_dll_chain(void) 282be4f3cd0SPaolo Pisati { 283be4f3cd0SPaolo Pisati struct dll *t; 284be4f3cd0SPaolo Pisati 285be4f3cd0SPaolo Pisati t = SLIST_FIRST(&dll_chain); 286be4f3cd0SPaolo Pisati if (t == NULL) 287be4f3cd0SPaolo Pisati return (NULL); 288be4f3cd0SPaolo Pisati SLIST_REMOVE_HEAD(&dll_chain, next); 289be4f3cd0SPaolo Pisati return (t); 290be4f3cd0SPaolo Pisati } 291*1019f603SGleb Smirnoff #endif /* !_KERNEL */ 292