1 /*	if_imphost.c	4.2	82/02/12	*/
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/host.h"
15 #include "../net/if_imp.h"
16 
17 /*
18  * Head of host table hash chains.
19  */
20 struct mbuf hosttable = { 0, MMINOFF };
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 printf("hostlookup(%x)\n", addr);
36 	for (m = &hosttable; m; m = m->m_next) {
37 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
38 		if (hp->h_refcnt == 0)
39 			break;
40 printf("hostlookup: addr=%x\n", hp->h_addr.s_addr);
41 	        if (hp->h_addr.s_addr == addr.s_addr)
42 			return (hp);
43 	}
44 	return (0);
45 }
46 
47 /*
48  * Enter a reference to this host's internet
49  * address.  If no host structure exists, create
50  * one and hook it into the host database.
51  */
52 struct host *
53 hostenter(addr)
54 	struct in_addr addr;
55 {
56 	register struct mbuf *m, *mprev;
57 	register struct host *hp;
58 	register int hash = HOSTHASH(addr);
59 
60 COUNT(HOSTENTER);
61 printf("hostenter(%x)\n", addr);
62 	for (m = &hosttable; m; mprev = m, m = m->m_next) {
63 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
64 		if (hp->h_refcnt == 0)
65 			break;
66 printf("hostenter: addr=%x\n", addr);
67 	        if (hp->h_addr.s_addr == addr.s_addr)
68 			goto foundhost;
69 	}
70 
71 	/*
72 	 * No current host structure, make one.
73 	 * If our search ran off the end of the
74 	 * chain of mbuf's, allocate another.
75 	 */
76 printf("hostenter: new host\n");
77 	if (m == 0) {
78 		m = m_getclr(M_DONTWAIT);
79 		if (m == 0)
80 			return (0);
81 		mprev->m_next = m;
82 		m->m_act = mprev;
83 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
84 	}
85 	mtod(m, struct hmbuf *)->hm_count++;
86 	hp->h_addr = addr;
87 	hp->h_status = HOSTS_UP;
88 
89 foundhost:
90 	hp->h_refcnt++;		/* know new structures have 0 val */
91 	return (hp);
92 }
93 
94 /*
95  * Free a reference to a host.  If this causes the
96  * host structure to be released do so.
97  */
98 hostfree(addr)
99 	struct in_addr addr;
100 {
101 	register struct mbuf *m;
102 	register struct host *hp;
103 	register int hash = HOSTHASH(addr);
104 
105 COUNT(HOSTFREE);
106 printf("hostfree(%x)\n", addr);
107 	for (m = &hosttable; m; m = m->m_next) {
108 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
109 		if (hp->h_refcnt == 0)
110 			return;
111 	        if (hp->h_addr.s_addr == addr.s_addr) {
112 			if (--hp->h_refcnt == 0)
113 				hostrelease(mtod(m, struct hmbuf *), hp);
114 			return;
115 		}
116 	}
117 	panic("hostfree");
118 }
119 
120 /*
121  * Reset a given network's host entries.
122  * This involves clearing all packet queue's
123  * and releasing host structures.
124  */
125 hostreset(net)
126 	int net;
127 {
128 	register struct mbuf *m;
129 	register struct host *hp, *lp;
130 
131 COUNT(HOSTRESET);
132 printf("hostreset(%x)\n", net);
133 	for (m = &hosttable; m; m = m->m_next) {
134 		hp = mtod(m, struct hmbuf *)->hm_hosts;
135 		lp = hp + HPMBUF;
136 		while (hp < lp) {
137 			if (hp->h_addr.s_net == net)
138 				hostrelease(mtod(m, struct hmbuf *), hp);
139 			hp++;
140 		}
141 	}
142 }
143 
144 /*
145  * Remove a host structure and release
146  * any resources it's accumulated.
147  */
148 hostrelease(hm, hp)
149 	struct hmbuf *hm;
150 	register struct host *hp;
151 {
152 	register struct mbuf *m;
153 
154 COUNT(HOSTRELEASE);
155 printf("hostrelease(%x,%x)\n", hm, hp);
156 	/*
157 	 * Discard any packets left on the waiting q
158 	 */
159 	if (m = hp->h_q) {
160 		m = m->m_next;
161 		hp->h_q->m_next = 0;
162 		hp->h_q = 0;
163 		m_freem(m);
164 	}
165 	/*
166 	 * We could compact the database here, but is
167 	 * it worth it?  For now we assume not and just
168 	 * handle the simple case.
169 	 */
170 printf("hostrelease: count=%d\n", hm->hm_count);
171 	if (--hm->hm_count || (m = dtom(hm)) == &hosttable)
172 		return;
173 	m->m_act->m_next = m->m_next;
174 	m->m_next->m_act = m->m_act;
175 	(void) m_free(m);
176 }
177