1*11241Ssam /*	if_imphost.c	4.18	83/02/23	*/
25712Ssam 
35712Ssam #include "imp.h"
45712Ssam #if NIMP > 0
55712Ssam /*
65712Ssam  * Host table manipulation routines.
75712Ssam  * Only needed when shipping stuff through an IMP.
811231Ssam  *
911231Ssam  * Everything in here is called at splimp from
1011231Ssam  * from the IMP protocol code (if_imp.c), or
1111231Ssam  * interlocks with the code at splimp.
125712Ssam  */
135712Ssam #include "../h/param.h"
145712Ssam #include "../h/mbuf.h"
1511231Ssam 
168412Swnj #include "../netinet/in.h"
178412Swnj #include "../netinet/in_systm.h"
1811231Ssam 
198412Swnj #include "../netimp/if_imp.h"
208412Swnj #include "../netimp/if_imphost.h"
215712Ssam 
225712Ssam /*
235712Ssam  * Head of host table hash chains.
245712Ssam  */
255860Sroot struct mbuf *hosts;
265712Ssam 
275712Ssam /*
285712Ssam  * Given an internet address
295712Ssam  * return a host structure (if it exists).
305712Ssam  */
315712Ssam struct host *
325771Swnj hostlookup(addr)
335712Ssam 	struct in_addr addr;
345712Ssam {
355712Ssam 	register struct host *hp;
365712Ssam 	register struct mbuf *m;
375712Ssam 	register int hash = HOSTHASH(addr);
385712Ssam 
395860Sroot 	for (m = hosts; m; m = m->m_next) {
405712Ssam 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
416589Ssam 	        if (hp->h_addr.s_addr == addr.s_addr) {
426589Ssam 			hp->h_flags |= HF_INUSE;
4311231Ssam 			return (hp);
446589Ssam 		}
455712Ssam 	}
4611231Ssam 	return ((struct host *)0);
475712Ssam }
485712Ssam 
495712Ssam /*
505712Ssam  * Enter a reference to this host's internet
515712Ssam  * address.  If no host structure exists, create
525712Ssam  * one and hook it into the host database.
535712Ssam  */
545712Ssam struct host *
555771Swnj hostenter(addr)
565712Ssam 	struct in_addr addr;
575712Ssam {
585860Sroot 	register struct mbuf *m, **mprev;
595860Sroot 	register struct host *hp, *hp0 = 0;
605712Ssam 	register int hash = HOSTHASH(addr);
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) {
839646Ssam 		m = m_getclr(M_DONTWAIT, MT_HTABLE);
8411231Ssam 		if (m == NULL)
8511231Ssam 			return ((struct host *)0);
865860Sroot 		*mprev = m;
875860Sroot 		hp0 = &mtod(m, struct hmbuf *)->hm_hosts[hash];
885712Ssam 	}
895860Sroot 	mtod(dtom(hp0), struct hmbuf *)->hm_count++;
905860Sroot 	hp = hp0;
915712Ssam 	hp->h_addr = addr;
926589Ssam 	hp->h_timer = 0;
936725Ssam 	hp->h_flags = 0;
945712Ssam 
955712Ssam foundhost:
966589Ssam 	hp->h_flags |= HF_INUSE;
975712Ssam 	return (hp);
985712Ssam }
995712Ssam 
1005712Ssam /*
1016589Ssam  * Mark a host structure free and set it's
1026589Ssam  * timer going.
1035712Ssam  */
1045860Sroot hostfree(hp)
1055860Sroot 	register struct host *hp;
1065712Ssam {
1076589Ssam 
1086589Ssam 	hp->h_flags &= ~HF_INUSE;
1096589Ssam 	hp->h_timer = HOSTTIMER;
1106589Ssam 	hp->h_rfnm = 0;
1115712Ssam }
1125712Ssam 
1135712Ssam /*
1145712Ssam  * Reset a given network's host entries.
1155712Ssam  */
1165771Swnj hostreset(net)
1175712Ssam 	int net;
1185712Ssam {
1195712Ssam 	register struct mbuf *m;
1205712Ssam 	register struct host *hp, *lp;
1215860Sroot 	struct hmbuf *hm;
1225712Ssam 
1235860Sroot 	for (m = hosts; m; m = m->m_next) {
1245860Sroot 		hm = mtod(m, struct hmbuf *);
1255860Sroot 		hp = hm->hm_hosts;
1265712Ssam 		lp = hp + HPMBUF;
1276589Ssam 		while (hm->hm_count > 0 && hp < lp) {
1286089Sroot 			if (hp->h_addr.s_net == net) {
1296589Ssam 				hp->h_flags &= ~HF_INUSE;
1306145Ssam 				hostrelease(hp);
1316089Sroot 			}
1325712Ssam 			hp++;
1335712Ssam 		}
1345712Ssam 	}
1355712Ssam }
1365712Ssam 
1375712Ssam /*
1385712Ssam  * Remove a host structure and release
1395712Ssam  * any resources it's accumulated.
1405712Ssam  */
1415860Sroot hostrelease(hp)
1425712Ssam 	register struct host *hp;
1435712Ssam {
1445860Sroot 	register struct mbuf *m, **mprev, *mh = dtom(hp);
1455712Ssam 
1465712Ssam 	/*
1475712Ssam 	 * Discard any packets left on the waiting q
1485712Ssam 	 */
1495771Swnj 	if (m = hp->h_q) {
1505868Sroot 		register struct mbuf *n;
1515868Sroot 
1525868Sroot 		do {
1535868Sroot 			n = m->m_act;
1545868Sroot 			m_freem(m);
1555868Sroot 			m = n;
1565868Sroot 		} while (m != hp->h_q);
1575771Swnj 		hp->h_q = 0;
1585712Ssam 	}
1596725Ssam 	hp->h_flags = 0;
1605860Sroot 	if (--mtod(mh, struct hmbuf *)->hm_count)
1615712Ssam 		return;
1625860Sroot 	mprev = &hosts;
1635860Sroot 	while ((m = *mprev) != mh)
1645860Sroot 		mprev = &m->m_next;
1656589Ssam 	*mprev = m_free(mh);
1665712Ssam }
1675924Sroot 
1685924Sroot /*
1695924Sroot  * Remove a packet from the holding q.
1705924Sroot  * The RFNM counter is also bumped.
1715924Sroot  */
1725924Sroot struct mbuf *
1735924Sroot hostdeque(hp)
1745924Sroot 	register struct host *hp;
1755924Sroot {
1765924Sroot 	register struct mbuf *m;
1775924Sroot 
1785924Sroot 	hp->h_rfnm--;
1795924Sroot 	HOST_DEQUE(hp, m);
1805924Sroot 	if (m)
1815924Sroot 		return (m);
1825924Sroot 	if (hp->h_rfnm == 0)
1835924Sroot 		hostfree(hp);
1845924Sroot 	return (0);
1855924Sroot }
1866589Ssam 
1876589Ssam /*
1886589Ssam  * Host data base timer routine.
1896589Ssam  * Decrement timers on structures which are
1906589Ssam  * waiting to be deallocated.  On expiration
1916589Ssam  * release resources, possibly deallocating
1926589Ssam  * mbuf associated with structure.
1936589Ssam  */
1946589Ssam hostslowtimo()
1956589Ssam {
1966589Ssam 	register struct mbuf *m;
1976589Ssam 	register struct host *hp, *lp;
1986589Ssam 	struct hmbuf *hm;
19911231Ssam 	int s = splimp();
2006589Ssam 
2016589Ssam 	for (m = hosts; m; m = m->m_next) {
2026589Ssam 		hm = mtod(m, struct hmbuf *);
2036589Ssam 		hp = hm->hm_hosts;
2046589Ssam 		lp = hp + HPMBUF;
2056779Ssam 		for (; hm->hm_count > 0 && hp < lp; hp++) {
2066589Ssam 			if (hp->h_flags & HF_INUSE)
2076589Ssam 				continue;
2086589Ssam 			if (hp->h_timer && --hp->h_timer == 0)
2096589Ssam 				hostrelease(hp);
2106589Ssam 		}
2116589Ssam 	}
212*11241Ssam 	splx(s);
2136589Ssam }
214