/*
* Copyright (C) 1998-2003 by Darren Reed & Guido van Rooij.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#endif
#if !defined(_KERNEL)
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# define _KERNEL
# ifdef __OpenBSD__
struct file;
# endif
#endif
#else
#endif
#if !defined(linux)
#endif
#if defined(_KERNEL)
# endif
#endif
# include <sys/byteorder.h>
# ifdef _KERNEL
# include <sys/dditypes.h>
# endif
#endif
#endif
#endif
#endif
#ifdef sun
#endif
#include <netinet/in_systm.h>
# define KERNEL
# define _KERNEL
# define NOT_KERNEL
#endif
#if !defined(linux)
#endif
#ifdef NOT_KERNEL
#endif
#else
# if __FreeBSD_version >= 300000
# if __FreeBSD_version >= 500042
# endif /* __FreeBSD_version >= 500042 */
# endif
# endif
#endif
#include "netinet/ip_compat.h"
#include "netinet/ipf_stack.h"
# ifdef __FreeBSD__
# endif
#endif
#if (__FreeBSD_version >= 300000)
# if defined(_KERNEL) && !defined(IPFILTER_LKM)
# endif
#endif
/* END OF INCLUDES */
#if !defined(lint)
#endif
{
else
return -1;
else
return -2;
#endif
#endif
return 0;
}
/*
* Check if a packet has authorization. If the packet is found to match an
* authorization result and that would result in a feedback loop (i.e. it
* will end up returning FR_AUTH) then return FR_BLOCK instead.
*/
{
int i;
return NULL;
/*
* index becomes -2 only after an SIOCAUTHW. Check this in
* case the same packet gets sent again and it hasn't yet been
* auth'd.
*/
/*
* Avoid feedback loop.
*/
/*
* Create a dummy rule for the stateful checking to
* use and return. Zero out any values we don't
* trust from userland!
*/
if (fr) {
}
} else
}
ifs->ifs_fr_authused--;
if (i == ifs->ifs_fr_authstart) {
i++;
fra++;
if (i == ifs->ifs_fr_authsize) {
i = 0;
}
ifs->ifs_fr_authstart = i;
if (i == ifs->ifs_fr_authend)
break;
}
ifs->ifs_fr_authnext = 0;
ifs->ifs_fr_authstart = 0;
ifs->ifs_fr_authend = 0;
}
}
return fr;
}
i++;
if (i == ifs->ifs_fr_authsize)
i = 0;
}
return NULL;
}
/*
* Check if we have room in the auth array to hold details for another packet.
* If we do, store it and wake up any user programs which are waiting to
* hear about these events.
*/
mb_t *m;
{
#endif
#endif
int i;
if (ifs->ifs_fr_auth_lock)
return 0;
return 0;
} else {
return 0;
}
}
ifs->ifs_fr_authused++;
i = ifs->ifs_fr_authend++;
ifs->ifs_fr_authend = 0;
/*
* No need to copyback here as we want to undo the changes, not keep
* them.
*/
# endif
{
}
#endif
#else
}
# endif
ifs->ifs_fr_authpkts[i] = m;
#endif
return 1;
}
void *ctx;
{
mb_t *m;
SPL_INT(s);
#endif
char *t;
int ret;
switch (cmd)
{
case SIOCGENITER :
{
if (error != 0)
break;
else
break;
}
case SIOCSTLCK :
break;
}
break;
case SIOCATHST:
break;
case SIOCIPFFL:
SPL_NET(s);
i = fr_authflush(ifs);
SPL_X(s);
break;
case SIOCAUTHW:
/*
* Copy packet contents out to user space if
* requested. Bail on an error.
*/
t, i);
len -= i;
t += i;
if (error != 0)
break;
}
}
if (error != 0)
break;
SPL_NET(s);
ifs->ifs_fr_authnext++;
ifs->ifs_fr_authnext = 0;
SPL_X(s);
return 0;
}
/*
* We exit ipf_global here because a program that enters in
* here will have a lock on it and goto sleep having this lock.
* If someone were to do an 'ipf -D' the system would then
* deadlock. The catch with releasing it here is that the
* caller of this function expects it to be held when we
* return so we have to reacquire it in here.
*/
#ifdef _KERNEL
# if SOLARIS
error = 0;
# else /* SOLARIS */
# ifdef __hpux
{
lock_t *l;
spinunlock(l);
}
# else
# ifdef __osf__
"fr_authnext", 0,
# else
# endif /* __osf__ */
# endif /* __hpux */
# endif /* SOLARIS */
#endif
if (error == 0) {
goto fr_authioctlloop;
}
break;
case SIOCAUTHR:
if (error != 0)
return error;
SPL_NET(s);
if ((i < 0) || (i >= ifs->ifs_fr_authsize) ||
SPL_X(s);
return ESRCH;
}
m = ifs->ifs_fr_authpkts[i];
#ifdef _KERNEL
} else {
return (-1);
}
/*
* We're putting the packet back on the same interface
* queue that it was originally seen on so that it can
* progress through the system properly, with the result
* of the auth check done.
*/
# ifdef MENTAT
if (ret < 0)
else
# else /* MENTAT */
# else
NULL);
# else
# endif
if (error != 0)
else
# endif /* Linux */
# endif /* MENTAT */
} else if (m) {
# ifdef MENTAT
# else /* MENTAT */
# else
# if (__FreeBSD_version >= 501000)
netisr_dispatch(NETISR_IP, m);
# else
# if (IRIX >= 60516)
# else
# endif
FREE_MB_T(m);
} else {
IF_ENQUEUE(ifq, m);
# if IRIX < 60500
# endif
}
# endif
# endif /* Linux */
# endif /* MENTAT */
if (error != 0)
else
} else
# ifdef MENTAT
if (error != 0)
# else /* MENTAT */
/*
* If we experience an error which will result in the packet
* not being processed, make sure we advance to the next one.
*/
ifs->ifs_fr_authused--;
if (i == ifs->ifs_fr_authstart) {
i++;
if (i == ifs->ifs_fr_authsize)
i = 0;
ifs->ifs_fr_authstart = i;
if (i == ifs->ifs_fr_authend)
break;
}
ifs->ifs_fr_authnext = 0;
ifs->ifs_fr_authstart = 0;
ifs->ifs_fr_authend = 0;
}
}
}
# endif /* MENTAT */
#endif /* _KERNEL */
SPL_X(s);
break;
default :
break;
}
return error;
}
/*
* Free all network buffer memory used to keep saved packets.
*/
{
register int i;
mb_t *m;
}
for (i = 0; i < ifs->ifs_fr_authsize; i++) {
m = ifs->ifs_fr_authpkts[i];
if (m != NULL) {
FREE_MB_T(m);
}
}
}
}
} else
}
}
# endif
ifs->ifs_fr_auth_init = 0;
}
}
/*
* Slowly expire held auth records. Timeouts are set
* in expectation of this being called twice per second.
*/
{
register int i;
mb_t *m;
SPL_INT(s);
if (ifs->ifs_fr_auth_lock)
return;
SPL_NET(s);
FREE_MB_T(m);
ifs->ifs_fr_authused--;
}
}
} else
}
else
} else
}
SPL_X(s);
}
{
int error = 0;
SPL_INT(s);
return EIO;
break;
else
}
else {
SPL_NET(s);
SPL_X(s);
}
sizeof(*fr));
SPL_NET(s);
SPL_X(s);
} else
} else
return error;
}
/*
* Flush held packets.
* Must already be properly SPL'ed and Locked on &ipf_auth.
*
*/
{
register int i, num_flushed;
mb_t *m;
if (ifs->ifs_fr_auth_lock)
return -1;
num_flushed = 0;
for (i = 0 ; i < ifs->ifs_fr_authsize; i++) {
m = ifs->ifs_fr_authpkts[i];
if (m != NULL) {
FREE_MB_T(m);
/* perhaps add & use a flush counter inst.*/
ifs->ifs_fr_authused--;
num_flushed++;
}
}
ifs->ifs_fr_authstart = 0;
ifs->ifs_fr_authend = 0;
ifs->ifs_fr_authnext = 0;
return num_flushed;
}
/* ------------------------------------------------------------------------ */
/* Function: fr_authgeniter */
/* Returns: int - 0 == success, else error */
/* Parameters: token(I) - pointer to ipftoken structure */
/* itp(I) - pointer to ipfgeniter structure */
/* */
/* ------------------------------------------------------------------------ */
{
int error;
return EFAULT;
return EINVAL;
/*
* Retrieve "previous" entry from token and find the next entry.
*/
} else {
}
/*
* If we found an entry, add reference to it and update token.
* Otherwise, zero out data to be returned and NULL out token.
*/
} else {
}
/*
* Safe to release the lock now that we have a reference.
*/
/*
* Copy out the data and clean up references and token as needed.
*/
if (error != 0)
} else {
fr_authderef(&fae);
}
}
return error;
}
frauthent_t **faep;
{
}
}