Skip to content

Commit

Permalink
os400: getpeername() and getsockname() return ebcdic AF_UNIX sockaddr,
Browse files Browse the repository at this point in the history
As libcurl now uses these 2 system functions, wrappers are needed on os400
to convert returned AF_UNIX sockaddrs to ascii.

This is a follow-up to commit 7fb54ef.
See also #4037.
Closes #4214
  • Loading branch information
monnerat committed Sep 24, 2019
1 parent 4a778f7 commit 3e0a8e5
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 55 deletions.
6 changes: 5 additions & 1 deletion lib/setup-os400.h
Expand Up @@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
Expand Down Expand Up @@ -206,11 +206,15 @@ extern int Curl_os400_sendto(int sd, char *buffer, int buflen, int flags,
struct sockaddr * dstaddr, int addrlen);
extern int Curl_os400_recvfrom(int sd, char *buffer, int buflen, int flags,
struct sockaddr *fromaddr, int *addrlen);
extern int Curl_os400_getpeername(int sd, struct sockaddr *addr, int *addrlen);
extern int Curl_os400_getsockname(int sd, struct sockaddr *addr, int *addrlen);

#define connect Curl_os400_connect
#define bind Curl_os400_bind
#define sendto Curl_os400_sendto
#define recvfrom Curl_os400_recvfrom
#define getpeername Curl_os400_getpeername
#define getsockname Curl_os400_getsockname

#ifdef HAVE_LIBZ
#define zlibVersion Curl_os400_zlibVersion
Expand Down
156 changes: 102 additions & 54 deletions packages/OS400/os400sys.c
Expand Up @@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
Expand Down Expand Up @@ -195,7 +195,7 @@ buffer_threaded(localkey_t key, long size)

/* Allocate buffer descriptors for the current thread. */

bufs = calloc((size_t) LK_LAST, sizeof *bufs);
bufs = calloc((size_t) LK_LAST, sizeof(*bufs));
if(!bufs)
return (char *) NULL;

Expand Down Expand Up @@ -224,7 +224,7 @@ buffer_undef(localkey_t key, long size)
if(Curl_thread_buffer == buffer_undef) { /* If unchanged during lock. */
if(!pthread_key_create(&thdkey, thdbufdestroy))
Curl_thread_buffer = buffer_threaded;
else if(!(locbufs = calloc((size_t) LK_LAST, sizeof *locbufs))) {
else if(!(locbufs = calloc((size_t) LK_LAST, sizeof(*locbufs)))) {
pthread_mutex_unlock(&mutex);
return (char *) NULL;
}
Expand Down Expand Up @@ -390,7 +390,7 @@ Curl_gsk_environment_open(gsk_handle * my_env_handle)

if(!my_env_handle)
return GSK_OS400_ERROR_INVALID_POINTER;
p = (struct Curl_gsk_descriptor *) malloc(sizeof *p);
p = (struct Curl_gsk_descriptor *) malloc(sizeof(*p));
if(!p)
return GSK_INSUFFICIENT_STORAGE;
p->strlist = (struct gskstrlist *) NULL;
Expand All @@ -417,7 +417,7 @@ Curl_gsk_secure_soc_open(gsk_handle my_env_handle,
if(!my_session_handle)
return GSK_OS400_ERROR_INVALID_POINTER;
h = ((struct Curl_gsk_descriptor *) my_env_handle)->h;
p = (struct Curl_gsk_descriptor *) malloc(sizeof *p);
p = (struct Curl_gsk_descriptor *) malloc(sizeof(*p));
if(!p)
return GSK_INSUFFICIENT_STORAGE;
p->strlist = (struct gskstrlist *) NULL;
Expand Down Expand Up @@ -598,7 +598,7 @@ cachestring(struct Curl_gsk_descriptor * p,
if(sp->ebcdicstr == ebcdicbuf)
break;
if(!sp) {
sp = (struct gskstrlist *) malloc(sizeof *sp);
sp = (struct gskstrlist *) malloc(sizeof(*sp));
if(!sp)
return GSK_INSUFFICIENT_STORAGE;
asciibuf = malloc(bufsize + 1);
Expand Down Expand Up @@ -800,7 +800,7 @@ Curl_gss_import_name_a(OM_uint32 * minor_status, gss_buffer_t in_name,
if(!in_name || !in_name->value || !in_name->length)
return gss_import_name(minor_status, in_name, in_name_type, out_name);

memcpy((char *) &in, (char *) in_name, sizeof in);
memcpy((char *) &in, (char *) in_name, sizeof(in));
i = in.length;

in.value = malloc(i + 1);
Expand Down Expand Up @@ -1048,7 +1048,7 @@ Curl_ldap_search_s_a(void * ld, char * base, int scope, char * filter,
for(i = 0; attrs[i++];)
;

eattrs = calloc(i, sizeof *eattrs);
eattrs = calloc(i, sizeof(*eattrs));
if(!eattrs)
status = LDAP_NO_MEMORY;
else {
Expand Down Expand Up @@ -1227,19 +1227,18 @@ Curl_ldap_next_attribute_a(void * ld,


static int
convert_sockaddr(struct sockaddr_storage * dstaddr,
const struct sockaddr * srcaddr, int srclen)

sockaddr2ebcdic(struct sockaddr_storage *dstaddr,
const struct sockaddr *srcaddr, int srclen)
{
const struct sockaddr_un * srcu;
struct sockaddr_un * dstu;
const struct sockaddr_un *srcu;
struct sockaddr_un *dstu;
unsigned int i;
unsigned int dstsize;

/* Convert a socket address into job CCSID, if needed. */
/* Convert a socket address to job CCSID, if needed. */

if(!srcaddr || srclen < offsetof(struct sockaddr, sa_family) +
sizeof srcaddr->sa_family || srclen > sizeof *dstaddr) {
sizeof(srcaddr->sa_family) || srclen > sizeof(*dstaddr)) {
errno = EINVAL;
return -1;
}
Expand All @@ -1251,26 +1250,67 @@ convert_sockaddr(struct sockaddr_storage * dstaddr,
case AF_UNIX:
srcu = (const struct sockaddr_un *) srcaddr;
dstu = (struct sockaddr_un *) dstaddr;
dstsize = sizeof *dstaddr - offsetof(struct sockaddr_un, sun_path);
dstsize = sizeof(*dstaddr) - offsetof(struct sockaddr_un, sun_path);
srclen -= offsetof(struct sockaddr_un, sun_path);
i = QadrtConvertA2E(dstu->sun_path, srcu->sun_path, dstsize - 1, srclen);
dstu->sun_path[i] = '\0';
i += offsetof(struct sockaddr_un, sun_path);
srclen = i;
srclen = i + offsetof(struct sockaddr_un, sun_path);
}

return srclen;
}


static int
sockaddr2ascii(struct sockaddr *dstaddr, int dstlen,
const struct sockaddr_storage *srcaddr, int srclen)
{
const struct sockaddr_un *srcu;
struct sockaddr_un *dstu;
unsigned int dstsize;

/* Convert a socket address to ASCII, if needed. */

if(!srclen)
return 0;
if(srclen > dstlen)
srclen = dstlen;
if(!srcaddr || srclen < 0) {
errno = EINVAL;
return -1;
}

memcpy((char *) dstaddr, (char *) srcaddr, srclen);

if(srclen >= offsetof(struct sockaddr_storage, ss_family) +
sizeof(srcaddr->ss_family)) {
switch (srcaddr->ss_family) {

case AF_UNIX:
srcu = (const struct sockaddr_un *) srcaddr;
dstu = (struct sockaddr_un *) dstaddr;
dstsize = dstlen - offsetof(struct sockaddr_un, sun_path);
srclen -= offsetof(struct sockaddr_un, sun_path);
if(dstsize > 0 && srclen > 0) {
srclen = QadrtConvertE2A(dstu->sun_path, srcu->sun_path,
dstsize - 1, srclen);
dstu->sun_path[srclen] = '\0';
}
srclen += offsetof(struct sockaddr_un, sun_path);
}
}

return srclen;
}


int
Curl_os400_connect(int sd, struct sockaddr * destaddr, int addrlen)

{
int i;
struct sockaddr_storage laddr;

i = convert_sockaddr(&laddr, destaddr, addrlen);
i = sockaddr2ebcdic(&laddr, destaddr, addrlen);

if(i < 0)
return -1;
Expand All @@ -1281,12 +1321,11 @@ Curl_os400_connect(int sd, struct sockaddr * destaddr, int addrlen)

int
Curl_os400_bind(int sd, struct sockaddr * localaddr, int addrlen)

{
int i;
struct sockaddr_storage laddr;

i = convert_sockaddr(&laddr, localaddr, addrlen);
i = sockaddr2ebcdic(&laddr, localaddr, addrlen);

if(i < 0)
return -1;
Expand All @@ -1298,12 +1337,11 @@ Curl_os400_bind(int sd, struct sockaddr * localaddr, int addrlen)
int
Curl_os400_sendto(int sd, char * buffer, int buflen, int flags,
struct sockaddr * dstaddr, int addrlen)

{
int i;
struct sockaddr_storage laddr;

i = convert_sockaddr(&laddr, dstaddr, addrlen);
i = sockaddr2ebcdic(&laddr, dstaddr, addrlen);

if(i < 0)
return -1;
Expand All @@ -1315,56 +1353,66 @@ Curl_os400_sendto(int sd, char * buffer, int buflen, int flags,
int
Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags,
struct sockaddr * fromaddr, int * addrlen)

{
int i;
int rcvlen;
int laddrlen;
const struct sockaddr_un * srcu;
struct sockaddr_un * dstu;
struct sockaddr_storage laddr;
int laddrlen = sizeof(laddr);

if(!fromaddr || !addrlen || *addrlen <= 0)
return recvfrom(sd, buffer, buflen, flags, fromaddr, addrlen);

laddrlen = sizeof laddr;
laddr.ss_family = AF_UNSPEC; /* To detect if unused. */
rcvlen = recvfrom(sd, buffer, buflen, flags,
(struct sockaddr *) &laddr, &laddrlen);

if(rcvlen < 0)
return rcvlen;

switch (laddr.ss_family) {

case AF_UNIX:
srcu = (const struct sockaddr_un *) &laddr;
dstu = (struct sockaddr_un *) fromaddr;
i = *addrlen - offsetof(struct sockaddr_un, sun_path);
laddrlen -= offsetof(struct sockaddr_un, sun_path);
i = QadrtConvertE2A(dstu->sun_path, srcu->sun_path, i, laddrlen);
laddrlen = i + offsetof(struct sockaddr_un, sun_path);

if(laddrlen < *addrlen)
dstu->sun_path[i] = '\0';
if(laddr.ss_family == AF_UNSPEC)
laddrlen = 0;
else {
laddrlen = sockaddr2ascii(fromaddr, *addrlen, &laddr, laddrlen);
if(laddrlen < 0)
return laddrlen;
}
*addrlen = laddrlen;
return rcvlen;
}

break;

case AF_UNSPEC:
break;
int
Curl_os400_getpeername(int sd, struct sockaddr *addr, int *addrlen)
{
struct sockaddr_storage laddr;
int laddrlen = sizeof(laddr);
int retcode = getpeername(sd, (struct sockaddr *) &laddr, &laddrlen);

if(!retcode) {
laddrlen = sockaddr2ascii(addr, *addrlen, &laddr, laddrlen);
if(laddrlen < 0)
return laddrlen;
*addrlen = laddrlen;
}

default:
if(laddrlen > *addrlen)
laddrlen = *addrlen;
return retcode;
}

if(laddrlen)
memcpy((char *) fromaddr, (char *) &laddr, laddrlen);

break;
}
int
Curl_os400_getsockname(int sd, struct sockaddr *addr, int *addrlen)
{
struct sockaddr_storage laddr;
int laddrlen = sizeof(laddr);
int retcode = getsockname(sd, (struct sockaddr *) &laddr, &laddrlen);

if(!retcode) {
laddrlen = sockaddr2ascii(addr, *addrlen, &laddr, laddrlen);
if(laddrlen < 0)
return laddrlen;
*addrlen = laddrlen;
}

*addrlen = laddrlen;
return rcvlen;
return retcode;
}


Expand Down

0 comments on commit 3e0a8e5

Please sign in to comment.