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