1 /*	if_imphost.c	4.8	82/03/15	*/
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 		mprev = &m->m_next;
64 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
65 		if (hp->h_refcnt == 0) {
66 			if (hp0 == 0)
67 				hp0 = hp;
68 			continue;
69 		}
70 	        if (hp->h_addr.s_addr == addr.s_addr)
71 			goto foundhost;
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 COUNT(HOSTFREE);
105 	if (--hp->h_refcnt)
106 		return;
107 	hostrelease(hp);
108 }
109 
110 /*
111  * Reset a given network's host entries.
112  * This involves clearing all packet queue's
113  * and releasing host structures.
114  */
115 hostreset(net)
116 	int net;
117 {
118 	register struct mbuf *m;
119 	register struct host *hp, *lp;
120 	struct hmbuf *hm;
121 	int x;
122 
123 COUNT(HOSTRESET);
124 	x = splimp();
125 	for (m = hosts; m; m = m->m_next) {
126 		hm = mtod(m, struct hmbuf *);
127 		hp = hm->hm_hosts;
128 		lp = hp + HPMBUF;
129 		while (hm->hm_count != 0 && hp < lp) {
130 			if (hp->h_addr.s_net == net) {
131 				hp->h_refcnt = 0;
132 				hostrelease(hp);
133 			}
134 			hp++;
135 		}
136 	}
137 	splx(x);
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 	register struct mbuf *m, **mprev, *mh = dtom(hp);
148 
149 COUNT(HOSTRELEASE);
150 	/*
151 	 * Discard any packets left on the waiting q
152 	 */
153 	if (m = hp->h_q) {
154 		register struct mbuf *n;
155 
156 		do {
157 			n = m->m_act;
158 			m_freem(m);
159 			m = n;
160 		} while (m != hp->h_q);
161 		hp->h_q = 0;
162 	}
163 	if (--mtod(mh, struct hmbuf *)->hm_count)
164 		return;
165 	mprev = &hosts;
166 	while ((m = *mprev) != mh)
167 		mprev = &m->m_next;
168 	*mprev = mh->m_next;
169 	(void) m_free(mh);
170 }
171 
172 /*
173  * Remove a packet from the holding q.
174  * The RFNM counter is also bumped.
175  */
176 struct mbuf *
177 hostdeque(hp)
178 	register struct host *hp;
179 {
180 	register struct mbuf *m;
181 
182 	hp->h_rfnm--;
183 	HOST_DEQUE(hp, m);
184 	if (m)
185 		return (m);
186 	if (hp->h_rfnm == 0)
187 		hostfree(hp);
188 	return (0);
189 }
190