From 3e0a8e539c57b9bed8265b38c2c3007cab6040e3 Mon Sep 17 00:00:00 2001 From: Patrick Monnerat Date: Sun, 11 Aug 2019 17:22:45 +0200 Subject: [PATCH] os400: getpeername() and getsockname() return ebcdic AF_UNIX sockaddr, 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 --- lib/setup-os400.h | 6 +- packages/OS400/os400sys.c | 164 ++++++++++++++++++++++++-------------- 2 files changed, 111 insertions(+), 59 deletions(-) diff --git a/lib/setup-os400.h b/lib/setup-os400.h index a3c2a7bdc..629fd94c4 100644 --- a/lib/setup-os400.h +++ b/lib/setup-os400.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -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 diff --git a/packages/OS400/os400sys.c b/packages/OS400/os400sys.c index 67b34a84c..3490fc779 100644 --- a/packages/OS400/os400sys.c +++ b/packages/OS400/os400sys.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -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; @@ -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; } @@ -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; @@ -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; @@ -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); @@ -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); @@ -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 { @@ -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; } @@ -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; @@ -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; @@ -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; @@ -1315,19 +1353,14 @@ 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); @@ -1335,39 +1368,54 @@ Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags, 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'; - - break; - - case AF_UNSPEC: - break; - - default: - if(laddrlen > *addrlen) - laddrlen = *addrlen; - - if(laddrlen) - memcpy((char *) fromaddr, (char *) &laddr, laddrlen); - - break; - } - + if(laddr.ss_family == AF_UNSPEC) + laddrlen = 0; + else { + laddrlen = sockaddr2ascii(fromaddr, *addrlen, &laddr, laddrlen); + if(laddrlen < 0) + return laddrlen; + } *addrlen = laddrlen; return rcvlen; } +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; + } + + return retcode; +} + + +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; + } + + return retcode; +} + + #ifdef HAVE_LIBZ const char * Curl_os400_zlibVersion(void)