SPDX: license tags (mostly by guesswork)
[exim.git] / src / src / host_address.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) The Exim Maintainers 2020 - 2022 */
6 /* Copyright (c) University of Cambridge 1995 - 2018 */
7 /* See the file NOTICE for conditions of use and distribution. */
8 /* SPDX-License-Identifier: GPL-2.0-only */
9
10 #include "exim.h"
11
12 /*************************************************
13 *        Extract port from address string        *
14 *************************************************/
15
16 /* In the spool file, and in the -oMa and -oMi options, a host plus port is
17 given as an IP address followed by a dot and a port number. This function
18 decodes this.
19
20 An alternative format for the -oMa and -oMi options is [ip address]:port which
21 is what Exim 4 uses for output, because it seems to becoming commonly used,
22 whereas the dot form confuses some programs/people. So we recognize that form
23 too.
24
25 Argument:
26   address    points to the string; if there is a port, the '.' in the string
27              is overwritten with zero to terminate the address; if the string
28              is in the [xxx]:ppp format, the address is shifted left and the
29              brackets are removed
30
31 Returns:     0 if there is no port, else the port number. If there's a syntax
32              error, leave the incoming address alone, and return 0.
33 */
34
35 int
36 host_address_extract_port(uschar * address)
37 {
38 int port = 0;
39 uschar *endptr;
40
41 /* Handle the "bracketed with colon on the end" format */
42
43 if (*address == '[')
44   {
45   uschar *rb = address + 1;
46   while (*rb != 0 && *rb != ']') rb++;
47   if (*rb++ == 0) return 0;        /* Missing ]; leave invalid address */
48   if (*rb == ':')
49     {
50     port = Ustrtol(rb + 1, &endptr, 10);
51     if (*endptr != 0) return 0;    /* Invalid port; leave invalid address */
52     }
53   else if (*rb != 0) return 0;     /* Bad syntax; leave invalid address */
54   memmove(address, address + 1, rb - address - 2);
55   rb[-2] = 0;
56   }
57
58 /* Handle the "dot on the end" format */
59
60 else
61   {
62   int skip = -3;                   /* Skip 3 dots in IPv4 addresses */
63   address--;
64   while (*(++address) != 0)
65     {
66     int ch = *address;
67     if (ch == ':') skip = 0;       /* Skip 0 dots in IPv6 addresses */
68       else if (ch == '.' && skip++ >= 0) break;
69     }
70   if (*address == 0) return 0;
71   port = Ustrtol(address + 1, &endptr, 10);
72   if (*endptr != 0) return 0;      /* Invalid port; leave invalid address */
73   *address = 0;
74   }
75
76 return port;
77 }
78
79 /* vi: aw ai sw=2
80 */
81 /* End of host.c */