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