1 /* 2 * Copyright (c) 2008 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * $DragonFly: src/usr.sbin/vknetd/mac.c,v 1.1 2008/05/27 01:58:01 dillon Exp $ 35 */ 36 /* 37 * Bridging code (serialized) 38 */ 39 #include "vknetd.h" 40 41 static struct mac_list LRUList = TAILQ_HEAD_INITIALIZER(LRUList); 42 static mac_t MacHash[MAC_HSIZE]; 43 44 void 45 mac_init(void) 46 { 47 static struct mac MacAry[NMACS]; 48 int i; 49 50 for (i = 0; i < NMACS; ++i) 51 TAILQ_INSERT_TAIL(&LRUList, &MacAry[i], lru_entry); 52 } 53 54 static __inline int 55 machash(u_int8_t *macbuf) 56 { 57 int hv; 58 59 hv = macbuf[0] ^ (macbuf[1] << 1) ^ (macbuf[2] << 2) ^ 60 (macbuf[3] << 3) ^ (macbuf[4] << 4) ^ (macbuf[5] << 5); 61 return(hv & MAC_HMASK); 62 } 63 64 /* 65 * Locate a cached MAC address, return NULL if we do not have it cached. 66 * The MAC is moved to the head of the LRU list. 67 */ 68 mac_t 69 mac_find(u_int8_t *macbuf) 70 { 71 mac_t scan; 72 73 for (scan = MacHash[machash(macbuf)]; scan; scan = scan->mac_next) { 74 if (bcmp(macbuf, scan->macbuf, 6) == 0) { 75 if (TAILQ_FIRST(&LRUList) != scan) { 76 TAILQ_REMOVE(&LRUList, scan, lru_entry); 77 TAILQ_INSERT_HEAD(&LRUList, scan, lru_entry); 78 } 79 return(scan); 80 } 81 } 82 return(NULL); 83 } 84 85 /* 86 * Create a bridge association for a MAC address. The caller must 87 * have already deleted any pre-existing association. 88 */ 89 void 90 mac_add(bridge_t bridge, u_int8_t *macbuf) 91 { 92 mac_t *hashp; 93 mac_t mac; 94 95 /* 96 * Recycle least recently used MAC 97 */ 98 mac = TAILQ_LAST(&LRUList, mac_list); 99 if (mac->bridge) 100 mac_delete(mac); 101 102 /* 103 * Create the bridge assocation and enter the MAC into the hash 104 * table. 105 */ 106 bcopy(macbuf, mac->macbuf, 6); 107 TAILQ_INSERT_TAIL(&bridge->mac_list, mac, bridge_entry); 108 109 hashp = &MacHash[machash(mac->macbuf)]; 110 mac->mac_next = *hashp; 111 *hashp = mac; 112 113 mac->bridge = bridge; 114 115 /* 116 * We don't want to recycle the MAC any time soon. 117 */ 118 TAILQ_REMOVE(&LRUList, mac, lru_entry); 119 TAILQ_INSERT_HEAD(&LRUList, mac, lru_entry); 120 } 121 122 /* 123 * Delete a MAC's bridge assocation 124 */ 125 void 126 mac_delete(mac_t mac) 127 { 128 mac_t *hashp; 129 130 /* 131 * Remove the bridge linkage 132 */ 133 TAILQ_REMOVE(&mac->bridge->mac_list, mac, bridge_entry); 134 mac->bridge = NULL; 135 136 /* 137 * Remove the MAC hash linkage 138 */ 139 hashp = &MacHash[machash(mac->macbuf)]; 140 while (*hashp != mac) { 141 assert(*hashp); 142 hashp = &(*hashp)->mac_next; 143 } 144 *hashp = mac->mac_next; 145 146 /* 147 * This MAC is now unused, place on end of LRU list. 148 */ 149 TAILQ_REMOVE(&LRUList, mac, lru_entry); 150 TAILQ_INSERT_TAIL(&LRUList, mac, lru_entry); 151 } 152 153 /* 154 * Return non-zero if this is a broadcast MAC 155 */ 156 int 157 mac_broadcast(u_int8_t *macbuf) 158 { 159 if (macbuf[0] == 0 && macbuf[1] == 0 && macbuf[2] == 0 && 160 macbuf[3] == 0 && macbuf[4] == 0 && macbuf[5] == 0) { 161 return(1); 162 } 163 if (macbuf[0] == 0xFF && macbuf[1] == 0xFF && macbuf[2] == 0xFF && 164 macbuf[3] == 0xFF && macbuf[4] == 0xFF && macbuf[5] == 0xFF) { 165 return(1); 166 } 167 return(0); 168 } 169 170