1/*	$NetBSD: smtpd_peer.c,v 1.5 2023/12/23 20:30:45 christos Exp $	*/
2
3/*++
4/* NAME
5/*	smtpd_peer 3
6/* SUMMARY
7/*	look up peer name/address information
8/* SYNOPSIS
9/*	#include "smtpd.h"
10/*
11/*	void	smtpd_peer_init(state)
12/*	SMTPD_STATE *state;
13/*
14/*	void	smtpd_peer_reset(state)
15/*	SMTPD_STATE *state;
16/* AUXILIARY METHODS
17/*	void	smtpd_peer_from_default(state)
18/*	SMTPD_STATE *state;
19/* DESCRIPTION
20/*	The smtpd_peer_init() routine attempts to produce a printable
21/*	version of the peer name and address of the specified socket.
22/*	Where information is unavailable, the name and/or address
23/*	are set to "unknown".
24/*
25/*	Alternatively, the peer address and port may be obtained
26/*	from a proxy server.
27/*
28/*	This module uses the local name service via getaddrinfo()
29/*	and getnameinfo(). It does not query the DNS directly.
30/*
31/*	smtpd_peer_init() updates the following fields:
32/* .IP name
33/*	The verified client hostname. This name is represented by
34/*	the string "unknown" when 1) the address->name lookup failed,
35/*	2) the name->address mapping fails, or 3) the name->address
36/*	mapping does not produce the client IP address.
37/* .IP reverse_name
38/*	The unverified client hostname as found with address->name
39/*	lookup; it is not verified for consistency with the client
40/*	IP address result from name->address lookup.
41/* .IP forward_name
42/*	The unverified client hostname as found with address->name
43/*	lookup followed by name->address lookup; it is not verified
44/*	for consistency with the result from address->name lookup.
45/*	For example, when the address->name lookup produces as
46/*	hostname an alias, the name->address lookup will produce
47/*	as hostname the expansion of that alias, so that the two
48/*	lookups produce different names.
49/* .IP addr
50/*	Printable representation of the client address.
51/* .IP namaddr
52/*	String of the form: "name[addr]:port".
53/* .IP rfc_addr
54/*	String of the form "ipv4addr" or "ipv6:ipv6addr" for use
55/*	in Received: message headers.
56/* .IP dest_addr
57/*	Server address, used by the Dovecot authentication server,
58/*	available as Milter {daemon_addr} macro, and as server_address
59/*	policy delegation attribute.
60/* .IP dest_port
61/*	Server port, available as Milter {daemon_port} macro, and
62/*	as server_port policy delegation attribute.
63/* .IP name_status
64/*	The name_status result field specifies how the name
65/*	information should be interpreted:
66/* .RS
67/* .IP 2
68/*	The address->name lookup and name->address lookup produced
69/*	the client IP address.
70/* .IP 4
71/*	The address->name lookup or name->address lookup failed
72/*	with a recoverable error.
73/* .IP 5
74/*	The address->name lookup or name->address lookup failed
75/*	with an unrecoverable error, or the result did not match
76/*	the client IP address.
77/* .RE
78/* .IP reverse_name_status
79/*	The reverse_name_status result field specifies how the
80/*	reverse_name information should be interpreted:
81/* .RS
82/* .IP 2
83/*	The address->name lookup succeeded.
84/* .IP 4
85/*	The address->name lookup failed with a recoverable error.
86/* .IP 5
87/*	The address->name lookup failed with an unrecoverable error.
88/* .RE
89/* .IP forward_name_status
90/*	The forward_name_status result field specifies how the
91/*	forward_name information should be interpreted:
92/* .RS
93/* .IP 2
94/*	The address->name and name->address lookup succeeded.
95/* .IP 4
96/*	The address->name lookup or name->address failed with a
97/*	recoverable error.
98/* .IP 5
99/*	The address->name lookup or name->address failed with an
100/*	unrecoverable error.
101/* .RE
102/* .PP
103/*	smtpd_peer_reset() releases memory allocated by smtpd_peer_init().
104/*
105/*	smtpd_peer_from_default() looks up connection information
106/*	when an up-stream proxy indicates that a connection is not
107/*	proxied.
108/* LICENSE
109/* .ad
110/* .fi
111/*	The Secure Mailer license must be distributed with this software.
112/* AUTHOR(S)
113/*	Wietse Venema
114/*	IBM T.J. Watson Research
115/*	P.O. Box 704
116/*	Yorktown Heights, NY 10598, USA
117/*
118/*	Wietse Venema
119/*	Google, Inc.
120/*	111 8th Avenue
121/*	New York, NY 10011, USA
122/*--*/
123
124/* System library. */
125
126#include <sys_defs.h>
127#include <sys/socket.h>
128#include <netinet/in.h>
129#include <arpa/inet.h>
130#include <errno.h>
131#include <netdb.h>
132#include <string.h>
133#include <htable.h>
134
135/* Utility library. */
136
137#include <msg.h>
138#include <mymalloc.h>
139#include <stringops.h>
140#include <myaddrinfo.h>
141#include <sock_addr.h>
142#include <inet_proto.h>
143#include <split_at.h>
144#include <inet_prefix_top.h>
145
146/* Global library. */
147
148#include <mail_proto.h>
149#include <valid_mailhost_addr.h>
150#include <mail_params.h>
151#include <haproxy_srvr.h>
152
153/* Application-specific. */
154
155#include "smtpd.h"
156
157static const INET_PROTO_INFO *proto_info;
158
159 /*
160  * XXX If we make local port information available via logging, then we must
161  * also support these attributes with the XFORWARD command.
162  *
163  * XXX If support were to be added for Milter applications in down-stream MTAs,
164  * then consistency demands that we propagate a lot of Sendmail macro
165  * information via the XFORWARD command. Otherwise we could end up with a
166  * very confusing situation.
167  */
168
169/* smtpd_peer_sockaddr_to_hostaddr - client address/port to printable form */
170
171static int smtpd_peer_sockaddr_to_hostaddr(SMTPD_STATE *state)
172{
173    const char *myname = "smtpd_peer_sockaddr_to_hostaddr";
174    struct sockaddr *sa = (struct sockaddr *) &(state->sockaddr);
175    SOCKADDR_SIZE sa_length = state->sockaddr_len;
176
177    /*
178     * XXX If we're given an IPv6 (or IPv4) connection from, e.g., inetd,
179     * while Postfix IPv6 (or IPv4) support is turned off, don't (skip to the
180     * final else clause, pretend the origin is localhost[127.0.0.1], and
181     * become an open relay).
182     */
183    if (sa->sa_family == AF_INET
184#ifdef AF_INET6
185	|| sa->sa_family == AF_INET6
186#endif
187	) {
188	MAI_HOSTADDR_STR client_addr;
189	MAI_SERVPORT_STR client_port;
190	MAI_HOSTADDR_STR server_addr;
191	MAI_SERVPORT_STR server_port;
192	int     aierr;
193	char   *colonp;
194
195	/*
196	 * Sanity check: we can't use sockets that we're not configured for.
197	 */
198	if (strchr((char *) proto_info->sa_family_list, sa->sa_family) == 0)
199	    msg_fatal("cannot handle socket type %s with \"%s = %s\"",
200#ifdef AF_INET6
201		      sa->sa_family == AF_INET6 ? "AF_INET6" :
202#endif
203		      sa->sa_family == AF_INET ? "AF_INET" :
204		      "other", VAR_INET_PROTOCOLS, var_inet_protocols);
205
206	/*
207	 * Sorry, but there are some things that we just cannot do while
208	 * connected to the network.
209	 */
210	if (geteuid() != var_owner_uid || getuid() != var_owner_uid) {
211	    msg_error("incorrect SMTP server privileges: uid=%lu euid=%lu",
212		      (unsigned long) getuid(), (unsigned long) geteuid());
213	    msg_fatal("the Postfix SMTP server must run with $%s privileges",
214		      VAR_MAIL_OWNER);
215	}
216
217	/*
218	 * Convert the client address to printable form.
219	 */
220	if ((aierr = sockaddr_to_hostaddr(sa, sa_length, &client_addr,
221					  &client_port, 0)) != 0)
222	    msg_fatal("%s: cannot convert client address/port to string: %s",
223		      myname, MAI_STRERROR(aierr));
224	state->port = mystrdup(client_port.buf);
225
226	/*
227	 * XXX Require that the infrastructure strips off the IPv6 datalink
228	 * suffix to avoid false alarms with strict address syntax checks.
229	 */
230#ifdef HAS_IPV6
231	if (strchr(client_addr.buf, '%') != 0)
232	    msg_panic("%s: address %s has datalink suffix",
233		      myname, client_addr.buf);
234#endif
235
236	/*
237	 * We convert IPv4-in-IPv6 address to 'true' IPv4 address early on,
238	 * but only if IPv4 support is enabled (why would anyone want to turn
239	 * it off)? With IPv4 support enabled we have no need for the IPv6
240	 * form in logging, hostname verification and access checks.
241	 */
242#ifdef HAS_IPV6
243	if (sa->sa_family == AF_INET6) {
244	    if (strchr((char *) proto_info->sa_family_list, AF_INET) != 0
245		&& IN6_IS_ADDR_V4MAPPED(&SOCK_ADDR_IN6_ADDR(sa))
246		&& (colonp = strrchr(client_addr.buf, ':')) != 0) {
247		struct addrinfo *res0;
248
249		if (msg_verbose > 1)
250		    msg_info("%s: rewriting V4-mapped address \"%s\" to \"%s\"",
251			     myname, client_addr.buf, colonp + 1);
252
253		state->addr = mystrdup(colonp + 1);
254		state->rfc_addr = mystrdup(colonp + 1);
255		state->addr_family = AF_INET;
256		aierr =
257		    hostaddr_to_sockaddr(state->addr, state->port, 0, &res0);
258		if (aierr)
259		    msg_fatal("%s: cannot convert [%s]:%s to binary: %s",
260			      myname, state->addr, state->port,
261			      MAI_STRERROR(aierr));
262		sa_length = res0->ai_addrlen;
263		if (sa_length > sizeof(state->sockaddr))
264		    sa_length = sizeof(state->sockaddr);
265		memcpy((void *) sa, res0->ai_addr, sa_length);
266		freeaddrinfo(res0);		/* 200412 */
267	    }
268
269	    /*
270	     * Following RFC 2821 section 4.1.3, an IPv6 address literal gets
271	     * a prefix of 'IPv6:'. We do this consistently for all IPv6
272	     * addresses that appear in headers or envelopes. The fact that
273	     * valid_mailhost_addr() enforces the form helps of course. We
274	     * use the form without IPV6: prefix when doing access control,
275	     * or when accessing the connection cache.
276	     */
277	    else {
278		state->addr = mystrdup(client_addr.buf);
279		state->rfc_addr =
280		    concatenate(IPV6_COL, client_addr.buf, (char *) 0);
281		state->addr_family = sa->sa_family;
282	    }
283	}
284
285	/*
286	 * An IPv4 address is in dotted quad decimal form.
287	 */
288	else
289#endif
290	{
291	    state->addr = mystrdup(client_addr.buf);
292	    state->rfc_addr = mystrdup(client_addr.buf);
293	    state->addr_family = sa->sa_family;
294	}
295
296	/*
297	 * Convert the server address/port to printable form.
298	 */
299	if ((aierr = sockaddr_to_hostaddr((struct sockaddr *)
300					  &state->dest_sockaddr,
301					  state->dest_sockaddr_len,
302					  &server_addr,
303					  &server_port, 0)) != 0)
304	    msg_fatal("%s: cannot convert server address/port to string: %s",
305		      myname, MAI_STRERROR(aierr));
306	/* TODO: convert IPv4-in-IPv6 to IPv4 form. */
307	state->dest_addr = mystrdup(server_addr.buf);
308	state->dest_port = mystrdup(server_port.buf);
309
310	return (0);
311    }
312
313    /*
314     * It's not Internet.
315     */
316    else {
317	return (-1);
318    }
319}
320
321/* smtpd_peer_sockaddr_to_hostname - client hostname lookup */
322
323static void smtpd_peer_sockaddr_to_hostname(SMTPD_STATE *state)
324{
325    struct sockaddr *sa = (struct sockaddr *) &(state->sockaddr);
326    SOCKADDR_SIZE sa_length = state->sockaddr_len;
327    MAI_HOSTNAME_STR client_name;
328    int     aierr;
329
330    /*
331     * Look up and sanity check the client hostname.
332     *
333     * It is unsafe to allow numeric hostnames, especially because there exists
334     * pressure to turn off the name->addr double check. In that case an
335     * attacker could trivally bypass access restrictions.
336     *
337     * sockaddr_to_hostname() already rejects malformed or numeric names.
338     */
339#define TEMP_AI_ERROR(e) \
340	((e) == EAI_AGAIN || (e) == EAI_MEMORY || (e) == EAI_SYSTEM)
341
342#define REJECT_PEER_NAME(state, code) { \
343	myfree(state->name); \
344	state->name = mystrdup(CLIENT_NAME_UNKNOWN); \
345	state->name_status = code; \
346    }
347
348    if (var_smtpd_peername_lookup == 0) {
349	state->name = mystrdup(CLIENT_NAME_UNKNOWN);
350	state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
351	state->name_status = SMTPD_PEER_CODE_PERM;
352	state->reverse_name_status = SMTPD_PEER_CODE_PERM;
353    } else if ((aierr = sockaddr_to_hostname(sa, sa_length, &client_name,
354					 (MAI_SERVNAME_STR *) 0, 0)) != 0) {
355	state->name = mystrdup(CLIENT_NAME_UNKNOWN);
356	state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
357	state->name_status = (TEMP_AI_ERROR(aierr) ?
358			      SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM);
359	state->reverse_name_status = (TEMP_AI_ERROR(aierr) ?
360			       SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM);
361    } else {
362	struct addrinfo *res0;
363	struct addrinfo *res;
364
365	state->name = mystrdup(client_name.buf);
366	state->reverse_name = mystrdup(client_name.buf);
367	state->name_status = SMTPD_PEER_CODE_OK;
368	state->reverse_name_status = SMTPD_PEER_CODE_OK;
369
370	/*
371	 * Reject the hostname if it does not list the peer address. Without
372	 * further validation or qualification, such information must not be
373	 * allowed to enter the audit trail, as people would draw false
374	 * conclusions.
375	 */
376	aierr = hostname_to_sockaddr_pf(state->name, state->addr_family,
377					(char *) 0, 0, &res0);
378	if (aierr) {
379	    msg_warn("hostname %s does not resolve to address %s: %s",
380		     state->name, state->addr, MAI_STRERROR(aierr));
381	    REJECT_PEER_NAME(state, (TEMP_AI_ERROR(aierr) ?
382			    SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_FORGED));
383	} else {
384	    for (res = res0; /* void */ ; res = res->ai_next) {
385		if (res == 0) {
386		    msg_warn("hostname %s does not resolve to address %s",
387			     state->name, state->addr);
388		    REJECT_PEER_NAME(state, SMTPD_PEER_CODE_FORGED);
389		    break;
390		}
391		if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
392		    msg_info("skipping address family %d for host %s",
393			     res->ai_family, state->name);
394		    continue;
395		}
396		if (sock_addr_cmp_addr(res->ai_addr, sa) == 0)
397		    break;			/* keep peer name */
398	    }
399	    freeaddrinfo(res0);
400	}
401    }
402}
403
404/* smtpd_peer_hostaddr_to_sockaddr - convert numeric string to binary */
405
406static void smtpd_peer_hostaddr_to_sockaddr(SMTPD_STATE *state)
407{
408    const char *myname = "smtpd_peer_hostaddr_to_sockaddr";
409    struct addrinfo *res;
410    int     aierr;
411
412    if ((aierr = hostaddr_to_sockaddr(state->addr, state->port,
413				      SOCK_STREAM, &res)) != 0)
414	msg_fatal("%s: cannot convert client address/port to string: %s",
415		  myname, MAI_STRERROR(aierr));
416    if (res->ai_addrlen > sizeof(state->sockaddr))
417	msg_panic("%s: address length > struct sockaddr_storage", myname);
418    memcpy((void *) &(state->sockaddr), res->ai_addr, res->ai_addrlen);
419    state->sockaddr_len = res->ai_addrlen;
420    freeaddrinfo(res);
421}
422
423/* smtpd_peer_not_inet - non-socket or non-Internet endpoint */
424
425static void smtpd_peer_not_inet(SMTPD_STATE *state)
426{
427
428    /*
429     * If it's not Internet, assume the client is local, and avoid using the
430     * naming service because that can hang when the machine is disconnected.
431     */
432    state->name = mystrdup("localhost");
433    state->reverse_name = mystrdup("localhost");
434#ifdef AF_INET6
435    if (proto_info->sa_family_list[0] == PF_INET6) {
436	state->addr = mystrdup("::1");		/* XXX bogus. */
437	state->rfc_addr = mystrdup(IPV6_COL "::1");	/* XXX bogus. */
438    } else
439#endif
440    {
441	state->addr = mystrdup("127.0.0.1");	/* XXX bogus. */
442	state->rfc_addr = mystrdup("127.0.0.1");/* XXX bogus. */
443    }
444    state->addr_family = AF_UNSPEC;
445    state->name_status = SMTPD_PEER_CODE_OK;
446    state->reverse_name_status = SMTPD_PEER_CODE_OK;
447    state->port = mystrdup("0");		/* XXX bogus. */
448
449    state->dest_addr = mystrdup(state->addr);	/* XXX bogus. */
450    state->dest_port = mystrdup(state->port);	/* XXX bogus. */
451}
452
453/* smtpd_peer_no_client - peer went away, or peer info unavailable */
454
455static void smtpd_peer_no_client(SMTPD_STATE *state)
456{
457    smtpd_peer_reset(state);
458    state->name = mystrdup(CLIENT_NAME_UNKNOWN);
459    state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
460    state->addr = mystrdup(CLIENT_ADDR_UNKNOWN);
461    state->rfc_addr = mystrdup(CLIENT_ADDR_UNKNOWN);
462    state->addr_family = AF_UNSPEC;
463    state->name_status = SMTPD_PEER_CODE_PERM;
464    state->reverse_name_status = SMTPD_PEER_CODE_PERM;
465    state->port = mystrdup(CLIENT_PORT_UNKNOWN);
466
467    state->dest_addr = mystrdup(SERVER_ADDR_UNKNOWN);
468    state->dest_port = mystrdup(SERVER_PORT_UNKNOWN);
469}
470
471/* smtpd_peer_from_pass_attr - initialize from attribute hash */
472
473static void smtpd_peer_from_pass_attr(SMTPD_STATE *state)
474{
475    HTABLE *attr = (HTABLE *) vstream_context(state->client);
476    const char *cp;
477
478    /*
479     * Extract the client endpoint information from the attribute hash.
480     */
481    if ((cp = htable_find(attr, MAIL_ATTR_ACT_CLIENT_ADDR)) == 0)
482	msg_fatal("missing client address from proxy");
483    if (strrchr(cp, ':') != 0) {
484	if (valid_ipv6_hostaddr(cp, DO_GRIPE) == 0)
485	    msg_fatal("bad IPv6 client address syntax from proxy: %s", cp);
486	state->addr = mystrdup(cp);
487	state->rfc_addr = concatenate(IPV6_COL, cp, (char *) 0);
488	state->addr_family = AF_INET6;
489    } else {
490	if (valid_ipv4_hostaddr(cp, DO_GRIPE) == 0)
491	    msg_fatal("bad IPv4 client address syntax from proxy: %s", cp);
492	state->addr = mystrdup(cp);
493	state->rfc_addr = mystrdup(cp);
494	state->addr_family = AF_INET;
495    }
496    if ((cp = htable_find(attr, MAIL_ATTR_ACT_CLIENT_PORT)) == 0)
497	msg_fatal("missing client port from proxy");
498    if (valid_hostport(cp, DO_GRIPE) == 0)
499	msg_fatal("bad TCP client port number syntax from proxy: %s", cp);
500    state->port = mystrdup(cp);
501
502    /*
503     * The Dovecot authentication server needs the server IP address.
504     */
505    if ((cp = htable_find(attr, MAIL_ATTR_ACT_SERVER_ADDR)) == 0)
506	msg_fatal("missing server address from proxy");
507    if (valid_hostaddr(cp, DO_GRIPE) == 0)
508	msg_fatal("bad IPv6 server address syntax from proxy: %s", cp);
509    state->dest_addr = mystrdup(cp);
510
511    if ((cp = htable_find(attr, MAIL_ATTR_ACT_SERVER_PORT)) == 0)
512	msg_fatal("missing server port from proxy");
513    if (valid_hostport(cp, DO_GRIPE) == 0)
514	msg_fatal("bad TCP server port number syntax from proxy: %s", cp);
515    state->dest_port = mystrdup(cp);
516
517    /*
518     * Convert the client address from string to binary form.
519     */
520    smtpd_peer_hostaddr_to_sockaddr(state);
521}
522
523/* smtpd_peer_from_default - try to initialize peer information from socket */
524
525void    smtpd_peer_from_default(SMTPD_STATE *state)
526{
527
528    /*
529     * The "no client" routine provides surrogate information so that the
530     * application can produce sensible logging when a client disconnects
531     * before the server wakes up. The "not inet" routine provides surrogate
532     * state for (presumably) local IPC channels.
533     */
534    state->sockaddr_len = sizeof(state->sockaddr);
535    state->dest_sockaddr_len = sizeof(state->dest_sockaddr);
536    if (getpeername(vstream_fileno(state->client),
537		    (struct sockaddr *) &state->sockaddr,
538		    &state->sockaddr_len) <0
539	|| getsockname(vstream_fileno(state->client),
540		       (struct sockaddr *) &state->dest_sockaddr,
541		       &state->dest_sockaddr_len) < 0) {
542	if (errno == ENOTSOCK)
543	    smtpd_peer_not_inet(state);
544	else
545	    smtpd_peer_no_client(state);
546    } else {
547	if (smtpd_peer_sockaddr_to_hostaddr(state) < 0)
548	    smtpd_peer_not_inet(state);
549    }
550}
551
552/* smtpd_peer_from_proxy - get endpoint info from proxy agent */
553
554static void smtpd_peer_from_proxy(SMTPD_STATE *state)
555{
556    typedef struct {
557	const char *name;
558	int     (*endpt_lookup) (SMTPD_STATE *);
559    } SMTPD_ENDPT_LOOKUP_INFO;
560    static const SMTPD_ENDPT_LOOKUP_INFO smtpd_endpt_lookup_info[] = {
561	HAPROXY_PROTO_NAME, smtpd_peer_from_haproxy,
562	0,
563    };
564    const SMTPD_ENDPT_LOOKUP_INFO *pp;
565
566    /*
567     * When the proxy information is unavailable, we can't maintain an audit
568     * trail or enforce access control, therefore we forcibly hang up.
569     */
570    for (pp = smtpd_endpt_lookup_info; /* see below */ ; pp++) {
571	if (pp->name == 0)
572	    msg_fatal("unsupported %s value: %s",
573		      VAR_SMTPD_UPROXY_PROTO, var_smtpd_uproxy_proto);
574	if (strcmp(var_smtpd_uproxy_proto, pp->name) == 0)
575	    break;
576    }
577    if (pp->endpt_lookup(state) < 0) {
578	smtpd_peer_from_default(state);
579	state->flags |= SMTPD_FLAG_HANGUP;
580    } else {
581	smtpd_peer_hostaddr_to_sockaddr(state);
582    }
583}
584
585/* smtpd_peer_init - initialize peer information */
586
587void    smtpd_peer_init(SMTPD_STATE *state)
588{
589    int     af;
590
591    /*
592     * Initialize.
593     */
594    if (proto_info == 0)
595	proto_info = inet_proto_info();
596
597    /*
598     * Prepare for partial initialization after error.
599     */
600    memset((void *) &(state->sockaddr), 0, sizeof(state->sockaddr));
601    state->sockaddr_len = 0;
602    state->name = 0;
603    state->reverse_name = 0;
604    state->addr = 0;
605    state->namaddr = 0;
606    state->rfc_addr = 0;
607    state->port = 0;
608    state->anvil_range = 0;
609    state->dest_addr = 0;
610    state->dest_port = 0;
611
612    /*
613     * Determine the remote SMTP client address and port.
614     *
615     * XXX In stand-alone mode, don't assume that the peer will be a local
616     * process. That could introduce a gaping hole when the SMTP daemon is
617     * hooked up to the network via inetd or some other super-server.
618     */
619    if (vstream_context(state->client) != 0) {
620	smtpd_peer_from_pass_attr(state);
621	if (*var_smtpd_uproxy_proto != 0)
622	    msg_warn("ignoring non-empty %s setting behind postscreen",
623		     VAR_SMTPD_UPROXY_PROTO);
624    } else if (SMTPD_STAND_ALONE(state) || *var_smtpd_uproxy_proto == 0) {
625	smtpd_peer_from_default(state);
626    } else {
627	smtpd_peer_from_proxy(state);
628    }
629
630    /*
631     * Determine the remote SMTP client hostname. Note: some of the handlers
632     * above provide surrogate endpoint information in case of error. In that
633     * case, leave the surrogate information alone.
634     */
635    if (state->name == 0)
636	smtpd_peer_sockaddr_to_hostname(state);
637
638    /*
639     * Do the name[addr]:port formatting for pretty reports.
640     */
641    state->namaddr = SMTPD_BUILD_NAMADDRPORT(state->name, state->addr,
642					     state->port);
643
644    /*
645     * Generate 'address' or 'net/mask' index for anvil event aggregation.
646     * Don't do this for non-socket input. See smtpd_peer_not_inet().
647     */
648    if (state->addr_family != AF_UNSPEC) {
649	af = SOCK_ADDR_FAMILY(&(state->sockaddr));
650	state->anvil_range = inet_prefix_top(af,
651					SOCK_ADDR_ADDRP(&(state->sockaddr)),
652					     af == AF_INET ?
653					     var_smtpd_cipv4_prefix :
654					     var_smtpd_cipv6_prefix);
655    }
656}
657
658/* smtpd_peer_reset - destroy peer information */
659
660void    smtpd_peer_reset(SMTPD_STATE *state)
661{
662    if (state->name)
663	myfree(state->name);
664    if (state->reverse_name)
665	myfree(state->reverse_name);
666    if (state->addr)
667	myfree(state->addr);
668    if (state->namaddr)
669	myfree(state->namaddr);
670    if (state->rfc_addr)
671	myfree(state->rfc_addr);
672    if (state->port)
673	myfree(state->port);
674    if (state->dest_addr)
675	myfree(state->dest_addr);
676    if (state->dest_port)
677	myfree(state->dest_port);
678    if (state->anvil_range)
679	myfree(state->anvil_range);
680}
681