109#endif 110 111 112#if (SOLARIS || defined(__sgi)) && defined(_KERNEL) 113extern KRWLOCK_T ipf_auth, ipf_mutex; 114extern kmutex_t ipf_authmx; 115# if SOLARIS 116extern kcondvar_t ipfauthwait; 117# endif 118#endif 119#ifdef linux 120static struct wait_queue *ipfauthwait = NULL; 121#endif 122 123int fr_authsize = FR_NUMAUTH; 124int fr_authused = 0; 125int fr_defaultauthage = 600; 126int fr_auth_lock = 0; 127fr_authstat_t fr_authstats; 128static frauth_t fr_auth[FR_NUMAUTH]; 129mb_t *fr_authpkts[FR_NUMAUTH]; 130static int fr_authstart = 0, fr_authend = 0, fr_authnext = 0; 131static frauthent_t *fae_list = NULL; 132frentry_t *ipauth = NULL, 133 *fr_authlist = NULL; 134 135 136/* 137 * Check if a packet has authorization. If the packet is found to match an 138 * authorization result and that would result in a feedback loop (i.e. it 139 * will end up returning FR_AUTH) then return FR_BLOCK instead. 140 */ 141u_32_t fr_checkauth(ip, fin) 142ip_t *ip; 143fr_info_t *fin; 144{ 145 u_short id = ip->ip_id; 146 frentry_t *fr; 147 frauth_t *fra; 148 u_32_t pass; 149 int i; 150 151 if (fr_auth_lock || !fr_authused) 152 return 0; 153 154 READ_ENTER(&ipf_auth); 155 for (i = fr_authstart; i != fr_authend; ) { 156 /* 157 * index becomes -2 only after an SIOCAUTHW. Check this in 158 * case the same packet gets sent again and it hasn't yet been 159 * auth'd. 160 */ 161 fra = fr_auth + i; 162 if ((fra->fra_index == -2) && (id == fra->fra_info.fin_id) && 163 !bcmp((char *)fin, (char *)&fra->fra_info, FI_CSIZE)) { 164 /* 165 * Avoid feedback loop. 166 */ 167 if (!(pass = fra->fra_pass) || (pass & FR_AUTH)) 168 pass = FR_BLOCK; 169 /* 170 * Create a dummy rule for the stateful checking to 171 * use and return. Zero out any values we don't 172 * trust from userland! 173 */ 174 if ((pass & FR_KEEPSTATE) || ((pass & FR_KEEPFRAG) && 175 (fin->fin_fi.fi_fl & FI_FRAG))) { 176 KMALLOC(fr, frentry_t *); 177 if (fr) { 178 bcopy((char *)fra->fra_info.fin_fr, 179 fr, sizeof(*fr)); 180 fr->fr_grp = NULL; 181 fr->fr_ifa = fin->fin_ifp; 182 fr->fr_func = NULL; 183 fr->fr_ref = 1; 184 fr->fr_flags = pass; 185#if BSD >= 199306 186 fr->fr_oifa = NULL; 187#endif 188 } 189 } else 190 fr = fra->fra_info.fin_fr; 191 fin->fin_fr = fr; 192 RWLOCK_EXIT(&ipf_auth); 193 WRITE_ENTER(&ipf_auth); 194 if (fr && fr != fra->fra_info.fin_fr) { 195 fr->fr_next = fr_authlist; 196 fr_authlist = fr; 197 } 198 fr_authstats.fas_hits++; 199 fra->fra_index = -1; 200 fr_authused--; 201 if (i == fr_authstart) { 202 while (fra->fra_index == -1) { 203 i++; 204 fra++; 205 if (i == FR_NUMAUTH) { 206 i = 0; 207 fra = fr_auth; 208 } 209 fr_authstart = i; 210 if (i == fr_authend) 211 break; 212 } 213 if (fr_authstart == fr_authend) { 214 fr_authnext = 0; 215 fr_authstart = fr_authend = 0; 216 } 217 } 218 RWLOCK_EXIT(&ipf_auth); 219 return pass; 220 } 221 i++; 222 if (i == FR_NUMAUTH) 223 i = 0; 224 } 225 fr_authstats.fas_miss++; 226 RWLOCK_EXIT(&ipf_auth); 227 return 0; 228} 229 230 231/* 232 * Check if we have room in the auth array to hold details for another packet. 233 * If we do, store it and wake up any user programs which are waiting to 234 * hear about these events. 235 */ 236int fr_newauth(m, fin, ip) 237mb_t *m; 238fr_info_t *fin; 239ip_t *ip; 240{ 241#if defined(_KERNEL) && SOLARIS 242 qif_t *qif = fin->fin_qif; 243#endif 244 frauth_t *fra; 245 int i; 246 247 if (fr_auth_lock) 248 return 0; 249 250 WRITE_ENTER(&ipf_auth); 251 if (fr_authstart > fr_authend) { 252 fr_authstats.fas_nospace++; 253 RWLOCK_EXIT(&ipf_auth); 254 return 0; 255 } else { 256 if (fr_authused == FR_NUMAUTH) { 257 fr_authstats.fas_nospace++; 258 RWLOCK_EXIT(&ipf_auth); 259 return 0; 260 } 261 } 262 263 fr_authstats.fas_added++; 264 fr_authused++; 265 i = fr_authend++; 266 if (fr_authend == FR_NUMAUTH) 267 fr_authend = 0; 268 RWLOCK_EXIT(&ipf_auth); 269 fra = fr_auth + i; 270 fra->fra_index = i; 271 fra->fra_pass = 0; 272 fra->fra_age = fr_defaultauthage; 273 bcopy((char *)fin, (char *)&fra->fra_info, sizeof(*fin)); 274#if SOLARIS && defined(_KERNEL) 275# if !defined(sparc) 276 /* 277 * No need to copyback here as we want to undo the changes, not keep 278 * them. 279 */ 280 if ((ip == (ip_t *)m->b_rptr) && (ip->ip_v == 4)) 281 { 282 register u_short bo; 283 284 bo = ip->ip_len; 285 ip->ip_len = htons(bo); 286# if !SOLARIS && !defined(__NetBSD__) && !defined(__FreeBSD__) 287 /* 4.4BSD converts this ip_input.c, but I don't in solaris.c */ 288 bo = ip->ip_id; 289 ip->ip_id = htons(bo); 290# endif 291 bo = ip->ip_off; 292 ip->ip_off = htons(bo); 293 } 294# endif 295 m->b_rptr -= qif->qf_off; 296 fr_authpkts[i] = *(mblk_t **)fin->fin_mp; 297 fra->fra_q = qif->qf_q; 298 cv_signal(&ipfauthwait); 299#else 300# if defined(BSD) && !defined(sparc) && (BSD >= 199306) 301 if (!fin->fin_out) { 302 ip->ip_len = htons(ip->ip_len); 303 ip->ip_off = htons(ip->ip_off); 304 } 305# endif 306 fr_authpkts[i] = m; 307 WAKEUP(&fr_authnext); 308#endif 309 return 1; 310} 311 312 313int fr_auth_ioctl(data, mode, cmd, fr, frptr) 314caddr_t data; 315int mode; 316#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003) 317u_long cmd; 318#else 319int cmd; 320#endif 321frentry_t *fr, **frptr; 322{ 323 mb_t *m; 324#if defined(_KERNEL) && !SOLARIS 325 int s; 326#endif 327 frauth_t auth, *au = &auth, *fra; 328 frauthent_t *fae, **faep; 329 int i, error = 0; 330 331 switch (cmd) 332 { 333 case SIOCSTLCK : 334 error = fr_lock(data, &fr_auth_lock); 335 break; 336 case SIOCINIFR : 337 case SIOCRMIFR : 338 case SIOCADIFR : 339 error = EINVAL; 340 break; 341 case SIOCINAFR : 342 error = EINVAL; 343 break; 344 case SIOCRMAFR : 345 case SIOCADAFR : 346 for (faep = &fae_list; (fae = *faep); ) 347 if (&fae->fae_fr == fr) 348 break; 349 else 350 faep = &fae->fae_next; 351 if (cmd == SIOCRMAFR) { 352 if (!fr || !frptr) 353 error = EINVAL; 354 else if (!fae) 355 error = ESRCH; 356 else { 357 WRITE_ENTER(&ipf_auth); 358 SPL_NET(s); 359 *faep = fae->fae_next; 360 *frptr = fr->fr_next; 361 SPL_X(s); 362 RWLOCK_EXIT(&ipf_auth); 363 KFREE(fae); 364 } 365 } else if (fr && frptr) { 366 KMALLOC(fae, frauthent_t *); 367 if (fae != NULL) { 368 bcopy((char *)fr, (char *)&fae->fae_fr, 369 sizeof(*fr)); 370 WRITE_ENTER(&ipf_auth); 371 SPL_NET(s); 372 fae->fae_age = fr_defaultauthage; 373 fae->fae_fr.fr_hits = 0; 374 fae->fae_fr.fr_next = *frptr; 375 *frptr = &fae->fae_fr; 376 fae->fae_next = *faep; 377 *faep = fae; 378 ipauth = &fae_list->fae_fr; 379 SPL_X(s); 380 RWLOCK_EXIT(&ipf_auth); 381 } else 382 error = ENOMEM; 383 } else 384 error = EINVAL; 385 break; 386 case SIOCATHST: 387 fr_authstats.fas_faelist = fae_list; 388 error = IWCOPYPTR((char *)&fr_authstats, data, 389 sizeof(fr_authstats)); 390 break; 391 case SIOCAUTHW: 392 if (!(mode & FWRITE)) { 393 error = EPERM; 394 break; 395 } 396fr_authioctlloop: 397 READ_ENTER(&ipf_auth); 398 if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) { 399 error = IWCOPYPTR((char *)&fr_auth[fr_authnext], data, 400 sizeof(frauth_t)); 401 RWLOCK_EXIT(&ipf_auth); 402 if (error) 403 break; 404 WRITE_ENTER(&ipf_auth); 405 SPL_NET(s); 406 fr_authnext++; 407 if (fr_authnext == FR_NUMAUTH) 408 fr_authnext = 0; 409 SPL_X(s); 410 RWLOCK_EXIT(&ipf_auth); 411 return 0; 412 } 413 RWLOCK_EXIT(&ipf_auth); 414#ifdef _KERNEL 415# if SOLARIS 416 mutex_enter(&ipf_authmx); 417 if (!cv_wait_sig(&ipfauthwait, &ipf_authmx)) { 418 mutex_exit(&ipf_authmx); 419 return EINTR; 420 } 421 mutex_exit(&ipf_authmx); 422# else 423 error = SLEEP(&fr_authnext, "fr_authnext"); 424# endif 425#endif 426 if (!error) 427 goto fr_authioctlloop; 428 break; 429 case SIOCAUTHR: 430 if (!(mode & FWRITE)) { 431 error = EPERM; 432 break; 433 } 434 error = IRCOPYPTR(data, (caddr_t)&auth, sizeof(auth)); 435 if (error) 436 return error; 437 WRITE_ENTER(&ipf_auth); 438 SPL_NET(s); 439 i = au->fra_index; 440 fra = fr_auth + i; 441 if ((i < 0) || (i > FR_NUMAUTH) || 442 (fra->fra_info.fin_id != au->fra_info.fin_id)) { 443 SPL_X(s); 444 RWLOCK_EXIT(&ipf_auth); 445 return EINVAL; 446 } 447 m = fr_authpkts[i]; 448 fra->fra_index = -2; 449 fra->fra_pass = au->fra_pass; 450 fr_authpkts[i] = NULL; 451 RWLOCK_EXIT(&ipf_auth); 452#ifdef _KERNEL 453 if (m && au->fra_info.fin_out) { 454# if SOLARIS 455 error = (fr_qout(fra->fra_q, m) == 0) ? EINVAL : 0; 456# else /* SOLARIS */ 457 struct route ro; 458 459 bzero((char *)&ro, sizeof(ro)); 460# if ((_BSDI_VERSION >= 199802) && (_BSDI_VERSION < 200005)) || \
| 109#endif 110 111 112#if (SOLARIS || defined(__sgi)) && defined(_KERNEL) 113extern KRWLOCK_T ipf_auth, ipf_mutex; 114extern kmutex_t ipf_authmx; 115# if SOLARIS 116extern kcondvar_t ipfauthwait; 117# endif 118#endif 119#ifdef linux 120static struct wait_queue *ipfauthwait = NULL; 121#endif 122 123int fr_authsize = FR_NUMAUTH; 124int fr_authused = 0; 125int fr_defaultauthage = 600; 126int fr_auth_lock = 0; 127fr_authstat_t fr_authstats; 128static frauth_t fr_auth[FR_NUMAUTH]; 129mb_t *fr_authpkts[FR_NUMAUTH]; 130static int fr_authstart = 0, fr_authend = 0, fr_authnext = 0; 131static frauthent_t *fae_list = NULL; 132frentry_t *ipauth = NULL, 133 *fr_authlist = NULL; 134 135 136/* 137 * Check if a packet has authorization. If the packet is found to match an 138 * authorization result and that would result in a feedback loop (i.e. it 139 * will end up returning FR_AUTH) then return FR_BLOCK instead. 140 */ 141u_32_t fr_checkauth(ip, fin) 142ip_t *ip; 143fr_info_t *fin; 144{ 145 u_short id = ip->ip_id; 146 frentry_t *fr; 147 frauth_t *fra; 148 u_32_t pass; 149 int i; 150 151 if (fr_auth_lock || !fr_authused) 152 return 0; 153 154 READ_ENTER(&ipf_auth); 155 for (i = fr_authstart; i != fr_authend; ) { 156 /* 157 * index becomes -2 only after an SIOCAUTHW. Check this in 158 * case the same packet gets sent again and it hasn't yet been 159 * auth'd. 160 */ 161 fra = fr_auth + i; 162 if ((fra->fra_index == -2) && (id == fra->fra_info.fin_id) && 163 !bcmp((char *)fin, (char *)&fra->fra_info, FI_CSIZE)) { 164 /* 165 * Avoid feedback loop. 166 */ 167 if (!(pass = fra->fra_pass) || (pass & FR_AUTH)) 168 pass = FR_BLOCK; 169 /* 170 * Create a dummy rule for the stateful checking to 171 * use and return. Zero out any values we don't 172 * trust from userland! 173 */ 174 if ((pass & FR_KEEPSTATE) || ((pass & FR_KEEPFRAG) && 175 (fin->fin_fi.fi_fl & FI_FRAG))) { 176 KMALLOC(fr, frentry_t *); 177 if (fr) { 178 bcopy((char *)fra->fra_info.fin_fr, 179 fr, sizeof(*fr)); 180 fr->fr_grp = NULL; 181 fr->fr_ifa = fin->fin_ifp; 182 fr->fr_func = NULL; 183 fr->fr_ref = 1; 184 fr->fr_flags = pass; 185#if BSD >= 199306 186 fr->fr_oifa = NULL; 187#endif 188 } 189 } else 190 fr = fra->fra_info.fin_fr; 191 fin->fin_fr = fr; 192 RWLOCK_EXIT(&ipf_auth); 193 WRITE_ENTER(&ipf_auth); 194 if (fr && fr != fra->fra_info.fin_fr) { 195 fr->fr_next = fr_authlist; 196 fr_authlist = fr; 197 } 198 fr_authstats.fas_hits++; 199 fra->fra_index = -1; 200 fr_authused--; 201 if (i == fr_authstart) { 202 while (fra->fra_index == -1) { 203 i++; 204 fra++; 205 if (i == FR_NUMAUTH) { 206 i = 0; 207 fra = fr_auth; 208 } 209 fr_authstart = i; 210 if (i == fr_authend) 211 break; 212 } 213 if (fr_authstart == fr_authend) { 214 fr_authnext = 0; 215 fr_authstart = fr_authend = 0; 216 } 217 } 218 RWLOCK_EXIT(&ipf_auth); 219 return pass; 220 } 221 i++; 222 if (i == FR_NUMAUTH) 223 i = 0; 224 } 225 fr_authstats.fas_miss++; 226 RWLOCK_EXIT(&ipf_auth); 227 return 0; 228} 229 230 231/* 232 * Check if we have room in the auth array to hold details for another packet. 233 * If we do, store it and wake up any user programs which are waiting to 234 * hear about these events. 235 */ 236int fr_newauth(m, fin, ip) 237mb_t *m; 238fr_info_t *fin; 239ip_t *ip; 240{ 241#if defined(_KERNEL) && SOLARIS 242 qif_t *qif = fin->fin_qif; 243#endif 244 frauth_t *fra; 245 int i; 246 247 if (fr_auth_lock) 248 return 0; 249 250 WRITE_ENTER(&ipf_auth); 251 if (fr_authstart > fr_authend) { 252 fr_authstats.fas_nospace++; 253 RWLOCK_EXIT(&ipf_auth); 254 return 0; 255 } else { 256 if (fr_authused == FR_NUMAUTH) { 257 fr_authstats.fas_nospace++; 258 RWLOCK_EXIT(&ipf_auth); 259 return 0; 260 } 261 } 262 263 fr_authstats.fas_added++; 264 fr_authused++; 265 i = fr_authend++; 266 if (fr_authend == FR_NUMAUTH) 267 fr_authend = 0; 268 RWLOCK_EXIT(&ipf_auth); 269 fra = fr_auth + i; 270 fra->fra_index = i; 271 fra->fra_pass = 0; 272 fra->fra_age = fr_defaultauthage; 273 bcopy((char *)fin, (char *)&fra->fra_info, sizeof(*fin)); 274#if SOLARIS && defined(_KERNEL) 275# if !defined(sparc) 276 /* 277 * No need to copyback here as we want to undo the changes, not keep 278 * them. 279 */ 280 if ((ip == (ip_t *)m->b_rptr) && (ip->ip_v == 4)) 281 { 282 register u_short bo; 283 284 bo = ip->ip_len; 285 ip->ip_len = htons(bo); 286# if !SOLARIS && !defined(__NetBSD__) && !defined(__FreeBSD__) 287 /* 4.4BSD converts this ip_input.c, but I don't in solaris.c */ 288 bo = ip->ip_id; 289 ip->ip_id = htons(bo); 290# endif 291 bo = ip->ip_off; 292 ip->ip_off = htons(bo); 293 } 294# endif 295 m->b_rptr -= qif->qf_off; 296 fr_authpkts[i] = *(mblk_t **)fin->fin_mp; 297 fra->fra_q = qif->qf_q; 298 cv_signal(&ipfauthwait); 299#else 300# if defined(BSD) && !defined(sparc) && (BSD >= 199306) 301 if (!fin->fin_out) { 302 ip->ip_len = htons(ip->ip_len); 303 ip->ip_off = htons(ip->ip_off); 304 } 305# endif 306 fr_authpkts[i] = m; 307 WAKEUP(&fr_authnext); 308#endif 309 return 1; 310} 311 312 313int fr_auth_ioctl(data, mode, cmd, fr, frptr) 314caddr_t data; 315int mode; 316#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003) 317u_long cmd; 318#else 319int cmd; 320#endif 321frentry_t *fr, **frptr; 322{ 323 mb_t *m; 324#if defined(_KERNEL) && !SOLARIS 325 int s; 326#endif 327 frauth_t auth, *au = &auth, *fra; 328 frauthent_t *fae, **faep; 329 int i, error = 0; 330 331 switch (cmd) 332 { 333 case SIOCSTLCK : 334 error = fr_lock(data, &fr_auth_lock); 335 break; 336 case SIOCINIFR : 337 case SIOCRMIFR : 338 case SIOCADIFR : 339 error = EINVAL; 340 break; 341 case SIOCINAFR : 342 error = EINVAL; 343 break; 344 case SIOCRMAFR : 345 case SIOCADAFR : 346 for (faep = &fae_list; (fae = *faep); ) 347 if (&fae->fae_fr == fr) 348 break; 349 else 350 faep = &fae->fae_next; 351 if (cmd == SIOCRMAFR) { 352 if (!fr || !frptr) 353 error = EINVAL; 354 else if (!fae) 355 error = ESRCH; 356 else { 357 WRITE_ENTER(&ipf_auth); 358 SPL_NET(s); 359 *faep = fae->fae_next; 360 *frptr = fr->fr_next; 361 SPL_X(s); 362 RWLOCK_EXIT(&ipf_auth); 363 KFREE(fae); 364 } 365 } else if (fr && frptr) { 366 KMALLOC(fae, frauthent_t *); 367 if (fae != NULL) { 368 bcopy((char *)fr, (char *)&fae->fae_fr, 369 sizeof(*fr)); 370 WRITE_ENTER(&ipf_auth); 371 SPL_NET(s); 372 fae->fae_age = fr_defaultauthage; 373 fae->fae_fr.fr_hits = 0; 374 fae->fae_fr.fr_next = *frptr; 375 *frptr = &fae->fae_fr; 376 fae->fae_next = *faep; 377 *faep = fae; 378 ipauth = &fae_list->fae_fr; 379 SPL_X(s); 380 RWLOCK_EXIT(&ipf_auth); 381 } else 382 error = ENOMEM; 383 } else 384 error = EINVAL; 385 break; 386 case SIOCATHST: 387 fr_authstats.fas_faelist = fae_list; 388 error = IWCOPYPTR((char *)&fr_authstats, data, 389 sizeof(fr_authstats)); 390 break; 391 case SIOCAUTHW: 392 if (!(mode & FWRITE)) { 393 error = EPERM; 394 break; 395 } 396fr_authioctlloop: 397 READ_ENTER(&ipf_auth); 398 if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) { 399 error = IWCOPYPTR((char *)&fr_auth[fr_authnext], data, 400 sizeof(frauth_t)); 401 RWLOCK_EXIT(&ipf_auth); 402 if (error) 403 break; 404 WRITE_ENTER(&ipf_auth); 405 SPL_NET(s); 406 fr_authnext++; 407 if (fr_authnext == FR_NUMAUTH) 408 fr_authnext = 0; 409 SPL_X(s); 410 RWLOCK_EXIT(&ipf_auth); 411 return 0; 412 } 413 RWLOCK_EXIT(&ipf_auth); 414#ifdef _KERNEL 415# if SOLARIS 416 mutex_enter(&ipf_authmx); 417 if (!cv_wait_sig(&ipfauthwait, &ipf_authmx)) { 418 mutex_exit(&ipf_authmx); 419 return EINTR; 420 } 421 mutex_exit(&ipf_authmx); 422# else 423 error = SLEEP(&fr_authnext, "fr_authnext"); 424# endif 425#endif 426 if (!error) 427 goto fr_authioctlloop; 428 break; 429 case SIOCAUTHR: 430 if (!(mode & FWRITE)) { 431 error = EPERM; 432 break; 433 } 434 error = IRCOPYPTR(data, (caddr_t)&auth, sizeof(auth)); 435 if (error) 436 return error; 437 WRITE_ENTER(&ipf_auth); 438 SPL_NET(s); 439 i = au->fra_index; 440 fra = fr_auth + i; 441 if ((i < 0) || (i > FR_NUMAUTH) || 442 (fra->fra_info.fin_id != au->fra_info.fin_id)) { 443 SPL_X(s); 444 RWLOCK_EXIT(&ipf_auth); 445 return EINVAL; 446 } 447 m = fr_authpkts[i]; 448 fra->fra_index = -2; 449 fra->fra_pass = au->fra_pass; 450 fr_authpkts[i] = NULL; 451 RWLOCK_EXIT(&ipf_auth); 452#ifdef _KERNEL 453 if (m && au->fra_info.fin_out) { 454# if SOLARIS 455 error = (fr_qout(fra->fra_q, m) == 0) ? EINVAL : 0; 456# else /* SOLARIS */ 457 struct route ro; 458 459 bzero((char *)&ro, sizeof(ro)); 460# if ((_BSDI_VERSION >= 199802) && (_BSDI_VERSION < 200005)) || \
|
462 error = ip_output(m, NULL, &ro, IP_FORWARDING, NULL, 463 NULL); 464# else 465 error = ip_output(m, NULL, &ro, IP_FORWARDING, NULL); 466# endif 467 if (ro.ro_rt) { 468 RTFREE(ro.ro_rt); 469 } 470# endif /* SOLARIS */ 471 if (error) 472 fr_authstats.fas_sendfail++; 473 else 474 fr_authstats.fas_sendok++; 475 } else if (m) { 476# if SOLARIS 477 error = (fr_qin(fra->fra_q, m) == 0) ? EINVAL : 0; 478# else /* SOLARIS */ 479 if (! IF_HANDOFF(&ipintrq, m, NULL)) 480 error = ENOBUFS; 481 else 482 schednetisr(NETISR_IP); 483# endif /* SOLARIS */ 484 if (error) 485 fr_authstats.fas_quefail++; 486 else 487 fr_authstats.fas_queok++; 488 } else 489 error = EINVAL; 490# if SOLARIS 491 if (error) 492 error = EINVAL; 493# else 494 /* 495 * If we experience an error which will result in the packet 496 * not being processed, make sure we advance to the next one. 497 */ 498 if (error == ENOBUFS) { 499 fr_authused--; 500 fra->fra_index = -1; 501 fra->fra_pass = 0; 502 if (i == fr_authstart) { 503 while (fra->fra_index == -1) { 504 i++; 505 if (i == FR_NUMAUTH) 506 i = 0; 507 fr_authstart = i; 508 if (i == fr_authend) 509 break; 510 } 511 if (fr_authstart == fr_authend) { 512 fr_authnext = 0; 513 fr_authstart = fr_authend = 0; 514 } 515 } 516 } 517# endif 518#endif /* _KERNEL */ 519 SPL_X(s); 520 break; 521 default : 522 error = EINVAL; 523 break; 524 } 525 return error; 526} 527 528 529/* 530 * Free all network buffer memory used to keep saved packets. 531 */ 532void fr_authunload() 533{ 534 register int i; 535 register frauthent_t *fae, **faep; 536 frentry_t *fr, **frp; 537 mb_t *m; 538 539 WRITE_ENTER(&ipf_auth); 540 for (i = 0; i < FR_NUMAUTH; i++) { 541 if ((m = fr_authpkts[i])) { 542 FREE_MB_T(m); 543 fr_authpkts[i] = NULL; 544 fr_auth[i].fra_index = -1; 545 } 546 } 547 548 549 for (faep = &fae_list; (fae = *faep); ) { 550 *faep = fae->fae_next; 551 KFREE(fae); 552 } 553 ipauth = NULL; 554 RWLOCK_EXIT(&ipf_auth); 555 556 if (fr_authlist) { 557 /* 558 * We *MuST* reget ipf_auth because otherwise we won't get the 559 * locks in the right order and risk deadlock. 560 * We need ipf_mutex here to prevent a rule from using it 561 * inside fr_check(). 562 */ 563 WRITE_ENTER(&ipf_mutex); 564 WRITE_ENTER(&ipf_auth); 565 for (frp = &fr_authlist; (fr = *frp); ) { 566 if (fr->fr_ref == 1) { 567 *frp = fr->fr_next; 568 KFREE(fr); 569 } else 570 frp = &fr->fr_next; 571 } 572 RWLOCK_EXIT(&ipf_auth); 573 RWLOCK_EXIT(&ipf_mutex); 574 } 575} 576 577 578/* 579 * Slowly expire held auth records. Timeouts are set 580 * in expectation of this being called twice per second. 581 */ 582void fr_authexpire() 583{ 584 register int i; 585 register frauth_t *fra; 586 register frauthent_t *fae, **faep; 587 register frentry_t *fr, **frp; 588 mb_t *m; 589#if !SOLARIS && defined(_KERNEL) 590 int s; 591#endif 592 593 if (fr_auth_lock) 594 return; 595 596 SPL_NET(s); 597 WRITE_ENTER(&ipf_auth); 598 for (i = 0, fra = fr_auth; i < FR_NUMAUTH; i++, fra++) { 599 if ((!--fra->fra_age) && (m = fr_authpkts[i])) { 600 FREE_MB_T(m); 601 fr_authpkts[i] = NULL; 602 fr_auth[i].fra_index = -1; 603 fr_authstats.fas_expire++; 604 fr_authused--; 605 } 606 } 607 608 for (faep = &fae_list; (fae = *faep); ) { 609 if (!--fae->fae_age) { 610 *faep = fae->fae_next; 611 KFREE(fae); 612 fr_authstats.fas_expire++; 613 } else 614 faep = &fae->fae_next; 615 } 616 if (fae_list != NULL) 617 ipauth = &fae_list->fae_fr; 618 else 619 ipauth = NULL; 620 621 for (frp = &fr_authlist; (fr = *frp); ) { 622 if (fr->fr_ref == 1) { 623 *frp = fr->fr_next; 624 KFREE(fr); 625 } else 626 frp = &fr->fr_next; 627 } 628 RWLOCK_EXIT(&ipf_auth); 629 SPL_X(s); 630}
| 463 error = ip_output(m, NULL, &ro, IP_FORWARDING, NULL, 464 NULL); 465# else 466 error = ip_output(m, NULL, &ro, IP_FORWARDING, NULL); 467# endif 468 if (ro.ro_rt) { 469 RTFREE(ro.ro_rt); 470 } 471# endif /* SOLARIS */ 472 if (error) 473 fr_authstats.fas_sendfail++; 474 else 475 fr_authstats.fas_sendok++; 476 } else if (m) { 477# if SOLARIS 478 error = (fr_qin(fra->fra_q, m) == 0) ? EINVAL : 0; 479# else /* SOLARIS */ 480 if (! IF_HANDOFF(&ipintrq, m, NULL)) 481 error = ENOBUFS; 482 else 483 schednetisr(NETISR_IP); 484# endif /* SOLARIS */ 485 if (error) 486 fr_authstats.fas_quefail++; 487 else 488 fr_authstats.fas_queok++; 489 } else 490 error = EINVAL; 491# if SOLARIS 492 if (error) 493 error = EINVAL; 494# else 495 /* 496 * If we experience an error which will result in the packet 497 * not being processed, make sure we advance to the next one. 498 */ 499 if (error == ENOBUFS) { 500 fr_authused--; 501 fra->fra_index = -1; 502 fra->fra_pass = 0; 503 if (i == fr_authstart) { 504 while (fra->fra_index == -1) { 505 i++; 506 if (i == FR_NUMAUTH) 507 i = 0; 508 fr_authstart = i; 509 if (i == fr_authend) 510 break; 511 } 512 if (fr_authstart == fr_authend) { 513 fr_authnext = 0; 514 fr_authstart = fr_authend = 0; 515 } 516 } 517 } 518# endif 519#endif /* _KERNEL */ 520 SPL_X(s); 521 break; 522 default : 523 error = EINVAL; 524 break; 525 } 526 return error; 527} 528 529 530/* 531 * Free all network buffer memory used to keep saved packets. 532 */ 533void fr_authunload() 534{ 535 register int i; 536 register frauthent_t *fae, **faep; 537 frentry_t *fr, **frp; 538 mb_t *m; 539 540 WRITE_ENTER(&ipf_auth); 541 for (i = 0; i < FR_NUMAUTH; i++) { 542 if ((m = fr_authpkts[i])) { 543 FREE_MB_T(m); 544 fr_authpkts[i] = NULL; 545 fr_auth[i].fra_index = -1; 546 } 547 } 548 549 550 for (faep = &fae_list; (fae = *faep); ) { 551 *faep = fae->fae_next; 552 KFREE(fae); 553 } 554 ipauth = NULL; 555 RWLOCK_EXIT(&ipf_auth); 556 557 if (fr_authlist) { 558 /* 559 * We *MuST* reget ipf_auth because otherwise we won't get the 560 * locks in the right order and risk deadlock. 561 * We need ipf_mutex here to prevent a rule from using it 562 * inside fr_check(). 563 */ 564 WRITE_ENTER(&ipf_mutex); 565 WRITE_ENTER(&ipf_auth); 566 for (frp = &fr_authlist; (fr = *frp); ) { 567 if (fr->fr_ref == 1) { 568 *frp = fr->fr_next; 569 KFREE(fr); 570 } else 571 frp = &fr->fr_next; 572 } 573 RWLOCK_EXIT(&ipf_auth); 574 RWLOCK_EXIT(&ipf_mutex); 575 } 576} 577 578 579/* 580 * Slowly expire held auth records. Timeouts are set 581 * in expectation of this being called twice per second. 582 */ 583void fr_authexpire() 584{ 585 register int i; 586 register frauth_t *fra; 587 register frauthent_t *fae, **faep; 588 register frentry_t *fr, **frp; 589 mb_t *m; 590#if !SOLARIS && defined(_KERNEL) 591 int s; 592#endif 593 594 if (fr_auth_lock) 595 return; 596 597 SPL_NET(s); 598 WRITE_ENTER(&ipf_auth); 599 for (i = 0, fra = fr_auth; i < FR_NUMAUTH; i++, fra++) { 600 if ((!--fra->fra_age) && (m = fr_authpkts[i])) { 601 FREE_MB_T(m); 602 fr_authpkts[i] = NULL; 603 fr_auth[i].fra_index = -1; 604 fr_authstats.fas_expire++; 605 fr_authused--; 606 } 607 } 608 609 for (faep = &fae_list; (fae = *faep); ) { 610 if (!--fae->fae_age) { 611 *faep = fae->fae_next; 612 KFREE(fae); 613 fr_authstats.fas_expire++; 614 } else 615 faep = &fae->fae_next; 616 } 617 if (fae_list != NULL) 618 ipauth = &fae_list->fae_fr; 619 else 620 ipauth = NULL; 621 622 for (frp = &fr_authlist; (fr = *frp); ) { 623 if (fr->fr_ref == 1) { 624 *frp = fr->fr_next; 625 KFREE(fr); 626 } else 627 frp = &fr->fr_next; 628 } 629 RWLOCK_EXIT(&ipf_auth); 630 SPL_X(s); 631}
|