1*5860Sroot /*	if_imphost.c	4.3	82/02/16	*/
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"
15*5860Sroot #include "../net/if_imphost.h"
165712Ssam 
175712Ssam /*
185712Ssam  * Head of host table hash chains.
195712Ssam  */
20*5860Sroot 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*5860Sroot 	for (m = hosts; m; m = m->m_next) {
365712Ssam 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
375712Ssam 		if (hp->h_refcnt == 0)
38*5860Sroot 			continue;
395712Ssam 	        if (hp->h_addr.s_addr == addr.s_addr)
405712Ssam 			return (hp);
415712Ssam 	}
425712Ssam 	return (0);
435712Ssam }
445712Ssam 
455712Ssam /*
465712Ssam  * Enter a reference to this host's internet
475712Ssam  * address.  If no host structure exists, create
485712Ssam  * one and hook it into the host database.
495712Ssam  */
505712Ssam struct host *
515771Swnj hostenter(addr)
525712Ssam 	struct in_addr addr;
535712Ssam {
54*5860Sroot 	register struct mbuf *m, **mprev;
55*5860Sroot 	register struct host *hp, *hp0 = 0;
565712Ssam 	register int hash = HOSTHASH(addr);
575712Ssam 
585771Swnj COUNT(HOSTENTER);
59*5860Sroot 	mprev = &hosts;
60*5860Sroot 	while (m = *mprev) {
615712Ssam 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
62*5860Sroot 		if (hp->h_refcnt == 0) {
63*5860Sroot 			if (hp0 == 0)
64*5860Sroot 				hp0 = hp;
65*5860Sroot 			continue;
66*5860Sroot 		}
675712Ssam 	        if (hp->h_addr.s_addr == addr.s_addr)
685712Ssam 			goto foundhost;
69*5860Sroot 		mprev = &m->m_next;
705712Ssam 	}
715712Ssam 
725712Ssam 	/*
735712Ssam 	 * No current host structure, make one.
745712Ssam 	 * If our search ran off the end of the
755712Ssam 	 * chain of mbuf's, allocate another.
765712Ssam 	 */
77*5860Sroot 	if (hp0 == 0) {
785712Ssam 		m = m_getclr(M_DONTWAIT);
795712Ssam 		if (m == 0)
805712Ssam 			return (0);
81*5860Sroot 		*mprev = m;
82*5860Sroot 		m->m_off = MMINOFF;
83*5860Sroot 		hp0 = &mtod(m, struct hmbuf *)->hm_hosts[hash];
845712Ssam 	}
85*5860Sroot 	mtod(dtom(hp0), struct hmbuf *)->hm_count++;
86*5860Sroot 	hp = hp0;
875712Ssam 	hp->h_addr = addr;
885712Ssam 	hp->h_status = HOSTS_UP;
895712Ssam 
905712Ssam foundhost:
915712Ssam 	hp->h_refcnt++;		/* know new structures have 0 val */
925712Ssam 	return (hp);
935712Ssam }
945712Ssam 
955712Ssam /*
965712Ssam  * Free a reference to a host.  If this causes the
975712Ssam  * host structure to be released do so.
985712Ssam  */
99*5860Sroot hostfree(hp)
100*5860Sroot 	register struct host *hp;
1015712Ssam {
1025712Ssam 	register struct mbuf *m;
1035712Ssam 
1045771Swnj COUNT(HOSTFREE);
105*5860Sroot 	if (--hp->h_refcnt)
106*5860Sroot 		return;
107*5860Sroot 	hostrelease(hp);
1085712Ssam }
1095712Ssam 
1105712Ssam /*
1115712Ssam  * Reset a given network's host entries.
1125712Ssam  * This involves clearing all packet queue's
1135712Ssam  * and releasing host structures.
1145712Ssam  */
1155771Swnj hostreset(net)
1165712Ssam 	int net;
1175712Ssam {
1185712Ssam 	register struct mbuf *m;
1195712Ssam 	register struct host *hp, *lp;
120*5860Sroot 	struct hmbuf *hm;
121*5860Sroot 	int x;
1225712Ssam 
1235771Swnj COUNT(HOSTRESET);
124*5860Sroot 	x = splimp();
125*5860Sroot 	for (m = hosts; m; m = m->m_next) {
126*5860Sroot 		hm = mtod(m, struct hmbuf *);
127*5860Sroot 		hp = hm->hm_hosts;
1285712Ssam 		lp = hp + HPMBUF;
129*5860Sroot 		while (hm->hm_count != 0 && hp < lp) {
1305712Ssam 			if (hp->h_addr.s_net == net)
1315771Swnj 				hostrelease(mtod(m, struct hmbuf *), hp);
1325712Ssam 			hp++;
1335712Ssam 		}
1345712Ssam 	}
135*5860Sroot 	splx(x);
1365712Ssam }
1375712Ssam 
1385712Ssam /*
1395712Ssam  * Remove a host structure and release
1405712Ssam  * any resources it's accumulated.
1415712Ssam  */
142*5860Sroot hostrelease(hp)
1435712Ssam 	register struct host *hp;
1445712Ssam {
145*5860Sroot 	register struct mbuf *m, **mprev, *mh = dtom(hp);
1465712Ssam 
1475771Swnj COUNT(HOSTRELEASE);
1485712Ssam 	/*
1495712Ssam 	 * Discard any packets left on the waiting q
1505712Ssam 	 */
1515771Swnj 	if (m = hp->h_q) {
1525771Swnj 		m = m->m_next;
1535771Swnj 		hp->h_q->m_next = 0;
1545771Swnj 		hp->h_q = 0;
1555712Ssam 		m_freem(m);
1565712Ssam 	}
157*5860Sroot 	if (--mtod(mh, struct hmbuf *)->hm_count)
1585712Ssam 		return;
159*5860Sroot 	mprev = &hosts;
160*5860Sroot 	while ((m = *mprev) != mh)
161*5860Sroot 		mprev = &m->m_next;
162*5860Sroot 	*mprev = mh->m_next;
163*5860Sroot 	(void) m_free(mh);
1645712Ssam }
165