Postfix3.3.1
haproxy_srvr.c
[詳解]
1 /*++
2 /* NAME
3 /* haproxy_srvr 3
4 /* SUMMARY
5 /* server-side haproxy protocol support
6 /* SYNOPSIS
7 /* #include <haproxy_srvr.h>
8 /*
9 /* const char *haproxy_srvr_parse(str,
10 /* smtp_client_addr, smtp_client_port,
11 /* smtp_server_addr, smtp_server_port)
12 /* const char *str;
13 /* MAI_HOSTADDR_STR *smtp_client_addr,
14 /* MAI_SERVPORT_STR *smtp_client_port,
15 /* MAI_HOSTADDR_STR *smtp_server_addr,
16 /* MAI_SERVPORT_STR *smtp_server_port;
17 /* DESCRIPTION
18 /* haproxy_srvr_parse() parses a haproxy line. The result is
19 /* null in case of success, a pointer to text (with the error
20 /* type) in case of error. If both IPv6 and IPv4 support are
21 /* enabled, IPV4_IN_IPV6 address syntax (::ffff:1.2.3.4) is
22 /* converted to IPV4 syntax.
23 /* LICENSE
24 /* .ad
25 /* .fi
26 /* The Secure Mailer license must be distributed with this software.
27 /* AUTHOR(S)
28 /* Wietse Venema
29 /* IBM T.J. Watson Research
30 /* P.O. Box 704
31 /* Yorktown Heights, NY 10598, USA
32 /*--*/
33 
34 /* System library. */
35 
36 #include <sys_defs.h>
37 #include <stdarg.h>
38 #include <stdlib.h>
39 #include <string.h>
40 
41 #ifdef STRCASECMP_IN_STRINGS_H
42 #include <strings.h>
43 #endif
44 
45 /* Utility library. */
46 
47 #include <msg.h>
48 #include <myaddrinfo.h>
49 #include <valid_hostname.h>
50 #include <stringops.h>
51 #include <mymalloc.h>
52 #include <inet_proto.h>
53 
54 /* Global library. */
55 
56 #include <haproxy_srvr.h>
57 
58 /* Application-specific. */
59 
60 static INET_PROTO_INFO *proto_info;
61 
62 /* haproxy_srvr_parse_lit - extract and validate string literal */
63 
64 static int haproxy_srvr_parse_lit(const char *str,...)
65 {
66  va_list ap;
67  const char *cp;
68  int result = -1;
69 
70  if (msg_verbose)
71  msg_info("haproxy_srvr_parse: %s", str);
72 
73  if (str != 0) {
74  va_start(ap, str);
75  while (result < 0 && (cp = va_arg(ap, const char *)) != 0)
76  if (strcmp(str, cp) == 0)
77  result = 0;
78  va_end(ap);
79  }
80  return (result);
81 }
82 
83 /* haproxy_srvr_parse_proto - parse and validate the protocol type */
84 
85 static int haproxy_srvr_parse_proto(const char *str, int *addr_family)
86 {
87  if (msg_verbose)
88  msg_info("haproxy_srvr_parse: proto=%s", str);
89 
90 #ifdef AF_INET6
91  if (strcasecmp(str, "TCP6") == 0) {
92  if (strchr((char *) proto_info->sa_family_list, AF_INET6) != 0) {
93  *addr_family = AF_INET6;
94  return (0);
95  }
96  } else
97 #endif
98  if (strcasecmp(str, "TCP4") == 0) {
99  if (strchr((char *) proto_info->sa_family_list, AF_INET) != 0) {
100  *addr_family = AF_INET;
101  return (0);
102  }
103  }
104  return (-1);
105 }
106 
107 /* haproxy_srvr_parse_addr - extract and validate IP address */
108 
109 static int haproxy_srvr_parse_addr(const char *str, MAI_HOSTADDR_STR *addr,
110  int addr_family)
111 {
112  if (msg_verbose)
113  msg_info("haproxy_srvr_parse: addr=%s proto=%d", str, addr_family);
114 
115  if (str == 0 || strlen(str) >= sizeof(MAI_HOSTADDR_STR))
116  return (-1);
117 
118  switch (addr_family) {
119 #ifdef AF_INET6
120  case AF_INET6:
121  if (!valid_ipv6_hostaddr(str, DONT_GRIPE))
122  return (-1);
123  if (strncasecmp("::ffff:", str, 7) == 0
124  && strchr((char *) proto_info->sa_family_list, AF_INET) != 0) {
125  memcpy(addr->buf, str + 7, strlen(str) + 1 - 7);
126  return (0);
127  } else {
128  memcpy(addr->buf, str, strlen(str) + 1);
129  return (0);
130  }
131 #endif
132  case AF_INET:
133  if (!valid_ipv4_hostaddr(str, DONT_GRIPE))
134  return (-1);
135  memcpy(addr->buf, str, strlen(str) + 1);
136  return (0);
137  default:
138  msg_panic("haproxy_srvr_parse: unexpected address family: %d",
139  addr_family);
140  }
141 }
142 
143 /* haproxy_srvr_parse_port - extract and validate TCP port */
144 
145 static int haproxy_srvr_parse_port(const char *str, MAI_SERVPORT_STR *port)
146 {
147  if (msg_verbose)
148  msg_info("haproxy_srvr_parse: port=%s", str);
149  if (str == 0 || strlen(str) >= sizeof(MAI_SERVPORT_STR)
150  || !valid_hostport(str, DONT_GRIPE)) {
151  return (-1);
152  } else {
153  memcpy(port->buf, str, strlen(str) + 1);
154  return (0);
155  }
156 }
157 
158 /* haproxy_srvr_parse - parse haproxy line */
159 
160 const char *haproxy_srvr_parse(const char *str,
161  MAI_HOSTADDR_STR *smtp_client_addr,
162  MAI_SERVPORT_STR *smtp_client_port,
163  MAI_HOSTADDR_STR *smtp_server_addr,
164  MAI_SERVPORT_STR *smtp_server_port)
165 {
166  char *saved_str = mystrdup(str);
167  char *cp = saved_str;
168  const char *err;
169  int addr_family;
170 
171  if (proto_info == 0)
172  proto_info = inet_proto_info();
173 
174  /*
175  * XXX We don't accept connections with the "UNKNOWN" protocol type,
176  * because those would sidestep address-based access control mechanisms.
177  */
178 #define NEXT_TOKEN mystrtok(&cp, " \r\n")
179  if (haproxy_srvr_parse_lit(NEXT_TOKEN, "PROXY", (char *) 0) < 0)
180  err = "unexpected protocol header";
181  else if (haproxy_srvr_parse_proto(NEXT_TOKEN, &addr_family) < 0)
182  err = "unsupported protocol type";
183  else if (haproxy_srvr_parse_addr(NEXT_TOKEN, smtp_client_addr,
184  addr_family) < 0)
185  err = "unexpected client address syntax";
186  else if (haproxy_srvr_parse_addr(NEXT_TOKEN, smtp_server_addr,
187  addr_family) < 0)
188  err = "unexpected server address syntax";
189  else if (haproxy_srvr_parse_port(NEXT_TOKEN, smtp_client_port) < 0)
190  err = "unexpected client port syntax";
191  else if (haproxy_srvr_parse_port(NEXT_TOKEN, smtp_server_port) < 0)
192  err = "unexpected server port syntax";
193  else
194  err = 0;
195  myfree(saved_str);
196  return (err);
197 }
int msg_verbose
Definition: msg.c:177
int valid_ipv6_hostaddr(const char *addr, int gripe)
void myfree(void *ptr)
Definition: mymalloc.c:207
char * mystrdup(const char *str)
Definition: mymalloc.c:225
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
#define inet_proto_info()
Definition: inet_proto.h:29
int valid_hostport(const char *str, int gripe)
const char * haproxy_srvr_parse(const char *str, MAI_HOSTADDR_STR *smtp_client_addr, MAI_SERVPORT_STR *smtp_client_port, MAI_HOSTADDR_STR *smtp_server_addr, MAI_SERVPORT_STR *smtp_server_port)
Definition: haproxy_srvr.c:160
int strncasecmp(const char *s1, const char *s2, size_t n)
Definition: strcasecmp.c:52
int valid_ipv4_hostaddr(const char *addr, int gripe)
char buf[MAI_HOSTADDR_STRSIZE]
Definition: myaddrinfo.h:146
#define NEXT_TOKEN
unsigned char * sa_family_list
Definition: inet_proto.h:21
int strcasecmp(const char *s1, const char *s2)
Definition: strcasecmp.c:41
char buf[MAI_SERVPORT_STRSIZE]
Definition: myaddrinfo.h:154
#define DONT_GRIPE
Definition: haproxy_srvr.h:31
void msg_info(const char *fmt,...)
Definition: msg.c:199