]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MINOR] frontend: add a make_proxy_line function
authorWilly Tarreau <w@1wt.eu>
Sun, 20 Mar 2011 09:15:22 +0000 (10:15 +0100)
committerWilly Tarreau <w@1wt.eu>
Sun, 20 Mar 2011 09:15:22 +0000 (10:15 +0100)
This function will build a PROXY protocol line header from two addresses
(IPv4 or IPv6). AF_UNIX family will be reported as UNKNOWN.

include/proto/frontend.h
src/frontend.c

index 2f0930f13a7a903052f07cf79b02368fbef180ee..6a686229f4b970f85c9528e87599665ab673fd9a 100644 (file)
@@ -2,7 +2,7 @@
  * include/proto/frontend.h
  * This file declares frontend-specific functions.
  *
- * Copyright (C) 2000-2010 Willy Tarreau - w@1wt.eu
+ * Copyright (C) 2000-2011 Willy Tarreau - w@1wt.eu
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -28,6 +28,7 @@
 void get_frt_addr(struct session *s);
 int frontend_accept(struct session *s);
 int frontend_decode_proxy_request(struct session *s, struct buffer *req, int an_bit);
+int make_proxy_line(char *buf, int buf_len, struct sockaddr_storage *src, struct sockaddr_storage *dst);
 
 
 #endif /* _PROTO_FRONTEND_H */
index 75218df53967a4eaa8f6d6b709d6fb6c16fd6ba9..558bb9ec1d98fa5e3753f4f135725de6fbb999ea 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Frontend variables and functions.
  *
- * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
+ * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -460,6 +460,85 @@ int frontend_decode_proxy_request(struct session *s, struct buffer *req, int an_
        return 0;
 }
 
+/* Makes a PROXY protocol line from the two addresses. The output is sent to
+ * buffer <buf> for a maximum size of <buf_len> (including the trailing zero).
+ * It returns the number of bytes composing this line (including the trailing
+ * LF), or zero in case of failure (eg: not enough space). It supports TCP4,
+ * TCP6 and "UNKNOWN" formats.
+ */
+int make_proxy_line(char *buf, int buf_len, struct sockaddr_storage *src, struct sockaddr_storage *dst)
+{
+       int ret = 0;
+
+       if (src->ss_family == dst->ss_family && src->ss_family == AF_INET) {
+               ret = snprintf(buf + ret, buf_len - ret, "PROXY TCP4 ");
+               if (ret >= buf_len)
+                       return 0;
+
+               /* IPv4 src */
+               if (!inet_ntop(src->ss_family, &((struct sockaddr_in *)src)->sin_addr, buf + ret, buf_len - ret))
+                       return 0;
+
+               ret += strlen(buf + ret);
+               if (ret >= buf_len)
+                       return 0;
+
+               buf[ret++] = ' ';
+
+               /* IPv4 dst */
+               if (!inet_ntop(dst->ss_family, &((struct sockaddr_in *)dst)->sin_addr, buf + ret, buf_len - ret))
+                       return 0;
+
+               ret += strlen(buf + ret);
+               if (ret >= buf_len)
+                       return 0;
+
+               /* source and destination ports */
+               ret += snprintf(buf + ret, buf_len - ret, " %u %u\r\n",
+                               ntohs(((struct sockaddr_in *)src)->sin_port),
+                               ntohs(((struct sockaddr_in *)dst)->sin_port));
+               if (ret >= buf_len)
+                       return 0;
+       }
+       else if (src->ss_family == dst->ss_family && src->ss_family == AF_INET6) {
+               ret = snprintf(buf + ret, buf_len - ret, "PROXY TCP6 ");
+               if (ret >= buf_len)
+                       return 0;
+
+               /* IPv6 src */
+               if (!inet_ntop(src->ss_family, &((struct sockaddr_in6 *)src)->sin6_addr, buf + ret, buf_len - ret))
+                       return 0;
+
+               ret += strlen(buf + ret);
+               if (ret >= buf_len)
+                       return 0;
+
+               buf[ret++] = ' ';
+
+               /* IPv6 dst */
+               if (!inet_ntop(dst->ss_family, &((struct sockaddr_in6 *)dst)->sin6_addr, buf + ret, buf_len - ret))
+                       return 0;
+
+               ret += strlen(buf + ret);
+               if (ret >= buf_len)
+                       return 0;
+
+               /* source and destination ports */
+               ret += snprintf(buf + ret, buf_len - ret, " %u %u\r\n",
+                               ntohs(((struct sockaddr_in6 *)src)->sin6_port),
+                               ntohs(((struct sockaddr_in6 *)dst)->sin6_port));
+               if (ret >= buf_len)
+                       return 0;
+       }
+       else {
+               /* unknown family combination */
+               ret = snprintf(buf, buf_len, "PROXY UNKNOWN\r\n");
+               if (ret >= buf_len)
+                       return 0;
+       }
+       return ret;
+}
+
 /* set test->i to the id of the frontend */
 static int
 acl_fetch_fe_id(struct proxy *px, struct session *l4, void *l7, int dir,