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