⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 engine.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	size_t i;
	char *s, family;
	u_short port = 0;
	_SOCK_ADDR sockaddr;
	sfsistat (*fi_connect) __P((SMFICTX *, char *, _SOCK_ADDR *));

	if (g == NULL)
		return _SMFIS_ABORT;
	mi_clr_macros(g->a_ctx, g->a_idx + 1);
	if (g->a_ctx->ctx_smfi == NULL ||
	    (fi_connect = g->a_ctx->ctx_smfi->xxfi_connect) == NULL)
		return SMFIS_CONTINUE;

	s = g->a_buf;
	i = 0;
	l = g->a_len;
	while (s[i] != '\0' && i <= l)
		++i;
	if (i >= l)
		return _SMFIS_ABORT;

	/* Move past trailing \0 in host string */
	i++;
	family = s[i++];
	memset(&sockaddr, '\0', sizeof sockaddr);
	if (family != SMFIA_UNKNOWN)
	{
		(void) memcpy((void *) &port, (void *) (s + i),
			      sizeof port);
		port = ntohs(port);
		if ((i += sizeof port) >= l)
		{
			smi_log(SMI_LOG_ERR,
				"%s: connect[%d]: wrong len %d >= %d",
				g->a_ctx->ctx_smfi->xxfi_name,
				(int) g->a_ctx->ctx_id, i, l);
			return _SMFIS_ABORT;
		}
# if NETINET
		if (family == SMFIA_INET)
		{
			if (inet_aton(s + i, (struct in_addr *) &sockaddr.sin.sin_addr)
			    == INADDR_NONE)
			{
				smi_log(SMI_LOG_ERR,
					"%s: connect[%d]: inet_aton failed",
					g->a_ctx->ctx_smfi->xxfi_name,
					(int) g->a_ctx->ctx_id);
				return _SMFIS_ABORT;
			}
			sockaddr.sa.sa_family = AF_INET;
			if (port > 0)
				sockaddr.sin.sin_port = port;
		}
		else
# endif /* NETINET */
# if NETINET6
		if (family == SMFIA_INET6)
		{
			if (inet_pton(AF_INET6, s + i,
				      &sockaddr.sin6.sin6_addr) != 1)
			{
				smi_log(SMI_LOG_ERR,
					"%s: connect[%d]: inet_pton failed",
					g->a_ctx->ctx_smfi->xxfi_name,
					(int) g->a_ctx->ctx_id);
				return _SMFIS_ABORT;
			}
			sockaddr.sa.sa_family = AF_INET6;
			if (port > 0)
				sockaddr.sin6.sin6_port = port;
		}
		else
# endif /* NETINET6 */
# if NETUNIX
		if (family == SMFIA_UNIX)
		{
			if (strlcpy(sockaddr.sunix.sun_path, s + i,
			    sizeof sockaddr.sunix.sun_path) >=
			    sizeof sockaddr.sunix.sun_path)
			{
				smi_log(SMI_LOG_ERR,
					"%s: connect[%d]: path too long",
					g->a_ctx->ctx_smfi->xxfi_name,
					(int) g->a_ctx->ctx_id);
				return _SMFIS_ABORT;
			}
			sockaddr.sunix.sun_family = AF_UNIX;
		}
		else
# endif /* NETUNIX */
		{
			smi_log(SMI_LOG_ERR,
				"%s: connect[%d]: unknown family %d",
				g->a_ctx->ctx_smfi->xxfi_name,
				(int) g->a_ctx->ctx_id, family);
			return _SMFIS_ABORT;
		}
	}
	return (*fi_connect)(g->a_ctx, g->a_buf,
			     family != SMFIA_UNKNOWN ? &sockaddr : NULL);
}
/*
**  ST_EOH -- end of headers
**
**	Parameters:
**		g -- generic argument structure
**
**	Returns:
**		continue or filter-specified value
*/

static int
st_eoh(g)
	genarg *g;
{
	sfsistat (*fi_eoh) __P((SMFICTX *));

	if (g == NULL)
		return _SMFIS_ABORT;
	if (g->a_ctx->ctx_smfi != NULL &&
	    (fi_eoh = g->a_ctx->ctx_smfi->xxfi_eoh) != NULL)
		return (*fi_eoh)(g->a_ctx);
	return SMFIS_CONTINUE;
}
/*
**  ST_HELO -- helo/ehlo command
**
**	Parameters:
**		g -- generic argument structure
**
**	Returns:
**		continue or filter-specified value
*/
static int
st_helo(g)
	genarg *g;
{
	sfsistat (*fi_helo) __P((SMFICTX *, char *));

	if (g == NULL)
		return _SMFIS_ABORT;
	mi_clr_macros(g->a_ctx, g->a_idx + 1);
	if (g->a_ctx->ctx_smfi != NULL &&
	    (fi_helo = g->a_ctx->ctx_smfi->xxfi_helo) != NULL)
		return (*fi_helo)(g->a_ctx, g->a_buf);
	return SMFIS_CONTINUE;
}
/*
**  ST_HEADER -- header line
**
**	Parameters:
**		g -- generic argument structure
**
**	Returns:
**		continue or filter-specified value
*/

static int
st_header(g)
	genarg *g;
{
	char *hf, *hv;
	sfsistat (*fi_header) __P((SMFICTX *, char *, char *));

	if (g == NULL)
		return _SMFIS_ABORT;
	if (g->a_ctx->ctx_smfi == NULL ||
	    (fi_header = g->a_ctx->ctx_smfi->xxfi_header) == NULL)
		return SMFIS_CONTINUE;
	if (dec_arg2(g->a_buf, g->a_len, &hf, &hv) == MI_SUCCESS)
		return (*fi_header)(g->a_ctx, hf, hv);
	else
		return _SMFIS_ABORT;
}

#define ARGV_FCT(lf, rf, idx) \
	char **argv;	\
	sfsistat (*lf) __P((SMFICTX *, char **));	\
	int r;	\
	\
	if (g == NULL)	\
		return _SMFIS_ABORT;	\
	mi_clr_macros(g->a_ctx, g->a_idx + 1);	\
	if (g->a_ctx->ctx_smfi == NULL ||	\
	    (lf = g->a_ctx->ctx_smfi->rf) == NULL)	\
		return SMFIS_CONTINUE;	\
	if ((argv = dec_argv(g->a_buf, g->a_len)) == NULL)	\
		return _SMFIS_ABORT;	\
	r = (*lf)(g->a_ctx, argv);	\
	free(argv);	\
	return r;

/*
**  ST_SENDER -- MAIL FROM command
**
**	Parameters:
**		g -- generic argument structure
**
**	Returns:
**		continue or filter-specified value
*/

static int
st_sender(g)
	genarg *g;
{
	ARGV_FCT(fi_envfrom, xxfi_envfrom, CI_MAIL)
}
/*
**  ST_RCPT -- RCPT TO command
**
**	Parameters:
**		g -- generic argument structure
**
**	Returns:
**		continue or filter-specified value
*/

static int
st_rcpt(g)
	genarg *g;
{
	ARGV_FCT(fi_envrcpt, xxfi_envrcpt, CI_RCPT)
}
/*
**  ST_MACROS -- deal with macros received from the MTA
**
**	Parameters:
**		g -- generic argument structure
**
**	Returns:
**		continue/keep
**
**	Side effects:
**		set pointer in macro array to current values.
*/

static int
st_macros(g)
	genarg *g;
{
	int i;
	char **argv;

	if (g == NULL || g->a_len < 1)
		return _SMFIS_FAIL;
	if ((argv = dec_argv(g->a_buf + 1, g->a_len - 1)) == NULL)
		return _SMFIS_FAIL;
	switch(g->a_buf[0])
	{
	  case SMFIC_CONNECT:
		i = CI_CONN;
		break;
	  case SMFIC_HELO:
		i = CI_HELO;
		break;
	  case SMFIC_MAIL:
		i = CI_MAIL;
		break;
	  case SMFIC_RCPT:
		i = CI_RCPT;
		break;
	  default:
		free(argv);
		return _SMFIS_FAIL;
	}
	if (g->a_ctx->ctx_mac_ptr[i] != NULL)
		free(g->a_ctx->ctx_mac_ptr[i]);
	if (g->a_ctx->ctx_mac_buf[i] != NULL)
		free(g->a_ctx->ctx_mac_buf[i]);
	g->a_ctx->ctx_mac_ptr[i] = argv;
	g->a_ctx->ctx_mac_buf[i] = g->a_buf;
	return _SMFIS_KEEP;
}
/*
**  ST_QUIT -- quit command
**
**	Parameters:
**		g -- generic argument structure
**
**	Returns:
**		noreply
*/

static int
st_quit(g)
	genarg *g;
{
	return _SMFIS_NOREPLY;
}
/*
**  ST_BODYCHUNK -- deal with a piece of the mail body
**
**	Parameters:
**		g -- generic argument structure
**
**	Returns:
**		continue or filter-specified value
*/

static int
st_bodychunk(g)
	genarg *g;
{
	sfsistat (*fi_body) __P((SMFICTX *, u_char *, size_t));

	if (g == NULL)
		return _SMFIS_ABORT;
	if (g->a_ctx->ctx_smfi != NULL &&
	    (fi_body = g->a_ctx->ctx_smfi->xxfi_body) != NULL)
		return (*fi_body)(g->a_ctx, (u_char *)g->a_buf, g->a_len);
	return SMFIS_CONTINUE;
}
/*
**  ST_BODYEND -- deal with the last piece of the mail body
**
**	Parameters:
**		g -- generic argument structure
**
**	Returns:
**		continue or filter-specified value
**
**	Side effects:
**		sends a reply for the body part (if non-empty).
*/

static int
st_bodyend(g)
	genarg *g;
{
	sfsistat r;
	sfsistat (*fi_body) __P((SMFICTX *, u_char *, size_t));
	sfsistat (*fi_eom) __P((SMFICTX *));

	if (g == NULL)
		return _SMFIS_ABORT;
	r = SMFIS_CONTINUE;
	if (g->a_ctx->ctx_smfi != NULL)
	{
		if ((fi_body = g->a_ctx->ctx_smfi->xxfi_body) != NULL &&
		    g->a_len > 0)
		{
			socket_t sd;
			struct timeval timeout;

			timeout.tv_sec = g->a_ctx->ctx_timeout;
			timeout.tv_usec = 0;
			sd = g->a_ctx->ctx_sd;
			r = (*fi_body)(g->a_ctx, (u_char *)g->a_buf, g->a_len);
			if (r != SMFIS_CONTINUE &&
			    sendreply(r, sd, &timeout, g->a_ctx) != MI_SUCCESS)
				return _SMFIS_ABORT;
		}
	}
	if (r == SMFIS_CONTINUE &&
	    (fi_eom = g->a_ctx->ctx_smfi->xxfi_eom) != NULL)
		return (*fi_eom)(g->a_ctx);
	return r;
}
/*
**  ST_ABORTFCT -- deal with aborts
**
**	Parameters:
**		g -- generic argument structure
**
**	Returns:
**		abort or filter-specified value
*/

static int
st_abortfct(g)
	genarg *g;
{
	sfsistat (*fi_abort) __P((SMFICTX *));

	if (g == NULL)
		return _SMFIS_ABORT;
	if (g != NULL && g->a_ctx->ctx_smfi != NULL &&
	    (fi_abort = g->a_ctx->ctx_smfi->xxfi_abort) != NULL)
		(void) (*fi_abort)(g->a_ctx);
	return _SMFIS_NOREPLY;
}
/*
**  TRANS_OK -- is the state transition ok?
**
**	Parameters:
**		old -- old state
**		new -- new state
**
**	Returns:
**		state transition ok
*/

static bool
trans_ok(old, new)
	int old, new;
{
	int s, n;

	s = old;
	do
	{
		/* is this state transition allowed? */
		if ((MASK(new) & next_states[s]) != 0)
			return TRUE;

		/*
		**  no: try next state;
		**  this works since the relevant states are ordered
		**  strict sequentially
		*/
		n = s + 1;

		/*
		**  can we actually "skip" this state?
		**  see fix_stm() which sets this bit for those
		**  states which the filter program is not interested in
		*/
		if (bitset(NX_SKIP, next_states[n]))
			s = n;
		else
			return FALSE;
	} while (s <= ST_LAST);
	return FALSE;
}
/*
**  FIX_STM -- add "skip" bits to the state transition table
**
**	Parameters:
**		ctx -- context structure
**
**	Returns:
**		None.
**
**	Side effects:
**		may change state transition table.
*/

static void
fix_stm(ctx)
	SMFICTX_PTR ctx;
{
	u_long fl;

	if (ctx == NULL || ctx->ctx_smfi == NULL)
		return;
	fl = ctx->ctx_pflags;
	if (bitset(SMFIP_NOCONNECT, fl))
		next_states[ST_CONN] |= NX_SKIP;
	if (bitset(SMFIP_NOHELO, fl))
		next_states[ST_HELO] |= NX_SKIP;
	if (bitset(SMFIP_NOMAIL, fl))
		next_states[ST_MAIL] |= NX_SKIP;
	if (bitset(SMFIP_NORCPT, fl))
		next_states[ST_RCPT] |= NX_SKIP;
	if (bitset(SMFIP_NOHDRS, fl))
		next_states[ST_HDRS] |= NX_SKIP;
	if (bitset(SMFIP_NOEOH, fl))
		next_states[ST_EOHS] |= NX_SKIP;
	if (bitset(SMFIP_NOBODY, fl))
		next_states[ST_BODY] |= NX_SKIP;
}
/*
**  DEC_ARGV -- split a buffer into a list of strings, NULL terminated
**
**	Parameters:
**		buf -- buffer with several strings
**		len -- length of buffer
**
**	Returns:
**		array of pointers to the individual strings
*/

static char **
dec_argv(buf, len)
	char *buf;
	size_t len;
{
	char **s;
	size_t i;
	int elem, nelem;

	nelem = 0;
	for (i = 0; i < len; i++)
	{
		if (buf[i] == '\0')
			++nelem;
	}
	if (nelem == 0)
		return NULL;

	/* last entry is only for the name */
	s = (char **)malloc((nelem + 1) * (sizeof *s));
	if (s == NULL)
		return NULL;
	s[0] = buf;
	for (i = 0, elem = 0; i < len && elem < nelem; i++)
	{
		if (buf[i] == '\0')
			s[++elem] = &(buf[i + 1]);
	}

	/* overwrite last entry */
	s[elem] = NULL;
	return s;
}
/*
**  DEC_ARG2 -- split a buffer into two strings
**
**	Parameters:
**		buf -- buffer with two strings
**		len -- length of buffer
**		s1,s2 -- pointer to result strings
**
**	Returns:
**		MI_FAILURE/MI_SUCCESS
*/

static int
dec_arg2(buf, len, s1, s2)
	char *buf;
	size_t len;
	char **s1;
	char **s2;
{
	size_t i;

	*s1 = buf;
	for (i = 1; i < len && buf[i] != '\0'; i++)
		continue;
	if (i >= len - 1)
		return MI_FAILURE;
	*s2 = buf + i + 1;
	return MI_SUCCESS;
}
/*
**  SENDOK -- is it ok for the filter to send stuff to the MTA?
**
**	Parameters:
**		ctx -- context structure
**		flag -- flag to check
**
**	Returns:
**		sending allowed (in current state)
*/

bool
mi_sendok(ctx, flag)
	SMFICTX_PTR ctx;
	int flag;
{
	if (ctx == NULL || ctx->ctx_smfi == NULL)
		return FALSE;
	if (flag != 0 && !bitset(flag, ctx->ctx_smfi->xxfi_flags))
		return FALSE;
	return ctx->ctx_state == ST_ENDM;
}
#endif /* _FFR_MILTER */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -