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