1*8412Swnj /*	if_imphost.c	4.15	82/10/09	*/
25712Ssam 
35712Ssam #include "imp.h"
45712Ssam #if NIMP > 0
55712Ssam /*
65712Ssam  * Host table manipulation routines.
75712Ssam  * Only needed when shipping stuff through an IMP.
85712Ssam  */
95712Ssam 
105712Ssam #include "../h/param.h"
115712Ssam #include "../h/mbuf.h"
12*8412Swnj #include "../netinet/in.h"
13*8412Swnj #include "../netinet/in_systm.h"
14*8412Swnj #include "../netimp/if_imp.h"
15*8412Swnj #include "../netimp/if_imphost.h"
165712Ssam 
175712Ssam /*
185712Ssam  * Head of host table hash chains.
195712Ssam  */
205860Sroot struct mbuf *hosts;
215712Ssam 
225712Ssam /*
235712Ssam  * Given an internet address
245712Ssam  * return a host structure (if it exists).
255712Ssam  */
265712Ssam struct host *
275771Swnj hostlookup(addr)
285712Ssam 	struct in_addr addr;
295712Ssam {
305712Ssam 	register struct host *hp;
315712Ssam 	register struct mbuf *m;
325712Ssam 	register int hash = HOSTHASH(addr);
336589Ssam 	int s = splnet();
345712Ssam 
355860Sroot 	for (m = hosts; m; m = m->m_next) {
365712Ssam 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
376589Ssam 	        if (hp->h_addr.s_addr == addr.s_addr) {
386589Ssam 			hp->h_flags |= HF_INUSE;
396589Ssam 			goto found;
406589Ssam 		}
415712Ssam 	}
426589Ssam 	hp = 0;
436589Ssam found:
446589Ssam 	splx(s);
456589Ssam 	return (hp);
465712Ssam }
475712Ssam 
485712Ssam /*
495712Ssam  * Enter a reference to this host's internet
505712Ssam  * address.  If no host structure exists, create
515712Ssam  * one and hook it into the host database.
525712Ssam  */
535712Ssam struct host *
545771Swnj hostenter(addr)
555712Ssam 	struct in_addr addr;
565712Ssam {
575860Sroot 	register struct mbuf *m, **mprev;
585860Sroot 	register struct host *hp, *hp0 = 0;
595712Ssam 	register int hash = HOSTHASH(addr);
606589Ssam 	int s = splnet();
615712Ssam 
625860Sroot 	mprev = &hosts;
635860Sroot 	while (m = *mprev) {
646209Swnj 		mprev = &m->m_next;
655712Ssam 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
666589Ssam 		if ((hp->h_flags & HF_INUSE) == 0) {
676589Ssam 			if (hp->h_addr.s_addr == addr.s_addr)
686589Ssam 				goto foundhost;
695860Sroot 			if (hp0 == 0)
705860Sroot 				hp0 = hp;
715860Sroot 			continue;
725860Sroot 		}
735712Ssam 	        if (hp->h_addr.s_addr == addr.s_addr)
745712Ssam 			goto foundhost;
755712Ssam 	}
765712Ssam 
775712Ssam 	/*
785712Ssam 	 * No current host structure, make one.
795712Ssam 	 * If our search ran off the end of the
805712Ssam 	 * chain of mbuf's, allocate another.
815712Ssam 	 */
825860Sroot 	if (hp0 == 0) {
835712Ssam 		m = m_getclr(M_DONTWAIT);
846589Ssam 		if (m == 0) {
856589Ssam 			splx(s);
865712Ssam 			return (0);
876589Ssam 		}
885860Sroot 		*mprev = m;
895860Sroot 		hp0 = &mtod(m, struct hmbuf *)->hm_hosts[hash];
905712Ssam 	}
915860Sroot 	mtod(dtom(hp0), struct hmbuf *)->hm_count++;
925860Sroot 	hp = hp0;
935712Ssam 	hp->h_addr = addr;
946589Ssam 	hp->h_timer = 0;
956725Ssam 	hp->h_flags = 0;
965712Ssam 
975712Ssam foundhost:
986589Ssam 	hp->h_flags |= HF_INUSE;
996589Ssam 	splx(s);
1005712Ssam 	return (hp);
1015712Ssam }
1025712Ssam 
1035712Ssam /*
1046589Ssam  * Mark a host structure free and set it's
1056589Ssam  * timer going.
1065712Ssam  */
1075860Sroot hostfree(hp)
1085860Sroot 	register struct host *hp;
1095712Ssam {
1106589Ssam 	int s = splnet();
1116589Ssam 
1126589Ssam 	hp->h_flags &= ~HF_INUSE;
1136589Ssam 	hp->h_timer = HOSTTIMER;
1146589Ssam 	hp->h_rfnm = 0;
1156589Ssam 	splx(s);
1165712Ssam }
1175712Ssam 
1185712Ssam /*
1195712Ssam  * Reset a given network's host entries.
1205712Ssam  */
1215771Swnj hostreset(net)
1225712Ssam 	int net;
1235712Ssam {
1245712Ssam 	register struct mbuf *m;
1255712Ssam 	register struct host *hp, *lp;
1265860Sroot 	struct hmbuf *hm;
1276589Ssam 	int s = splnet();
1285712Ssam 
1295860Sroot 	for (m = hosts; m; m = m->m_next) {
1305860Sroot 		hm = mtod(m, struct hmbuf *);
1315860Sroot 		hp = hm->hm_hosts;
1325712Ssam 		lp = hp + HPMBUF;
1336589Ssam 		while (hm->hm_count > 0 && hp < lp) {
1346089Sroot 			if (hp->h_addr.s_net == net) {
1356589Ssam 				hp->h_flags &= ~HF_INUSE;
1366145Ssam 				hostrelease(hp);
1376089Sroot 			}
1385712Ssam 			hp++;
1395712Ssam 		}
1405712Ssam 	}
1416589Ssam 	splx(s);
1425712Ssam }
1435712Ssam 
1445712Ssam /*
1455712Ssam  * Remove a host structure and release
1465712Ssam  * any resources it's accumulated.
1476589Ssam  * This routine is always called at splnet.
1485712Ssam  */
1495860Sroot hostrelease(hp)
1505712Ssam 	register struct host *hp;
1515712Ssam {
1525860Sroot 	register struct mbuf *m, **mprev, *mh = dtom(hp);
1535712Ssam 
1545712Ssam 	/*
1555712Ssam 	 * Discard any packets left on the waiting q
1565712Ssam 	 */
1575771Swnj 	if (m = hp->h_q) {
1585868Sroot 		register struct mbuf *n;
1595868Sroot 
1605868Sroot 		do {
1615868Sroot 			n = m->m_act;
1625868Sroot 			m_freem(m);
1635868Sroot 			m = n;
1645868Sroot 		} while (m != hp->h_q);
1655771Swnj 		hp->h_q = 0;
1665712Ssam 	}
1676725Ssam 	hp->h_flags = 0;
1685860Sroot 	if (--mtod(mh, struct hmbuf *)->hm_count)
1695712Ssam 		return;
1705860Sroot 	mprev = &hosts;
1715860Sroot 	while ((m = *mprev) != mh)
1725860Sroot 		mprev = &m->m_next;
1736589Ssam 	*mprev = m_free(mh);
1745712Ssam }
1755924Sroot 
1765924Sroot /*
1775924Sroot  * Remove a packet from the holding q.
1785924Sroot  * The RFNM counter is also bumped.
1795924Sroot  */
1805924Sroot struct mbuf *
1815924Sroot hostdeque(hp)
1825924Sroot 	register struct host *hp;
1835924Sroot {
1845924Sroot 	register struct mbuf *m;
1855924Sroot 
1865924Sroot 	hp->h_rfnm--;
1875924Sroot 	HOST_DEQUE(hp, m);
1885924Sroot 	if (m)
1895924Sroot 		return (m);
1905924Sroot 	if (hp->h_rfnm == 0)
1915924Sroot 		hostfree(hp);
1925924Sroot 	return (0);
1935924Sroot }
1946589Ssam 
1956589Ssam /*
1966589Ssam  * Host data base timer routine.
1976589Ssam  * Decrement timers on structures which are
1986589Ssam  * waiting to be deallocated.  On expiration
1996589Ssam  * release resources, possibly deallocating
2006589Ssam  * mbuf associated with structure.
2016589Ssam  */
2026589Ssam hostslowtimo()
2036589Ssam {
2046589Ssam 	register struct mbuf *m;
2056589Ssam 	register struct host *hp, *lp;
2066589Ssam 	struct hmbuf *hm;
2076589Ssam 	int s = splnet();
2086589Ssam 
2096589Ssam 	for (m = hosts; m; m = m->m_next) {
2106589Ssam 		hm = mtod(m, struct hmbuf *);
2116589Ssam 		hp = hm->hm_hosts;
2126589Ssam 		lp = hp + HPMBUF;
2136779Ssam 		for (; hm->hm_count > 0 && hp < lp; hp++) {
2146589Ssam 			if (hp->h_flags & HF_INUSE)
2156589Ssam 				continue;
2166589Ssam 			if (hp->h_timer && --hp->h_timer == 0)
2176589Ssam 				hostrelease(hp);
2186589Ssam 		}
2196589Ssam 	}
2206589Ssam 	splx(s);
2216589Ssam }
222