1*6589Ssam /*	if_imphost.c	4.10	82/04/25	*/
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);
33*6589Ssam 	int s = splnet();
345712Ssam 
355771Swnj COUNT(HOSTLOOKUP);
365860Sroot 	for (m = hosts; m; m = m->m_next) {
375712Ssam 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
38*6589Ssam 	        if (hp->h_addr.s_addr == addr.s_addr) {
39*6589Ssam 			hp->h_flags |= HF_INUSE;
40*6589Ssam 			goto found;
41*6589Ssam 		}
425712Ssam 	}
43*6589Ssam 	hp = 0;
44*6589Ssam found:
45*6589Ssam 	splx(s);
46*6589Ssam 	return (hp);
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);
61*6589Ssam 	int s = splnet();
625712Ssam 
635771Swnj COUNT(HOSTENTER);
645860Sroot 	mprev = &hosts;
655860Sroot 	while (m = *mprev) {
666209Swnj 		mprev = &m->m_next;
675712Ssam 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
68*6589Ssam 		if ((hp->h_flags & HF_INUSE) == 0) {
69*6589Ssam 			if (hp->h_addr.s_addr == addr.s_addr)
70*6589Ssam 				goto foundhost;
715860Sroot 			if (hp0 == 0)
725860Sroot 				hp0 = hp;
735860Sroot 			continue;
745860Sroot 		}
755712Ssam 	        if (hp->h_addr.s_addr == addr.s_addr)
765712Ssam 			goto foundhost;
775712Ssam 	}
785712Ssam 
795712Ssam 	/*
805712Ssam 	 * No current host structure, make one.
815712Ssam 	 * If our search ran off the end of the
825712Ssam 	 * chain of mbuf's, allocate another.
835712Ssam 	 */
845860Sroot 	if (hp0 == 0) {
855712Ssam 		m = m_getclr(M_DONTWAIT);
86*6589Ssam 		if (m == 0) {
87*6589Ssam 			splx(s);
885712Ssam 			return (0);
89*6589Ssam 		}
905860Sroot 		*mprev = m;
915860Sroot 		m->m_off = MMINOFF;
925860Sroot 		hp0 = &mtod(m, struct hmbuf *)->hm_hosts[hash];
935712Ssam 	}
945860Sroot 	mtod(dtom(hp0), struct hmbuf *)->hm_count++;
955860Sroot 	hp = hp0;
965712Ssam 	hp->h_addr = addr;
97*6589Ssam 	hp->h_timer = 0;
985712Ssam 
995712Ssam foundhost:
100*6589Ssam 	hp->h_flags |= HF_INUSE;
101*6589Ssam 	splx(s);
1025712Ssam 	return (hp);
1035712Ssam }
1045712Ssam 
1055712Ssam /*
106*6589Ssam  * Mark a host structure free and set it's
107*6589Ssam  * timer going.
1085712Ssam  */
1095860Sroot hostfree(hp)
1105860Sroot 	register struct host *hp;
1115712Ssam {
112*6589Ssam 	int s = splnet();
113*6589Ssam 
1145771Swnj COUNT(HOSTFREE);
115*6589Ssam 	hp->h_flags &= ~HF_INUSE;
116*6589Ssam 	hp->h_timer = HOSTTIMER;
117*6589Ssam 	hp->h_rfnm = 0;
118*6589Ssam 	splx(s);
1195712Ssam }
1205712Ssam 
1215712Ssam /*
1225712Ssam  * Reset a given network's host entries.
1235712Ssam  */
1245771Swnj hostreset(net)
1255712Ssam 	int net;
1265712Ssam {
1275712Ssam 	register struct mbuf *m;
1285712Ssam 	register struct host *hp, *lp;
1295860Sroot 	struct hmbuf *hm;
130*6589Ssam 	int s = splnet();
1315712Ssam 
1325771Swnj COUNT(HOSTRESET);
1335860Sroot 	for (m = hosts; m; m = m->m_next) {
1345860Sroot 		hm = mtod(m, struct hmbuf *);
1355860Sroot 		hp = hm->hm_hosts;
1365712Ssam 		lp = hp + HPMBUF;
137*6589Ssam 		while (hm->hm_count > 0 && hp < lp) {
1386089Sroot 			if (hp->h_addr.s_net == net) {
139*6589Ssam 				hp->h_flags &= ~HF_INUSE;
1406145Ssam 				hostrelease(hp);
1416089Sroot 			}
1425712Ssam 			hp++;
1435712Ssam 		}
1445712Ssam 	}
145*6589Ssam 	splx(s);
1465712Ssam }
1475712Ssam 
1485712Ssam /*
1495712Ssam  * Remove a host structure and release
1505712Ssam  * any resources it's accumulated.
151*6589Ssam  * This routine is always called at splnet.
1525712Ssam  */
1535860Sroot hostrelease(hp)
1545712Ssam 	register struct host *hp;
1555712Ssam {
1565860Sroot 	register struct mbuf *m, **mprev, *mh = dtom(hp);
1575712Ssam 
1585771Swnj COUNT(HOSTRELEASE);
1595712Ssam 	/*
1605712Ssam 	 * Discard any packets left on the waiting q
1615712Ssam 	 */
1625771Swnj 	if (m = hp->h_q) {
1635868Sroot 		register struct mbuf *n;
1645868Sroot 
1655868Sroot 		do {
1665868Sroot 			n = m->m_act;
1675868Sroot 			m_freem(m);
1685868Sroot 			m = n;
1695868Sroot 		} while (m != hp->h_q);
1705771Swnj 		hp->h_q = 0;
1715712Ssam 	}
1725860Sroot 	if (--mtod(mh, struct hmbuf *)->hm_count)
1735712Ssam 		return;
1745860Sroot 	mprev = &hosts;
1755860Sroot 	while ((m = *mprev) != mh)
1765860Sroot 		mprev = &m->m_next;
177*6589Ssam 	*mprev = m_free(mh);
1785712Ssam }
1795924Sroot 
1805924Sroot /*
1815924Sroot  * Remove a packet from the holding q.
1825924Sroot  * The RFNM counter is also bumped.
1835924Sroot  */
1845924Sroot struct mbuf *
1855924Sroot hostdeque(hp)
1865924Sroot 	register struct host *hp;
1875924Sroot {
1885924Sroot 	register struct mbuf *m;
1895924Sroot 
1905924Sroot 	hp->h_rfnm--;
1915924Sroot 	HOST_DEQUE(hp, m);
1925924Sroot 	if (m)
1935924Sroot 		return (m);
1945924Sroot 	if (hp->h_rfnm == 0)
1955924Sroot 		hostfree(hp);
1965924Sroot 	return (0);
1975924Sroot }
198*6589Ssam 
199*6589Ssam /*
200*6589Ssam  * Host data base timer routine.
201*6589Ssam  * Decrement timers on structures which are
202*6589Ssam  * waiting to be deallocated.  On expiration
203*6589Ssam  * release resources, possibly deallocating
204*6589Ssam  * mbuf associated with structure.
205*6589Ssam  */
206*6589Ssam hostslowtimo()
207*6589Ssam {
208*6589Ssam 	register struct mbuf *m;
209*6589Ssam 	register struct host *hp, *lp;
210*6589Ssam 	struct hmbuf *hm;
211*6589Ssam 	int s = splnet();
212*6589Ssam 
213*6589Ssam COUNT(HOSTSLOWTIMO);
214*6589Ssam 	for (m = hosts; m; m = m->m_next) {
215*6589Ssam 		hm = mtod(m, struct hmbuf *);
216*6589Ssam 		hp = hm->hm_hosts;
217*6589Ssam 		lp = hp + HPMBUF;
218*6589Ssam 		while (hm->hm_count > 0 && hp < lp) {
219*6589Ssam 			if (hp->h_flags & HF_INUSE)
220*6589Ssam 				continue;
221*6589Ssam 			if (hp->h_timer && --hp->h_timer == 0)
222*6589Ssam 				hostrelease(hp);
223*6589Ssam 			hp++;
224*6589Ssam 		}
225*6589Ssam 	}
226*6589Ssam 	splx(s);
227*6589Ssam }
228