1 /*
2  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)if_imphost.c	7.10 (Berkeley) 06/28/90
8  */
9 
10 #include "imp.h"
11 #if NIMP > 0
12 /*
13  * Host table manipulation routines.
14  * Only needed when shipping stuff through an IMP.
15  *
16  * Everything in here is called at splimp from
17  * from the IMP protocol code (if_imp.c), or
18  * interlocks with the code at splimp.
19  */
20 #include "param.h"
21 #include "mbuf.h"
22 #include "socket.h"
23 #include "syslog.h"
24 
25 #include "../net/if.h"
26 
27 #include "../netinet/in.h"
28 #include "../netinet/in_systm.h"
29 
30 #include "if_imp.h"
31 #include "if_imphost.h"
32 
33 extern struct imp_softc imp_softc[];
34 
35 /*
36  * Given an internet address
37  * return a host structure (if it exists).
38  */
39 struct host *
40 hostlookup(imp, host, unit)
41 	int imp, host, unit;
42 {
43 	register struct host *hp;
44 	register struct mbuf *m;
45 	register int hash = HOSTHASH(imp, host);
46 
47 	for (m = imp_softc[unit].imp_hosts; m; m = m->m_next) {
48 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
49 	        if (hp->h_imp == imp && hp->h_host == host) {
50 			if ((hp->h_flags & HF_INUSE) == 0)
51 				mtod(dtom(hp), struct hmbuf *)->hm_count++;
52 			hp->h_flags |= HF_INUSE;
53 			return (hp);
54 		}
55 	}
56 	return ((struct host *)0);
57 }
58 
59 /*
60  * Enter a reference to this host's internet
61  * address.  If no host structure exists, create
62  * one and hook it into the host database.
63  */
64 struct host *
65 hostenter(imp, host, unit)
66 	int imp, host, unit;
67 {
68 	register struct mbuf *m, **mprev;
69 	register struct host *hp, *hp0 = 0;
70 	register int hash = HOSTHASH(imp, host);
71 
72 	mprev = &imp_softc[unit].imp_hosts;
73 	while (m = *mprev) {
74 		mprev = &m->m_next;
75 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
76 	        if (hp->h_imp == imp && hp->h_host == host) {
77 			if ((hp->h_flags & HF_INUSE) == 0)
78 				mtod(dtom(hp), struct hmbuf *)->hm_count++;
79 			goto foundhost;
80 		}
81 		if ((hp->h_flags & HF_INUSE) == 0) {
82 			if (hp0 == 0)
83 				hp0 = hp;
84 			continue;
85 		}
86 	}
87 
88 	/*
89 	 * No current host structure, make one.
90 	 * If our search ran off the end of the
91 	 * chain of mbuf's, allocate another.
92 	 */
93 	if (hp0 == 0) {
94 		m = m_getclr(M_DONTWAIT, MT_HTABLE);
95 		if (m == NULL)
96 			return ((struct host *)0);
97 		*mprev = m;
98 		hp0 = &mtod(m, struct hmbuf *)->hm_hosts[hash];
99 	}
100 	hp = hp0;
101 	mtod(dtom(hp), struct hmbuf *)->hm_count++;
102 	hp->h_imp = imp;
103 	hp->h_host = host;
104 	hp->h_timer = 0;
105 	hp->h_flags = 0;
106 
107 foundhost:
108 	hp->h_flags |= HF_INUSE;
109 	return (hp);
110 }
111 
112 /*
113  * Reset a given imp unit's host entries.
114  * Must be called at splimp.
115  */
116 hostreset(unit)
117 	int unit;
118 {
119 	register struct mbuf *m;
120 	register struct host *hp, *lp;
121 	struct hmbuf *hm;
122 
123 	for (m = imp_softc[unit].imp_hosts; m; m = m->m_next) {
124 		hm = mtod(m, struct hmbuf *);
125 		hp = hm->hm_hosts;
126 		lp = hp + HPMBUF;
127 		while (hm->hm_count > 0 && hp < lp) {
128 			hostrelease(hp);
129 			hp++;
130 		}
131 	}
132 	hostcompress(unit);
133 }
134 
135 /*
136  * Remove a host structure and release
137  * any resources it's accumulated.
138  */
139 hostrelease(hp)
140 	register struct host *hp;
141 {
142 
143 	if (hp->h_q)
144 		hostflush(hp);
145 	hp->h_rfnm = 0;
146 	if (hp->h_flags & HF_INUSE)
147 		--mtod(dtom(hp), struct hmbuf *)->hm_count;
148 	hp->h_flags = 0;
149 }
150 
151 /*
152  * Flush the message queue for a host.
153  */
154 hostflush(hp)
155 	register struct host *hp;
156 {
157 	register struct mbuf *m;
158 
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 		hp->h_qcnt = 0;
172 	}
173 }
174 
175 /*
176  * Release mbufs in host table that contain no entries
177  * currently in use.  Must be called at splimp.
178  */
179 hostcompress(unit)
180 	int unit;
181 {
182 	register struct mbuf *m, **mprev;
183 	struct imp_softc *sc = &imp_softc[unit];
184 
185 	mprev = &sc->imp_hosts;
186 	sc->imp_hostq = 0;
187 	while (m = *mprev) {
188 		if (mtod(m, struct hmbuf *)->hm_count == 0)
189 			*mprev = m_free(m);
190 		else
191 			mprev = &m->m_next;
192 	}
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 imp_softc *sc;
207 	struct hmbuf *hm;
208 	int s = splimp(), unit, any;
209 
210 	for (unit = 0; unit < NIMP; unit++) {
211 	    any = 0;
212 	    sc = &imp_softc[unit];
213 	    for (m = sc->imp_hosts; m; m = 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(LOG_INFO,			/* XXX */
221 				    "imp%d: host %d/imp %d, lost rfnm\n",
222 				    unit, hp->h_host, ntohs(hp->h_imp));
223 				sc->imp_lostrfnm++;
224 				imprestarthost(sc, hp);
225 			} else {
226 				any = 1;
227 				hostrelease(hp);
228 				if (sc->imp_hostq == m)
229 					sc->imp_hostq = 0;
230 			}
231 		    }
232 		}
233 	    }
234 	    if (any)
235 		hostcompress(unit);
236 	}
237 	splx(s);
238 }
239 #endif
240