[master] 358f7331c VSA_BuildFAP: Build a suckaddr from Family, Address and Port

Nils Goroll nils.goroll at uplex.de
Wed Apr 1 18:37:07 UTC 2020


commit 358f7331c3bcc595fb161370256c0b13b960ccda
Author: Nils Goroll <nils.goroll at uplex.de>
Date:   Thu Dec 12 15:31:11 2019 +0100

    VSA_BuildFAP: Build a suckaddr from Family, Address and Port
    
    Follow the spirit of the vsa.c top level rant and spare callers the
    hassle of creating sockaddrs specific to ip4/ip6 just to build a VSA,
    which is intended to avoid having to special-case the protocols in the
    first place.

diff --git a/bin/varnishd/proxy/cache_proxy_proto.c b/bin/varnishd/proxy/cache_proxy_proto.c
index 4eb5526ee..53851a24c 100644
--- a/bin/varnishd/proxy/cache_proxy_proto.c
+++ b/bin/varnishd/proxy/cache_proxy_proto.c
@@ -326,8 +326,6 @@ vpx_proto2(const struct worker *wrk, struct req *req)
 	const uint8_t *p;
 	char *d, *tlv_start;
 	sa_family_t pfam = 0xff;
-	struct sockaddr_in sin4;
-	struct sockaddr_in6 sin6;
 	struct suckaddr *sa = NULL;
 	char ha[VTCP_ADDRBUFSIZE];
 	char pa[VTCP_PORTBUFSIZE];
@@ -387,23 +385,17 @@ vpx_proto2(const struct worker *wrk, struct req *req)
 		}
 		l -= 12;
 		d += 12;
-		memset(&sin4, 0, sizeof sin4);
-		sin4.sin_family = pfam;
 
 		/* dst/server */
-		memcpy(&sin4.sin_addr, p + 20, 4);
-		memcpy(&sin4.sin_port, p + 26, 2);
 		if (! SES_Reserve_server_addr(req->sp, &sa))
 			return (vpx_ws_err(req));
-		AN(VSA_Build(sa, &sin4, sizeof sin4));
+		AN(VSA_BuildFAP(sa, pfam, p + 20, 4, p + 26, 2));
 		VTCP_name(sa, ha, sizeof ha, pa, sizeof pa);
 
 		/* src/client */
-		memcpy(&sin4.sin_addr, p + 16, 4);
-		memcpy(&sin4.sin_port, p + 24, 2);
 		if (! SES_Reserve_client_addr(req->sp, &sa))
 			return (vpx_ws_err(req));
-		AN(VSA_Build(sa, &sin4, sizeof sin4));
+		AN(VSA_BuildFAP(sa, pfam, p + 16, 4, p + 24, 2));
 		break;
 	case 0x21:
 		/* IPv6|TCP */
@@ -415,23 +407,17 @@ vpx_proto2(const struct worker *wrk, struct req *req)
 		}
 		l -= 36;
 		d += 36;
-		memset(&sin6, 0, sizeof sin6);
-		sin6.sin6_family = pfam;
 
 		/* dst/server */
-		memcpy(&sin6.sin6_addr, p + 32, 16);
-		memcpy(&sin6.sin6_port, p + 50, 2);
 		if (! SES_Reserve_server_addr(req->sp, &sa))
 			return (vpx_ws_err(req));
-		AN(VSA_Build(sa, &sin6, sizeof sin6));
+		AN(VSA_BuildFAP(sa, pfam, p + 32, 16, p + 50, 2));
 		VTCP_name(sa, ha, sizeof ha, pa, sizeof pa);
 
 		/* src/client */
-		memcpy(&sin6.sin6_addr, p + 16, 16);
-		memcpy(&sin6.sin6_port, p + 48, 2);
 		if (! SES_Reserve_client_addr(req->sp, &sa))
 			return (vpx_ws_err(req));
-		AN(VSA_Build(sa, &sin6, sizeof sin6));
+		AN(VSA_BuildFAP(sa, pfam, p + 16, 16, p + 48, 2));
 		break;
 	default:
 		/* Ignore proxy header */
diff --git a/include/vsa.h b/include/vsa.h
index e44544d55..eb6e4a2df 100644
--- a/include/vsa.h
+++ b/include/vsa.h
@@ -57,6 +57,18 @@ struct suckaddr *VSA_Malloc(const void *s, unsigned  sal);
  */
 struct suckaddr *VSA_Build(void *d, const void *s, unsigned sal);
 
+/* 'd' SHALL point to vsa_suckaddr_len aligned bytes of storage
+ *
+ * fam: address family
+ * a / al : address and length
+ * p / pl : port and length
+ *
+ * NULL or 0 length argument are ignored.
+ * argument of the wrong length are an error (NULL return value, EINVAL)
+ */
+struct suckaddr * VSA_BuildFAP(void *d, sa_family_t fam,
+    const void *a, unsigned al, const void *p, unsigned pl);
+
 /*
  * This VRT interface is for the VCC generated ACL code, which needs
  * to know the address family and a pointer to the actual address.
diff --git a/lib/libvarnish/vsa.c b/lib/libvarnish/vsa.c
index 3ade79e14..3f842458d 100644
--- a/lib/libvarnish/vsa.c
+++ b/lib/libvarnish/vsa.c
@@ -187,16 +187,7 @@ const struct suckaddr *bogo_ip = &bogo_ip_vsa;
 void
 VSA_Init()
 {
-	struct addrinfo hints, *res = NULL;
-
-	memset(&hints, 0, sizeof(hints));
-	hints.ai_family = AF_INET;
-	hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
-	hints.ai_socktype = SOCK_STREAM;
-	AZ(getaddrinfo("0.0.0.0", "0", &hints, &res));
-	AN(VSA_Build(&bogo_ip_vsa, res->ai_addr, res->ai_addrlen));
-	assert(VSA_Sane(bogo_ip));
-	freeaddrinfo(res);
+	AN(VSA_BuildFAP(&bogo_ip_vsa, PF_INET, NULL, 0, NULL, 0));
 }
 
 /*
@@ -266,6 +257,59 @@ VSA_Malloc(const void *s, unsigned  sal)
 	return (VSA_Build(d, s, sal));
 }
 
+/* 'd' SHALL point to vsa_suckaddr_len aligned bytes of storage
+ *
+ * fam: address family
+ * a / al : address and length
+ * p / pl : port and length
+ *
+ * NULL or 0 length argument are ignored.
+ * argument of the wrong length are an error (NULL return value, EINVAL)
+ */
+struct suckaddr *
+VSA_BuildFAP(void *d, sa_family_t fam, const void *a, unsigned al,
+	    const void *p, unsigned pl)
+{
+	struct sockaddr_in sin4;
+	struct sockaddr_in6 sin6;
+
+	switch (fam) {
+	case PF_INET:
+		memset(&sin4, 0, sizeof sin4);
+		sin4.sin_family = fam;
+		if (a != NULL && al > 0) {
+			if (al != sizeof(sin4.sin_addr))
+				break;
+			memcpy(&sin4.sin_addr, a, al);
+		}
+		if (p != NULL && pl > 0) {
+			if (pl != sizeof(sin4.sin_port))
+				break;
+			memcpy(&sin4.sin_port, p, pl);
+		}
+		return (VSA_Build(d, &sin4, sizeof sin4));
+	case PF_INET6:
+		memset(&sin6, 0, sizeof sin6);
+		sin6.sin6_family = fam;
+		if (a != NULL && al > 0) {
+			if (al != sizeof(sin6.sin6_addr))
+				break;
+			memcpy(&sin6.sin6_addr, a, al);
+		}
+		if (p != NULL && pl > 0) {
+			if (pl != sizeof(sin6.sin6_port))
+				break;
+			memcpy(&sin6.sin6_port, p, pl);
+		}
+		return (VSA_Build(d, &sin6, sizeof sin6));
+	default:
+		errno = EAFNOSUPPORT;
+		return (NULL);
+	}
+	errno = EINVAL;
+	return (NULL);
+}
+
 /* 'd' SHALL point to vsa_suckaddr_len aligned bytes of storage */
 struct suckaddr *
 VSA_Build(void *d, const void *s, unsigned sal)


More information about the varnish-commit mailing list