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

📄 daemon.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		errno = save_errno;
		return EX_TEMPFAIL;
	}

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

	mci_setstat(mci, EX_OK, NULL, NULL);
	errno = 0;
	return EX_OK;
}
# endif /* NETUNIX */
/*
**  MYHOSTNAME -- return the name of this host.
**
**	Parameters:
**		hostbuf -- a place to return the name of this host.
**		size -- the size of hostbuf.
**
**	Returns:
**		A list of aliases for this host.
**
**	Side Effects:
**		Adds numeric codes to $=w.
*/

struct hostent *
myhostname(hostbuf, size)
	char hostbuf[];
	int size;
{
	register struct hostent *hp;

	if (gethostname(hostbuf, size) < 0)
	{
		(void) strlcpy(hostbuf, "localhost", size);
	}
	hp = sm_gethostbyname(hostbuf, InetMode);
	if (hp == NULL)
		return NULL;
	if (strchr(hp->h_name, '.') != NULL || strchr(hostbuf, '.') == NULL)
		(void) cleanstrcpy(hostbuf, hp->h_name, size);

# if NETINFO
	if (strchr(hostbuf, '.') == NULL)
	{
		char *domainname;

		domainname = ni_propval("/locations", NULL, "resolver",
					"domain", '\0');
		if (domainname != NULL &&
		    strlen(domainname) + strlen(hostbuf) + 1 < size)
		{
			(void) strlcat(hostbuf, ".", size);
			(void) strlcat(hostbuf, domainname, size);
		}
	}
# endif /* NETINFO */

	/*
	**  If there is still no dot in the name, try looking for a
	**  dotted alias.
	*/

	if (strchr(hostbuf, '.') == NULL)
	{
		char **ha;

		for (ha = hp->h_aliases; ha != NULL && *ha != NULL; ha++)
		{
			if (strchr(*ha, '.') != NULL)
			{
				(void) cleanstrcpy(hostbuf, *ha, size - 1);
				hostbuf[size - 1] = '\0';
				break;
			}
		}
	}

	/*
	**  If _still_ no dot, wait for a while and try again -- it is
	**  possible that some service is starting up.  This can result
	**  in excessive delays if the system is badly configured, but
	**  there really isn't a way around that, particularly given that
	**  the config file hasn't been read at this point.
	**  All in all, a bit of a mess.
	*/

	if (strchr(hostbuf, '.') == NULL &&
	    !getcanonname(hostbuf, size, TRUE))
	{
		sm_syslog(LOG_CRIT, NOQID,
			  "My unqualified host name (%s) unknown; sleeping for retry",
			  hostbuf);
		message("My unqualified host name (%s) unknown; sleeping for retry",
			hostbuf);
		(void) sleep(60);
		if (!getcanonname(hostbuf, size, TRUE))
		{
			sm_syslog(LOG_ALERT, NOQID,
				  "unable to qualify my own domain name (%s) -- using short name",
				  hostbuf);
			message("WARNING: unable to qualify my own domain name (%s) -- using short name",
				hostbuf);
		}
	}
	return hp;
}
/*
**  ADDRCMP -- compare two host addresses
**
**	Parameters:
**		hp -- hostent structure for the first address
**		ha -- actual first address
**		sa -- second address
**
**	Returns:
**		0 -- if ha and sa match
**		else -- they don't match
*/

static int
addrcmp(hp, ha, sa)
	struct hostent *hp;
	char *ha;
	SOCKADDR *sa;
{
# if NETINET6
	u_char *a;
# endif /* NETINET6 */

	switch (sa->sa.sa_family)
	{
# if NETINET
	  case AF_INET:
		if (hp->h_addrtype == AF_INET)
			return memcmp(ha, (char *) &sa->sin.sin_addr, INADDRSZ);
		break;
# endif /* NETINET */

# if NETINET6
	  case AF_INET6:
		a = (u_char *) &sa->sin6.sin6_addr;

		/* Straight binary comparison */
		if (hp->h_addrtype == AF_INET6)
			return memcmp(ha, a, IN6ADDRSZ);

		/* If IPv4-mapped IPv6 address, compare the IPv4 section */
		if (hp->h_addrtype == AF_INET &&
		    IN6_IS_ADDR_V4MAPPED(&sa->sin6.sin6_addr))
			return memcmp(a + IN6ADDRSZ - INADDRSZ, ha, INADDRSZ);
		break;
# endif /* NETINET6 */
	}
	return -1;
}
/*
**  GETAUTHINFO -- get the real host name associated with a file descriptor
**
**	Uses RFC1413 protocol to try to get info from the other end.
**
**	Parameters:
**		fd -- the descriptor
**		may_be_forged -- an outage that is set to TRUE if the
**			forward lookup of RealHostName does not match
**			RealHostAddr; set to FALSE if they do match.
**
**	Returns:
**		The user@host information associated with this descriptor.
*/

static jmp_buf	CtxAuthTimeout;

static void
authtimeout()
{
	longjmp(CtxAuthTimeout, 1);
}

char *
getauthinfo(fd, may_be_forged)
	int fd;
	bool *may_be_forged;
{
	volatile u_short port = 0;
	SOCKADDR_LEN_T falen;
	register char *volatile p = NULL;
	SOCKADDR la;
	SOCKADDR_LEN_T lalen;
	register struct servent *sp;
	volatile int s;
	int i = 0;
	EVENT *ev;
	int nleft;
	struct hostent *hp;
	char *ostype = NULL;
	char **ha;
	char ibuf[MAXNAME + 1];
	static char hbuf[MAXNAME * 2 + 11];

	*may_be_forged = FALSE;
	falen = sizeof RealHostAddr;
	if (isatty(fd) || (i = getpeername(fd, &RealHostAddr.sa, &falen)) < 0 ||
	    falen <= 0 || RealHostAddr.sa.sa_family == 0)
	{
		if (i < 0)
		{
			/*
			**  ENOTSOCK is OK: bail on anything else, but reset
			**  errno in this case, so a mis-report doesn't
			**  happen later.
			*/
			if (errno != ENOTSOCK)
				return NULL;
			errno = 0;
		}
		(void) snprintf(hbuf, sizeof hbuf, "%s@localhost",
			RealUserName);
		if (tTd(9, 1))
			dprintf("getauthinfo: %s\n", hbuf);
		return hbuf;
	}

	if (RealHostName == NULL)
	{
		/* translate that to a host name */
		RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr));
		if (strlen(RealHostName) > MAXNAME)
			RealHostName[MAXNAME] = '\0';
	}

	/* cross check RealHostName with forward DNS lookup */
	if (anynet_ntoa(&RealHostAddr)[0] == '[' ||
	    RealHostName[0] == '[')
	{
		/*
		**  address is not a socket or have an
		**  IP address with no forward lookup
		*/
		*may_be_forged = FALSE;
	}
	else
	{
		/* try to match the reverse against the forward lookup */
		hp = sm_gethostbyname(RealHostName,
				      RealHostAddr.sa.sa_family);

		if (hp == NULL)
			*may_be_forged = TRUE;
		else
		{
			for (ha = hp->h_addr_list; *ha != NULL; ha++)
				if (addrcmp(hp, *ha, &RealHostAddr) == 0)
					break;
			*may_be_forged = *ha == NULL;
		}
	}

	if (TimeOuts.to_ident == 0)
		goto noident;

	lalen = sizeof la;
	switch (RealHostAddr.sa.sa_family)
	{
# if NETINET
	  case AF_INET:
		if (getsockname(fd, &la.sa, &lalen) < 0 ||
		    lalen <= 0 ||
		    la.sa.sa_family != AF_INET)
		{
			/* no ident info */
			goto noident;
		}
		port = RealHostAddr.sin.sin_port;

		/* create ident query */
		(void) snprintf(ibuf, sizeof ibuf, "%d,%d\r\n",
				ntohs(RealHostAddr.sin.sin_port),
				ntohs(la.sin.sin_port));

		/* create local address */
		la.sin.sin_port = 0;

		/* create foreign address */
#  ifdef NO_GETSERVBYNAME
		RealHostAddr.sin.sin_port = htons(113);
#  else /* NO_GETSERVBYNAME */
		sp = getservbyname("auth", "tcp");
		if (sp != NULL)
			RealHostAddr.sin.sin_port = sp->s_port;
		else
			RealHostAddr.sin.sin_port = htons(113);
		break;
#  endif /* NO_GETSERVBYNAME */
# endif /* NETINET */

# if NETINET6
	  case AF_INET6:
		if (getsockname(fd, &la.sa, &lalen) < 0 ||
		    lalen <= 0 ||
		    la.sa.sa_family != AF_INET6)
		{
			/* no ident info */
			goto noident;
		}
		port = RealHostAddr.sin6.sin6_port;

		/* create ident query */
		(void) snprintf(ibuf, sizeof ibuf, "%d,%d\r\n",
				ntohs(RealHostAddr.sin6.sin6_port),
				ntohs(la.sin6.sin6_port));

		/* create local address */
		la.sin6.sin6_port = 0;

		/* create foreign address */
#  ifdef NO_GETSERVBYNAME
		RealHostAddr.sin6.sin6_port = htons(113);
#  else /* NO_GETSERVBYNAME */
		sp = getservbyname("auth", "tcp");
		if (sp != NULL)
			RealHostAddr.sin6.sin6_port = sp->s_port;
		else
			RealHostAddr.sin6.sin6_port = htons(113);
		break;
#  endif /* NO_GETSERVBYNAME */
# endif /* NETINET6 */
	  default:
		/* no ident info */
		goto noident;
	}

	s = -1;
	if (setjmp(CtxAuthTimeout) != 0)
	{
		if (s >= 0)
			(void) close(s);
		goto noident;
	}

	/* put a timeout around the whole thing */
	ev = setevent(TimeOuts.to_ident, authtimeout, 0);


	/* connect to foreign IDENT server using same address as SMTP socket */
	s = socket(la.sa.sa_family, SOCK_STREAM, 0);
	if (s < 0)
	{
		clrevent(ev);
		goto noident;
	}
	if (bind(s, &la.sa, lalen) < 0 ||
	    connect(s, &RealHostAddr.sa, lalen) < 0)
	{
		goto closeident;
	}

	if (tTd(9, 10))
		dprintf("getauthinfo: sent %s", ibuf);

	/* send query */
	if (write(s, ibuf, strlen(ibuf)) < 0)
		goto closeident;

	/* get result */
	p = &ibuf[0];
	nleft = sizeof ibuf - 1;
	while ((i = read(s, p, nleft)) > 0)
	{
		p += i;
		nleft -= i;
		*p = '\0';
		if (strchr(ibuf, '\n') != NULL)
			break;
	}
	(void) close(s);
	clrevent(ev);
	if (i < 0 || p == &ibuf[0])
		goto noident;

	if (*--p == '\n' && *--p == '\r')
		p--;
	*++p = '\0';

	if (tTd(9, 3))
		dprintf("getauthinfo:  got %s\n", ibuf);

	/* parse result */
	p = strchr(ibuf, ':');
	if (p == NULL)
	{
		/* malformed response */
		goto noident;
	}
	while (isascii(*++p) && isspace(*p))
		continue;
	if (strncasecmp(p, "userid", 6) != 0)
	{
		/* presumably an error string */
		goto noident;
	}
	p += 6;
	while (isascii(*p) && isspace(*p))
		p++;
	if (*p++ != ':')
	{
		/* either useridxx or malformed response */
		goto noident;
	}

	/* p now points to the OSTYPE field */
	while (isascii(*p) && isspace(*p))
		p++;
	ostype = p;
	p = strchr(p, ':');
	if (p == NULL)
	{
		/* malformed response */
		goto noident;
	}
	else
	{
		char *charset;

		*p = '\0';
		charset = strchr(ostype, ',');
		if (charset != NULL)
			*charset = '\0';
	}

	/* 1413 says don't do this -- but it's broken otherwise */
	while (isascii(*++p) && isspace(*p))
		continue;

	/* p now points to the authenticated name -- copy carefully */
	if (strncasecmp(ostype, "other", 5) == 0 &&
	    (ostype[5] == ' ' || ostype[5] == '\0'))
	{
		snprintf(hbuf, sizeof hbuf, "IDENT:");
		cleanstrcpy(&hbuf[6], p, MAXNAME);
	}
	else
		cleanstrcpy(hbuf, p, MAXNAME);
	i = strlen(hbuf);
	snprintf(&hbuf[i], sizeof hbuf - i, "@%s",
		 RealHostName == NULL ? "localhost" : RealHostName);
	goto postident;

closeident:
	(void) close(s);
	clrevent(ev);

noident:
	/* put back the original incoming port */
	switch (RealHostAddr.sa.sa_family)
	{
# if NETINET
	  case AF_INET:
		if (port > 0)
			RealHostAddr.sin.sin_port = port;
		break;
# endif /* NETINET */

# if NETINET6
	  case AF_INET6:
		if (port > 0)
			RealHostAddr.sin6.sin6_port = port;
		break;
# endif /* NETINET6 */
	}

	if (RealHostName == NULL)
	{
		if (tTd(9, 1))
			dprintf("getauthinfo: NULL\n");
		return NULL;
	}
	snprintf(hbuf, sizeof hbuf, "%s", RealHostName);

postident:
# if IP_SRCROUTE
#  ifndef GET_IPOPT_DST
#   define GET_IPOPT_DST(dst)	(dst)
#  endif /* ! GET_IPOPT_DST */
	/*
	**  Extract IP source routing information.
	**
	**	Format of output for a connection from site a through b
	**	through c to d:
	**		loose:      @site-c@site-b:site-a
	**		strict:	   !@site-c@site-b:site-a
	**
	**	o - pointer within ipopt_list structure.
	**	q - pointer within ls/ss rr route data
	**	p - pointer to hbuf
	*/

	if (RealHostAddr.sa.sa_family == AF_INET)
	{
		SOCKOPT_LEN_T ipoptlen;
		int j;
		u_char *q;
		u_char *o;
		int l;
		struct IPOPTION ipopt;

		ipoptlen = sizeof ipopt;
		if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS,
			       (char *) &ipopt, &ipoptlen) < 0)
			goto noipsr;
		if (ipoptlen == 0)
			goto noipsr;
		o = (u_char *) ipopt.IP_LIST;
		while (o != NULL && o < (u_char *) &ipopt + ipoptlen)
		{
			switch (*o)
			{
			  case IPOPT_EOL:
				o = NULL;
				break;

			  case IPOPT_NOP:
				o++;
				break;

			  case IPOPT_SSRR:
			  case IPOPT_LSRR:
				/*
				**  Source routing.
				**	o[0] is the option type (loose/strict).
				**	o[1] is the length of this option,
				**		including option type and
				**		length.
				**	o[2] is the pointer into the route
				**		data.
				**	o[3] begins the route data.
				*/

				p = &hbuf[strlen(hbuf)];
		

⌨️ 快捷键说明

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