1*5712Ssam /*	if_imphost.c	4.1	82/02/06	*/
2*5712Ssam 
3*5712Ssam #include "imp.h"
4*5712Ssam #if NIMP > 0
5*5712Ssam /*
6*5712Ssam  * Host table manipulation routines.
7*5712Ssam  * Only needed when shipping stuff through an IMP.
8*5712Ssam  */
9*5712Ssam 
10*5712Ssam #include "../h/param.h"
11*5712Ssam #include "../h/mbuf.h"
12*5712Ssam #include "../net/in.h"
13*5712Ssam #include "../net/in_systm.h"
14*5712Ssam #include "../net/host.h"
15*5712Ssam #include "../net/if_imp.h"
16*5712Ssam 
17*5712Ssam /*
18*5712Ssam  * Head of host table hash chains.
19*5712Ssam  */
20*5712Ssam struct mbuf hosttable = { 0, MMINOFF };
21*5712Ssam 
22*5712Ssam /*
23*5712Ssam  * Given an internet address
24*5712Ssam  * return a host structure (if it exists).
25*5712Ssam  */
26*5712Ssam struct host *
27*5712Ssam h_lookup(addr)
28*5712Ssam 	struct in_addr addr;
29*5712Ssam {
30*5712Ssam 	register struct host *hp;
31*5712Ssam 	register struct mbuf *m;
32*5712Ssam 	register int hash = HOSTHASH(addr);
33*5712Ssam 
34*5712Ssam COUNT(H_LOOKUP);
35*5712Ssam printf("h_lookup(%x)\n", addr);
36*5712Ssam 	for (m = &hosttable; m; m = m->m_next) {
37*5712Ssam 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
38*5712Ssam 		if (hp->h_refcnt == 0)
39*5712Ssam 			break;
40*5712Ssam printf("h_lookup: addr=%x\n", hp->h_addr.s_addr);
41*5712Ssam 	        if (hp->h_addr.s_addr == addr.s_addr)
42*5712Ssam 			return (hp);
43*5712Ssam 	}
44*5712Ssam 	return (0);
45*5712Ssam }
46*5712Ssam 
47*5712Ssam /*
48*5712Ssam  * Enter a reference to this host's internet
49*5712Ssam  * address.  If no host structure exists, create
50*5712Ssam  * one and hook it into the host database.
51*5712Ssam  */
52*5712Ssam struct host *
53*5712Ssam h_enter(addr)
54*5712Ssam 	struct in_addr addr;
55*5712Ssam {
56*5712Ssam 	register struct mbuf *m, *mprev;
57*5712Ssam 	register struct host *hp;
58*5712Ssam 	register int hash = HOSTHASH(addr);
59*5712Ssam 
60*5712Ssam COUNT(H_ENTER);
61*5712Ssam printf("h_enter(%x)\n", addr);
62*5712Ssam 	for (m = &hosttable; m; mprev = m, m = m->m_next) {
63*5712Ssam 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
64*5712Ssam 		if (hp->h_refcnt == 0)
65*5712Ssam 			break;
66*5712Ssam printf("h_enter: addr=%x\n", addr);
67*5712Ssam 	        if (hp->h_addr.s_addr == addr.s_addr)
68*5712Ssam 			goto foundhost;
69*5712Ssam 	}
70*5712Ssam 
71*5712Ssam 	/*
72*5712Ssam 	 * No current host structure, make one.
73*5712Ssam 	 * If our search ran off the end of the
74*5712Ssam 	 * chain of mbuf's, allocate another.
75*5712Ssam 	 */
76*5712Ssam printf("h_enter: new host\n");
77*5712Ssam 	if (m == 0) {
78*5712Ssam 		m = m_getclr(M_DONTWAIT);
79*5712Ssam 		if (m == 0)
80*5712Ssam 			return (0);
81*5712Ssam 		mprev->m_next = m;
82*5712Ssam 		m->m_act = mprev;
83*5712Ssam 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
84*5712Ssam 	}
85*5712Ssam 	mtod(m, struct hmbuf *)->hm_count++;
86*5712Ssam 	hp->h_addr = addr;
87*5712Ssam 	hp->h_status = HOSTS_UP;
88*5712Ssam 
89*5712Ssam foundhost:
90*5712Ssam 	hp->h_refcnt++;		/* know new structures have 0 val */
91*5712Ssam 	return (hp);
92*5712Ssam }
93*5712Ssam 
94*5712Ssam /*
95*5712Ssam  * Free a reference to a host.  If this causes the
96*5712Ssam  * host structure to be released do so.
97*5712Ssam  */
98*5712Ssam h_free(addr)
99*5712Ssam 	struct in_addr addr;
100*5712Ssam {
101*5712Ssam 	register struct mbuf *m;
102*5712Ssam 	register struct host *hp;
103*5712Ssam 	register int hash = HOSTHASH(addr);
104*5712Ssam 
105*5712Ssam COUNT(H_FREE);
106*5712Ssam printf("h_free(%x)\n", addr);
107*5712Ssam 	for (m = &hosttable; m; m = m->m_next) {
108*5712Ssam 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
109*5712Ssam 		if (hp->h_refcnt == 0)
110*5712Ssam 			return;
111*5712Ssam 	        if (hp->h_addr.s_addr == addr.s_addr) {
112*5712Ssam 			if (--hp->h_refcnt == 0)
113*5712Ssam 				h_release(mtod(m, struct hmbuf *), hp);
114*5712Ssam 			return;
115*5712Ssam 		}
116*5712Ssam 	}
117*5712Ssam 	panic("h_free");
118*5712Ssam }
119*5712Ssam 
120*5712Ssam /*
121*5712Ssam  * Reset a given network's host entries.
122*5712Ssam  * This involves clearing all packet queue's
123*5712Ssam  * and releasing host structures.
124*5712Ssam  */
125*5712Ssam h_reset(net)
126*5712Ssam 	int net;
127*5712Ssam {
128*5712Ssam 	register struct mbuf *m;
129*5712Ssam 	register struct host *hp, *lp;
130*5712Ssam 
131*5712Ssam COUNT(H_RESET);
132*5712Ssam printf("h_reset(%x)\n", net);
133*5712Ssam 	for (m = &hosttable; m; m = m->m_next) {
134*5712Ssam 		hp = mtod(m, struct hmbuf *)->hm_hosts;
135*5712Ssam 		lp = hp + HPMBUF;
136*5712Ssam 		while (hp < lp) {
137*5712Ssam 			if (hp->h_addr.s_net == net)
138*5712Ssam 				h_release(mtod(m, struct hmbuf *), hp);
139*5712Ssam 			hp++;
140*5712Ssam 		}
141*5712Ssam 	}
142*5712Ssam }
143*5712Ssam 
144*5712Ssam /*
145*5712Ssam  * Remove a host structure and release
146*5712Ssam  * any resources it's accumulated.
147*5712Ssam  */
148*5712Ssam h_release(hm, hp)
149*5712Ssam 	struct hmbuf *hm;
150*5712Ssam 	register struct host *hp;
151*5712Ssam {
152*5712Ssam 	register struct mbuf *m;
153*5712Ssam 
154*5712Ssam COUNT(H_RELEASE);
155*5712Ssam printf("h_release(%x,%x)\n", hm, hp);
156*5712Ssam 	/*
157*5712Ssam 	 * Discard any packets left on the waiting q
158*5712Ssam 	 */
159*5712Ssam 	while (m = hp->h_q) {
160*5712Ssam 		hp->h_q = m->m_act;
161*5712Ssam 		m_freem(m);
162*5712Ssam 	}
163*5712Ssam 	/*
164*5712Ssam 	 * We could compact the database here, but is
165*5712Ssam 	 * it worth it?  For now we assume not and just
166*5712Ssam 	 * handle the simple case.
167*5712Ssam 	 */
168*5712Ssam printf("h_releasse: count=%d\n", hm->h_count);
169*5712Ssam 	if (--hm->hm_count || (m = dtom(hm)) == &hosttable)
170*5712Ssam 		return;
171*5712Ssam 	m->m_act->m_next = m->m_next;
172*5712Ssam 	m->m_next->m_act = m->m_act;
173*5712Ssam 	m_freem(m);
174*5712Ssam }
175