1 /*	if_imphost.c	4.6	82/03/09	*/
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 
10 #include "../h/param.h"
11 #include "../h/mbuf.h"
12 #include "../net/in.h"
13 #include "../net/in_systm.h"
14 #include "../net/if_imp.h"
15 #include "../net/if_imphost.h"
16 
17 /*
18  * Head of host table hash chains.
19  */
20 struct mbuf *hosts;
21 
22 /*
23  * Given an internet address
24  * return a host structure (if it exists).
25  */
26 struct host *
27 hostlookup(addr)
28 	struct in_addr addr;
29 {
30 	register struct host *hp;
31 	register struct mbuf *m;
32 	register int hash = HOSTHASH(addr);
33 
34 COUNT(HOSTLOOKUP);
35 	addr.s_lh = 0;
36 	for (m = hosts; m; m = m->m_next) {
37 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
38 		if (hp->h_refcnt == 0)
39 			continue;
40 	        if (hp->h_addr.s_addr == addr.s_addr)
41 			return (hp);
42 	}
43 	return (0);
44 }
45 
46 /*
47  * Enter a reference to this host's internet
48  * address.  If no host structure exists, create
49  * one and hook it into the host database.
50  */
51 struct host *
52 hostenter(addr)
53 	struct in_addr addr;
54 {
55 	register struct mbuf *m, **mprev;
56 	register struct host *hp, *hp0 = 0;
57 	register int hash = HOSTHASH(addr);
58 
59 COUNT(HOSTENTER);
60 	addr.s_lh = 0;
61 	mprev = &hosts;
62 	while (m = *mprev) {
63 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
64 		if (hp->h_refcnt == 0) {
65 			if (hp0 == 0)
66 				hp0 = hp;
67 			continue;
68 		}
69 	        if (hp->h_addr.s_addr == addr.s_addr)
70 			goto foundhost;
71 		mprev = &m->m_next;
72 	}
73 
74 	/*
75 	 * No current host structure, make one.
76 	 * If our search ran off the end of the
77 	 * chain of mbuf's, allocate another.
78 	 */
79 	if (hp0 == 0) {
80 		m = m_getclr(M_DONTWAIT);
81 		if (m == 0)
82 			return (0);
83 		*mprev = m;
84 		m->m_off = MMINOFF;
85 		hp0 = &mtod(m, struct hmbuf *)->hm_hosts[hash];
86 	}
87 	mtod(dtom(hp0), struct hmbuf *)->hm_count++;
88 	hp = hp0;
89 	hp->h_addr = addr;
90 	hp->h_qcnt = 0;
91 
92 foundhost:
93 	hp->h_refcnt++;		/* know new structures have 0 val */
94 	return (hp);
95 }
96 
97 /*
98  * Free a reference to a host.  If this causes the
99  * host structure to be released do so.
100  */
101 hostfree(hp)
102 	register struct host *hp;
103 {
104 	register struct mbuf *m;
105 
106 COUNT(HOSTFREE);
107 	if (--hp->h_refcnt)
108 		return;
109 	hostrelease(hp);
110 }
111 
112 /*
113  * Reset a given network's host entries.
114  * This involves clearing all packet queue's
115  * and releasing host structures.
116  */
117 hostreset(net)
118 	int net;
119 {
120 	register struct mbuf *m;
121 	register struct host *hp, *lp;
122 	struct hmbuf *hm;
123 	int x;
124 
125 COUNT(HOSTRESET);
126 	x = splimp();
127 	for (m = hosts; m; m = m->m_next) {
128 		hm = mtod(m, struct hmbuf *);
129 		hp = hm->hm_hosts;
130 		lp = hp + HPMBUF;
131 		while (hm->hm_count != 0 && hp < lp) {
132 			if (hp->h_addr.s_net == net) {
133 				hp->h_refcnt = 0;
134 				hostrelease(mtod(m, struct hmbuf *), hp);
135 			}
136 			hp++;
137 		}
138 	}
139 	splx(x);
140 }
141 
142 /*
143  * Remove a host structure and release
144  * any resources it's accumulated.
145  */
146 hostrelease(hp)
147 	register struct host *hp;
148 {
149 	register struct mbuf *m, **mprev, *mh = dtom(hp);
150 
151 COUNT(HOSTRELEASE);
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 	if (--mtod(mh, struct hmbuf *)->hm_count)
166 		return;
167 	mprev = &hosts;
168 	while ((m = *mprev) != mh)
169 		mprev = &m->m_next;
170 	*mprev = mh->m_next;
171 	(void) m_free(mh);
172 }
173 
174 /*
175  * Remove a packet from the holding q.
176  * The RFNM counter is also bumped.
177  */
178 struct mbuf *
179 hostdeque(hp)
180 	register struct host *hp;
181 {
182 	register struct mbuf *m;
183 
184 	hp->h_rfnm--;
185 	HOST_DEQUE(hp, m);
186 	if (m)
187 		return (m);
188 	if (hp->h_rfnm == 0)
189 		hostfree(hp);
190 	return (0);
191 }
192