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.5 (Berkeley) 05/06/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 */ 120 hostreset(unit) 121 int unit; 122 { 123 register struct mbuf *m; 124 register struct host *hp, *lp; 125 struct hmbuf *hm; 126 127 for (m = imp_softc[unit].imp_hosts; m; m = m->m_next) { 128 hm = mtod(m, struct hmbuf *); 129 hp = hm->hm_hosts; 130 lp = hp + HPMBUF; 131 while (hm->hm_count > 0 && hp < lp) { 132 hostrelease(hp); 133 hp++; 134 } 135 } 136 hostcompress(unit); 137 } 138 139 /* 140 * Remove a host structure and release 141 * any resources it's accumulated. 142 */ 143 hostrelease(hp) 144 register struct host *hp; 145 { 146 147 if (hp->h_q) 148 hostflush(hp); 149 hp->h_rfnm = 0; 150 if (hp->h_flags & HF_INUSE) 151 --mtod(dtom(hp), struct hmbuf *)->hm_count; 152 hp->h_flags = 0; 153 } 154 155 /* 156 * Flush the message queue for a host. 157 */ 158 hostflush(hp) 159 register struct host *hp; 160 { 161 register struct mbuf *m, **mprev; 162 163 /* 164 * Discard any packets left on the waiting q 165 */ 166 if (m = hp->h_q) { 167 register struct mbuf *n; 168 169 do { 170 n = m->m_act; 171 m_freem(m); 172 m = n; 173 } while (m != hp->h_q); 174 hp->h_q = 0; 175 hp->h_qcnt = 0; 176 } 177 } 178 179 hostcompress(unit) 180 int unit; 181 { 182 register struct mbuf *m, **mprev; 183 184 mprev = &imp_softc[unit].imp_hosts; 185 while (m = *mprev) { 186 if (mtod(m, struct hmbuf *)->hm_count == 0) 187 *mprev = m_free(m); 188 else 189 mprev = &m->m_next; 190 } 191 } 192 193 /* 194 * Host data base timer routine. 195 * Decrement timers on structures which are 196 * waiting to be deallocated. On expiration 197 * release resources, possibly deallocating 198 * mbuf associated with structure. 199 */ 200 hostslowtimo() 201 { 202 register struct mbuf *m; 203 register struct host *hp, *lp; 204 struct imp_softc *sc; 205 struct hmbuf *hm; 206 int s = splimp(), unit, any; 207 extern int imppri; 208 209 for (unit = 0; unit < NIMP; unit++) { 210 any = 0; 211 sc = &imp_softc[unit]; 212 for (m = sc->imp_hosts; m; m = m->m_next) { 213 hm = mtod(m, struct hmbuf *); 214 hp = hm->hm_hosts; 215 lp = hp + HPMBUF; 216 for (; hm->hm_count > 0 && hp < lp; hp++) { 217 if (hp->h_timer && --hp->h_timer == 0) { 218 if (hp->h_rfnm) { 219 log(imppri, 220 "imp%d: host %d/imp %d, lost rfnm\n", 221 unit, hp->h_host, ntohs(hp->h_imp)); 222 sc->imp_lostrfnm++; 223 imprestarthost(sc, hp); 224 } else { 225 any = 1; 226 hostrelease(hp); 227 if (sc->imp_hostq == m) 228 sc->imp_hostq = 0; 229 } 230 } 231 } 232 } 233 if (any) 234 hostcompress(unit); 235 } 236 splx(s); 237 } 238 #endif 239