1*6089Sroot /*	if_imphost.c	4.6	82/03/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"
125712Ssam #include "../net/in.h"
135712Ssam #include "../net/in_systm.h"
145712Ssam #include "../net/if_imp.h"
155860Sroot #include "../net/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);
335712Ssam 
345771Swnj COUNT(HOSTLOOKUP);
35*6089Sroot 	addr.s_lh = 0;
365860Sroot 	for (m = hosts; m; m = m->m_next) {
375712Ssam 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
385712Ssam 		if (hp->h_refcnt == 0)
395860Sroot 			continue;
40*6089Sroot 	        if (hp->h_addr.s_addr == addr.s_addr)
415712Ssam 			return (hp);
425712Ssam 	}
435712Ssam 	return (0);
445712Ssam }
455712Ssam 
465712Ssam /*
475712Ssam  * Enter a reference to this host's internet
485712Ssam  * address.  If no host structure exists, create
495712Ssam  * one and hook it into the host database.
505712Ssam  */
515712Ssam struct host *
525771Swnj hostenter(addr)
535712Ssam 	struct in_addr addr;
545712Ssam {
555860Sroot 	register struct mbuf *m, **mprev;
565860Sroot 	register struct host *hp, *hp0 = 0;
575712Ssam 	register int hash = HOSTHASH(addr);
585712Ssam 
595771Swnj COUNT(HOSTENTER);
60*6089Sroot 	addr.s_lh = 0;
615860Sroot 	mprev = &hosts;
625860Sroot 	while (m = *mprev) {
635712Ssam 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
645860Sroot 		if (hp->h_refcnt == 0) {
655860Sroot 			if (hp0 == 0)
665860Sroot 				hp0 = hp;
675860Sroot 			continue;
685860Sroot 		}
695712Ssam 	        if (hp->h_addr.s_addr == addr.s_addr)
705712Ssam 			goto foundhost;
715860Sroot 		mprev = &m->m_next;
725712Ssam 	}
735712Ssam 
745712Ssam 	/*
755712Ssam 	 * No current host structure, make one.
765712Ssam 	 * If our search ran off the end of the
775712Ssam 	 * chain of mbuf's, allocate another.
785712Ssam 	 */
795860Sroot 	if (hp0 == 0) {
805712Ssam 		m = m_getclr(M_DONTWAIT);
815712Ssam 		if (m == 0)
825712Ssam 			return (0);
835860Sroot 		*mprev = m;
845860Sroot 		m->m_off = MMINOFF;
855860Sroot 		hp0 = &mtod(m, struct hmbuf *)->hm_hosts[hash];
865712Ssam 	}
875860Sroot 	mtod(dtom(hp0), struct hmbuf *)->hm_count++;
885860Sroot 	hp = hp0;
895712Ssam 	hp->h_addr = addr;
905924Sroot 	hp->h_qcnt = 0;
915712Ssam 
925712Ssam foundhost:
935712Ssam 	hp->h_refcnt++;		/* know new structures have 0 val */
945712Ssam 	return (hp);
955712Ssam }
965712Ssam 
975712Ssam /*
985712Ssam  * Free a reference to a host.  If this causes the
995712Ssam  * host structure to be released do so.
1005712Ssam  */
1015860Sroot hostfree(hp)
1025860Sroot 	register struct host *hp;
1035712Ssam {
1045712Ssam 	register struct mbuf *m;
1055712Ssam 
1065771Swnj COUNT(HOSTFREE);
1075860Sroot 	if (--hp->h_refcnt)
1085860Sroot 		return;
1095860Sroot 	hostrelease(hp);
1105712Ssam }
1115712Ssam 
1125712Ssam /*
1135712Ssam  * Reset a given network's host entries.
1145712Ssam  * This involves clearing all packet queue's
1155712Ssam  * and releasing host structures.
1165712Ssam  */
1175771Swnj hostreset(net)
1185712Ssam 	int net;
1195712Ssam {
1205712Ssam 	register struct mbuf *m;
1215712Ssam 	register struct host *hp, *lp;
1225860Sroot 	struct hmbuf *hm;
1235860Sroot 	int x;
1245712Ssam 
1255771Swnj COUNT(HOSTRESET);
1265860Sroot 	x = splimp();
1275860Sroot 	for (m = hosts; m; m = m->m_next) {
1285860Sroot 		hm = mtod(m, struct hmbuf *);
1295860Sroot 		hp = hm->hm_hosts;
1305712Ssam 		lp = hp + HPMBUF;
1315860Sroot 		while (hm->hm_count != 0 && hp < lp) {
132*6089Sroot 			if (hp->h_addr.s_net == net) {
133*6089Sroot 				hp->h_refcnt = 0;
1345771Swnj 				hostrelease(mtod(m, struct hmbuf *), hp);
135*6089Sroot 			}
1365712Ssam 			hp++;
1375712Ssam 		}
1385712Ssam 	}
1395860Sroot 	splx(x);
1405712Ssam }
1415712Ssam 
1425712Ssam /*
1435712Ssam  * Remove a host structure and release
1445712Ssam  * any resources it's accumulated.
1455712Ssam  */
1465860Sroot hostrelease(hp)
1475712Ssam 	register struct host *hp;
1485712Ssam {
1495860Sroot 	register struct mbuf *m, **mprev, *mh = dtom(hp);
1505712Ssam 
1515771Swnj COUNT(HOSTRELEASE);
1525712Ssam 	/*
1535712Ssam 	 * Discard any packets left on the waiting q
1545712Ssam 	 */
1555771Swnj 	if (m = hp->h_q) {
1565868Sroot 		register struct mbuf *n;
1575868Sroot 
1585868Sroot 		do {
1595868Sroot 			n = m->m_act;
1605868Sroot 			m_freem(m);
1615868Sroot 			m = n;
1625868Sroot 		} while (m != hp->h_q);
1635771Swnj 		hp->h_q = 0;
1645712Ssam 	}
1655860Sroot 	if (--mtod(mh, struct hmbuf *)->hm_count)
1665712Ssam 		return;
1675860Sroot 	mprev = &hosts;
1685860Sroot 	while ((m = *mprev) != mh)
1695860Sroot 		mprev = &m->m_next;
1705860Sroot 	*mprev = mh->m_next;
1715860Sroot 	(void) m_free(mh);
1725712Ssam }
1735924Sroot 
1745924Sroot /*
1755924Sroot  * Remove a packet from the holding q.
1765924Sroot  * The RFNM counter is also bumped.
1775924Sroot  */
1785924Sroot struct mbuf *
1795924Sroot hostdeque(hp)
1805924Sroot 	register struct host *hp;
1815924Sroot {
1825924Sroot 	register struct mbuf *m;
1835924Sroot 
1845924Sroot 	hp->h_rfnm--;
1855924Sroot 	HOST_DEQUE(hp, m);
1865924Sroot 	if (m)
1875924Sroot 		return (m);
1885924Sroot 	if (hp->h_rfnm == 0)
1895924Sroot 		hostfree(hp);
1905924Sroot 	return (0);
1915924Sroot }
192