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