1*5771Swnj /*	if_imphost.c	4.2	82/02/12	*/
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/host.h"
155712Ssam #include "../net/if_imp.h"
165712Ssam 
175712Ssam /*
185712Ssam  * Head of host table hash chains.
195712Ssam  */
205712Ssam struct mbuf hosttable = { 0, MMINOFF };
215712Ssam 
225712Ssam /*
235712Ssam  * Given an internet address
245712Ssam  * return a host structure (if it exists).
255712Ssam  */
265712Ssam struct host *
27*5771Swnj 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 
34*5771Swnj COUNT(HOSTLOOKUP);
35*5771Swnj printf("hostlookup(%x)\n", addr);
365712Ssam 	for (m = &hosttable; m; m = m->m_next) {
375712Ssam 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
385712Ssam 		if (hp->h_refcnt == 0)
395712Ssam 			break;
40*5771Swnj printf("hostlookup: addr=%x\n", hp->h_addr.s_addr);
415712Ssam 	        if (hp->h_addr.s_addr == addr.s_addr)
425712Ssam 			return (hp);
435712Ssam 	}
445712Ssam 	return (0);
455712Ssam }
465712Ssam 
475712Ssam /*
485712Ssam  * Enter a reference to this host's internet
495712Ssam  * address.  If no host structure exists, create
505712Ssam  * one and hook it into the host database.
515712Ssam  */
525712Ssam struct host *
53*5771Swnj hostenter(addr)
545712Ssam 	struct in_addr addr;
555712Ssam {
565712Ssam 	register struct mbuf *m, *mprev;
575712Ssam 	register struct host *hp;
585712Ssam 	register int hash = HOSTHASH(addr);
595712Ssam 
60*5771Swnj COUNT(HOSTENTER);
61*5771Swnj printf("hostenter(%x)\n", addr);
625712Ssam 	for (m = &hosttable; m; mprev = m, m = m->m_next) {
635712Ssam 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
645712Ssam 		if (hp->h_refcnt == 0)
655712Ssam 			break;
66*5771Swnj printf("hostenter: addr=%x\n", addr);
675712Ssam 	        if (hp->h_addr.s_addr == addr.s_addr)
685712Ssam 			goto foundhost;
695712Ssam 	}
705712Ssam 
715712Ssam 	/*
725712Ssam 	 * No current host structure, make one.
735712Ssam 	 * If our search ran off the end of the
745712Ssam 	 * chain of mbuf's, allocate another.
755712Ssam 	 */
76*5771Swnj printf("hostenter: new host\n");
775712Ssam 	if (m == 0) {
785712Ssam 		m = m_getclr(M_DONTWAIT);
795712Ssam 		if (m == 0)
805712Ssam 			return (0);
815712Ssam 		mprev->m_next = m;
825712Ssam 		m->m_act = mprev;
835712Ssam 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
845712Ssam 	}
855712Ssam 	mtod(m, struct hmbuf *)->hm_count++;
865712Ssam 	hp->h_addr = addr;
875712Ssam 	hp->h_status = HOSTS_UP;
885712Ssam 
895712Ssam foundhost:
905712Ssam 	hp->h_refcnt++;		/* know new structures have 0 val */
915712Ssam 	return (hp);
925712Ssam }
935712Ssam 
945712Ssam /*
955712Ssam  * Free a reference to a host.  If this causes the
965712Ssam  * host structure to be released do so.
975712Ssam  */
98*5771Swnj hostfree(addr)
995712Ssam 	struct in_addr addr;
1005712Ssam {
1015712Ssam 	register struct mbuf *m;
1025712Ssam 	register struct host *hp;
1035712Ssam 	register int hash = HOSTHASH(addr);
1045712Ssam 
105*5771Swnj COUNT(HOSTFREE);
106*5771Swnj printf("hostfree(%x)\n", addr);
1075712Ssam 	for (m = &hosttable; m; m = m->m_next) {
1085712Ssam 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
1095712Ssam 		if (hp->h_refcnt == 0)
1105712Ssam 			return;
1115712Ssam 	        if (hp->h_addr.s_addr == addr.s_addr) {
1125712Ssam 			if (--hp->h_refcnt == 0)
113*5771Swnj 				hostrelease(mtod(m, struct hmbuf *), hp);
1145712Ssam 			return;
1155712Ssam 		}
1165712Ssam 	}
117*5771Swnj 	panic("hostfree");
1185712Ssam }
1195712Ssam 
1205712Ssam /*
1215712Ssam  * Reset a given network's host entries.
1225712Ssam  * This involves clearing all packet queue's
1235712Ssam  * and releasing host structures.
1245712Ssam  */
125*5771Swnj hostreset(net)
1265712Ssam 	int net;
1275712Ssam {
1285712Ssam 	register struct mbuf *m;
1295712Ssam 	register struct host *hp, *lp;
1305712Ssam 
131*5771Swnj COUNT(HOSTRESET);
132*5771Swnj printf("hostreset(%x)\n", net);
1335712Ssam 	for (m = &hosttable; m; m = m->m_next) {
1345712Ssam 		hp = mtod(m, struct hmbuf *)->hm_hosts;
1355712Ssam 		lp = hp + HPMBUF;
1365712Ssam 		while (hp < lp) {
1375712Ssam 			if (hp->h_addr.s_net == net)
138*5771Swnj 				hostrelease(mtod(m, struct hmbuf *), hp);
1395712Ssam 			hp++;
1405712Ssam 		}
1415712Ssam 	}
1425712Ssam }
1435712Ssam 
1445712Ssam /*
1455712Ssam  * Remove a host structure and release
1465712Ssam  * any resources it's accumulated.
1475712Ssam  */
148*5771Swnj hostrelease(hm, hp)
1495712Ssam 	struct hmbuf *hm;
1505712Ssam 	register struct host *hp;
1515712Ssam {
1525712Ssam 	register struct mbuf *m;
1535712Ssam 
154*5771Swnj COUNT(HOSTRELEASE);
155*5771Swnj printf("hostrelease(%x,%x)\n", hm, hp);
1565712Ssam 	/*
1575712Ssam 	 * Discard any packets left on the waiting q
1585712Ssam 	 */
159*5771Swnj 	if (m = hp->h_q) {
160*5771Swnj 		m = m->m_next;
161*5771Swnj 		hp->h_q->m_next = 0;
162*5771Swnj 		hp->h_q = 0;
1635712Ssam 		m_freem(m);
1645712Ssam 	}
1655712Ssam 	/*
1665712Ssam 	 * We could compact the database here, but is
1675712Ssam 	 * it worth it?  For now we assume not and just
1685712Ssam 	 * handle the simple case.
1695712Ssam 	 */
170*5771Swnj printf("hostrelease: count=%d\n", hm->hm_count);
1715712Ssam 	if (--hm->hm_count || (m = dtom(hm)) == &hosttable)
1725712Ssam 		return;
1735712Ssam 	m->m_act->m_next = m->m_next;
1745712Ssam 	m->m_next->m_act = m->m_act;
175*5771Swnj 	(void) m_free(m);
1765712Ssam }
177