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