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