📄 daemon.c
字号:
{
# if NETINET
case AF_INET:
if (!isascii(*v) || !isdigit(*v) ||
((d->d_addr.sin.sin_addr.s_addr = inet_addr(v)) == INADDR_NONE))
{
register struct hostent *hp;
hp = sm_gethostbyname(v, AF_INET);
if (hp == NULL)
syserr("554 5.3.0 host \"%s\" unknown",
v);
else
{
while (*(hp->h_addr_list) &&
hp->h_addrtype != AF_INET)
hp->h_addr_list++;
if (*(hp->h_addr_list) == NULL)
syserr("554 5.3.0 host \"%s\" unknown",
v);
else
memmove(&d->d_addr.sin.sin_addr,
*(hp->h_addr_list),
INADDRSZ);
}
}
break;
# endif /* NETINET */
# if NETINET6
case AF_INET6:
if (!isascii(*v) || !isxdigit(*v) ||
inet_pton(AF_INET6, v,
&d->d_addr.sin6.sin6_addr) != 1)
{
register struct hostent *hp;
hp = sm_gethostbyname(v, AF_INET6);
if (hp == NULL)
syserr("554 5.3.0 host \"%s\" unknown",
v);
else
{
while (*(hp->h_addr_list) &&
hp->h_addrtype != AF_INET6)
hp->h_addr_list++;
if (*(hp->h_addr_list) == NULL)
syserr("554 5.3.0 host \"%s\" unknown",
v);
else
memmove(&d->d_addr.sin6.sin6_addr,
*(hp->h_addr_list),
IN6ADDRSZ);
}
}
break;
# endif /* NETINET6 */
default:
syserr("554 5.3.5 address= option unsupported for family %d",
d->d_addr.sa.sa_family);
break;
}
break;
case 'P': /* port */
switch (d->d_addr.sa.sa_family)
{
# if NETINET
case AF_INET:
if (isascii(*v) && isdigit(*v))
d->d_addr.sin.sin_port = htons((u_short)atoi((const char *)v));
else
{
# ifdef NO_GETSERVBYNAME
syserr("554 5.3.5 invalid port number: %s",
v);
# else /* NO_GETSERVBYNAME */
register struct servent *sp;
sp = getservbyname(v, "tcp");
if (sp == NULL)
syserr("554 5.3.5 service \"%s\" unknown",
v);
else
d->d_addr.sin.sin_port = sp->s_port;
# endif /* NO_GETSERVBYNAME */
}
break;
# endif /* NETINET */
# if NETINET6
case AF_INET6:
if (isascii(*v) && isdigit(*v))
d->d_addr.sin6.sin6_port = htons((u_short)atoi(v));
else
{
# ifdef NO_GETSERVBYNAME
syserr("554 5.3.5 invalid port number: %s",
v);
# else /* NO_GETSERVBYNAME */
register struct servent *sp;
sp = getservbyname(v, "tcp");
if (sp == NULL)
syserr("554 5.3.5 service \"%s\" unknown",
v);
else
d->d_addr.sin6.sin6_port = sp->s_port;
# endif /* NO_GETSERVBYNAME */
}
break;
# endif /* NETINET6 */
# if NETISO
case AF_ISO:
/* assume two byte transport selector */
if (isascii(*v) && isdigit(*v))
port = htons((u_short)atoi(v));
else
{
# ifdef NO_GETSERVBYNAME
syserr("554 5.3.5 invalid port number: %s",
v);
# else /* NO_GETSERVBYNAME */
register struct servent *sp;
sp = getservbyname(v, "tcp");
if (sp == NULL)
syserr("554 5.3.5 service \"%s\" unknown",
v);
else
port = sp->s_port;
# endif /* NO_GETSERVBYNAME */
}
memmove(TSEL(&d->d_addr.siso),
(char *) &port, 2);
break;
# endif /* NETISO */
default:
syserr("554 5.3.5 Port= option unsupported for family %d",
d->d_addr.sa.sa_family);
break;
}
break;
case 'L': /* listen queue size */
d->d_listenqueue = atoi(v);
break;
case 'M': /* modifiers (flags) */
l = 3 * strlen(v) + 3;
h = v;
flags = xalloc(l);
d->d_mflags = flags;
for (; *h != '\0'; h++)
{
if (!(isascii(*h) && isspace(*h)))
{
if (flags != d->d_mflags)
*flags++ = ' ';
*flags++ = *h;
if (isupper(*h))
*flags++ = *h;
}
}
*flags++ = '\0';
for (; *v != '\0'; v++)
if (!(isascii(*v) && isspace(*v)))
setbitn(*v, d->d_flags);
break;
case 'S': /* send buffer size */
d->d_tcpsndbufsize = atoi(v);
break;
case 'R': /* receive buffer size */
d->d_tcprcvbufsize = atoi(v);
break;
case 'N': /* name */
d->d_name = v;
break;
default:
syserr("554 5.3.5 PortOptions parameter \"%s\" unknown",
f);
}
}
}
/*
** SETDAEMONOPTIONS -- set options for running the MTA daemon
**
** Parameters:
** p -- the options line.
**
** Returns:
** TRUE if successful, FALSE otherwise.
*/
bool
setdaemonoptions(p)
register char *p;
{
if (ndaemons >= MAXDAEMONS)
return FALSE;
Daemons[ndaemons].d_socket = -1;
Daemons[ndaemons].d_listenqueue = 10;
clrbitmap(Daemons[ndaemons].d_flags);
setsockaddroptions(p, &Daemons[ndaemons]);
if (Daemons[ndaemons].d_name != NULL)
Daemons[ndaemons].d_name = newstr(Daemons[ndaemons].d_name);
else
{
char num[30];
snprintf(num, sizeof num, "Daemon%d", ndaemons);
Daemons[ndaemons].d_name = newstr(num);
}
if (tTd(37, 1))
{
dprintf("Daemon %s flags: ", Daemons[ndaemons].d_name);
if (bitnset(D_ETRNONLY, Daemons[ndaemons].d_flags))
dprintf("ETRNONLY ");
if (bitnset(D_NOETRN, Daemons[ndaemons].d_flags))
dprintf("NOETRN ");
dprintf("\n");
}
++ndaemons;
return TRUE;
}
/*
** INITDAEMON -- initialize daemon if not yet done.
**
** Parameters:
** none
**
** Returns:
** none
**
** Side Effects:
** initializes structure for one daemon.
*/
void
initdaemon()
{
if (ndaemons == 0)
{
Daemons[ndaemons].d_socket = -1;
Daemons[ndaemons].d_listenqueue = 10;
Daemons[ndaemons].d_name = "Daemon0";
ndaemons = 1;
}
}
/*
** SETCLIENTOPTIONS -- set options for running the client
**
** Parameters:
** p -- the options line.
**
** Returns:
** none.
*/
static SOCKADDR ClientAddr; /* address for client */
void
setclientoptions(p)
register char *p;
{
struct daemon d;
extern ENVELOPE BlankEnvelope;
memset(&d, '\0', sizeof d);
setsockaddroptions(p, &d);
/* grab what we need */
memcpy(&ClientAddr, &d.d_addr, sizeof ClientAddr);
TcpSndBufferSize = d.d_tcpsndbufsize;
TcpRcvBufferSize = d.d_tcprcvbufsize;
if (d.d_mflags != NULL)
define(macid("{client_flags}", NULL), d.d_mflags,
&BlankEnvelope);
else
define(macid("{client_flags}", NULL), "", &BlankEnvelope);
}
/*
** ADDR_FAMILY -- determine address family from address
**
** Parameters:
** addr -- the string representation of the address
**
** Returns:
** AF_INET, AF_INET6 or AF_UNSPEC
**
** Side Effects:
** none.
*/
static int
addr_family(addr)
char *addr;
{
# if NETINET6
SOCKADDR clt_addr;
# endif /* NETINET6 */
# if NETINET
if (inet_addr(addr) != INADDR_NONE)
{
if (tTd(16, 9))
printf("addr_family(%s): INET\n", addr);
return AF_INET;
}
# endif /* NETINET */
# if NETINET6
if (inet_pton(AF_INET6, addr, &clt_addr.sin6.sin6_addr) == 1)
{
if (tTd(16, 9))
printf("addr_family(%s): INET6\n", addr);
return AF_INET6;
}
# endif /* NETINET6 */
if (tTd(16, 9))
printf("addr_family(%s): UNSPEC\n", addr);
return AF_UNSPEC;
}
/*
** MAKECONNECTION -- make a connection to an SMTP socket on a machine.
**
** Parameters:
** host -- the name of the host.
** port -- the port number to connect to.
** mci -- a pointer to the mail connection information
** structure to be filled in.
** e -- the current envelope.
**
** Returns:
** An exit code telling whether the connection could be
** made and if not why not.
**
** Side Effects:
** none.
*/
static jmp_buf CtxConnectTimeout;
SOCKADDR CurHostAddr; /* address of current host */
int
makeconnection(host, port, mci, e)
char *host;
volatile u_int port;
register MCI *mci;
ENVELOPE *e;
{
register volatile int addrno = 0;
register volatile int s;
register struct hostent *volatile hp = (struct hostent *)NULL;
SOCKADDR addr;
SOCKADDR clt_addr;
int save_errno = 0;
volatile SOCKADDR_LEN_T addrlen;
volatile bool firstconnect;
EVENT *volatile ev = NULL;
# if NETINET6
volatile bool v6found = FALSE;
# endif /* NETINET6 */
volatile int family = InetMode;
SOCKADDR_LEN_T len;
volatile SOCKADDR_LEN_T socksize = 0;
volatile bool clt_bind;
BITMAP256 d_flags;
char *p;
extern ENVELOPE BlankEnvelope;
/* retranslate ${daemon_flags} into bitmap */
clrbitmap(d_flags);
if ((p = macvalue(macid("{daemon_flags}", NULL), e)) != NULL)
{
for (; *p != '\0'; p++)
{
if (!(isascii(*p) && isspace(*p)))
setbitn(*p, d_flags);
}
}
/* "add" ${client_flags} to bitmap */
if ((p = macvalue(macid("{client_flags}", NULL), e)) != NULL)
{
for (; *p != '\0'; p++)
{
/* look for just this one flag */
if (*p == D_IFNHELO)
{
setbitn(*p, d_flags);
break;
}
}
}
# if NETINET6
v4retry:
# endif /* NETINET6 */
clt_bind = FALSE;
/* Set up the address for outgoing connection. */
if (bitnset(D_BINDIF, d_flags) &&
(p = macvalue(macid("{if_addr}", NULL), e)) != NULL)
{
# if NETINET6
char p6[INET6_ADDRSTRLEN];
# endif /* NETINET6 */
memset(&clt_addr, '\0', sizeof clt_addr);
/* infer the address family from the address itself */
clt_addr.sa.sa_family = addr_family(p);
switch (clt_addr.sa.sa_family)
{
# if NETINET
case AF_INET:
if ((clt_addr.sin.sin_addr.s_addr = inet_addr(p))
!= INADDR_NONE)
{
clt_bind = TRUE;
socksize = sizeof (struct sockaddr_in);
}
else if (clt_addr.sin.sin_port != 0)
{
clt_addr.sin.sin_addr.s_addr = INADDR_ANY;
clt_bind = TRUE;
socksize = sizeof (struct sockaddr_in);
}
break;
# endif /* NETINET */
# if NETINET6
case AF_INET6:
if (inet_addr(p) != INADDR_NONE)
snprintf(p6, sizeof p6, "::ffff:%s", p);
else
strlcpy(p6, p, sizeof p6);
if (inet_pton(AF_INET6, p6,
&clt_addr.sin6.sin6_addr) == 1)
{
clt_bind = TRUE;
socksize = sizeof (struct sockaddr_in6);
}
else if (clt_addr.sin6.sin6_port != 0)
{
if (IN6_IS_ADDR_UNSPECIFIED(&clt_addr.sin6.sin6_addr))
clt_addr.sin6.sin6_addr = in6addr_any;
clt_bind = TRUE;
socksize = sizeof (struct sockaddr_in6);
}
break;
# endif /* NETINET6 */
# if 0
default:
syserr("554 5.3.5 Address= option unsupported for family %d",
clt_addr.sa.sa_family);
break;
# endif /* 0 */
}
if (clt_bind)
family = clt_addr.sa.sa_family;
}
else
{
STRUCTCOPY(ClientAddr, clt_addr);
if (clt_addr.sa.sa_family == AF_UNSPEC)
clt_addr.sa.sa_family = InetMode;
switch (clt_addr.sa.sa_family)
{
# if NETINET
case AF_INET:
if (clt_addr.sin.sin_addr.s_addr == 0)
clt_addr.sin.sin_addr.s_addr = INADDR_ANY;
else
clt_bind = TRUE;
if (clt_addr.sin.sin_port != 0)
clt_bind = TRUE;
socksize = sizeof (struct sockaddr_in);
break;
# endif /* NETINET */
# if NETINET6
case AF_INET6:
if (IN6_IS_ADDR_UNSPECIFIED(&clt_addr.sin6.sin6_addr))
clt_addr.sin6.sin6_addr = in6addr_any;
else
clt_bind = TRUE;
socksize = sizeof (struct sockaddr_in6);
if (clt_addr.sin6.sin6_port != 0)
clt_bind = TRUE;
break;
# endif /* NETINET6 */
# if NETISO
case AF_ISO:
socksize = sizeof clt_addr.siso;
clt_bind = TRUE;
break;
# endif /* NETISO */
default:
break;
}
}
/*
** Set up the address for the mailer.
** Accept "[a.b.c.d]" syntax for host name.
*/
# if NAMED_BIND
h_errno = 0;
# endif /* NAMED_BIND */
errno = 0;
memset(&CurHostAddr, '\0', sizeof CurHostAddr);
memset(&addr, '\0', sizeof addr);
SmtpPhase = mci->mci_phase = "initial connection";
CurHostName = host;
if (host[0] == '[')
{
p = strchr(host, ']');
if (p != NULL)
{
# if NETINET
unsigned long hid = INADDR_NONE;
# endif /* NETINET */
# if NETINET6
struct sockaddr_in6 hid6;
# endif /* NETINET6 */
*p = '\0';
# if NETINET6
memset(&hid6, '\0', sizeof hid6);
# endif /* NETINET6 */
# if NETINET
if (family == AF_INET &&
(hid = inet_addr(&host[1])) != INADDR_NONE)
{
addr.sin.sin_family = AF_INET;
addr.sin.sin_addr.s_addr = hid;
}
else
# endif /* NETINET */
# if NETINET6
if (family == AF_INET6 &&
inet_pton(AF_INET6, &host[1],
&hid6.sin6_addr) == 1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -