1 /*
2  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  *	@(#)if_imphost.c	7.9 (Berkeley) 06/29/88
18  */
19 
20 #include "imp.h"
21 #if NIMP > 0
22 /*
23  * Host table manipulation routines.
24  * Only needed when shipping stuff through an IMP.
25  *
26  * Everything in here is called at splimp from
27  * from the IMP protocol code (if_imp.c), or
28  * interlocks with the code at splimp.
29  */
30 #include "param.h"
31 #include "mbuf.h"
32 #include "socket.h"
33 #include "syslog.h"
34 
35 #include "../net/if.h"
36 
37 #include "../netinet/in.h"
38 #include "../netinet/in_systm.h"
39 
40 #include "if_imp.h"
41 #include "if_imphost.h"
42 
43 extern struct imp_softc imp_softc[];
44 
45 /*
46  * Given an internet address
47  * return a host structure (if it exists).
48  */
49 struct host *
50 hostlookup(imp, host, unit)
51 	int imp, host, unit;
52 {
53 	register struct host *hp;
54 	register struct mbuf *m;
55 	register int hash = HOSTHASH(imp, host);
56 
57 	for (m = imp_softc[unit].imp_hosts; m; m = m->m_next) {
58 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
59 	        if (hp->h_imp == imp && hp->h_host == host) {
60 			if ((hp->h_flags & HF_INUSE) == 0)
61 				mtod(dtom(hp), struct hmbuf *)->hm_count++;
62 			hp->h_flags |= HF_INUSE;
63 			return (hp);
64 		}
65 	}
66 	return ((struct host *)0);
67 }
68 
69 /*
70  * Enter a reference to this host's internet
71  * address.  If no host structure exists, create
72  * one and hook it into the host database.
73  */
74 struct host *
75 hostenter(imp, host, unit)
76 	int imp, host, unit;
77 {
78 	register struct mbuf *m, **mprev;
79 	register struct host *hp, *hp0 = 0;
80 	register int hash = HOSTHASH(imp, host);
81 
82 	mprev = &imp_softc[unit].imp_hosts;
83 	while (m = *mprev) {
84 		mprev = &m->m_next;
85 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
86 	        if (hp->h_imp == imp && hp->h_host == host) {
87 			if ((hp->h_flags & HF_INUSE) == 0)
88 				mtod(dtom(hp), struct hmbuf *)->hm_count++;
89 			goto foundhost;
90 		}
91 		if ((hp->h_flags & HF_INUSE) == 0) {
92 			if (hp0 == 0)
93 				hp0 = hp;
94 			continue;
95 		}
96 	}
97 
98 	/*
99 	 * No current host structure, make one.
100 	 * If our search ran off the end of the
101 	 * chain of mbuf's, allocate another.
102 	 */
103 	if (hp0 == 0) {
104 		m = m_getclr(M_DONTWAIT, MT_HTABLE);
105 		if (m == NULL)
106 			return ((struct host *)0);
107 		*mprev = m;
108 		hp0 = &mtod(m, struct hmbuf *)->hm_hosts[hash];
109 	}
110 	hp = hp0;
111 	mtod(dtom(hp), struct hmbuf *)->hm_count++;
112 	hp->h_imp = imp;
113 	hp->h_host = host;
114 	hp->h_timer = 0;
115 	hp->h_flags = 0;
116 
117 foundhost:
118 	hp->h_flags |= HF_INUSE;
119 	return (hp);
120 }
121 
122 /*
123  * Reset a given imp unit's host entries.
124  * Must be called at splimp.
125  */
126 hostreset(unit)
127 	int unit;
128 {
129 	register struct mbuf *m;
130 	register struct host *hp, *lp;
131 	struct hmbuf *hm;
132 
133 	for (m = imp_softc[unit].imp_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 			hostrelease(hp);
139 			hp++;
140 		}
141 	}
142 	hostcompress(unit);
143 }
144 
145 /*
146  * Remove a host structure and release
147  * any resources it's accumulated.
148  */
149 hostrelease(hp)
150 	register struct host *hp;
151 {
152 
153 	if (hp->h_q)
154 		hostflush(hp);
155 	hp->h_rfnm = 0;
156 	if (hp->h_flags & HF_INUSE)
157 		--mtod(dtom(hp), struct hmbuf *)->hm_count;
158 	hp->h_flags = 0;
159 }
160 
161 /*
162  * Flush the message queue for a host.
163  */
164 hostflush(hp)
165 	register struct host *hp;
166 {
167 	register struct mbuf *m;
168 
169 	/*
170 	 * Discard any packets left on the waiting q
171 	 */
172 	if (m = hp->h_q) {
173 		register struct mbuf *n;
174 
175 		do {
176 			n = m->m_act;
177 			m_freem(m);
178 			m = n;
179 		} while (m != hp->h_q);
180 		hp->h_q = 0;
181 		hp->h_qcnt = 0;
182 	}
183 }
184 
185 /*
186  * Release mbufs in host table that contain no entries
187  * currently in use.  Must be called at splimp.
188  */
189 hostcompress(unit)
190 	int unit;
191 {
192 	register struct mbuf *m, **mprev;
193 	struct imp_softc *sc = &imp_softc[unit];
194 
195 	mprev = &sc->imp_hosts;
196 	sc->imp_hostq = 0;
197 	while (m = *mprev) {
198 		if (mtod(m, struct hmbuf *)->hm_count == 0)
199 			*mprev = m_free(m);
200 		else
201 			mprev = &m->m_next;
202 	}
203 }
204 
205 /*
206  * Host data base timer routine.
207  * Decrement timers on structures which are
208  * waiting to be deallocated.  On expiration
209  * release resources, possibly deallocating
210  * mbuf associated with structure.
211  */
212 hostslowtimo()
213 {
214 	register struct mbuf *m;
215 	register struct host *hp, *lp;
216 	struct imp_softc *sc;
217 	struct hmbuf *hm;
218 	int s = splimp(), unit, any;
219 
220 	for (unit = 0; unit < NIMP; unit++) {
221 	    any = 0;
222 	    sc = &imp_softc[unit];
223 	    for (m = sc->imp_hosts; m; m = m->m_next) {
224 		hm = mtod(m, struct hmbuf *);
225 		hp = hm->hm_hosts;
226 		lp = hp + HPMBUF;
227 		for (; hm->hm_count > 0 && hp < lp; hp++) {
228 		    if (hp->h_timer && --hp->h_timer == 0) {
229 			if (hp->h_rfnm) {
230 				log(LOG_INFO,			/* XXX */
231 				    "imp%d: host %d/imp %d, lost rfnm\n",
232 				    unit, hp->h_host, ntohs(hp->h_imp));
233 				sc->imp_lostrfnm++;
234 				imprestarthost(sc, hp);
235 			} else {
236 				any = 1;
237 				hostrelease(hp);
238 				if (sc->imp_hostq == m)
239 					sc->imp_hostq = 0;
240 			}
241 		    }
242 		}
243 	    }
244 	    if (any)
245 		hostcompress(unit);
246 	}
247 	splx(s);
248 }
249 #endif
250