1 /*	if_imphost.c	4.5	82/02/21	*/
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 	for (m = hosts; m; m = m->m_next) {
36 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
37 		if (hp->h_refcnt == 0)
38 			continue;
39 	        if (hp->h_addr.s_addr == addr.s_addr)
40 			return (hp);
41 	}
42 	return (0);
43 }
44 
45 /*
46  * Enter a reference to this host's internet
47  * address.  If no host structure exists, create
48  * one and hook it into the host database.
49  */
50 struct host *
51 hostenter(addr)
52 	struct in_addr addr;
53 {
54 	register struct mbuf *m, **mprev;
55 	register struct host *hp, *hp0 = 0;
56 	register int hash = HOSTHASH(addr);
57 
58 COUNT(HOSTENTER);
59 	mprev = &hosts;
60 	while (m = *mprev) {
61 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
62 		if (hp->h_refcnt == 0) {
63 			if (hp0 == 0)
64 				hp0 = hp;
65 			continue;
66 		}
67 	        if (hp->h_addr.s_addr == addr.s_addr)
68 			goto foundhost;
69 		mprev = &m->m_next;
70 	}
71 
72 	/*
73 	 * No current host structure, make one.
74 	 * If our search ran off the end of the
75 	 * chain of mbuf's, allocate another.
76 	 */
77 	if (hp0 == 0) {
78 		m = m_getclr(M_DONTWAIT);
79 		if (m == 0)
80 			return (0);
81 		*mprev = m;
82 		m->m_off = MMINOFF;
83 		hp0 = &mtod(m, struct hmbuf *)->hm_hosts[hash];
84 	}
85 	mtod(dtom(hp0), struct hmbuf *)->hm_count++;
86 	hp = hp0;
87 	hp->h_addr = addr;
88 	hp->h_qcnt = 0;
89 
90 foundhost:
91 	hp->h_refcnt++;		/* know new structures have 0 val */
92 	return (hp);
93 }
94 
95 /*
96  * Free a reference to a host.  If this causes the
97  * host structure to be released do so.
98  */
99 hostfree(hp)
100 	register struct host *hp;
101 {
102 	register struct mbuf *m;
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 				hostrelease(mtod(m, struct hmbuf *), hp);
132 			hp++;
133 		}
134 	}
135 	splx(x);
136 }
137 
138 /*
139  * Remove a host structure and release
140  * any resources it's accumulated.
141  */
142 hostrelease(hp)
143 	register struct host *hp;
144 {
145 	register struct mbuf *m, **mprev, *mh = dtom(hp);
146 
147 COUNT(HOSTRELEASE);
148 	/*
149 	 * Discard any packets left on the waiting q
150 	 */
151 	if (m = hp->h_q) {
152 		register struct mbuf *n;
153 
154 		do {
155 			n = m->m_act;
156 			m_freem(m);
157 			m = n;
158 		} while (m != hp->h_q);
159 		hp->h_q = 0;
160 	}
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 = mh->m_next;
167 	(void) m_free(mh);
168 }
169 
170 /*
171  * Remove a packet from the holding q.
172  * The RFNM counter is also bumped.
173  */
174 struct mbuf *
175 hostdeque(hp)
176 	register struct host *hp;
177 {
178 	register struct mbuf *m;
179 
180 	hp->h_rfnm--;
181 	HOST_DEQUE(hp, m);
182 	if (m)
183 		return (m);
184 	if (hp->h_rfnm == 0)
185 		hostfree(hp);
186 	return (0);
187 }
188