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