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