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