/* * Copyright 1997 Massachusetts Institute of Technology * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that both the above copyright notice and this * permission notice appear in all copies, that both the above * copyright notice and this permission notice appear in all * supporting documentation, and that the name of M.I.T. not be used * in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. M.I.T. makes * no representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied * warranty. * * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD: src/sys/netinet/in_hostcache.c,v 1.3 1999/08/28 00:49:16 peter Exp $ * $DragonFly: src/sys/netinet/Attic/in_hostcache.c,v 1.5 2005/01/06 17:59:32 hsu Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Manage the IP per-host cache (really a thin veneer over the generic * per-host cache code). */ /* Look up an entry -- can be called from interrupt context. */ struct in_hcentry * inhc_lookup(struct sockaddr_in *sin) { struct hcentry *hc; hc = hc_get((struct sockaddr *)sin); return ((struct in_hcentry *)hc); } /* Look up and possibly create an entry -- must be called from user mode. */ struct in_hcentry * inhc_alloc(struct sockaddr_in *sin) { struct in_hcentry *inhc; struct rtentry *rt; int error; /* xxx mutual exclusion for smp */ inhc = inhc_lookup(sin); if (inhc != 0) return inhc; rt = rtlookup(inhc->inhc_hc.hc_host); if (rt == 0) return 0; MALLOC(inhc, struct in_hcentry *, sizeof *inhc, M_HOSTCACHE, M_WAITOK); bzero(inhc, sizeof *inhc); inhc->inhc_hc.hc_host = dup_sockaddr((struct sockaddr *)sin); if (in_broadcast(sin->sin_addr, rt->rt_ifp)) inhc->inhc_flags |= INHC_BROADCAST; else if (((struct sockaddr_in *)rt->rt_ifa->ifa_addr)->sin_addr.s_addr == sin->sin_addr.s_addr) inhc->inhc_flags |= INHC_LOCAL; else if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) inhc->inhc_flags |= INHC_MULTICAST; inhc->inhc_pmtu = rt->rt_rmx.rmx_mtu; inhc->inhc_recvpipe = rt->rt_rmx.rmx_recvpipe; inhc->inhc_sendpipe = rt->rt_rmx.rmx_sendpipe; inhc->inhc_ssthresh = rt->rt_rmx.rmx_ssthresh; if (rt->rt_rmx.rmx_locks & RTV_RTT) inhc->inhc_rttmin = rt->rt_rmx.rmx_rtt / (RTM_RTTUNIT / TCP_RTT_SCALE); inhc->inhc_hc.hc_rt = rt; error = hc_insert(&inhc->inhc_hc); if (error != 0) { RTFREE(rt); FREE(inhc, M_HOSTCACHE); return 0; } /* * We don't return the structure directly because hc_get() needs * to be allowed to do its own processing. */ return (inhc_lookup(sin)); } /* * This is Van Jacobson's hash function for IPv4 addresses. * It is designed to work with a power-of-two-sized hash table. */ static u_long inhc_hash(struct sockaddr *sa, u_long nbuckets) { u_long ip; ip = ((struct sockaddr_in *)sa)->sin_addr.s_addr; return ((ip ^ (ip >> 23) ^ (ip >> 17)) & ~(nbuckets - 1)); } /* * We don't need to do any special work... if there are no references, * as the caller has already ensured, then it's OK to kill. */ static int inhc_delete(struct hcentry *hc) { return 0; } /* * Return the next increment for the number of buckets in the hash table. * Zero means ``do not bump''. */ static u_long inhc_bump(u_long oldsize) { if (oldsize < 512) return (oldsize << 1); return 0; } static struct hccallback inhc_cb = { inhc_hash, inhc_delete, inhc_bump }; int inhc_init(void) { return (hc_init(AF_INET, &inhc_cb, 128, 0)); }