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