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

📄 milter.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 5 页
字号:
				h->h_value == NULL ? "<NULL>" : h->h_value,
				val);
		}
	}

	if (h->h_value != NULL)
	{
		e->e_msgsize -= strlen(h->h_value);
		free(h->h_value);
	}

	if (*val == '\0')
	{
		/* Remove "Field: " from message size */
		e->e_msgsize -= strlen(h->h_field) + 2;
		h->h_value = NULL;
	}
	else
	{
		h->h_value = newstr(val);
		e->e_msgsize += strlen(h->h_value);
	}
}
/*
**  MILTER_ADDRCPT -- Add the supplied recipient to the message
**
**	Parameters:
**		response -- encoded form of recipient address.
**		rlen -- length of response.
**		e -- current envelope.
**
**	Returns:
**		none
*/

static void
milter_addrcpt(response, rlen, e)
	char *response;
	ssize_t rlen;
	ENVELOPE *e;
{
	if (tTd(64, 10))
		dprintf("milter_addrcpt: ");

	/* sanity checks */
	if (response == NULL)
	{
		if (tTd(64, 10))
			dprintf("NULL response\n");
		return;
	}

	if (*response == '\0' ||
	    strlen(response) + 1 != (size_t) rlen)
	{
		if (tTd(64, 10))
			dprintf("didn't follow protocol (total len %d != rlen %d)\n",
				strlen(response), rlen -1);
		return;
	}

	if (tTd(64, 10))
		dprintf("%s\n", response);
	(void) sendtolist(response, NULLADDR, &e->e_sendqueue, 0, e);
	return;
}
/*
**  MILTER_DELRCPT -- Delete the supplied recipient from the message
**
**	Parameters:
**		response -- encoded form of recipient address.
**		rlen -- length of response.
**		e -- current envelope.
**
**	Returns:
**		none
*/

static void
milter_delrcpt(response, rlen, e)
	char *response;
	ssize_t rlen;
	ENVELOPE *e;
{
	if (tTd(64, 10))
		dprintf("milter_delrcpt: ");

	/* sanity checks */
	if (response == NULL)
	{
		if (tTd(64, 10))
			dprintf("NULL response\n");
		return;
	}

	if (*response == '\0' ||
	    strlen(response) + 1 != (size_t) rlen)
	{
		if (tTd(64, 10))
			dprintf("didn't follow protocol (total len)\n");
		return;
	}

	if (tTd(64, 10))
		dprintf("%s\n", response);
	(void) removefromlist(response, &e->e_sendqueue, e);
	return;
}
/*
**  MILTER_REPLBODY -- Replace the current df file with new body
**
**	Parameters:
**		response -- encoded form of new body.
**		rlen -- length of response.
**		newfilter -- if first time called by a new filter
**		e -- current envelope.
**
**	Returns:
**		0 upon success, -1 upon failure
*/

static int
milter_replbody(response, rlen, newfilter, e)
	char *response;
	ssize_t rlen;
	bool newfilter;
	ENVELOPE *e;
{
	static char prevchar;
	int i;

	if (tTd(64, 10))
		dprintf("milter_replbody\n");

	/* If a new filter, reset previous character and truncate df */
	if (newfilter)
	{
		off_t prevsize = 0;
		char dfname[MAXPATHLEN];

		(void) strlcpy(dfname, queuename(e, 'd'), sizeof dfname);

		/* Reset prevchar */
		prevchar = '\0';

		/* Get the current df information */
		if (bitset(EF_HAS_DF, e->e_flags) && e->e_dfp != NULL)
		{
			int afd;
			struct stat st;

			afd = fileno(e->e_dfp);
			if (afd > 0 && fstat(afd, &st) == 0)
				prevsize = st.st_size;
		}

		/* truncate current df file */
		if (bftruncate(e->e_dfp) < 0)
		{
			MILTER_DF_ERROR("milter_reopen_df: bftruncate %s: %s");
			return -1;
		}
		else
		{
			if (prevsize > e->e_msgsize)
				e->e_msgsize = 0;
			else
				e->e_msgsize -= prevsize;
		}
	}

	if (response == NULL)
	{
		/* Flush the buffered '\r' */
		if (prevchar == '\r')
		{
			(void) putc(prevchar, e->e_dfp);
			e->e_msgsize++;
		}
		return 0;
	}

	for (i = 0; i < rlen; i++)
	{
		/* Buffered char from last chunk */
		if (i == 0 && prevchar == '\r')
		{
			/* Not CRLF, output prevchar */
			if (response[i] != '\n')
			{
				(void) putc(prevchar, e->e_dfp);
				e->e_msgsize++;
			}
			prevchar = '\0';
		}

		/* Turn CRLF into LF */
		if (response[i] == '\r')
		{
			/* check if at end of chunk */
			if (i + 1 < rlen)
			{
				/* If LF, strip CR */
				if (response[i + 1] == '\n')
					i++;
			}
			else
			{
				/* check next chunk */
				prevchar = '\r';
				continue;
			}
		}
		(void) putc(response[i], e->e_dfp);
		e->e_msgsize++;
	}
	return 0;
}

/*
**  MTA callouts
*/

/*
**  MILTER_INIT -- open and negotiate with all of the filters
**
**	Parameters:
**		e -- current envelope.
**		state -- return state from response.
**
**	Returns:
**		none
*/

/* ARGSUSED */
void
milter_init(e, state)
	ENVELOPE *e;
	char *state;
{
	int i;

	if (tTd(64, 10))
		dprintf("milter_init\n");

	*state = SMFIR_CONTINUE;
	for (i = 0; InputFilters[i] != NULL; i++)
	{
		struct milter *m = InputFilters[i];

		m->mf_sock = milter_open(m, FALSE, e);
		if (m->mf_state == SMFS_ERROR)
		{
			MILTER_CHECK_ERROR(continue);
			break;
		}

		if (m->mf_sock < 0 ||
		    milter_negotiate(m, e) < 0 ||
		    m->mf_state == SMFS_ERROR)
		{
			if (tTd(64, 5))
				dprintf("milter_init(%s): failed to %s\n",
					m->mf_name,
					m->mf_sock < 0 ? "open" : "negotiate");

			/* if negotation failure, close socket */
			if (m->mf_sock >= 0)
			{
				(void) close(m->mf_sock);
				m->mf_sock = -1;
			}
			milter_error(m);
			if (m->mf_state == SMFS_ERROR)
			{
				MILTER_CHECK_ERROR(continue);
				break;
			}
		}
	}

	/*
	**  If something temp/perm failed with one of the filters,
	**  we won't be using any of them, so clear any existing
	**  connections.
	*/

	if (*state != SMFIR_CONTINUE)
		milter_quit(e);
}
/*
**  MILTER_CONNECT -- send connection info to milter filters
**
**	Parameters:
**		hostname -- hostname of remote machine.
**		addr -- address of remote machine.
**		e -- current envelope.
**		state -- return state from response.
**
**	Returns:
**		response string (may be NULL)
*/

char *
milter_connect(hostname, addr, e, state)
	char *hostname;
	SOCKADDR addr;
	ENVELOPE *e;
	char *state;
{
	char family;
	u_short port;
	char *buf, *bp;
	char *response;
	char *sockinfo = NULL;
	ssize_t s;
# if NETINET6
	char buf6[INET6_ADDRSTRLEN];
# endif /* NETINET6 */

	if (tTd(64, 10))
		dprintf("milter_connect(%s)\n", hostname);

	/* gather data */
	switch (addr.sa.sa_family)
	{
# if NETUNIX
	  case AF_UNIX:
		family = SMFIA_UNIX;
		port = htons(0);
		sockinfo = addr.sunix.sun_path;
		break;
# endif /* NETUNIX */

# if NETINET
	  case AF_INET:
		family = SMFIA_INET;
		port = htons(addr.sin.sin_port);
		sockinfo = (char *) inet_ntoa(addr.sin.sin_addr);
		break;
# endif /* NETINET */

# if NETINET6
	  case AF_INET6:
		family = SMFIA_INET6;
		port = htons(addr.sin6.sin6_port);
		sockinfo = anynet_ntop(&addr.sin6.sin6_addr, buf6,
				       sizeof buf6);
		if (sockinfo == NULL)
			sockinfo = "";
		break;
# endif /* NETINET6 */

	  default:
		family = SMFIA_UNKNOWN;
		break;
	}

	s = strlen(hostname) + 1 + sizeof(family);
	if (family != SMFIA_UNKNOWN)
		s += sizeof(port) + strlen(sockinfo) + 1;

	buf = (char *)xalloc(s);
	bp = buf;

	/* put together data */
	(void) memcpy(bp, hostname, strlen(hostname));
	bp += strlen(hostname);
	*bp++ = '\0';
	(void) memcpy(bp, &family, sizeof family);
	bp += sizeof family;
	if (family != SMFIA_UNKNOWN)
	{
		(void) memcpy(bp, &port, sizeof port);
		bp += sizeof port;

		/* include trailing '\0' */
		(void) memcpy(bp, sockinfo, strlen(sockinfo) + 1);
	}

	response = milter_command(SMFIC_CONNECT, buf, s,
				  MilterConnectMacros, e, state);
	free(buf);

	/*
	**  If this message connection is done for,
	**  close the filters.
	*/

	if (*state != SMFIR_CONTINUE)
		milter_quit(e);
	else
		milter_per_connection_check(e);

	/*
	**  SMFIR_REPLYCODE can't work with connect due to
	**  the requirements of SMTP.  Therefore, ignore the
	**  reply code text but keep the state it would reflect.
	*/

	if (*state == SMFIR_REPLYCODE)
	{
		if (response != NULL &&
		    *response == '4')
			*state = SMFIR_TEMPFAIL;
		else
			*state = SMFIR_REJECT;
		if (response != NULL)
		{
			free(response);
			response = NULL;
		}
	}
	return response;
}
/*
**  MILTER_HELO -- send SMTP HELO/EHLO command info to milter filters
**
**	Parameters:
**		helo -- argument to SMTP HELO/EHLO command.
**		e -- current envelope.
**		state -- return state from response.
**
**	Returns:
**		response string (may be NULL)
*/

char *
milter_helo(helo, e, state)
	char *helo;
	ENVELOPE *e;
	char *state;
{
	char *response;

	if (tTd(64, 10))
		dprintf("milter_helo(%s)\n", helo);

	response = milter_command(SMFIC_HELO, helo, strlen(helo) + 1,
				  MilterHeloMacros, e, state);
	milter_per_connection_check(e);
	return response;
}
/*
**  MILTER_ENVFROM -- send SMTP MAIL command info to milter filters
**
**	Parameters:
**		args -- SMTP MAIL command args (args[0] == sender).
**		e -- current envelope.
**		state -- return state from response.
**
**	Returns:
**		response string (may be NULL)
*/

char *
milter_envfrom(args, e, state)
	char **args;
	ENVELOPE *e;
	char *state;
{
	int i;
	char *buf, *bp;
	char *response;
	ssize_t s;

	if (tTd(64, 10))
	{
		dprintf("milter_envfrom:");
		for (i = 0; args[i] != NULL; i++)
			dprintf(" %s", args[i]);
		dprintf("\n");
	}

	/* sanity check */
	if (args[0] == NULL)
	{
		*state = SMFIR_REJECT;
		return NULL;
	}

	/* new message, so ... */
	for (i = 0; InputFilters[i] != NULL; i++)
	{
		struct milter *m = InputFilters[i];

		switch (m->mf_state)
		{
		  case SMFS_INMSG:
			/* abort in message filters */
			milter_abort_filter(m, e);
			/* FALLTHROUGH */

		  case SMFS_DONE:
			/* reset done filters */
			m->mf_state = SMFS_OPEN;
			break;
		}
	}

	/* put together data */
	s = 0;
	for (i = 0; args[i] != NULL; i++)
		s += strlen(args[i]) + 1;
	buf = (char *)xalloc(s);
	bp = buf;
	for (i = 0; args[i] != NULL; i++)
	{
		(void) strlcpy(bp, args[i], s - (bp - buf));
		bp += strlen(bp) + 1;
	}

	/* send it over */
	response = milter_command(SMFIC_MAIL, buf, s,
				  MilterEnvFromMacros, e, state);
	free(buf);

	/*
	**  If filter rejects/discards a per message command,
	**  abort the other filters since we are done with the
	**  current message.
	*/

	MILTER_CHECK_DONE_MSG();
	return response;
}
/*
**  MILTER_ENVRCPT -- send SMTP RCPT command info to milter filters
**
**	Parameters:
**		args -- SMTP MAIL command args (args[0] == recipient).
**		e -- current envelope.
**		state -- return state from response.
**
**	Returns:
**		response string (may be NULL)
*/

char *
milter_envrcpt(args, e, state)
	char **args;
	ENVELOPE *e;
	char *state;
{
	int i;
	char *buf, *bp;
	char *response;
	ssize_t s;

	if (tTd(64, 10))
	{
		dprintf("milter_envrcpt:");
		for (i = 0; args[i] != NULL; i++)
			dprintf(" %s", args[i]);
		dprintf("\n");
	}

	/* sanity check */
	if (args[0] == NULL)
	{
		*state = SMFIR_REJECT;
		return NULL;
	}

	/* put together data */
	s = 0;
	for (i = 0; args[i] != NULL; i++)
		s += strlen(args[i]) + 1;
	buf = (char *)xalloc(s);
	bp = buf;
	for (i = 0; args[i] != NULL; i++)
	{
		(void) strlcpy(bp, args[i], s - (bp - buf));
		bp += strlen(bp) + 1;
	}

	/* send it over */
	response = milter_command(SMFIC_RCPT, buf, s,
				  MilterEnvRcptMacros, e, state);
	free(buf);
	return response;
}
/*
**  MILTER_DATA -- send message headers/body and gather final message results
**
**	Parameters:
**		e -- current envelope.
**		state -- return state from response.
**
**	Returns:
**		response string (may be NULL)
**
**	Side effects:
**		- Uses e->e_dfp for access to the body
**		- Can call the various milter action routines to
**		  modify the envelope or message.
*/

# define MILTER_CHECK_RESULTS() \
	if (*state == SMFIR_ACCEPT || \
	    m->mf_state == SMFS_DONE || \
	    m->mf_state == SMFS_ERROR) \
	{ \
		if (m->mf_state != SMFS_ERROR) \
			m->mf_state = SMFS_DONE; \
		continue;	/

⌨️ 快捷键说明

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