1 /*	if_imphost.c	4.10	82/04/25	*/
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 
99 foundhost:
100 	hp->h_flags |= HF_INUSE;
101 	splx(s);
102 	return (hp);
103 }
104 
105 /*
106  * Mark a host structure free and set it's
107  * timer going.
108  */
109 hostfree(hp)
110 	register struct host *hp;
111 {
112 	int s = splnet();
113 
114 COUNT(HOSTFREE);
115 	hp->h_flags &= ~HF_INUSE;
116 	hp->h_timer = HOSTTIMER;
117 	hp->h_rfnm = 0;
118 	splx(s);
119 }
120 
121 /*
122  * Reset a given network's host entries.
123  */
124 hostreset(net)
125 	int net;
126 {
127 	register struct mbuf *m;
128 	register struct host *hp, *lp;
129 	struct hmbuf *hm;
130 	int s = splnet();
131 
132 COUNT(HOSTRESET);
133 	for (m = hosts; m; m = m->m_next) {
134 		hm = mtod(m, struct hmbuf *);
135 		hp = hm->hm_hosts;
136 		lp = hp + HPMBUF;
137 		while (hm->hm_count > 0 && hp < lp) {
138 			if (hp->h_addr.s_net == net) {
139 				hp->h_flags &= ~HF_INUSE;
140 				hostrelease(hp);
141 			}
142 			hp++;
143 		}
144 	}
145 	splx(s);
146 }
147 
148 /*
149  * Remove a host structure and release
150  * any resources it's accumulated.
151  * This routine is always called at splnet.
152  */
153 hostrelease(hp)
154 	register struct host *hp;
155 {
156 	register struct mbuf *m, **mprev, *mh = dtom(hp);
157 
158 COUNT(HOSTRELEASE);
159 	/*
160 	 * Discard any packets left on the waiting q
161 	 */
162 	if (m = hp->h_q) {
163 		register struct mbuf *n;
164 
165 		do {
166 			n = m->m_act;
167 			m_freem(m);
168 			m = n;
169 		} while (m != hp->h_q);
170 		hp->h_q = 0;
171 	}
172 	if (--mtod(mh, struct hmbuf *)->hm_count)
173 		return;
174 	mprev = &hosts;
175 	while ((m = *mprev) != mh)
176 		mprev = &m->m_next;
177 	*mprev = m_free(mh);
178 }
179 
180 /*
181  * Remove a packet from the holding q.
182  * The RFNM counter is also bumped.
183  */
184 struct mbuf *
185 hostdeque(hp)
186 	register struct host *hp;
187 {
188 	register struct mbuf *m;
189 
190 	hp->h_rfnm--;
191 	HOST_DEQUE(hp, m);
192 	if (m)
193 		return (m);
194 	if (hp->h_rfnm == 0)
195 		hostfree(hp);
196 	return (0);
197 }
198 
199 /*
200  * Host data base timer routine.
201  * Decrement timers on structures which are
202  * waiting to be deallocated.  On expiration
203  * release resources, possibly deallocating
204  * mbuf associated with structure.
205  */
206 hostslowtimo()
207 {
208 	register struct mbuf *m;
209 	register struct host *hp, *lp;
210 	struct hmbuf *hm;
211 	int s = splnet();
212 
213 COUNT(HOSTSLOWTIMO);
214 	for (m = hosts; m; m = m->m_next) {
215 		hm = mtod(m, struct hmbuf *);
216 		hp = hm->hm_hosts;
217 		lp = hp + HPMBUF;
218 		while (hm->hm_count > 0 && hp < lp) {
219 			if (hp->h_flags & HF_INUSE)
220 				continue;
221 			if (hp->h_timer && --hp->h_timer == 0)
222 				hostrelease(hp);
223 			hp++;
224 		}
225 	}
226 	splx(s);
227 }
228