1 /*	if_imphost.c	4.12	82/05/11	*/
2 
3 #include "imp.h"
4 #if NIMP > 0
5 /*
6  * Host table manipulation routines.
7  * Only needed when shipping stuff through an IMP.
8  */
9 
10 #include "../h/param.h"
11 #include "../h/mbuf.h"
12 #include "../net/in.h"
13 #include "../net/in_systm.h"
14 #include "../net/if_imp.h"
15 #include "../net/if_imphost.h"
16 
17 /*
18  * Head of host table hash chains.
19  */
20 struct mbuf *hosts;
21 
22 /*
23  * Given an internet address
24  * return a host structure (if it exists).
25  */
26 struct host *
27 hostlookup(addr)
28 	struct in_addr addr;
29 {
30 	register struct host *hp;
31 	register struct mbuf *m;
32 	register int hash = HOSTHASH(addr);
33 	int s = splnet();
34 
35 COUNT(HOSTLOOKUP);
36 	for (m = hosts; m; m = m->m_next) {
37 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
38 	        if (hp->h_addr.s_addr == addr.s_addr) {
39 			hp->h_flags |= HF_INUSE;
40 			goto found;
41 		}
42 	}
43 	hp = 0;
44 found:
45 	splx(s);
46 	return (hp);
47 }
48 
49 /*
50  * Enter a reference to this host's internet
51  * address.  If no host structure exists, create
52  * one and hook it into the host database.
53  */
54 struct host *
55 hostenter(addr)
56 	struct in_addr addr;
57 {
58 	register struct mbuf *m, **mprev;
59 	register struct host *hp, *hp0 = 0;
60 	register int hash = HOSTHASH(addr);
61 	int s = splnet();
62 
63 COUNT(HOSTENTER);
64 	mprev = &hosts;
65 	while (m = *mprev) {
66 		mprev = &m->m_next;
67 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
68 		if ((hp->h_flags & HF_INUSE) == 0) {
69 			if (hp->h_addr.s_addr == addr.s_addr)
70 				goto foundhost;
71 			if (hp0 == 0)
72 				hp0 = hp;
73 			continue;
74 		}
75 	        if (hp->h_addr.s_addr == addr.s_addr)
76 			goto foundhost;
77 	}
78 
79 	/*
80 	 * No current host structure, make one.
81 	 * If our search ran off the end of the
82 	 * chain of mbuf's, allocate another.
83 	 */
84 	if (hp0 == 0) {
85 		m = m_getclr(M_DONTWAIT);
86 		if (m == 0) {
87 			splx(s);
88 			return (0);
89 		}
90 		*mprev = m;
91 		m->m_off = MMINOFF;
92 		hp0 = &mtod(m, struct hmbuf *)->hm_hosts[hash];
93 	}
94 	mtod(dtom(hp0), struct hmbuf *)->hm_count++;
95 	hp = hp0;
96 	hp->h_addr = addr;
97 	hp->h_timer = 0;
98 	hp->h_flags = 0;
99 
100 foundhost:
101 	hp->h_flags |= HF_INUSE;
102 	splx(s);
103 	return (hp);
104 }
105 
106 /*
107  * Mark a host structure free and set it's
108  * timer going.
109  */
110 hostfree(hp)
111 	register struct host *hp;
112 {
113 	int s = splnet();
114 
115 COUNT(HOSTFREE);
116 	hp->h_flags &= ~HF_INUSE;
117 	hp->h_timer = HOSTTIMER;
118 	hp->h_rfnm = 0;
119 	splx(s);
120 }
121 
122 /*
123  * Reset a given network's host entries.
124  */
125 hostreset(net)
126 	int net;
127 {
128 	register struct mbuf *m;
129 	register struct host *hp, *lp;
130 	struct hmbuf *hm;
131 	int s = splnet();
132 
133 COUNT(HOSTRESET);
134 	for (m = hosts; m; m = m->m_next) {
135 		hm = mtod(m, struct hmbuf *);
136 		hp = hm->hm_hosts;
137 		lp = hp + HPMBUF;
138 		while (hm->hm_count > 0 && hp < lp) {
139 			if (hp->h_addr.s_net == net) {
140 				hp->h_flags &= ~HF_INUSE;
141 				hostrelease(hp);
142 			}
143 			hp++;
144 		}
145 	}
146 	splx(s);
147 }
148 
149 /*
150  * Remove a host structure and release
151  * any resources it's accumulated.
152  * This routine is always called at splnet.
153  */
154 hostrelease(hp)
155 	register struct host *hp;
156 {
157 	register struct mbuf *m, **mprev, *mh = dtom(hp);
158 
159 COUNT(HOSTRELEASE);
160 	/*
161 	 * Discard any packets left on the waiting q
162 	 */
163 	if (m = hp->h_q) {
164 		register struct mbuf *n;
165 
166 		do {
167 			n = m->m_act;
168 			m_freem(m);
169 			m = n;
170 		} while (m != hp->h_q);
171 		hp->h_q = 0;
172 	}
173 	hp->h_flags = 0;
174 	if (--mtod(mh, struct hmbuf *)->hm_count)
175 		return;
176 	mprev = &hosts;
177 	while ((m = *mprev) != mh)
178 		mprev = &m->m_next;
179 	*mprev = m_free(mh);
180 }
181 
182 /*
183  * Remove a packet from the holding q.
184  * The RFNM counter is also bumped.
185  */
186 struct mbuf *
187 hostdeque(hp)
188 	register struct host *hp;
189 {
190 	register struct mbuf *m;
191 
192 	hp->h_rfnm--;
193 	HOST_DEQUE(hp, m);
194 	if (m)
195 		return (m);
196 	if (hp->h_rfnm == 0)
197 		hostfree(hp);
198 	return (0);
199 }
200 
201 /*
202  * Host data base timer routine.
203  * Decrement timers on structures which are
204  * waiting to be deallocated.  On expiration
205  * release resources, possibly deallocating
206  * mbuf associated with structure.
207  */
208 hostslowtimo()
209 {
210 	register struct mbuf *m;
211 	register struct host *hp, *lp;
212 	struct hmbuf *hm;
213 	int s = splnet();
214 
215 COUNT(HOSTSLOWTIMO);
216 	for (m = hosts; m; m = m->m_next) {
217 		hm = mtod(m, struct hmbuf *);
218 		hp = hm->hm_hosts;
219 		lp = hp + HPMBUF;
220 		for (; hm->hm_count > 0 && hp < lp; hp++) {
221 			if (hp->h_flags & HF_INUSE)
222 				continue;
223 			if (hp->h_timer && --hp->h_timer == 0)
224 				hostrelease(hp);
225 		}
226 	}
227 	splx(s);
228 }
229