1 /*
2  * Copyright (c) 1982, 1986 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	7.2 (Berkeley) 02/03/88
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 "socket.h"
22 #include "syslog.h"
23 
24 #include "../net/if.h"
25 
26 #include "../netinet/in.h"
27 #include "../netinet/in_systm.h"
28 
29 #include "if_imp.h"
30 #include "if_imphost.h"
31 
32 /*
33  * Head of host table hash chains.
34  */
35 struct mbuf *hosts;
36 extern struct imp_softc imp_softc[];
37 
38 /*
39  * Given an internet address
40  * return a host structure (if it exists).
41  */
42 struct host *
43 hostlookup(imp, host, unit)
44 	int imp, host, unit;
45 {
46 	register struct host *hp;
47 	register struct mbuf *m;
48 	register int hash = HOSTHASH(imp, host);
49 
50 	for (m = hosts; m; m = m->m_next) {
51 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
52 	        if (hp->h_imp == imp && hp->h_host == host &&
53 		    hp->h_unit == unit) {
54 			hp->h_flags |= HF_INUSE;
55 			return (hp);
56 		}
57 	}
58 	return ((struct host *)0);
59 }
60 
61 /*
62  * Enter a reference to this host's internet
63  * address.  If no host structure exists, create
64  * one and hook it into the host database.
65  */
66 struct host *
67 hostenter(imp, host, unit)
68 	int imp, host, unit;
69 {
70 	register struct mbuf *m, **mprev;
71 	register struct host *hp, *hp0 = 0;
72 	register int hash = HOSTHASH(imp, host);
73 
74 	mprev = &hosts;
75 	while (m = *mprev) {
76 		mprev = &m->m_next;
77 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
78 	        if (hp->h_imp == imp && hp->h_host == host &&
79 		    hp->h_unit == unit)
80 			goto foundhost;
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 	mtod(dtom(hp0), struct hmbuf *)->hm_count++;
101 	hp = hp0;
102 	hp->h_imp = imp;
103 	hp->h_host = host;
104 	hp->h_unit = unit;
105 	hp->h_timer = 0;
106 	hp->h_flags = 0;
107 
108 foundhost:
109 	hp->h_flags |= HF_INUSE;
110 	return (hp);
111 }
112 
113 /*
114  * Reset a given imp unit's host entries.
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 = 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 			if (hp->h_unit == unit)
129 				hostrelease(hp);
130 			hp++;
131 		}
132 	}
133 	hostcompress();
134 }
135 
136 /*
137  * Remove a host structure and release
138  * any resources it's accumulated.
139  */
140 hostrelease(hp)
141 	register struct host *hp;
142 {
143 	register struct mbuf *m, **mprev, *mh = dtom(hp);
144 
145 	/*
146 	 * Discard any packets left on the waiting q
147 	 */
148 	if (m = hp->h_q) {
149 		register struct mbuf *n;
150 
151 		do {
152 			n = m->m_act;
153 			m_freem(m);
154 			m = n;
155 		} while (m != hp->h_q);
156 		hp->h_q = 0;
157 	}
158 	hp->h_flags = 0;
159 	hp->h_rfnm = 0;
160 	--mtod(mh, struct hmbuf *)->hm_count;
161 }
162 
163 hostcompress()
164 {
165 	register struct mbuf *m, **mprev;
166 
167 	mprev = &hosts;
168 	while (m = *mprev) {
169 		if (mtod(m, struct hmbuf *)->hm_count == 0)
170 			*mprev = m_free(m);
171 		else
172 			mprev = &m->m_next;
173 	}
174 }
175 
176 /*
177  * Host data base timer routine.
178  * Decrement timers on structures which are
179  * waiting to be deallocated.  On expiration
180  * release resources, possibly deallocating
181  * mbuf associated with structure.
182  */
183 hostslowtimo()
184 {
185 	register struct mbuf *m;
186 	register struct host *hp, *lp;
187 	struct hmbuf *hm;
188 	int s = splimp(), any = 0;
189 
190 	for (m = hosts; m; m = m->m_next) {
191 		hm = mtod(m, struct hmbuf *);
192 		hp = hm->hm_hosts;
193 		lp = hp + HPMBUF;
194 		for (; hm->hm_count > 0 && hp < lp; hp++) {
195 		    if (hp->h_timer && --hp->h_timer == 0) {
196 			if (hp->h_rfnm) {
197 			    log(LOG_WARNING,
198 			        "imp%d: host %d/imp %d, lost %d rfnms\n",
199 			        hp->h_unit, hp->h_host, ntohs(hp->h_imp),
200 			        hp->h_rfnm);
201 			    imp_softc[hp->h_unit].imp_lostrfnm += hp->h_rfnm;
202 			    hp->h_rfnm = 0;
203 			    if (hp->h_q) {
204 				imprestarthost(hp);
205 				continue;
206 			    }
207 			}
208 			any = 1;
209 			hostrelease(hp);
210 		    }
211 		}
212 	}
213 	if (any)
214 		hostcompress();
215 	splx(s);
216 }
217 #endif
218