182f39c91SKip Macy /* 282f39c91SKip Macy * Copyright (c) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved. 382f39c91SKip Macy * Copyright (c) 2004-2008 Qing Li. All rights reserved. 482f39c91SKip Macy * Copyright (c) 2008 Kip Macy. All rights reserved. 582f39c91SKip Macy * 682f39c91SKip Macy * Redistribution and use in source and binary forms, with or without 782f39c91SKip Macy * modification, are permitted provided that the following conditions 882f39c91SKip Macy * are met: 982f39c91SKip Macy * 1. Redistributions of source code must retain the above copyright 1082f39c91SKip Macy * notice, this list of conditions and the following disclaimer. 1182f39c91SKip Macy * 2. Redistributions in binary form must reproduce the above copyright 1282f39c91SKip Macy * notice, this list of conditions and the following disclaimer in the 1382f39c91SKip Macy * documentation and/or other materials provided with the distribution. 1482f39c91SKip Macy * 1582f39c91SKip Macy * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1682f39c91SKip Macy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1782f39c91SKip Macy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1882f39c91SKip Macy * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 1982f39c91SKip Macy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2082f39c91SKip Macy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2182f39c91SKip Macy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2282f39c91SKip Macy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2382f39c91SKip Macy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2482f39c91SKip Macy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2582f39c91SKip Macy * SUCH DAMAGE. 2682f39c91SKip Macy */ 2782f39c91SKip Macy #include <sys/cdefs.h> 2882f39c91SKip Macy __FBSDID("$FreeBSD$"); 2982f39c91SKip Macy 30335b943fSBjoern A. Zeeb #include "opt_ddb.h" 3182f39c91SKip Macy #include "opt_inet.h" 3282f39c91SKip Macy #include "opt_inet6.h" 3382f39c91SKip Macy 3482f39c91SKip Macy #include <sys/param.h> 3582f39c91SKip Macy #include <sys/systm.h> 3682f39c91SKip Macy #include <sys/malloc.h> 3782f39c91SKip Macy #include <sys/mbuf.h> 3882f39c91SKip Macy #include <sys/syslog.h> 3982f39c91SKip Macy #include <sys/sysctl.h> 4082f39c91SKip Macy #include <sys/socket.h> 4182f39c91SKip Macy #include <sys/kernel.h> 4282f39c91SKip Macy #include <sys/lock.h> 4382f39c91SKip Macy #include <sys/mutex.h> 4482f39c91SKip Macy #include <sys/rwlock.h> 4582f39c91SKip Macy 46335b943fSBjoern A. Zeeb #ifdef DDB 47335b943fSBjoern A. Zeeb #include <ddb/ddb.h> 48335b943fSBjoern A. Zeeb #endif 49335b943fSBjoern A. Zeeb 5082f39c91SKip Macy #include <vm/uma.h> 5182f39c91SKip Macy 5282f39c91SKip Macy #include <netinet/in.h> 5382f39c91SKip Macy #include <net/if_llatbl.h> 5482f39c91SKip Macy #include <net/if.h> 5582f39c91SKip Macy #include <net/if_dl.h> 5682f39c91SKip Macy #include <net/if_var.h> 5782f39c91SKip Macy #include <net/route.h> 58530c0060SRobert Watson #include <net/vnet.h> 5982f39c91SKip Macy #include <netinet/if_ether.h> 6082f39c91SKip Macy #include <netinet6/in6_var.h> 6182f39c91SKip Macy #include <netinet6/nd6.h> 6282f39c91SKip Macy 6382f39c91SKip Macy MALLOC_DEFINE(M_LLTABLE, "lltable", "link level address tables"); 6482f39c91SKip Macy 653e288e62SDimitry Andric static VNET_DEFINE(SLIST_HEAD(, lltable), lltables); 66989e0411SMarko Zec #define V_lltables VNET(lltables) 6782f39c91SKip Macy 6882f39c91SKip Macy extern void arprequest(struct ifnet *, struct in_addr *, struct in_addr *, 6982f39c91SKip Macy u_char *); 7082f39c91SKip Macy 71989e0411SMarko Zec static void vnet_lltable_init(void); 72989e0411SMarko Zec 73dc56e98fSRobert Watson struct rwlock lltable_rwlock; 74dc56e98fSRobert Watson RW_SYSINIT(lltable_rwlock, &lltable_rwlock, "lltable_rwlock"); 75dc56e98fSRobert Watson 7682f39c91SKip Macy /* 7782f39c91SKip Macy * Dump arp state for a specific address family. 7882f39c91SKip Macy */ 7982f39c91SKip Macy int 8082f39c91SKip Macy lltable_sysctl_dumparp(int af, struct sysctl_req *wr) 8182f39c91SKip Macy { 8282f39c91SKip Macy struct lltable *llt; 8382f39c91SKip Macy int error = 0; 8482f39c91SKip Macy 85dc56e98fSRobert Watson LLTABLE_RLOCK(); 86989e0411SMarko Zec SLIST_FOREACH(llt, &V_lltables, llt_link) { 8782f39c91SKip Macy if (llt->llt_af == af) { 8882f39c91SKip Macy error = llt->llt_dump(llt, wr); 8982f39c91SKip Macy if (error != 0) 9082f39c91SKip Macy goto done; 9182f39c91SKip Macy } 9282f39c91SKip Macy } 9382f39c91SKip Macy done: 94dc56e98fSRobert Watson LLTABLE_RUNLOCK(); 9582f39c91SKip Macy return (error); 9682f39c91SKip Macy } 9782f39c91SKip Macy 9882f39c91SKip Macy /* 9982f39c91SKip Macy * Deletes an address from the address table. 10082f39c91SKip Macy * This function is called by the timer functions 10182f39c91SKip Macy * such as arptimer() and nd6_llinfo_timer(), and 10282f39c91SKip Macy * the caller does the locking. 103e162ea60SGeorge V. Neville-Neil * 104e162ea60SGeorge V. Neville-Neil * Returns the number of held packets, if any, that were dropped. 10582f39c91SKip Macy */ 106e162ea60SGeorge V. Neville-Neil size_t 10782f39c91SKip Macy llentry_free(struct llentry *lle) 10882f39c91SKip Macy { 109e162ea60SGeorge V. Neville-Neil size_t pkts_dropped; 110e162ea60SGeorge V. Neville-Neil struct mbuf *next; 11182f39c91SKip Macy 112e162ea60SGeorge V. Neville-Neil pkts_dropped = 0; 11382f39c91SKip Macy LLE_WLOCK_ASSERT(lle); 11482f39c91SKip Macy LIST_REMOVE(lle, lle_next); 11582f39c91SKip Macy 116e162ea60SGeorge V. Neville-Neil while ((lle->la_numheld > 0) && (lle->la_hold != NULL)) { 117e162ea60SGeorge V. Neville-Neil next = lle->la_hold->m_nextpkt; 11882f39c91SKip Macy m_freem(lle->la_hold); 119e162ea60SGeorge V. Neville-Neil lle->la_hold = next; 120e162ea60SGeorge V. Neville-Neil lle->la_numheld--; 121e162ea60SGeorge V. Neville-Neil pkts_dropped++; 122e162ea60SGeorge V. Neville-Neil } 123e162ea60SGeorge V. Neville-Neil 124e162ea60SGeorge V. Neville-Neil KASSERT(lle->la_numheld == 0, 1257b3b099eSKonstantin Belousov ("%s: la_numheld %d > 0, pkts_droped %zd", __func__, 126e162ea60SGeorge V. Neville-Neil lle->la_numheld, pkts_dropped)); 12782f39c91SKip Macy 12882f39c91SKip Macy LLE_FREE_LOCKED(lle); 129e162ea60SGeorge V. Neville-Neil 130e162ea60SGeorge V. Neville-Neil return (pkts_dropped); 13182f39c91SKip Macy } 13282f39c91SKip Macy 133adfc35ffSKip Macy /* 134adfc35ffSKip Macy * Update an llentry for address dst (equivalent to rtalloc for new-arp) 135d4121a02SKip Macy * Caller must pass in a valid struct llentry * (or NULL) 136e94ba2ceSKip Macy * 137e94ba2ceSKip Macy * if found the llentry * is returned referenced and unlocked 138adfc35ffSKip Macy */ 139c8da95acSKip Macy int 140c8da95acSKip Macy llentry_update(struct llentry **llep, struct lltable *lt, 141d4121a02SKip Macy struct sockaddr_storage *dst, struct ifnet *ifp) 142c8da95acSKip Macy { 143c8da95acSKip Macy struct llentry *la; 144c8da95acSKip Macy 145c8da95acSKip Macy IF_AFDATA_RLOCK(ifp); 146c8da95acSKip Macy la = lla_lookup(lt, LLE_EXCLUSIVE, 147c8da95acSKip Macy (struct sockaddr *)dst); 148c8da95acSKip Macy IF_AFDATA_RUNLOCK(ifp); 149c8da95acSKip Macy if ((la == NULL) && 150c8da95acSKip Macy (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0) { 151c8da95acSKip Macy IF_AFDATA_WLOCK(ifp); 152c8da95acSKip Macy la = lla_lookup(lt, 153c8da95acSKip Macy (LLE_CREATE | LLE_EXCLUSIVE), 154c8da95acSKip Macy (struct sockaddr *)dst); 155c8da95acSKip Macy IF_AFDATA_WUNLOCK(ifp); 156c8da95acSKip Macy } 157c8da95acSKip Macy if (la != NULL && (*llep != la)) { 158c8da95acSKip Macy if (*llep != NULL) 159c8da95acSKip Macy LLE_FREE(*llep); 160c8da95acSKip Macy LLE_ADDREF(la); 161c8da95acSKip Macy LLE_WUNLOCK(la); 162c8da95acSKip Macy *llep = la; 163c8da95acSKip Macy } else if (la != NULL) 164c8da95acSKip Macy LLE_WUNLOCK(la); 165c8da95acSKip Macy 166c8da95acSKip Macy if (la == NULL) 167c8da95acSKip Macy return (ENOENT); 168c8da95acSKip Macy 169c8da95acSKip Macy return (0); 170c8da95acSKip Macy } 171c8da95acSKip Macy 17282f39c91SKip Macy /* 17382f39c91SKip Macy * Free all entries from given table and free itself. 17482f39c91SKip Macy */ 17582f39c91SKip Macy void 17682f39c91SKip Macy lltable_free(struct lltable *llt) 17782f39c91SKip Macy { 17882f39c91SKip Macy struct llentry *lle, *next; 17982f39c91SKip Macy int i; 18082f39c91SKip Macy 18182f39c91SKip Macy KASSERT(llt != NULL, ("%s: llt is NULL", __func__)); 18282f39c91SKip Macy 183dc56e98fSRobert Watson LLTABLE_WLOCK(); 184989e0411SMarko Zec SLIST_REMOVE(&V_lltables, llt, lltable, llt_link); 185dc56e98fSRobert Watson LLTABLE_WUNLOCK(); 18682f39c91SKip Macy 18782f39c91SKip Macy for (i=0; i < LLTBL_HASHTBL_SIZE; i++) { 18882f39c91SKip Macy LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) { 189becba438SBjoern A. Zeeb int canceled; 19082f39c91SKip Macy 191becba438SBjoern A. Zeeb canceled = callout_drain(&lle->la_timer); 19282f39c91SKip Macy LLE_WLOCK(lle); 193becba438SBjoern A. Zeeb if (canceled) 194becba438SBjoern A. Zeeb LLE_REMREF(lle); 19582f39c91SKip Macy llentry_free(lle); 19682f39c91SKip Macy } 19782f39c91SKip Macy } 19882f39c91SKip Macy 19982f39c91SKip Macy free(llt, M_LLTABLE); 20082f39c91SKip Macy } 20182f39c91SKip Macy 202fc2bfb32SBjoern A. Zeeb #if 0 20382f39c91SKip Macy void 20482f39c91SKip Macy lltable_drain(int af) 20582f39c91SKip Macy { 20682f39c91SKip Macy struct lltable *llt; 20782f39c91SKip Macy struct llentry *lle; 20882f39c91SKip Macy register int i; 20982f39c91SKip Macy 210dc56e98fSRobert Watson LLTABLE_RLOCK(); 211989e0411SMarko Zec SLIST_FOREACH(llt, &V_lltables, llt_link) { 21282f39c91SKip Macy if (llt->llt_af != af) 21382f39c91SKip Macy continue; 21482f39c91SKip Macy 21582f39c91SKip Macy for (i=0; i < LLTBL_HASHTBL_SIZE; i++) { 21682f39c91SKip Macy LIST_FOREACH(lle, &llt->lle_head[i], lle_next) { 217fc2bfb32SBjoern A. Zeeb LLE_WLOCK(lle); 21882f39c91SKip Macy if (lle->la_hold) { 21982f39c91SKip Macy m_freem(lle->la_hold); 22082f39c91SKip Macy lle->la_hold = NULL; 22182f39c91SKip Macy } 222fc2bfb32SBjoern A. Zeeb LLE_WUNLOCK(lle); 22382f39c91SKip Macy } 22482f39c91SKip Macy } 22582f39c91SKip Macy } 226dc56e98fSRobert Watson LLTABLE_RUNLOCK(); 22782f39c91SKip Macy } 228fc2bfb32SBjoern A. Zeeb #endif 22982f39c91SKip Macy 230c9d763bfSQing Li void 231*5b84dc78SQing Li lltable_prefix_free(int af, struct sockaddr *prefix, struct sockaddr *mask, 232*5b84dc78SQing Li u_int flags) 233c9d763bfSQing Li { 234c9d763bfSQing Li struct lltable *llt; 235c9d763bfSQing Li 236dc56e98fSRobert Watson LLTABLE_RLOCK(); 237989e0411SMarko Zec SLIST_FOREACH(llt, &V_lltables, llt_link) { 238c9d763bfSQing Li if (llt->llt_af != af) 239c9d763bfSQing Li continue; 240c9d763bfSQing Li 241*5b84dc78SQing Li llt->llt_prefix_free(llt, prefix, mask, flags); 242c9d763bfSQing Li } 243dc56e98fSRobert Watson LLTABLE_RUNLOCK(); 244c9d763bfSQing Li } 245c9d763bfSQing Li 246c9d763bfSQing Li 247c9d763bfSQing Li 24882f39c91SKip Macy /* 24982f39c91SKip Macy * Create a new lltable. 25082f39c91SKip Macy */ 25182f39c91SKip Macy struct lltable * 25282f39c91SKip Macy lltable_init(struct ifnet *ifp, int af) 25382f39c91SKip Macy { 25482f39c91SKip Macy struct lltable *llt; 25582f39c91SKip Macy register int i; 25682f39c91SKip Macy 25782f39c91SKip Macy llt = malloc(sizeof(struct lltable), M_LLTABLE, M_WAITOK); 25882f39c91SKip Macy 25982f39c91SKip Macy llt->llt_af = af; 26082f39c91SKip Macy llt->llt_ifp = ifp; 26182f39c91SKip Macy for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) 26282f39c91SKip Macy LIST_INIT(&llt->lle_head[i]); 26382f39c91SKip Macy 264dc56e98fSRobert Watson LLTABLE_WLOCK(); 265989e0411SMarko Zec SLIST_INSERT_HEAD(&V_lltables, llt, llt_link); 266dc56e98fSRobert Watson LLTABLE_WUNLOCK(); 26782f39c91SKip Macy 26882f39c91SKip Macy return (llt); 26982f39c91SKip Macy } 27082f39c91SKip Macy 27182f39c91SKip Macy /* 27282f39c91SKip Macy * Called in route_output when adding/deleting a route to an interface. 27382f39c91SKip Macy */ 27482f39c91SKip Macy int 27582f39c91SKip Macy lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info) 27682f39c91SKip Macy { 27782f39c91SKip Macy struct sockaddr_dl *dl = 27882f39c91SKip Macy (struct sockaddr_dl *)info->rti_info[RTAX_GATEWAY]; 27982f39c91SKip Macy struct sockaddr *dst = (struct sockaddr *)info->rti_info[RTAX_DST]; 28082f39c91SKip Macy struct ifnet *ifp; 28182f39c91SKip Macy struct lltable *llt; 28282f39c91SKip Macy struct llentry *lle; 28382f39c91SKip Macy u_int laflags = 0, flags = 0; 28482f39c91SKip Macy int error = 0; 28582f39c91SKip Macy 28682f39c91SKip Macy if (dl == NULL || dl->sdl_family != AF_LINK) { 28782f39c91SKip Macy log(LOG_INFO, "%s: invalid dl\n", __func__); 28882f39c91SKip Macy return EINVAL; 28982f39c91SKip Macy } 29082f39c91SKip Macy ifp = ifnet_byindex(dl->sdl_index); 29182f39c91SKip Macy if (ifp == NULL) { 29282f39c91SKip Macy log(LOG_INFO, "%s: invalid ifp (sdl_index %d)\n", 29382f39c91SKip Macy __func__, dl->sdl_index); 29482f39c91SKip Macy return EINVAL; 29582f39c91SKip Macy } 29682f39c91SKip Macy 29782f39c91SKip Macy switch (rtm->rtm_type) { 29882f39c91SKip Macy case RTM_ADD: 29982f39c91SKip Macy if (rtm->rtm_flags & RTF_ANNOUNCE) { 30082f39c91SKip Macy flags |= LLE_PUB; 30182f39c91SKip Macy #ifdef INET 30282f39c91SKip Macy if (dst->sa_family == AF_INET && 30382f39c91SKip Macy ((struct sockaddr_inarp *)dst)->sin_other != 0) { 304c7ab6602SQing Li struct rtentry *rt; 305c7ab6602SQing Li ((struct sockaddr_inarp *)dst)->sin_other = 0; 306c7ab6602SQing Li rt = rtalloc1(dst, 0, 0); 30782f39c91SKip Macy if (rt == NULL || !(rt->rt_flags & RTF_HOST)) { 30882f39c91SKip Macy log(LOG_INFO, "%s: RTM_ADD publish " 30982f39c91SKip Macy "(proxy only) is invalid\n", 31082f39c91SKip Macy __func__); 3112e730beaSBjoern A. Zeeb if (rt) 3122e730beaSBjoern A. Zeeb RTFREE_LOCKED(rt); 31382f39c91SKip Macy return EINVAL; 31482f39c91SKip Macy } 3152e730beaSBjoern A. Zeeb RTFREE_LOCKED(rt); 31682f39c91SKip Macy 31782f39c91SKip Macy flags |= LLE_PROXY; 31882f39c91SKip Macy } 31982f39c91SKip Macy #endif 32082f39c91SKip Macy } 32182f39c91SKip Macy flags |= LLE_CREATE; 32282f39c91SKip Macy break; 32382f39c91SKip Macy 32482f39c91SKip Macy case RTM_DELETE: 32582f39c91SKip Macy flags |= LLE_DELETE; 32682f39c91SKip Macy break; 32782f39c91SKip Macy 32882f39c91SKip Macy case RTM_CHANGE: 32982f39c91SKip Macy break; 33082f39c91SKip Macy 33182f39c91SKip Macy default: 33282f39c91SKip Macy return EINVAL; /* XXX not implemented yet */ 33382f39c91SKip Macy } 33482f39c91SKip Macy 33582f39c91SKip Macy /* XXX linked list may be too expensive */ 336dc56e98fSRobert Watson LLTABLE_RLOCK(); 337989e0411SMarko Zec SLIST_FOREACH(llt, &V_lltables, llt_link) { 33882f39c91SKip Macy if (llt->llt_af == dst->sa_family && 33982f39c91SKip Macy llt->llt_ifp == ifp) 34082f39c91SKip Macy break; 34182f39c91SKip Macy } 342dc56e98fSRobert Watson LLTABLE_RUNLOCK(); 34382f39c91SKip Macy KASSERT(llt != NULL, ("Yep, ugly hacks are bad\n")); 34482f39c91SKip Macy 34582040afcSJung-uk Kim if (flags & LLE_CREATE) 34682f39c91SKip Macy flags |= LLE_EXCLUSIVE; 34782f39c91SKip Macy 34882f39c91SKip Macy IF_AFDATA_LOCK(ifp); 34982f39c91SKip Macy lle = lla_lookup(llt, flags, dst); 35082f39c91SKip Macy IF_AFDATA_UNLOCK(ifp); 35182f39c91SKip Macy if (LLE_IS_VALID(lle)) { 35282f39c91SKip Macy if (flags & LLE_CREATE) { 35382f39c91SKip Macy /* 35482f39c91SKip Macy * If we delay the delete, then a subsequent 35582f39c91SKip Macy * "arp add" should look up this entry, reset the 35682f39c91SKip Macy * LLE_DELETED flag, and reset the expiration timer 35782f39c91SKip Macy */ 35882f39c91SKip Macy bcopy(LLADDR(dl), &lle->ll_addr, ifp->if_addrlen); 35985011246SGleb Smirnoff lle->la_flags |= (flags & (LLE_PUB | LLE_PROXY)); 36082f39c91SKip Macy lle->la_flags |= LLE_VALID; 36182f39c91SKip Macy lle->la_flags &= ~LLE_DELETED; 36282f39c91SKip Macy #ifdef INET6 36382f39c91SKip Macy /* 36482f39c91SKip Macy * ND6 36582f39c91SKip Macy */ 36682f39c91SKip Macy if (dst->sa_family == AF_INET6) 36782f39c91SKip Macy lle->ln_state = ND6_LLINFO_REACHABLE; 36882f39c91SKip Macy #endif 36982f39c91SKip Macy /* 37082f39c91SKip Macy * NB: arp and ndp always set (RTF_STATIC | RTF_HOST) 37182f39c91SKip Macy */ 37282f39c91SKip Macy 37382f39c91SKip Macy if (rtm->rtm_rmx.rmx_expire == 0) { 37482f39c91SKip Macy lle->la_flags |= LLE_STATIC; 37582f39c91SKip Macy lle->la_expire = 0; 37682f39c91SKip Macy } else 37782f39c91SKip Macy lle->la_expire = rtm->rtm_rmx.rmx_expire; 37882f39c91SKip Macy laflags = lle->la_flags; 37982f39c91SKip Macy LLE_WUNLOCK(lle); 38082f39c91SKip Macy #ifdef INET 3817b4d716bSKip Macy /* gratuitous ARP */ 38282f39c91SKip Macy if ((laflags & LLE_PUB) && dst->sa_family == AF_INET) { 38382f39c91SKip Macy arprequest(ifp, 38482f39c91SKip Macy &((struct sockaddr_in *)dst)->sin_addr, 38582f39c91SKip Macy &((struct sockaddr_in *)dst)->sin_addr, 38682f39c91SKip Macy ((laflags & LLE_PROXY) ? 38782f39c91SKip Macy (u_char *)IF_LLADDR(ifp) : 38882f39c91SKip Macy (u_char *)LLADDR(dl))); 38982f39c91SKip Macy } 39082f39c91SKip Macy #endif 39182f39c91SKip Macy } else { 39282f39c91SKip Macy if (flags & LLE_EXCLUSIVE) 39382f39c91SKip Macy LLE_WUNLOCK(lle); 39482f39c91SKip Macy else 39582f39c91SKip Macy LLE_RUNLOCK(lle); 39682f39c91SKip Macy } 39782f39c91SKip Macy } else if ((lle == NULL) && (flags & LLE_DELETE)) 39882f39c91SKip Macy error = EINVAL; 39982f39c91SKip Macy 40082f39c91SKip Macy 40182f39c91SKip Macy return (error); 40282f39c91SKip Macy } 403989e0411SMarko Zec 404989e0411SMarko Zec static void 405989e0411SMarko Zec vnet_lltable_init() 406989e0411SMarko Zec { 407989e0411SMarko Zec 408989e0411SMarko Zec SLIST_INIT(&V_lltables); 409989e0411SMarko Zec } 41038d61195SMarko Zec VNET_SYSINIT(vnet_lltable_init, SI_SUB_PSEUDO, SI_ORDER_FIRST, 41138d61195SMarko Zec vnet_lltable_init, NULL); 412989e0411SMarko Zec 413335b943fSBjoern A. Zeeb #ifdef DDB 414335b943fSBjoern A. Zeeb struct llentry_sa { 415335b943fSBjoern A. Zeeb struct llentry base; 416335b943fSBjoern A. Zeeb struct sockaddr l3_addr; 417335b943fSBjoern A. Zeeb }; 418335b943fSBjoern A. Zeeb 419335b943fSBjoern A. Zeeb static void 420335b943fSBjoern A. Zeeb llatbl_lle_show(struct llentry_sa *la) 421335b943fSBjoern A. Zeeb { 422335b943fSBjoern A. Zeeb struct llentry *lle; 423335b943fSBjoern A. Zeeb uint8_t octet[6]; 424335b943fSBjoern A. Zeeb 425335b943fSBjoern A. Zeeb lle = &la->base; 426335b943fSBjoern A. Zeeb db_printf("lle=%p\n", lle); 427335b943fSBjoern A. Zeeb db_printf(" lle_next=%p\n", lle->lle_next.le_next); 428335b943fSBjoern A. Zeeb db_printf(" lle_lock=%p\n", &lle->lle_lock); 429335b943fSBjoern A. Zeeb db_printf(" lle_tbl=%p\n", lle->lle_tbl); 430335b943fSBjoern A. Zeeb db_printf(" lle_head=%p\n", lle->lle_head); 431335b943fSBjoern A. Zeeb db_printf(" la_hold=%p\n", lle->la_hold); 432e162ea60SGeorge V. Neville-Neil db_printf(" la_numheld=%d\n", lle->la_numheld); 433335b943fSBjoern A. Zeeb db_printf(" la_expire=%ju\n", (uintmax_t)lle->la_expire); 434335b943fSBjoern A. Zeeb db_printf(" la_flags=0x%04x\n", lle->la_flags); 435335b943fSBjoern A. Zeeb db_printf(" la_asked=%u\n", lle->la_asked); 436335b943fSBjoern A. Zeeb db_printf(" la_preempt=%u\n", lle->la_preempt); 437335b943fSBjoern A. Zeeb db_printf(" ln_byhint=%u\n", lle->ln_byhint); 438335b943fSBjoern A. Zeeb db_printf(" ln_state=%d\n", lle->ln_state); 439335b943fSBjoern A. Zeeb db_printf(" ln_router=%u\n", lle->ln_router); 440335b943fSBjoern A. Zeeb db_printf(" ln_ntick=%ju\n", (uintmax_t)lle->ln_ntick); 441335b943fSBjoern A. Zeeb db_printf(" lle_refcnt=%d\n", lle->lle_refcnt); 442335b943fSBjoern A. Zeeb bcopy(&lle->ll_addr.mac16, octet, sizeof(octet)); 443335b943fSBjoern A. Zeeb db_printf(" ll_addr=%02x:%02x:%02x:%02x:%02x:%02x\n", 444335b943fSBjoern A. Zeeb octet[0], octet[1], octet[2], octet[3], octet[4], octet[5]); 445335b943fSBjoern A. Zeeb db_printf(" la_timer=%p\n", &lle->la_timer); 446335b943fSBjoern A. Zeeb 447335b943fSBjoern A. Zeeb switch (la->l3_addr.sa_family) { 448335b943fSBjoern A. Zeeb #ifdef INET 449335b943fSBjoern A. Zeeb case AF_INET: 450335b943fSBjoern A. Zeeb { 451335b943fSBjoern A. Zeeb struct sockaddr_in *sin; 452335b943fSBjoern A. Zeeb char l3s[INET_ADDRSTRLEN]; 453335b943fSBjoern A. Zeeb 454335b943fSBjoern A. Zeeb sin = (struct sockaddr_in *)&la->l3_addr; 455335b943fSBjoern A. Zeeb inet_ntoa_r(sin->sin_addr, l3s); 456335b943fSBjoern A. Zeeb db_printf(" l3_addr=%s\n", l3s); 457335b943fSBjoern A. Zeeb break; 458335b943fSBjoern A. Zeeb } 459335b943fSBjoern A. Zeeb #endif 460335b943fSBjoern A. Zeeb #ifdef INET6 461335b943fSBjoern A. Zeeb case AF_INET6: 462335b943fSBjoern A. Zeeb { 463335b943fSBjoern A. Zeeb struct sockaddr_in6 *sin6; 464335b943fSBjoern A. Zeeb char l3s[INET6_ADDRSTRLEN]; 465335b943fSBjoern A. Zeeb 466335b943fSBjoern A. Zeeb sin6 = (struct sockaddr_in6 *)&la->l3_addr; 467335b943fSBjoern A. Zeeb ip6_sprintf(l3s, &sin6->sin6_addr); 468335b943fSBjoern A. Zeeb db_printf(" l3_addr=%s\n", l3s); 469335b943fSBjoern A. Zeeb break; 470335b943fSBjoern A. Zeeb } 471335b943fSBjoern A. Zeeb #endif 472335b943fSBjoern A. Zeeb default: 473335b943fSBjoern A. Zeeb db_printf(" l3_addr=N/A (af=%d)\n", la->l3_addr.sa_family); 474335b943fSBjoern A. Zeeb break; 475335b943fSBjoern A. Zeeb } 476335b943fSBjoern A. Zeeb } 477335b943fSBjoern A. Zeeb 478335b943fSBjoern A. Zeeb DB_SHOW_COMMAND(llentry, db_show_llentry) 479335b943fSBjoern A. Zeeb { 480335b943fSBjoern A. Zeeb 481335b943fSBjoern A. Zeeb if (!have_addr) { 482335b943fSBjoern A. Zeeb db_printf("usage: show llentry <struct llentry *>\n"); 483335b943fSBjoern A. Zeeb return; 484335b943fSBjoern A. Zeeb } 485335b943fSBjoern A. Zeeb 486335b943fSBjoern A. Zeeb llatbl_lle_show((struct llentry_sa *)addr); 487335b943fSBjoern A. Zeeb } 488335b943fSBjoern A. Zeeb 489335b943fSBjoern A. Zeeb static void 490335b943fSBjoern A. Zeeb llatbl_llt_show(struct lltable *llt) 491335b943fSBjoern A. Zeeb { 492335b943fSBjoern A. Zeeb int i; 493335b943fSBjoern A. Zeeb struct llentry *lle; 494335b943fSBjoern A. Zeeb 495335b943fSBjoern A. Zeeb db_printf("llt=%p llt_af=%d llt_ifp=%p\n", 496335b943fSBjoern A. Zeeb llt, llt->llt_af, llt->llt_ifp); 497335b943fSBjoern A. Zeeb 498335b943fSBjoern A. Zeeb for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) { 499335b943fSBjoern A. Zeeb LIST_FOREACH(lle, &llt->lle_head[i], lle_next) { 500335b943fSBjoern A. Zeeb 501335b943fSBjoern A. Zeeb llatbl_lle_show((struct llentry_sa *)lle); 502335b943fSBjoern A. Zeeb if (db_pager_quit) 503335b943fSBjoern A. Zeeb return; 504335b943fSBjoern A. Zeeb } 505335b943fSBjoern A. Zeeb } 506335b943fSBjoern A. Zeeb } 507335b943fSBjoern A. Zeeb 508335b943fSBjoern A. Zeeb DB_SHOW_COMMAND(lltable, db_show_lltable) 509335b943fSBjoern A. Zeeb { 510335b943fSBjoern A. Zeeb 511335b943fSBjoern A. Zeeb if (!have_addr) { 512335b943fSBjoern A. Zeeb db_printf("usage: show lltable <struct lltable *>\n"); 513335b943fSBjoern A. Zeeb return; 514335b943fSBjoern A. Zeeb } 515335b943fSBjoern A. Zeeb 516335b943fSBjoern A. Zeeb llatbl_llt_show((struct lltable *)addr); 517335b943fSBjoern A. Zeeb } 518335b943fSBjoern A. Zeeb 519335b943fSBjoern A. Zeeb DB_SHOW_ALL_COMMAND(lltables, db_show_all_lltables) 520335b943fSBjoern A. Zeeb { 521335b943fSBjoern A. Zeeb VNET_ITERATOR_DECL(vnet_iter); 522335b943fSBjoern A. Zeeb struct lltable *llt; 523335b943fSBjoern A. Zeeb 524335b943fSBjoern A. Zeeb VNET_FOREACH(vnet_iter) { 525335b943fSBjoern A. Zeeb CURVNET_SET_QUIET(vnet_iter); 526335b943fSBjoern A. Zeeb #ifdef VIMAGE 527335b943fSBjoern A. Zeeb db_printf("vnet=%p\n", curvnet); 528335b943fSBjoern A. Zeeb #endif 529335b943fSBjoern A. Zeeb SLIST_FOREACH(llt, &V_lltables, llt_link) { 530335b943fSBjoern A. Zeeb db_printf("llt=%p llt_af=%d llt_ifp=%p(%s)\n", 531335b943fSBjoern A. Zeeb llt, llt->llt_af, llt->llt_ifp, 532335b943fSBjoern A. Zeeb (llt->llt_ifp != NULL) ? 533335b943fSBjoern A. Zeeb llt->llt_ifp->if_xname : "?"); 534335b943fSBjoern A. Zeeb if (have_addr && addr != 0) /* verbose */ 535335b943fSBjoern A. Zeeb llatbl_llt_show(llt); 536335b943fSBjoern A. Zeeb if (db_pager_quit) { 537335b943fSBjoern A. Zeeb CURVNET_RESTORE(); 538335b943fSBjoern A. Zeeb return; 539335b943fSBjoern A. Zeeb } 540335b943fSBjoern A. Zeeb } 541335b943fSBjoern A. Zeeb CURVNET_RESTORE(); 542335b943fSBjoern A. Zeeb } 543335b943fSBjoern A. Zeeb } 544335b943fSBjoern A. Zeeb #endif 545