- switch (cmd)
- {
- case 0x01: /* PROXY command */
- switch (hdr.v2.fam)
- {
- case 0x11: /* TCPv4 address type */
- iptype = US"IPv4";
- tmpaddr.sin_addr.s_addr = hdr.v2.addr.ip4.src_addr;
- inet_ntop(AF_INET, &tmpaddr.sin_addr, CS &tmpip, sizeof(tmpip));
- if (!string_is_ip_address(US tmpip, NULL))
- {
- DEBUG(D_receive) debug_printf("Invalid %s source IP\n", iptype);
- goto proxyfail;
- }
- proxy_local_address = sender_host_address;
- sender_host_address = string_copy(US tmpip);
- tmpport = ntohs(hdr.v2.addr.ip4.src_port);
- proxy_local_port = sender_host_port;
- sender_host_port = tmpport;
- /* Save dest ip/port */
- tmpaddr.sin_addr.s_addr = hdr.v2.addr.ip4.dst_addr;
- inet_ntop(AF_INET, &tmpaddr.sin_addr, CS &tmpip, sizeof(tmpip));
- if (!string_is_ip_address(US tmpip, NULL))
- {
- DEBUG(D_receive) debug_printf("Invalid %s dest port\n", iptype);
- goto proxyfail;
- }
- proxy_external_address = string_copy(US tmpip);
- tmpport = ntohs(hdr.v2.addr.ip4.dst_port);
- proxy_external_port = tmpport;
- goto done;
- case 0x21: /* TCPv6 address type */
- iptype = US"IPv6";
- memmove(tmpaddr6.sin6_addr.s6_addr, hdr.v2.addr.ip6.src_addr, 16);
- inet_ntop(AF_INET6, &tmpaddr6.sin6_addr, CS &tmpip6, sizeof(tmpip6));
- if (!string_is_ip_address(US tmpip6, NULL))
- {
- DEBUG(D_receive) debug_printf("Invalid %s source IP\n", iptype);
- goto proxyfail;
- }
- proxy_local_address = sender_host_address;
- sender_host_address = string_copy(US tmpip6);
- tmpport = ntohs(hdr.v2.addr.ip6.src_port);
- proxy_local_port = sender_host_port;
- sender_host_port = tmpport;
- /* Save dest ip/port */
- memmove(tmpaddr6.sin6_addr.s6_addr, hdr.v2.addr.ip6.dst_addr, 16);
- inet_ntop(AF_INET6, &tmpaddr6.sin6_addr, CS &tmpip6, sizeof(tmpip6));
- if (!string_is_ip_address(US tmpip6, NULL))
- {
- DEBUG(D_receive) debug_printf("Invalid %s dest port\n", iptype);
- goto proxyfail;
- }
- proxy_external_address = string_copy(US tmpip6);
- tmpport = ntohs(hdr.v2.addr.ip6.dst_port);
- proxy_external_port = tmpport;
- goto done;
- default:
- DEBUG(D_receive)
- debug_printf("Unsupported PROXYv2 connection type: 0x%02x\n",
- hdr.v2.fam);
- goto proxyfail;
- }
- /* Unsupported protocol, keep local connection address */
- break;
- case 0x00: /* LOCAL command */
- /* Keep local connection address for LOCAL */
- iptype = US"local";
- break;
- default:
- DEBUG(D_receive)
- debug_printf("Unsupported PROXYv2 command: 0x%x\n", cmd);
- goto proxyfail;
- }
- }
-else if (ret >= 8 && memcmp(hdr.v1.line, "PROXY", 5) == 0)
- {
- uschar *p;
- uschar *end;
- uschar *sp; /* Utility variables follow */
- int tmp_port;
- int r2;
- char *endc;
-
- /* get the rest of the line */
- r2 = swallow_until_crlf(fd, (uschar*)&hdr, ret, sizeof(hdr)-ret);
- if (r2 == -1)
- goto proxyfail;
- ret += r2;
-
- p = string_copy(hdr.v1.line);
- end = memchr(p, '\r', ret - 1);
-
- if (!end || (end == (uschar*)&hdr + ret) || end[1] != '\n')
- {
- DEBUG(D_receive) debug_printf("Partial or invalid PROXY header\n");
- goto proxyfail;
- }
- *end = '\0'; /* Terminate the string */
- size = end + 2 - p; /* Skip header + CRLF */
- DEBUG(D_receive) debug_printf("Detected PROXYv1 header\n");
- DEBUG(D_receive) debug_printf("Bytes read not within PROXY header: %d\n", ret - size);
- /* Step through the string looking for the required fields. Ensure
- strict adherence to required formatting, exit for any error. */
- p += 5;
- if (!isspace(*(p++)))
- {
- DEBUG(D_receive) debug_printf("Missing space after PROXY command\n");
- goto proxyfail;
- }
- if (!Ustrncmp(p, CCS"TCP4", 4))
- iptype = US"IPv4";
- else if (!Ustrncmp(p,CCS"TCP6", 4))
- iptype = US"IPv6";
- else if (!Ustrncmp(p,CCS"UNKNOWN", 7))
- {
- iptype = US"Unknown";
- goto done;
- }
- else
- {
- DEBUG(D_receive) debug_printf("Invalid TCP type\n");
- goto proxyfail;
- }