1 /* 2 * Copyright (c) 1982, 1986, 1988 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)if_imphost.c 7.11 (Berkeley) 10/11/92 8 */ 9 10 #include "imp.h" 11 #if NIMP > 0 12 /* 13 * Host table manipulation routines. 14 * Only needed when shipping stuff through an IMP. 15 * 16 * Everything in here is called at splimp from 17 * from the IMP protocol code (if_imp.c), or 18 * interlocks with the code at splimp. 19 */ 20 #include <sys/param.h> 21 #include <sys/mbuf.h> 22 #include <sys/socket.h> 23 #include <sys/syslog.h> 24 25 #include <net/if.h> 26 27 #include <netinet/in.h> 28 #include <netinet/in_systm.h> 29 30 #include <netimp/if_imp.h> 31 #include <netimp/if_imphost.h> 32 33 extern struct imp_softc imp_softc[]; 34 35 /* 36 * Given an internet address 37 * return a host structure (if it exists). 38 */ 39 struct host * 40 hostlookup(imp, host, unit) 41 int imp, host, unit; 42 { 43 register struct host *hp; 44 register struct mbuf *m; 45 register int hash = HOSTHASH(imp, host); 46 47 for (m = imp_softc[unit].imp_hosts; m; m = m->m_next) { 48 hp = &mtod(m, struct hmbuf *)->hm_hosts[hash]; 49 if (hp->h_imp == imp && hp->h_host == host) { 50 if ((hp->h_flags & HF_INUSE) == 0) 51 mtod(dtom(hp), struct hmbuf *)->hm_count++; 52 hp->h_flags |= HF_INUSE; 53 return (hp); 54 } 55 } 56 return ((struct host *)0); 57 } 58 59 /* 60 * Enter a reference to this host's internet 61 * address. If no host structure exists, create 62 * one and hook it into the host database. 63 */ 64 struct host * 65 hostenter(imp, host, unit) 66 int imp, host, unit; 67 { 68 register struct mbuf *m, **mprev; 69 register struct host *hp, *hp0 = 0; 70 register int hash = HOSTHASH(imp, host); 71 72 mprev = &imp_softc[unit].imp_hosts; 73 while (m = *mprev) { 74 mprev = &m->m_next; 75 hp = &mtod(m, struct hmbuf *)->hm_hosts[hash]; 76 if (hp->h_imp == imp && hp->h_host == host) { 77 if ((hp->h_flags & HF_INUSE) == 0) 78 mtod(dtom(hp), struct hmbuf *)->hm_count++; 79 goto foundhost; 80 } 81 if ((hp->h_flags & HF_INUSE) == 0) { 82 if (hp0 == 0) 83 hp0 = hp; 84 continue; 85 } 86 } 87 88 /* 89 * No current host structure, make one. 90 * If our search ran off the end of the 91 * chain of mbuf's, allocate another. 92 */ 93 if (hp0 == 0) { 94 m = m_getclr(M_DONTWAIT, MT_HTABLE); 95 if (m == NULL) 96 return ((struct host *)0); 97 *mprev = m; 98 hp0 = &mtod(m, struct hmbuf *)->hm_hosts[hash]; 99 } 100 hp = hp0; 101 mtod(dtom(hp), struct hmbuf *)->hm_count++; 102 hp->h_imp = imp; 103 hp->h_host = host; 104 hp->h_timer = 0; 105 hp->h_flags = 0; 106 107 foundhost: 108 hp->h_flags |= HF_INUSE; 109 return (hp); 110 } 111 112 /* 113 * Reset a given imp unit's host entries. 114 * Must be called at splimp. 115 */ 116 hostreset(unit) 117 int unit; 118 { 119 register struct mbuf *m; 120 register struct host *hp, *lp; 121 struct hmbuf *hm; 122 123 for (m = imp_softc[unit].imp_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 hostrelease(hp); 129 hp++; 130 } 131 } 132 hostcompress(unit); 133 } 134 135 /* 136 * Remove a host structure and release 137 * any resources it's accumulated. 138 */ 139 hostrelease(hp) 140 register struct host *hp; 141 { 142 143 if (hp->h_q) 144 hostflush(hp); 145 hp->h_rfnm = 0; 146 if (hp->h_flags & HF_INUSE) 147 --mtod(dtom(hp), struct hmbuf *)->hm_count; 148 hp->h_flags = 0; 149 } 150 151 /* 152 * Flush the message queue for a host. 153 */ 154 hostflush(hp) 155 register struct host *hp; 156 { 157 register struct mbuf *m; 158 159 /* 160 * Discard any packets left on the waiting q 161 */ 162 if (m = hp->h_q) { 163 register struct mbuf *n; 164 165 do { 166 n = m->m_act; 167 m_freem(m); 168 m = n; 169 } while (m != hp->h_q); 170 hp->h_q = 0; 171 hp->h_qcnt = 0; 172 } 173 } 174 175 /* 176 * Release mbufs in host table that contain no entries 177 * currently in use. Must be called at splimp. 178 */ 179 hostcompress(unit) 180 int unit; 181 { 182 register struct mbuf *m, **mprev; 183 struct imp_softc *sc = &imp_softc[unit]; 184 185 mprev = &sc->imp_hosts; 186 sc->imp_hostq = 0; 187 while (m = *mprev) { 188 if (mtod(m, struct hmbuf *)->hm_count == 0) 189 *mprev = m_free(m); 190 else 191 mprev = &m->m_next; 192 } 193 } 194 195 /* 196 * Host data base timer routine. 197 * Decrement timers on structures which are 198 * waiting to be deallocated. On expiration 199 * release resources, possibly deallocating 200 * mbuf associated with structure. 201 */ 202 hostslowtimo() 203 { 204 register struct mbuf *m; 205 register struct host *hp, *lp; 206 struct imp_softc *sc; 207 struct hmbuf *hm; 208 int s = splimp(), unit, any; 209 210 for (unit = 0; unit < NIMP; unit++) { 211 any = 0; 212 sc = &imp_softc[unit]; 213 for (m = sc->imp_hosts; m; m = m->m_next) { 214 hm = mtod(m, struct hmbuf *); 215 hp = hm->hm_hosts; 216 lp = hp + HPMBUF; 217 for (; hm->hm_count > 0 && hp < lp; hp++) { 218 if (hp->h_timer && --hp->h_timer == 0) { 219 if (hp->h_rfnm) { 220 log(LOG_INFO, /* XXX */ 221 "imp%d: host %d/imp %d, lost rfnm\n", 222 unit, hp->h_host, ntohs(hp->h_imp)); 223 sc->imp_lostrfnm++; 224 imprestarthost(sc, hp); 225 } else { 226 any = 1; 227 hostrelease(hp); 228 if (sc->imp_hostq == m) 229 sc->imp_hostq = 0; 230 } 231 } 232 } 233 } 234 if (any) 235 hostcompress(unit); 236 } 237 splx(s); 238 } 239 #endif 240