1162674Spiso/*- 2162674Spiso * Copyright (c) 2005 Paolo Pisati <piso@FreeBSD.org> 3162674Spiso * All rights reserved. 4162674Spiso * 5162674Spiso * Redistribution and use in source and binary forms, with or without 6162674Spiso * modification, are permitted provided that the following conditions 7162674Spiso * are met: 8162674Spiso * 1. Redistributions of source code must retain the above copyright 9162674Spiso * notice, this list of conditions and the following disclaimer. 10162674Spiso * 2. Redistributions in binary form must reproduce the above copyright 11162674Spiso * notice, this list of conditions and the following disclaimer in the 12162674Spiso * documentation and/or other materials provided with the distribution. 13162674Spiso * 14162674Spiso * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15162674Spiso * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16162674Spiso * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17162674Spiso * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18162674Spiso * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19162674Spiso * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20162674Spiso * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21162674Spiso * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22162674Spiso * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23162674Spiso * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24162674Spiso * SUCH DAMAGE. 25162674Spiso * 26162674Spiso */ 27162685Spiso#include <sys/cdefs.h> 28162674Spiso__FBSDID("$FreeBSD$"); 29162674Spiso 30162674Spiso#ifdef _KERNEL 31162674Spiso#include <sys/libkern.h> 32162674Spiso#include <sys/param.h> 33162674Spiso#include <sys/lock.h> 34162674Spiso#include <sys/rwlock.h> 35162674Spiso#else 36162674Spiso#include <stdio.h> 37162674Spiso#include <string.h> 38162674Spiso#include <sys/types.h> 39162674Spiso#include <errno.h> 40162674Spiso#endif 41162674Spiso 42162674Spiso#include <netinet/in_systm.h> 43162674Spiso#include <netinet/in.h> 44162674Spiso#include <netinet/ip.h> 45162674Spiso 46162674Spiso#ifdef _KERNEL 47162674Spiso#include <netinet/libalias/alias_local.h> 48162674Spiso#include <netinet/libalias/alias_mod.h> 49162674Spiso#else 50162674Spiso#include "alias_local.h" 51162674Spiso#include "alias_mod.h" 52162674Spiso#endif 53162674Spiso 54162674Spiso/* Protocol and userland module handlers chains. */ 55201145SantoineLIST_HEAD(handler_chain, proto_handler) handler_chain = LIST_HEAD_INITIALIZER(handler_chain); 56162674Spiso#ifdef _KERNEL 57162674Spisostruct rwlock handler_rw; 58162674Spiso#endif 59201145SantoineSLIST_HEAD(dll_chain, dll) dll_chain = SLIST_HEAD_INITIALIZER(dll_chain); 60162674Spiso 61162674Spiso#ifdef _KERNEL 62162674Spiso 63165243Spiso#define LIBALIAS_RWLOCK_INIT() \ 64162674Spiso rw_init(&handler_rw, "Libalias_modules_rwlock") 65165243Spiso#define LIBALIAS_RWLOCK_DESTROY() rw_destroy(&handler_rw) 66162674Spiso#define LIBALIAS_WLOCK_ASSERT() \ 67162674Spiso rw_assert(&handler_rw, RA_WLOCKED) 68162674Spiso 69162674Spisostatic __inline void 70162674SpisoLIBALIAS_RLOCK(void) 71162674Spiso{ 72162674Spiso rw_rlock(&handler_rw); 73162674Spiso} 74162674Spiso 75162674Spisostatic __inline void 76162674SpisoLIBALIAS_RUNLOCK(void) 77162674Spiso{ 78162674Spiso rw_runlock(&handler_rw); 79162674Spiso} 80162674Spiso 81162674Spisostatic __inline void 82162674SpisoLIBALIAS_WLOCK(void) 83162674Spiso{ 84162674Spiso rw_wlock(&handler_rw); 85162674Spiso} 86162674Spiso 87162674Spisostatic __inline void 88162674SpisoLIBALIAS_WUNLOCK(void) 89162674Spiso{ 90162674Spiso rw_wunlock(&handler_rw); 91162674Spiso} 92162674Spiso 93162674Spisostatic void 94162674Spiso_handler_chain_init(void) 95162674Spiso{ 96162674Spiso 97162674Spiso if (!rw_initialized(&handler_rw)) 98165243Spiso LIBALIAS_RWLOCK_INIT(); 99162674Spiso} 100162674Spiso 101162674Spisostatic void 102162674Spiso_handler_chain_destroy(void) 103162674Spiso{ 104162674Spiso 105162674Spiso if (rw_initialized(&handler_rw)) 106165243Spiso LIBALIAS_RWLOCK_DESTROY(); 107162674Spiso} 108162674Spiso 109162674Spiso#else 110165243Spiso#define LIBALIAS_RWLOCK_INIT() ; 111165243Spiso#define LIBALIAS_RWLOCK_DESTROY() ; 112162674Spiso#define LIBALIAS_WLOCK_ASSERT() ; 113162674Spiso#define LIBALIAS_RLOCK() ; 114162674Spiso#define LIBALIAS_RUNLOCK() ; 115162674Spiso#define LIBALIAS_WLOCK() ; 116162674Spiso#define LIBALIAS_WUNLOCK() ; 117162674Spiso#define _handler_chain_init() ; 118162674Spiso#define _handler_chain_destroy() ; 119162674Spiso#endif 120162674Spiso 121162674Spisovoid 122162674Spisohandler_chain_init(void) 123162674Spiso{ 124162674Spiso _handler_chain_init(); 125162674Spiso} 126162674Spiso 127162674Spisovoid 128162674Spisohandler_chain_destroy(void) 129162674Spiso{ 130162674Spiso _handler_chain_destroy(); 131162674Spiso} 132162674Spiso 133162674Spisostatic int 134162674Spiso_attach_handler(struct proto_handler *p) 135162674Spiso{ 136190841Spiso struct proto_handler *b; 137162674Spiso 138190841Spiso LIBALIAS_WLOCK_ASSERT(); 139190841Spiso b = NULL; 140162674Spiso LIST_FOREACH(b, &handler_chain, entries) { 141162674Spiso if ((b->pri == p->pri) && 142162674Spiso (b->dir == p->dir) && 143162674Spiso (b->proto == p->proto)) 144162674Spiso return (EEXIST); /* Priority conflict. */ 145162674Spiso if (b->pri > p->pri) { 146162674Spiso LIST_INSERT_BEFORE(b, p, entries); 147162674Spiso return (0); 148162674Spiso } 149162674Spiso } 150162674Spiso /* End of list or found right position, inserts here. */ 151162674Spiso if (b) 152162674Spiso LIST_INSERT_AFTER(b, p, entries); 153162674Spiso else 154162674Spiso LIST_INSERT_HEAD(&handler_chain, p, entries); 155162674Spiso return (0); 156162674Spiso} 157162674Spiso 158162674Spisostatic int 159162674Spiso_detach_handler(struct proto_handler *p) 160162674Spiso{ 161201758Smbr struct proto_handler *b, *b_tmp; 162162674Spiso 163162674Spiso LIBALIAS_WLOCK_ASSERT(); 164162674Spiso LIST_FOREACH_SAFE(b, &handler_chain, entries, b_tmp) { 165162674Spiso if (b == p) { 166162674Spiso LIST_REMOVE(b, entries); 167162674Spiso return (0); 168162674Spiso } 169162674Spiso } 170162674Spiso return (ENOENT); /* Handler not found. */ 171162674Spiso} 172162674Spiso 173162674Spisoint 174162674SpisoLibAliasAttachHandlers(struct proto_handler *_p) 175162674Spiso{ 176190841Spiso int i, error; 177162674Spiso 178162674Spiso LIBALIAS_WLOCK(); 179190841Spiso error = -1; 180190841Spiso for (i = 0; 1; i++) { 181162674Spiso if (*((int *)&_p[i]) == EOH) 182162674Spiso break; 183162674Spiso error = _attach_handler(&_p[i]); 184162674Spiso if (error != 0) 185162674Spiso break; 186162674Spiso } 187162674Spiso LIBALIAS_WUNLOCK(); 188162674Spiso return (error); 189162674Spiso} 190162674Spiso 191162674Spisoint 192162674SpisoLibAliasDetachHandlers(struct proto_handler *_p) 193162674Spiso{ 194190841Spiso int i, error; 195162674Spiso 196162674Spiso LIBALIAS_WLOCK(); 197190841Spiso error = -1; 198190841Spiso for (i = 0; 1; i++) { 199162674Spiso if (*((int *)&_p[i]) == EOH) 200162674Spiso break; 201162674Spiso error = _detach_handler(&_p[i]); 202162674Spiso if (error != 0) 203162674Spiso break; 204162674Spiso } 205162674Spiso LIBALIAS_WUNLOCK(); 206162674Spiso return (error); 207162674Spiso} 208162674Spiso 209162674Spisoint 210162674Spisodetach_handler(struct proto_handler *_p) 211162674Spiso{ 212190841Spiso int error; 213162674Spiso 214162674Spiso LIBALIAS_WLOCK(); 215190841Spiso error = -1; 216162674Spiso error = _detach_handler(_p); 217162674Spiso LIBALIAS_WUNLOCK(); 218162674Spiso return (error); 219162674Spiso} 220162674Spiso 221162674Spisoint 222190841Spisofind_handler(int8_t dir, int8_t proto, struct libalias *la, __unused struct ip *pip, 223190841Spiso struct alias_data *ad) 224162674Spiso{ 225162674Spiso struct proto_handler *p; 226190841Spiso int error; 227162674Spiso 228162674Spiso LIBALIAS_RLOCK(); 229190841Spiso error = ENOENT; 230162674Spiso LIST_FOREACH(p, &handler_chain, entries) { 231162674Spiso if ((p->dir & dir) && (p->proto & proto)) 232190841Spiso if (p->fingerprint(la, ad) == 0) { 233162674Spiso error = p->protohandler(la, pip, ad); 234162674Spiso break; 235162674Spiso } 236162674Spiso } 237162674Spiso LIBALIAS_RUNLOCK(); 238162674Spiso return (error); 239162674Spiso} 240162674Spiso 241162674Spisostruct proto_handler * 242162674Spisofirst_handler(void) 243162674Spiso{ 244162674Spiso 245162674Spiso return (LIST_FIRST(&handler_chain)); 246162674Spiso} 247162674Spiso 248162674Spiso/* Dll manipulation code - this code is not thread safe... */ 249162674Spiso 250162674Spisoint 251162674Spisoattach_dll(struct dll *p) 252162674Spiso{ 253162674Spiso struct dll *b; 254162674Spiso 255162674Spiso SLIST_FOREACH(b, &dll_chain, next) { 256162674Spiso if (!strncmp(b->name, p->name, DLL_LEN)) 257162674Spiso return (EEXIST); /* Dll name conflict. */ 258162674Spiso } 259162674Spiso SLIST_INSERT_HEAD(&dll_chain, p, next); 260162674Spiso return (0); 261162674Spiso} 262162674Spiso 263162674Spisovoid * 264162674Spisodetach_dll(char *p) 265162674Spiso{ 266190841Spiso struct dll *b, *b_tmp; 267190841Spiso void *error; 268162674Spiso 269190841Spiso b = NULL; 270190841Spiso error = NULL; 271162674Spiso SLIST_FOREACH_SAFE(b, &dll_chain, next, b_tmp) 272162674Spiso if (!strncmp(b->name, p, DLL_LEN)) { 273162674Spiso SLIST_REMOVE(&dll_chain, b, dll, next); 274162674Spiso error = b; 275162674Spiso break; 276162674Spiso } 277162674Spiso return (error); 278162674Spiso} 279162674Spiso 280162674Spisostruct dll * 281162674Spisowalk_dll_chain(void) 282162674Spiso{ 283162674Spiso struct dll *t; 284162674Spiso 285162674Spiso t = SLIST_FIRST(&dll_chain); 286162674Spiso if (t == NULL) 287162674Spiso return (NULL); 288162674Spiso SLIST_REMOVE_HEAD(&dll_chain, next); 289162674Spiso return (t); 290162674Spiso} 291