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

📄 daemon.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 5 页
字号:
			{
				addr.sin6.sin6_family = AF_INET6;
				addr.sin6.sin6_addr = hid6.sin6_addr;
			}
			else
# endif /* NETINET6 */
			{
				/* try it as a host name (avoid MX lookup) */
				hp = sm_gethostbyname(&host[1], family);
				if (hp == NULL && p[-1] == '.')
				{
# if NAMED_BIND
					int oldopts = _res.options;

					_res.options &= ~(RES_DEFNAMES|RES_DNSRCH);
# endif /* NAMED_BIND */
					p[-1] = '\0';
					hp = sm_gethostbyname(&host[1],
							      family);
					p[-1] = '.';
# if NAMED_BIND
					_res.options = oldopts;
# endif /* NAMED_BIND */
				}
				*p = ']';
				goto gothostent;
			}
			*p = ']';
		}
		if (p == NULL)
		{
			extern char MsgBuf[];

			usrerrenh("5.1.2",
				  "553 Invalid numeric domain spec \"%s\"",
				  host);
			mci_setstat(mci, EX_NOHOST, "5.1.2", MsgBuf);
			errno = EINVAL;
			return EX_NOHOST;
		}
	}
	else
	{
		/* contortion to get around SGI cc complaints */
		{
			p = &host[strlen(host) - 1];
			hp = sm_gethostbyname(host, family);
			if (hp == NULL && *p == '.')
			{
# if NAMED_BIND
				int oldopts = _res.options;

				_res.options &= ~(RES_DEFNAMES|RES_DNSRCH);
# endif /* NAMED_BIND */
				*p = '\0';
				hp = sm_gethostbyname(host, family);
				*p = '.';
# if NAMED_BIND
				_res.options = oldopts;
# endif /* NAMED_BIND */
			}
		}
gothostent:
		if (hp == NULL)
		{
# if NAMED_BIND
			/* check for name server timeouts */
			if (errno == ETIMEDOUT || h_errno == TRY_AGAIN ||
			    (errno == ECONNREFUSED && UseNameServer))
			{
				save_errno = errno;
				mci_setstat(mci, EX_TEMPFAIL, "4.4.3", NULL);
				errno = save_errno;
				return EX_TEMPFAIL;
			}
# endif /* NAMED_BIND */
# if NETINET6
			/*
			**  Try v6 first, then fall back to v4.
			**  If we found a v6 address, but no v4
			**  addresses, then TEMPFAIL.
			*/

			if (family == AF_INET6)
			{
				family = AF_INET;
				goto v4retry;
			}
			if (v6found)
				goto v6tempfail;
# endif /* NETINET6 */
			save_errno = errno;
			mci_setstat(mci, EX_NOHOST, "5.1.2", NULL);
			errno = save_errno;
			return EX_NOHOST;
		}
		addr.sa.sa_family = hp->h_addrtype;
		switch (hp->h_addrtype)
		{
# if NETINET
		  case AF_INET:
			memmove(&addr.sin.sin_addr,
				hp->h_addr,
				INADDRSZ);
			break;
# endif /* NETINET */

# if NETINET6
		  case AF_INET6:
			memmove(&addr.sin6.sin6_addr,
				hp->h_addr,
				IN6ADDRSZ);
			break;
# endif /* NETINET6 */

		  default:
			if (hp->h_length > sizeof addr.sa.sa_data)
			{
				syserr("makeconnection: long sa_data: family %d len %d",
					hp->h_addrtype, hp->h_length);
				mci_setstat(mci, EX_NOHOST, "5.1.2", NULL);
				errno = EINVAL;
				return EX_NOHOST;
			}
			memmove(addr.sa.sa_data,
				hp->h_addr,
				hp->h_length);
			break;
		}
		addrno = 1;
	}

	/*
	**  Determine the port number.
	*/

	if (port == 0)
	{
# ifdef NO_GETSERVBYNAME
		port = htons(25);
# else /* NO_GETSERVBYNAME */
		register struct servent *sp = getservbyname("smtp", "tcp");

		if (sp == NULL)
		{
			if (LogLevel > 2)
				sm_syslog(LOG_ERR, NOQID,
					  "makeconnection: service \"smtp\" unknown");
			port = htons(25);
		}
		else
			port = sp->s_port;
# endif /* NO_GETSERVBYNAME */
	}

	switch (addr.sa.sa_family)
	{
# if NETINET
	  case AF_INET:
		addr.sin.sin_port = port;
		addrlen = sizeof (struct sockaddr_in);
		break;
# endif /* NETINET */

# if NETINET6
	  case AF_INET6:
		addr.sin6.sin6_port = port;
		addrlen = sizeof (struct sockaddr_in6);
		break;
# endif /* NETINET6 */

# if NETISO
	  case AF_ISO:
		/* assume two byte transport selector */
		memmove(TSEL((struct sockaddr_iso *) &addr), (char *) &port, 2);
		addrlen = sizeof (struct sockaddr_iso);
		break;
# endif /* NETISO */

	  default:
		syserr("Can't connect to address family %d", addr.sa.sa_family);
		mci_setstat(mci, EX_NOHOST, "5.1.2", NULL);
		errno = EINVAL;
		return EX_NOHOST;
	}

	/*
	**  Try to actually open the connection.
	*/

# ifdef XLA
	/* if too many connections, don't bother trying */
	if (!xla_noqueue_ok(host))
		return EX_TEMPFAIL;
# endif /* XLA */

	firstconnect = TRUE;
	for (;;)
	{
		if (tTd(16, 1))
			dprintf("makeconnection (%s [%s])\n",
				host, anynet_ntoa(&addr));

		/* save for logging */
		CurHostAddr = addr;

		if (bitnset(M_SECURE_PORT, mci->mci_mailer->m_flags))
		{
			int rport = IPPORT_RESERVED - 1;

			s = rresvport(&rport);
		}
		else
		{
			s = socket(addr.sa.sa_family, SOCK_STREAM, 0);
		}
		if (s < 0)
		{
			save_errno = errno;
			syserr("makeconnection: cannot create socket");
# ifdef XLA
			xla_host_end(host);
# endif /* XLA */
			mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
			errno = save_errno;
			return EX_TEMPFAIL;
		}

# ifdef SO_SNDBUF
		if (TcpSndBufferSize > 0)
		{
			if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
				       (char *) &TcpSndBufferSize,
				       sizeof(TcpSndBufferSize)) < 0)
				syserr("makeconnection: setsockopt(SO_SNDBUF)");
		}
# endif /* SO_SNDBUF */
# ifdef SO_RCVBUF
		if (TcpRcvBufferSize > 0)
		{
			if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
				       (char *) &TcpRcvBufferSize,
				       sizeof(TcpRcvBufferSize)) < 0)
				syserr("makeconnection: setsockopt(SO_RCVBUF)");
		}
# endif /* SO_RCVBUF */


		if (tTd(16, 1))
			dprintf("makeconnection: fd=%d\n", s);

		/* turn on network debugging? */
		if (tTd(16, 101))
		{
			int on = 1;

			(void) setsockopt(s, SOL_SOCKET, SO_DEBUG,
					  (char *)&on, sizeof on);
		}
		if (e->e_xfp != NULL)
			(void) fflush(e->e_xfp);	/* for debugging */
		errno = 0;				/* for debugging */

		if (clt_bind)
		{
			int on = 1;

			switch (clt_addr.sa.sa_family)
			{
# if NETINET
			  case AF_INET:
				if (clt_addr.sin.sin_port != 0)
					(void) setsockopt(s, SOL_SOCKET,
							  SO_REUSEADDR,
							  (char *) &on,
							  sizeof on);
				break;
# endif /* NETINET */

# if NETINET6
			  case AF_INET6:
				if (clt_addr.sin6.sin6_port != 0)
					(void) setsockopt(s, SOL_SOCKET,
							  SO_REUSEADDR,
							  (char *) &on,
							  sizeof on);
				break;
# endif /* NETINET6 */
			}

			if (bind(s, &clt_addr.sa, socksize) < 0)
			{
				save_errno = errno;
				(void) close(s);
				errno = save_errno;
				syserr("makeconnection: cannot bind socket [%s]",
				       anynet_ntoa(&clt_addr));
				errno = save_errno;
				return EX_TEMPFAIL;
			}
		}

		/*
		**  Linux seems to hang in connect for 90 minutes (!!!).
		**  Time out the connect to avoid this problem.
		*/

		if (setjmp(CtxConnectTimeout) == 0)
		{
			int i;

			if (e->e_ntries <= 0 && TimeOuts.to_iconnect != 0)
				ev = setevent(TimeOuts.to_iconnect, connecttimeout, 0);
			else if (TimeOuts.to_connect != 0)
				ev = setevent(TimeOuts.to_connect, connecttimeout, 0);
			else
				ev = NULL;

			switch (ConnectOnlyTo.sa.sa_family)
			{
# if NETINET
			  case AF_INET:
				addr.sin.sin_addr.s_addr = ConnectOnlyTo.sin.sin_addr.s_addr;
				break;
# endif /* NETINET */

# if NETINET6
			  case AF_INET6:
				memmove(&addr.sin6.sin6_addr,
					&ConnectOnlyTo.sin6.sin6_addr,
					IN6ADDRSZ);
				break;
# endif /* NETINET6 */
			}
			i = connect(s, (struct sockaddr *) &addr, addrlen);
			save_errno = errno;
			if (ev != NULL)
				clrevent(ev);
			if (i >= 0)
				break;
		}
		else
			save_errno = errno;

		/* if running demand-dialed connection, try again */
		if (DialDelay > 0 && firstconnect)
		{
			if (tTd(16, 1))
				dprintf("Connect failed (%s); trying again...\n",
					errstring(save_errno));
			firstconnect = FALSE;
			(void) sleep(DialDelay);
			continue;
		}

		/* couldn't connect.... figure out why */
		(void) close(s);

		if (LogLevel >= 14)
			sm_syslog(LOG_INFO, e->e_id,
				  "makeconnection (%s [%s]) failed: %s",
				  host, anynet_ntoa(&addr),
				  errstring(save_errno));

		if (hp != NULL && hp->h_addr_list[addrno] != NULL)
		{
			if (tTd(16, 1))
				dprintf("Connect failed (%s); trying new address....\n",
					errstring(save_errno));
			switch (addr.sa.sa_family)
			{
# if NETINET
			  case AF_INET:
				memmove(&addr.sin.sin_addr,
					hp->h_addr_list[addrno++],
					INADDRSZ);
				break;
# endif /* NETINET */

# if NETINET6
			  case AF_INET6:
				memmove(&addr.sin6.sin6_addr,
					hp->h_addr_list[addrno++],
					IN6ADDRSZ);
				break;
# endif /* NETINET6 */

			  default:
				memmove(addr.sa.sa_data,
					hp->h_addr_list[addrno++],
					hp->h_length);
				break;
			}
			continue;
		}
		errno = save_errno;

# if NETINET6
		if (family == AF_INET6)
		{
			if (tTd(16, 1))
				dprintf("Connect failed (%s); retrying with AF_INET....\n",
					errstring(save_errno));
			v6found = TRUE;
			family = AF_INET;
			goto v4retry;
		}
	v6tempfail:
# endif /* NETINET6 */
		/* couldn't open connection */
# if NETINET6
		/* Don't clobber an already saved errno from v4retry */
		if (errno > 0)
# endif /* NETINET6 */
			save_errno = errno;
		if (tTd(16, 1))
			dprintf("Connect failed (%s)\n", errstring(save_errno));
# ifdef XLA
		xla_host_end(host);
# endif /* XLA */
		mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL);
		errno = save_errno;
		return EX_TEMPFAIL;
	}

	/* connection ok, put it into canonical form */
	mci->mci_out = NULL;
	if ((mci->mci_out = fdopen(s, "w")) == NULL ||
	    (s = dup(s)) < 0 ||
	    (mci->mci_in = fdopen(s, "r")) == NULL)
	{
		save_errno = errno;
		syserr("cannot open SMTP client channel, fd=%d", s);
		mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
		if (mci->mci_out != NULL)
			(void) fclose(mci->mci_out);
		(void) close(s);
		errno = save_errno;
		return EX_TEMPFAIL;
	}

	/* find out name for Interface through which we connect */
	len = sizeof addr;
	if (getsockname(s, &addr.sa, &len) == 0)
	{
		char *name;
		char *p;

		define(macid("{if_addr}", NULL), newstr(anynet_ntoa(&addr)),
		       &BlankEnvelope);
		p = xalloc(5);
		snprintf(p, 4, "%d", addr.sa.sa_family);
		define(macid("{if_family}", NULL), p, &BlankEnvelope);

		name = hostnamebyanyaddr(&addr);
		define(macid("{if_name}", NULL), newstr(name), &BlankEnvelope);
		if (LogLevel > 11)
		{
			/* log connection information */
			sm_syslog(LOG_INFO, e->e_id,
				  "SMTP outgoing connect on %.40s", name);
		}
		if (bitnset(D_IFNHELO, d_flags))
		{
			if (name[0] != '[' && strchr(name, '.') != NULL)
				mci->mci_heloname = newstr(name);
		}
	}
	else
	{
		define(macid("{if_name}", NULL), NULL, &BlankEnvelope);
		define(macid("{if_addr}", NULL), NULL, &BlankEnvelope);
		define(macid("{if_family}", NULL), NULL, &BlankEnvelope);
	}
	mci_setstat(mci, EX_OK, NULL, NULL);
	return EX_OK;
}

static void
connecttimeout()
{
	errno = ETIMEDOUT;
	longjmp(CtxConnectTimeout, 1);
}
/*
**  MAKECONNECTION_DS -- make a connection to a domain socket.
**
**	Parameters:
**		mux_path -- the path of the socket to connect to.
**		mci -- a pointer to the mail connection information
**			structure to be filled in.
**
**	Returns:
**		An exit code telling whether the connection could be
**			made and if not why not.
**
**	Side Effects:
**		none.
*/

# if NETUNIX
int makeconnection_ds(mux_path, mci)
	char *mux_path;
	register MCI *mci;
{
	int sock;
	int rval, save_errno;
	long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_ROOTOK|SFF_EXECOK;
	struct sockaddr_un unix_addr;

	/* if not safe, don't connect */
	rval = safefile(mux_path, RunAsUid, RunAsGid, RunAsUserName,
			sff, S_IRUSR|S_IWUSR, NULL);

	if (rval != 0)
	{
		syserr("makeconnection_ds: unsafe domain socket");
		mci_setstat(mci, EX_TEMPFAIL, "4.3.5", NULL);
		errno = rval;
		return EX_TEMPFAIL;
	}

	/* prepare address structure */
	memset(&unix_addr, '\0', sizeof unix_addr);
	unix_addr.sun_family = AF_UNIX;

	if (strlen(mux_path) >= sizeof unix_addr.sun_path)
	{
		syserr("makeconnection_ds: domain socket name too long");
		/* XXX why TEMPFAIL ? */
		mci_setstat(mci, EX_TEMPFAIL, "5.3.5", NULL);
		errno = ENAMETOOLONG;
		return EX_UNAVAILABLE;
	}
	(void) strlcpy(unix_addr.sun_path, mux_path, sizeof unix_addr.sun_path);

	/* initialize domain socket */
	sock = socket(AF_UNIX, SOCK_STREAM, 0);
	if (sock == -1)
	{
		save_errno = errno;
		syserr("makeconnection_ds: could not create domain socket");
		mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
		errno = save_errno;
		return EX_TEMPFAIL;
	}

	/* connect to server */
	if (connect(sock, (struct sockaddr *) &unix_addr,
		    sizeof(unix_addr)) == -1)
	{
		save_errno = errno;
		syserr("Could not connect to socket %s", mux_path);
		mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL);
		(void) close(sock);

⌨️ 快捷键说明

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