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.4 (Berkeley) 06/08/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 
22 #include "../netinet/in.h"
23 #include "../netinet/in_systm.h"
24 
25 #include "if_imp.h"
26 #include "if_imphost.h"
27 
28 /*
29  * Head of host table hash chains.
30  */
31 struct mbuf *hosts;
32 
33 /*
34  * Given an internet address
35  * return a host structure (if it exists).
36  */
37 struct host *
38 hostlookup(addr)
39 	struct in_addr addr;
40 {
41 	register struct host *hp;
42 	register struct mbuf *m;
43 	register int hash = HOSTHASH(addr);
44 
45 	for (m = hosts; m; m = m->m_next) {
46 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
47 	        if (hp->h_addr.s_addr == addr.s_addr) {
48 			hp->h_flags |= HF_INUSE;
49 			return (hp);
50 		}
51 	}
52 	return ((struct host *)0);
53 }
54 
55 /*
56  * Enter a reference to this host's internet
57  * address.  If no host structure exists, create
58  * one and hook it into the host database.
59  */
60 struct host *
61 hostenter(addr)
62 	struct in_addr addr;
63 {
64 	register struct mbuf *m, **mprev;
65 	register struct host *hp, *hp0 = 0;
66 	register int hash = HOSTHASH(addr);
67 
68 	mprev = &hosts;
69 	while (m = *mprev) {
70 		mprev = &m->m_next;
71 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
72 		if ((hp->h_flags & HF_INUSE) == 0) {
73 			if (hp->h_addr.s_addr == addr.s_addr)
74 				goto foundhost;
75 			if (hp0 == 0)
76 				hp0 = hp;
77 			continue;
78 		}
79 	        if (hp->h_addr.s_addr == addr.s_addr)
80 			goto foundhost;
81 	}
82 
83 	/*
84 	 * No current host structure, make one.
85 	 * If our search ran off the end of the
86 	 * chain of mbuf's, allocate another.
87 	 */
88 	if (hp0 == 0) {
89 		m = m_getclr(M_DONTWAIT, MT_HTABLE);
90 		if (m == NULL)
91 			return ((struct host *)0);
92 		*mprev = m;
93 		hp0 = &mtod(m, struct hmbuf *)->hm_hosts[hash];
94 	}
95 	mtod(dtom(hp0), struct hmbuf *)->hm_count++;
96 	hp = hp0;
97 	hp->h_addr = addr;
98 	hp->h_timer = 0;
99 	hp->h_flags = 0;
100 
101 foundhost:
102 	hp->h_flags |= HF_INUSE;
103 	return (hp);
104 }
105 
106 /*
107  * Mark a host structure free and set it's
108  * timer going.
109  */
110 hostfree(hp)
111 	register struct host *hp;
112 {
113 
114 	hp->h_flags &= ~HF_INUSE;
115 	hp->h_timer = HOSTTIMER;
116 	hp->h_rfnm = 0;
117 }
118 
119 /*
120  * Reset a given network's host entries.
121  */
122 hostreset(net)
123 	long net;
124 {
125 	register struct mbuf *m;
126 	register struct host *hp, *lp;
127 	struct hmbuf *hm;
128 
129 	for (m = hosts; m; m = m->m_next) {
130 		hm = mtod(m, struct hmbuf *);
131 		hp = hm->hm_hosts;
132 		lp = hp + HPMBUF;
133 		while (hm->hm_count > 0 && hp < lp) {
134 			if (in_netof(hp->h_addr) == net) {
135 				hp->h_flags &= ~HF_INUSE;
136 				hostrelease(hp);
137 			}
138 			hp++;
139 		}
140 	}
141 }
142 
143 /*
144  * Remove a host structure and release
145  * any resources it's accumulated.
146  */
147 hostrelease(hp)
148 	register struct host *hp;
149 {
150 	register struct mbuf *m, **mprev, *mh = dtom(hp);
151 
152 	/*
153 	 * Discard any packets left on the waiting q
154 	 */
155 	if (m = hp->h_q) {
156 		register struct mbuf *n;
157 
158 		do {
159 			n = m->m_act;
160 			m_freem(m);
161 			m = n;
162 		} while (m != hp->h_q);
163 		hp->h_q = 0;
164 	}
165 	hp->h_flags = 0;
166 	hp->h_rfnm = 0;
167 	if (--mtod(mh, struct hmbuf *)->hm_count)
168 		return;
169 	mprev = &hosts;
170 	while ((m = *mprev) != mh)
171 		mprev = &m->m_next;
172 	*mprev = m_free(mh);
173 }
174 
175 /*
176  * Remove a packet from the holding q.
177  * The RFNM counter is also bumped.
178  */
179 struct mbuf *
180 hostdeque(hp)
181 	register struct host *hp;
182 {
183 	register struct mbuf *m;
184 
185 	hp->h_rfnm--;
186 	HOST_DEQUE(hp, m);
187 	if (m)
188 		return (m);
189 	if (hp->h_rfnm == 0)
190 		hostfree(hp);
191 	return (0);
192 }
193 
194 /*
195  * Host data base timer routine.
196  * Decrement timers on structures which are
197  * waiting to be deallocated.  On expiration
198  * release resources, possibly deallocating
199  * mbuf associated with structure.
200  */
201 hostslowtimo()
202 {
203 	register struct mbuf *m;
204 	register struct host *hp, *lp;
205 	struct hmbuf *hm;
206 	int s = splimp();
207 
208 	for (m = hosts; m; m = m->m_next) {
209 		hm = mtod(m, struct hmbuf *);
210 		hp = hm->hm_hosts;
211 		lp = hp + HPMBUF;
212 		for (; hm->hm_count > 0 && hp < lp; hp++) {
213 			if (hp->h_flags & HF_INUSE)
214 				continue;
215 			if (hp->h_timer && --hp->h_timer == 0)
216 				hostrelease(hp);
217 		}
218 	}
219 	splx(s);
220 }
221 #endif
222