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.
parent 544f62bd
......@@ -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 */
......
......@@ -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.
......
......@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment