113498266Sopenharmony_ci/***************************************************************************
213498266Sopenharmony_ci *                                  _   _ ____  _
313498266Sopenharmony_ci *  Project                     ___| | | |  _ \| |
413498266Sopenharmony_ci *                             / __| | | | |_) | |
513498266Sopenharmony_ci *                            | (__| |_| |  _ <| |___
613498266Sopenharmony_ci *                             \___|\___/|_| \_\_____|
713498266Sopenharmony_ci *
813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
913498266Sopenharmony_ci *
1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which
1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms
1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html.
1313498266Sopenharmony_ci *
1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell
1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is
1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file.
1713498266Sopenharmony_ci *
1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
1913498266Sopenharmony_ci * KIND, either express or implied.
2013498266Sopenharmony_ci *
2113498266Sopenharmony_ci * SPDX-License-Identifier: curl
2213498266Sopenharmony_ci *
2313498266Sopenharmony_ci *
2413498266Sopenharmony_ci ***************************************************************************/
2513498266Sopenharmony_ci
2613498266Sopenharmony_ci/* OS/400 additional support. */
2713498266Sopenharmony_ci
2813498266Sopenharmony_ci#include <curl/curl.h>
2913498266Sopenharmony_ci#include "config-os400.h"  /* Not curl_setup.h: we only need some defines. */
3013498266Sopenharmony_ci
3113498266Sopenharmony_ci#include <sys/types.h>
3213498266Sopenharmony_ci#include <sys/socket.h>
3313498266Sopenharmony_ci#include <sys/un.h>
3413498266Sopenharmony_ci
3513498266Sopenharmony_ci#include <stdlib.h>
3613498266Sopenharmony_ci#include <stddef.h>
3713498266Sopenharmony_ci#include <string.h>
3813498266Sopenharmony_ci#include <pthread.h>
3913498266Sopenharmony_ci#include <netdb.h>
4013498266Sopenharmony_ci#include <qadrt.h>
4113498266Sopenharmony_ci#include <errno.h>
4213498266Sopenharmony_ci
4313498266Sopenharmony_ci#ifdef HAVE_LIBZ
4413498266Sopenharmony_ci#include <zlib.h>
4513498266Sopenharmony_ci#endif
4613498266Sopenharmony_ci
4713498266Sopenharmony_ci#ifdef HAVE_GSSAPI
4813498266Sopenharmony_ci#include <gssapi.h>
4913498266Sopenharmony_ci#endif
5013498266Sopenharmony_ci
5113498266Sopenharmony_ci#ifndef CURL_DISABLE_LDAP
5213498266Sopenharmony_ci#include <ldap.h>
5313498266Sopenharmony_ci#endif
5413498266Sopenharmony_ci
5513498266Sopenharmony_ci#include <netinet/in.h>
5613498266Sopenharmony_ci#include <arpa/inet.h>
5713498266Sopenharmony_ci
5813498266Sopenharmony_ci#include "os400sys.h"
5913498266Sopenharmony_ci
6013498266Sopenharmony_ci/**
6113498266Sopenharmony_ci*** QADRT OS/400 ASCII runtime defines only the most used procedures, but a
6213498266Sopenharmony_ci*** lot of them are not supported. This module implements ASCII wrappers for
6313498266Sopenharmony_ci*** those that are used by libcurl, but not defined by QADRT.
6413498266Sopenharmony_ci**/
6513498266Sopenharmony_ci
6613498266Sopenharmony_ci#pragma convert(0)                              /* Restore EBCDIC. */
6713498266Sopenharmony_ci
6813498266Sopenharmony_ci#define MIN_BYTE_GAIN   1024    /* Minimum gain when shortening a buffer. */
6913498266Sopenharmony_ci
7013498266Sopenharmony_cistruct buffer_t {
7113498266Sopenharmony_ci  unsigned long size;            /* Buffer size. */
7213498266Sopenharmony_ci  char *buf;                     /* Buffer address. */
7313498266Sopenharmony_ci};
7413498266Sopenharmony_ci
7513498266Sopenharmony_ci
7613498266Sopenharmony_cistatic char *buffer_undef(localkey_t key, long size);
7713498266Sopenharmony_cistatic char *buffer_threaded(localkey_t key, long size);
7813498266Sopenharmony_cistatic char *buffer_unthreaded(localkey_t key, long size);
7913498266Sopenharmony_ci
8013498266Sopenharmony_cistatic pthread_mutex_t  mutex = PTHREAD_MUTEX_INITIALIZER;
8113498266Sopenharmony_cistatic pthread_key_t    thdkey;
8213498266Sopenharmony_cistatic struct buffer_t *locbufs;
8313498266Sopenharmony_ci
8413498266Sopenharmony_cichar *(*Curl_thread_buffer)(localkey_t key, long size) = buffer_undef;
8513498266Sopenharmony_ci
8613498266Sopenharmony_cistatic void thdbufdestroy(void *private)
8713498266Sopenharmony_ci{
8813498266Sopenharmony_ci  if(private) {
8913498266Sopenharmony_ci    struct buffer_t *p = (struct buffer_t *) private;
9013498266Sopenharmony_ci    localkey_t i;
9113498266Sopenharmony_ci
9213498266Sopenharmony_ci    for(i = (localkey_t) 0; i < LK_LAST; i++) {
9313498266Sopenharmony_ci      free(p->buf);
9413498266Sopenharmony_ci      p++;
9513498266Sopenharmony_ci    }
9613498266Sopenharmony_ci
9713498266Sopenharmony_ci    free(private);
9813498266Sopenharmony_ci  }
9913498266Sopenharmony_ci}
10013498266Sopenharmony_ci
10113498266Sopenharmony_ci
10213498266Sopenharmony_cistatic void
10313498266Sopenharmony_citerminate(void)
10413498266Sopenharmony_ci{
10513498266Sopenharmony_ci  if(Curl_thread_buffer == buffer_threaded) {
10613498266Sopenharmony_ci    locbufs = pthread_getspecific(thdkey);
10713498266Sopenharmony_ci    pthread_setspecific(thdkey, (void *) NULL);
10813498266Sopenharmony_ci    pthread_key_delete(thdkey);
10913498266Sopenharmony_ci  }
11013498266Sopenharmony_ci
11113498266Sopenharmony_ci  if(Curl_thread_buffer != buffer_undef) {
11213498266Sopenharmony_ci    thdbufdestroy((void *) locbufs);
11313498266Sopenharmony_ci    locbufs = (struct buffer_t *) NULL;
11413498266Sopenharmony_ci  }
11513498266Sopenharmony_ci
11613498266Sopenharmony_ci  Curl_thread_buffer = buffer_undef;
11713498266Sopenharmony_ci}
11813498266Sopenharmony_ci
11913498266Sopenharmony_ci
12013498266Sopenharmony_cistatic char *
12113498266Sopenharmony_ciget_buffer(struct buffer_t *buf, long size)
12213498266Sopenharmony_ci{
12313498266Sopenharmony_ci  char *cp;
12413498266Sopenharmony_ci
12513498266Sopenharmony_ci  /* If `size' >= 0, make sure buffer at `buf' is at least `size'-byte long.
12613498266Sopenharmony_ci     Return the buffer address. */
12713498266Sopenharmony_ci
12813498266Sopenharmony_ci  if(size < 0)
12913498266Sopenharmony_ci    return buf->buf;
13013498266Sopenharmony_ci
13113498266Sopenharmony_ci  if(!buf->buf) {
13213498266Sopenharmony_ci    buf->buf = malloc(size);
13313498266Sopenharmony_ci    if(buf->buf)
13413498266Sopenharmony_ci      buf->size = size;
13513498266Sopenharmony_ci
13613498266Sopenharmony_ci    return buf->buf;
13713498266Sopenharmony_ci  }
13813498266Sopenharmony_ci
13913498266Sopenharmony_ci  if((unsigned long) size <= buf->size) {
14013498266Sopenharmony_ci    /* Shorten the buffer only if it frees a significant byte count. This
14113498266Sopenharmony_ci       avoids some realloc() overhead. */
14213498266Sopenharmony_ci
14313498266Sopenharmony_ci    if(buf->size - size < MIN_BYTE_GAIN)
14413498266Sopenharmony_ci      return buf->buf;
14513498266Sopenharmony_ci  }
14613498266Sopenharmony_ci
14713498266Sopenharmony_ci  /* Resize the buffer. */
14813498266Sopenharmony_ci
14913498266Sopenharmony_ci  cp = realloc(buf->buf, size);
15013498266Sopenharmony_ci  if(cp) {
15113498266Sopenharmony_ci    buf->buf = cp;
15213498266Sopenharmony_ci    buf->size = size;
15313498266Sopenharmony_ci  }
15413498266Sopenharmony_ci  else if(size <= buf->size)
15513498266Sopenharmony_ci    cp = buf->buf;
15613498266Sopenharmony_ci
15713498266Sopenharmony_ci  return cp;
15813498266Sopenharmony_ci}
15913498266Sopenharmony_ci
16013498266Sopenharmony_ci
16113498266Sopenharmony_cistatic char *
16213498266Sopenharmony_cibuffer_unthreaded(localkey_t key, long size)
16313498266Sopenharmony_ci{
16413498266Sopenharmony_ci  return get_buffer(locbufs + key, size);
16513498266Sopenharmony_ci}
16613498266Sopenharmony_ci
16713498266Sopenharmony_ci
16813498266Sopenharmony_cistatic char *
16913498266Sopenharmony_cibuffer_threaded(localkey_t key, long size)
17013498266Sopenharmony_ci{
17113498266Sopenharmony_ci  struct buffer_t *bufs;
17213498266Sopenharmony_ci
17313498266Sopenharmony_ci  /* Get the buffer for the given local key in the current thread, and
17413498266Sopenharmony_ci     make sure it is at least `size'-byte long. Set `size' to < 0 to get
17513498266Sopenharmony_ci     its address only. */
17613498266Sopenharmony_ci
17713498266Sopenharmony_ci  bufs = (struct buffer_t *) pthread_getspecific(thdkey);
17813498266Sopenharmony_ci
17913498266Sopenharmony_ci  if(!bufs) {
18013498266Sopenharmony_ci    if(size < 0)
18113498266Sopenharmony_ci      return (char *) NULL;             /* No buffer yet. */
18213498266Sopenharmony_ci
18313498266Sopenharmony_ci    /* Allocate buffer descriptors for the current thread. */
18413498266Sopenharmony_ci
18513498266Sopenharmony_ci    bufs = calloc((size_t) LK_LAST, sizeof(*bufs));
18613498266Sopenharmony_ci    if(!bufs)
18713498266Sopenharmony_ci      return (char *) NULL;
18813498266Sopenharmony_ci
18913498266Sopenharmony_ci    if(pthread_setspecific(thdkey, (void *) bufs)) {
19013498266Sopenharmony_ci      free(bufs);
19113498266Sopenharmony_ci      return (char *) NULL;
19213498266Sopenharmony_ci    }
19313498266Sopenharmony_ci  }
19413498266Sopenharmony_ci
19513498266Sopenharmony_ci  return get_buffer(bufs + key, size);
19613498266Sopenharmony_ci}
19713498266Sopenharmony_ci
19813498266Sopenharmony_ci
19913498266Sopenharmony_cistatic char *
20013498266Sopenharmony_cibuffer_undef(localkey_t key, long size)
20113498266Sopenharmony_ci{
20213498266Sopenharmony_ci  /* Define the buffer system, get the buffer for the given local key in
20313498266Sopenharmony_ci     the current thread, and make sure it is at least `size'-byte long.
20413498266Sopenharmony_ci     Set `size' to < 0 to get its address only. */
20513498266Sopenharmony_ci
20613498266Sopenharmony_ci  pthread_mutex_lock(&mutex);
20713498266Sopenharmony_ci
20813498266Sopenharmony_ci  /* Determine if we can use pthread-specific data. */
20913498266Sopenharmony_ci
21013498266Sopenharmony_ci  if(Curl_thread_buffer == buffer_undef) {      /* If unchanged during lock. */
21113498266Sopenharmony_ci    if(!pthread_key_create(&thdkey, thdbufdestroy))
21213498266Sopenharmony_ci      Curl_thread_buffer = buffer_threaded;
21313498266Sopenharmony_ci    else {
21413498266Sopenharmony_ci      locbufs = calloc((size_t) LK_LAST, sizeof(*locbufs));
21513498266Sopenharmony_ci      if(!locbufs) {
21613498266Sopenharmony_ci        pthread_mutex_unlock(&mutex);
21713498266Sopenharmony_ci        return (char *) NULL;
21813498266Sopenharmony_ci      }
21913498266Sopenharmony_ci      else
22013498266Sopenharmony_ci        Curl_thread_buffer = buffer_unthreaded;
22113498266Sopenharmony_ci    }
22213498266Sopenharmony_ci
22313498266Sopenharmony_ci    atexit(terminate);
22413498266Sopenharmony_ci  }
22513498266Sopenharmony_ci
22613498266Sopenharmony_ci  pthread_mutex_unlock(&mutex);
22713498266Sopenharmony_ci  return Curl_thread_buffer(key, size);
22813498266Sopenharmony_ci}
22913498266Sopenharmony_ci
23013498266Sopenharmony_ci
23113498266Sopenharmony_cistatic char *
23213498266Sopenharmony_ciset_thread_string(localkey_t key, const char *s)
23313498266Sopenharmony_ci{
23413498266Sopenharmony_ci  int i;
23513498266Sopenharmony_ci  char *cp;
23613498266Sopenharmony_ci
23713498266Sopenharmony_ci  if(!s)
23813498266Sopenharmony_ci    return (char *) NULL;
23913498266Sopenharmony_ci
24013498266Sopenharmony_ci  i = strlen(s) + 1;
24113498266Sopenharmony_ci  cp = Curl_thread_buffer(key, MAX_CONV_EXPANSION * i + 1);
24213498266Sopenharmony_ci
24313498266Sopenharmony_ci  if(cp) {
24413498266Sopenharmony_ci    i = QadrtConvertE2A(cp, s, MAX_CONV_EXPANSION * i, i);
24513498266Sopenharmony_ci    cp[i] = '\0';
24613498266Sopenharmony_ci  }
24713498266Sopenharmony_ci
24813498266Sopenharmony_ci  return cp;
24913498266Sopenharmony_ci}
25013498266Sopenharmony_ci
25113498266Sopenharmony_ci
25213498266Sopenharmony_ciint
25313498266Sopenharmony_ciCurl_getnameinfo_a(const struct sockaddr *sa, socklen_t salen,
25413498266Sopenharmony_ci                   char *nodename, socklen_t nodenamelen,
25513498266Sopenharmony_ci                   char *servname, socklen_t servnamelen,
25613498266Sopenharmony_ci                   int flags)
25713498266Sopenharmony_ci{
25813498266Sopenharmony_ci  char *enodename = NULL;
25913498266Sopenharmony_ci  char *eservname = NULL;
26013498266Sopenharmony_ci  int status;
26113498266Sopenharmony_ci
26213498266Sopenharmony_ci  if(nodename && nodenamelen) {
26313498266Sopenharmony_ci    enodename = malloc(nodenamelen);
26413498266Sopenharmony_ci    if(!enodename)
26513498266Sopenharmony_ci      return EAI_MEMORY;
26613498266Sopenharmony_ci  }
26713498266Sopenharmony_ci
26813498266Sopenharmony_ci  if(servname && servnamelen) {
26913498266Sopenharmony_ci    eservname = malloc(servnamelen);
27013498266Sopenharmony_ci    if(!eservname) {
27113498266Sopenharmony_ci      free(enodename);
27213498266Sopenharmony_ci      return EAI_MEMORY;
27313498266Sopenharmony_ci    }
27413498266Sopenharmony_ci  }
27513498266Sopenharmony_ci
27613498266Sopenharmony_ci  status = getnameinfo(sa, salen, enodename, nodenamelen,
27713498266Sopenharmony_ci                       eservname, servnamelen, flags);
27813498266Sopenharmony_ci
27913498266Sopenharmony_ci  if(!status) {
28013498266Sopenharmony_ci    int i;
28113498266Sopenharmony_ci    if(enodename) {
28213498266Sopenharmony_ci      i = QadrtConvertE2A(nodename, enodename,
28313498266Sopenharmony_ci                          nodenamelen - 1, strlen(enodename));
28413498266Sopenharmony_ci      nodename[i] = '\0';
28513498266Sopenharmony_ci    }
28613498266Sopenharmony_ci
28713498266Sopenharmony_ci    if(eservname) {
28813498266Sopenharmony_ci      i = QadrtConvertE2A(servname, eservname,
28913498266Sopenharmony_ci                          servnamelen - 1, strlen(eservname));
29013498266Sopenharmony_ci      servname[i] = '\0';
29113498266Sopenharmony_ci    }
29213498266Sopenharmony_ci  }
29313498266Sopenharmony_ci
29413498266Sopenharmony_ci  free(enodename);
29513498266Sopenharmony_ci  free(eservname);
29613498266Sopenharmony_ci  return status;
29713498266Sopenharmony_ci}
29813498266Sopenharmony_ci
29913498266Sopenharmony_ciint
30013498266Sopenharmony_ciCurl_getaddrinfo_a(const char *nodename, const char *servname,
30113498266Sopenharmony_ci                   const struct addrinfo *hints,
30213498266Sopenharmony_ci                   struct addrinfo **res)
30313498266Sopenharmony_ci{
30413498266Sopenharmony_ci  char *enodename;
30513498266Sopenharmony_ci  char *eservname;
30613498266Sopenharmony_ci  int status;
30713498266Sopenharmony_ci  int i;
30813498266Sopenharmony_ci
30913498266Sopenharmony_ci  enodename = (char *) NULL;
31013498266Sopenharmony_ci  eservname = (char *) NULL;
31113498266Sopenharmony_ci
31213498266Sopenharmony_ci  if(nodename) {
31313498266Sopenharmony_ci    i = strlen(nodename);
31413498266Sopenharmony_ci
31513498266Sopenharmony_ci    enodename = malloc(i + 1);
31613498266Sopenharmony_ci    if(!enodename)
31713498266Sopenharmony_ci      return EAI_MEMORY;
31813498266Sopenharmony_ci
31913498266Sopenharmony_ci    i = QadrtConvertA2E(enodename, nodename, i, i);
32013498266Sopenharmony_ci    enodename[i] = '\0';
32113498266Sopenharmony_ci  }
32213498266Sopenharmony_ci
32313498266Sopenharmony_ci  if(servname) {
32413498266Sopenharmony_ci    i = strlen(servname);
32513498266Sopenharmony_ci
32613498266Sopenharmony_ci    eservname = malloc(i + 1);
32713498266Sopenharmony_ci    if(!eservname) {
32813498266Sopenharmony_ci      free(enodename);
32913498266Sopenharmony_ci      return EAI_MEMORY;
33013498266Sopenharmony_ci    }
33113498266Sopenharmony_ci
33213498266Sopenharmony_ci    QadrtConvertA2E(eservname, servname, i, i);
33313498266Sopenharmony_ci    eservname[i] = '\0';
33413498266Sopenharmony_ci  }
33513498266Sopenharmony_ci
33613498266Sopenharmony_ci  status = getaddrinfo(enodename, eservname, hints, res);
33713498266Sopenharmony_ci  free(enodename);
33813498266Sopenharmony_ci  free(eservname);
33913498266Sopenharmony_ci  return status;
34013498266Sopenharmony_ci}
34113498266Sopenharmony_ci
34213498266Sopenharmony_ci#ifdef HAVE_GSSAPI
34313498266Sopenharmony_ci
34413498266Sopenharmony_ci/* ASCII wrappers for the GSSAPI procedures. */
34513498266Sopenharmony_ci
34613498266Sopenharmony_cistatic int
34713498266Sopenharmony_ciCurl_gss_convert_in_place(OM_uint32 *minor_status, gss_buffer_t buf)
34813498266Sopenharmony_ci{
34913498266Sopenharmony_ci  unsigned int i = buf->length;
35013498266Sopenharmony_ci
35113498266Sopenharmony_ci  /* Convert `buf' in place, from EBCDIC to ASCII.
35213498266Sopenharmony_ci     If error, release the buffer and return -1. Else return 0. */
35313498266Sopenharmony_ci
35413498266Sopenharmony_ci  if(i) {
35513498266Sopenharmony_ci    char *t = malloc(i);
35613498266Sopenharmony_ci    if(!t) {
35713498266Sopenharmony_ci      gss_release_buffer(minor_status, buf);
35813498266Sopenharmony_ci
35913498266Sopenharmony_ci      if(minor_status)
36013498266Sopenharmony_ci        *minor_status = ENOMEM;
36113498266Sopenharmony_ci
36213498266Sopenharmony_ci      return -1;
36313498266Sopenharmony_ci    }
36413498266Sopenharmony_ci
36513498266Sopenharmony_ci    QadrtConvertE2A(t, buf->value, i, i);
36613498266Sopenharmony_ci    memcpy(buf->value, t, i);
36713498266Sopenharmony_ci    free(t);
36813498266Sopenharmony_ci  }
36913498266Sopenharmony_ci
37013498266Sopenharmony_ci  return 0;
37113498266Sopenharmony_ci}
37213498266Sopenharmony_ci
37313498266Sopenharmony_ci
37413498266Sopenharmony_ciOM_uint32
37513498266Sopenharmony_ciCurl_gss_import_name_a(OM_uint32 *minor_status, gss_buffer_t in_name,
37613498266Sopenharmony_ci                       gss_OID in_name_type, gss_name_t *out_name)
37713498266Sopenharmony_ci{
37813498266Sopenharmony_ci  OM_uint32 rc;
37913498266Sopenharmony_ci  unsigned int i;
38013498266Sopenharmony_ci  gss_buffer_desc in;
38113498266Sopenharmony_ci
38213498266Sopenharmony_ci  if(!in_name || !in_name->value || !in_name->length)
38313498266Sopenharmony_ci    return gss_import_name(minor_status, in_name, in_name_type, out_name);
38413498266Sopenharmony_ci
38513498266Sopenharmony_ci  memcpy((char *) &in, (char *) in_name, sizeof(in));
38613498266Sopenharmony_ci  i = in.length;
38713498266Sopenharmony_ci
38813498266Sopenharmony_ci  in.value = malloc(i + 1);
38913498266Sopenharmony_ci  if(!in.value) {
39013498266Sopenharmony_ci    if(minor_status)
39113498266Sopenharmony_ci      *minor_status = ENOMEM;
39213498266Sopenharmony_ci
39313498266Sopenharmony_ci    return GSS_S_FAILURE;
39413498266Sopenharmony_ci  }
39513498266Sopenharmony_ci
39613498266Sopenharmony_ci  QadrtConvertA2E(in.value, in_name->value, i, i);
39713498266Sopenharmony_ci  ((char *) in.value)[i] = '\0';
39813498266Sopenharmony_ci  rc = gss_import_name(minor_status, &in, in_name_type, out_name);
39913498266Sopenharmony_ci  free(in.value);
40013498266Sopenharmony_ci  return rc;
40113498266Sopenharmony_ci}
40213498266Sopenharmony_ci
40313498266Sopenharmony_ciOM_uint32
40413498266Sopenharmony_ciCurl_gss_display_status_a(OM_uint32 *minor_status, OM_uint32 status_value,
40513498266Sopenharmony_ci                          int status_type, gss_OID mech_type,
40613498266Sopenharmony_ci                          gss_msg_ctx_t *message_context,
40713498266Sopenharmony_ci                          gss_buffer_t status_string)
40813498266Sopenharmony_ci{
40913498266Sopenharmony_ci  int rc;
41013498266Sopenharmony_ci
41113498266Sopenharmony_ci  rc = gss_display_status(minor_status, status_value, status_type,
41213498266Sopenharmony_ci                          mech_type, message_context, status_string);
41313498266Sopenharmony_ci
41413498266Sopenharmony_ci  if(rc != GSS_S_COMPLETE || !status_string ||
41513498266Sopenharmony_ci     !status_string->length || !status_string->value)
41613498266Sopenharmony_ci    return rc;
41713498266Sopenharmony_ci
41813498266Sopenharmony_ci  /* No way to allocate a buffer here, because it will be released by
41913498266Sopenharmony_ci     gss_release_buffer(). The solution is to overwrite the EBCDIC buffer
42013498266Sopenharmony_ci     with ASCII to return it. */
42113498266Sopenharmony_ci
42213498266Sopenharmony_ci  if(Curl_gss_convert_in_place(minor_status, status_string))
42313498266Sopenharmony_ci    return GSS_S_FAILURE;
42413498266Sopenharmony_ci
42513498266Sopenharmony_ci  return rc;
42613498266Sopenharmony_ci}
42713498266Sopenharmony_ci
42813498266Sopenharmony_ciOM_uint32
42913498266Sopenharmony_ciCurl_gss_init_sec_context_a(OM_uint32 *minor_status,
43013498266Sopenharmony_ci                            gss_cred_id_t cred_handle,
43113498266Sopenharmony_ci                            gss_ctx_id_t *context_handle,
43213498266Sopenharmony_ci                            gss_name_t target_name, gss_OID mech_type,
43313498266Sopenharmony_ci                            gss_flags_t req_flags, OM_uint32 time_req,
43413498266Sopenharmony_ci                            gss_channel_bindings_t input_chan_bindings,
43513498266Sopenharmony_ci                            gss_buffer_t input_token,
43613498266Sopenharmony_ci                            gss_OID *actual_mech_type,
43713498266Sopenharmony_ci                            gss_buffer_t output_token, gss_flags_t *ret_flags,
43813498266Sopenharmony_ci                            OM_uint32 *time_rec)
43913498266Sopenharmony_ci{
44013498266Sopenharmony_ci  int rc;
44113498266Sopenharmony_ci  gss_buffer_desc in;
44213498266Sopenharmony_ci  gss_buffer_t inp;
44313498266Sopenharmony_ci
44413498266Sopenharmony_ci  in.value = NULL;
44513498266Sopenharmony_ci  inp = input_token;
44613498266Sopenharmony_ci
44713498266Sopenharmony_ci  if(inp) {
44813498266Sopenharmony_ci    if(inp->length && inp->value) {
44913498266Sopenharmony_ci      unsigned int i = inp->length;
45013498266Sopenharmony_ci
45113498266Sopenharmony_ci      in.value = malloc(i + 1);
45213498266Sopenharmony_ci      if(!in.value) {
45313498266Sopenharmony_ci        if(minor_status)
45413498266Sopenharmony_ci          *minor_status = ENOMEM;
45513498266Sopenharmony_ci
45613498266Sopenharmony_ci        return GSS_S_FAILURE;
45713498266Sopenharmony_ci      }
45813498266Sopenharmony_ci
45913498266Sopenharmony_ci      QadrtConvertA2E(in.value, input_token->value, i, i);
46013498266Sopenharmony_ci      ((char *) in.value)[i] = '\0';
46113498266Sopenharmony_ci      in.length = i;
46213498266Sopenharmony_ci      inp = &in;
46313498266Sopenharmony_ci    }
46413498266Sopenharmony_ci  }
46513498266Sopenharmony_ci
46613498266Sopenharmony_ci  rc = gss_init_sec_context(minor_status, cred_handle, context_handle,
46713498266Sopenharmony_ci                            target_name, mech_type, req_flags, time_req,
46813498266Sopenharmony_ci                            input_chan_bindings, inp, actual_mech_type,
46913498266Sopenharmony_ci                            output_token, ret_flags, time_rec);
47013498266Sopenharmony_ci  free(in.value);
47113498266Sopenharmony_ci
47213498266Sopenharmony_ci  if(rc != GSS_S_COMPLETE || !output_token ||
47313498266Sopenharmony_ci     !output_token->length || !output_token->value)
47413498266Sopenharmony_ci    return rc;
47513498266Sopenharmony_ci
47613498266Sopenharmony_ci  /* No way to allocate a buffer here, because it will be released by
47713498266Sopenharmony_ci     gss_release_buffer(). The solution is to overwrite the EBCDIC buffer
47813498266Sopenharmony_ci     with ASCII to return it. */
47913498266Sopenharmony_ci
48013498266Sopenharmony_ci  if(Curl_gss_convert_in_place(minor_status, output_token))
48113498266Sopenharmony_ci    return GSS_S_FAILURE;
48213498266Sopenharmony_ci
48313498266Sopenharmony_ci  return rc;
48413498266Sopenharmony_ci}
48513498266Sopenharmony_ci
48613498266Sopenharmony_ci
48713498266Sopenharmony_ciOM_uint32
48813498266Sopenharmony_ciCurl_gss_delete_sec_context_a(OM_uint32 *minor_status,
48913498266Sopenharmony_ci                              gss_ctx_id_t *context_handle,
49013498266Sopenharmony_ci                              gss_buffer_t output_token)
49113498266Sopenharmony_ci{
49213498266Sopenharmony_ci  OM_uint32 rc;
49313498266Sopenharmony_ci
49413498266Sopenharmony_ci  rc = gss_delete_sec_context(minor_status, context_handle, output_token);
49513498266Sopenharmony_ci
49613498266Sopenharmony_ci  if(rc != GSS_S_COMPLETE || !output_token ||
49713498266Sopenharmony_ci     !output_token->length || !output_token->value)
49813498266Sopenharmony_ci    return rc;
49913498266Sopenharmony_ci
50013498266Sopenharmony_ci  /* No way to allocate a buffer here, because it will be released by
50113498266Sopenharmony_ci     gss_release_buffer(). The solution is to overwrite the EBCDIC buffer
50213498266Sopenharmony_ci     with ASCII to return it. */
50313498266Sopenharmony_ci
50413498266Sopenharmony_ci  if(Curl_gss_convert_in_place(minor_status, output_token))
50513498266Sopenharmony_ci    return GSS_S_FAILURE;
50613498266Sopenharmony_ci
50713498266Sopenharmony_ci  return rc;
50813498266Sopenharmony_ci}
50913498266Sopenharmony_ci
51013498266Sopenharmony_ci#endif /* HAVE_GSSAPI */
51113498266Sopenharmony_ci
51213498266Sopenharmony_ci#ifndef CURL_DISABLE_LDAP
51313498266Sopenharmony_ci
51413498266Sopenharmony_ci/* ASCII wrappers for the LDAP procedures. */
51513498266Sopenharmony_ci
51613498266Sopenharmony_civoid *
51713498266Sopenharmony_ciCurl_ldap_init_a(char *host, int port)
51813498266Sopenharmony_ci{
51913498266Sopenharmony_ci  size_t i;
52013498266Sopenharmony_ci  char *ehost;
52113498266Sopenharmony_ci  void *result;
52213498266Sopenharmony_ci
52313498266Sopenharmony_ci  if(!host)
52413498266Sopenharmony_ci    return (void *) ldap_init(host, port);
52513498266Sopenharmony_ci
52613498266Sopenharmony_ci  i = strlen(host);
52713498266Sopenharmony_ci
52813498266Sopenharmony_ci  ehost = malloc(i + 1);
52913498266Sopenharmony_ci  if(!ehost)
53013498266Sopenharmony_ci    return (void *) NULL;
53113498266Sopenharmony_ci
53213498266Sopenharmony_ci  QadrtConvertA2E(ehost, host, i, i);
53313498266Sopenharmony_ci  ehost[i] = '\0';
53413498266Sopenharmony_ci  result = (void *) ldap_init(ehost, port);
53513498266Sopenharmony_ci  free(ehost);
53613498266Sopenharmony_ci  return result;
53713498266Sopenharmony_ci}
53813498266Sopenharmony_ci
53913498266Sopenharmony_ciint
54013498266Sopenharmony_ciCurl_ldap_simple_bind_s_a(void *ld, char *dn, char *passwd)
54113498266Sopenharmony_ci{
54213498266Sopenharmony_ci  int i;
54313498266Sopenharmony_ci  char *edn;
54413498266Sopenharmony_ci  char *epasswd;
54513498266Sopenharmony_ci
54613498266Sopenharmony_ci  edn = (char *) NULL;
54713498266Sopenharmony_ci  epasswd = (char *) NULL;
54813498266Sopenharmony_ci
54913498266Sopenharmony_ci  if(dn) {
55013498266Sopenharmony_ci    i = strlen(dn);
55113498266Sopenharmony_ci
55213498266Sopenharmony_ci    edn = malloc(i + 1);
55313498266Sopenharmony_ci    if(!edn)
55413498266Sopenharmony_ci      return LDAP_NO_MEMORY;
55513498266Sopenharmony_ci
55613498266Sopenharmony_ci    QadrtConvertA2E(edn, dn, i, i);
55713498266Sopenharmony_ci    edn[i] = '\0';
55813498266Sopenharmony_ci  }
55913498266Sopenharmony_ci
56013498266Sopenharmony_ci  if(passwd) {
56113498266Sopenharmony_ci    i = strlen(passwd);
56213498266Sopenharmony_ci
56313498266Sopenharmony_ci    epasswd = malloc(i + 1);
56413498266Sopenharmony_ci    if(!epasswd) {
56513498266Sopenharmony_ci      free(edn);
56613498266Sopenharmony_ci      return LDAP_NO_MEMORY;
56713498266Sopenharmony_ci    }
56813498266Sopenharmony_ci
56913498266Sopenharmony_ci    QadrtConvertA2E(epasswd, passwd, i, i);
57013498266Sopenharmony_ci    epasswd[i] = '\0';
57113498266Sopenharmony_ci  }
57213498266Sopenharmony_ci
57313498266Sopenharmony_ci  i = ldap_simple_bind_s(ld, edn, epasswd);
57413498266Sopenharmony_ci  free(epasswd);
57513498266Sopenharmony_ci  free(edn);
57613498266Sopenharmony_ci  return i;
57713498266Sopenharmony_ci}
57813498266Sopenharmony_ci
57913498266Sopenharmony_ciint
58013498266Sopenharmony_ciCurl_ldap_search_s_a(void *ld, char *base, int scope, char *filter,
58113498266Sopenharmony_ci                     char **attrs, int attrsonly, LDAPMessage **res)
58213498266Sopenharmony_ci{
58313498266Sopenharmony_ci  int i;
58413498266Sopenharmony_ci  int j;
58513498266Sopenharmony_ci  char *ebase;
58613498266Sopenharmony_ci  char *efilter;
58713498266Sopenharmony_ci  char **eattrs;
58813498266Sopenharmony_ci  int status;
58913498266Sopenharmony_ci
59013498266Sopenharmony_ci  ebase = (char *) NULL;
59113498266Sopenharmony_ci  efilter = (char *) NULL;
59213498266Sopenharmony_ci  eattrs = (char **) NULL;
59313498266Sopenharmony_ci  status = LDAP_SUCCESS;
59413498266Sopenharmony_ci
59513498266Sopenharmony_ci  if(base) {
59613498266Sopenharmony_ci    i = strlen(base);
59713498266Sopenharmony_ci
59813498266Sopenharmony_ci    ebase = malloc(i + 1);
59913498266Sopenharmony_ci    if(!ebase)
60013498266Sopenharmony_ci      status = LDAP_NO_MEMORY;
60113498266Sopenharmony_ci    else {
60213498266Sopenharmony_ci      QadrtConvertA2E(ebase, base, i, i);
60313498266Sopenharmony_ci      ebase[i] = '\0';
60413498266Sopenharmony_ci    }
60513498266Sopenharmony_ci  }
60613498266Sopenharmony_ci
60713498266Sopenharmony_ci  if(filter && status == LDAP_SUCCESS) {
60813498266Sopenharmony_ci    i = strlen(filter);
60913498266Sopenharmony_ci
61013498266Sopenharmony_ci    efilter = malloc(i + 1);
61113498266Sopenharmony_ci    if(!efilter)
61213498266Sopenharmony_ci      status = LDAP_NO_MEMORY;
61313498266Sopenharmony_ci    else {
61413498266Sopenharmony_ci      QadrtConvertA2E(efilter, filter, i, i);
61513498266Sopenharmony_ci      efilter[i] = '\0';
61613498266Sopenharmony_ci    }
61713498266Sopenharmony_ci  }
61813498266Sopenharmony_ci
61913498266Sopenharmony_ci  if(attrs && status == LDAP_SUCCESS) {
62013498266Sopenharmony_ci    for(i = 0; attrs[i++];)
62113498266Sopenharmony_ci      ;
62213498266Sopenharmony_ci
62313498266Sopenharmony_ci    eattrs = calloc(i, sizeof(*eattrs));
62413498266Sopenharmony_ci    if(!eattrs)
62513498266Sopenharmony_ci      status = LDAP_NO_MEMORY;
62613498266Sopenharmony_ci    else {
62713498266Sopenharmony_ci      for(j = 0; attrs[j]; j++) {
62813498266Sopenharmony_ci        i = strlen(attrs[j]);
62913498266Sopenharmony_ci
63013498266Sopenharmony_ci        eattrs[j] = malloc(i + 1);
63113498266Sopenharmony_ci        if(!eattrs[j]) {
63213498266Sopenharmony_ci          status = LDAP_NO_MEMORY;
63313498266Sopenharmony_ci          break;
63413498266Sopenharmony_ci        }
63513498266Sopenharmony_ci
63613498266Sopenharmony_ci        QadrtConvertA2E(eattrs[j], attrs[j], i, i);
63713498266Sopenharmony_ci        eattrs[j][i] = '\0';
63813498266Sopenharmony_ci      }
63913498266Sopenharmony_ci    }
64013498266Sopenharmony_ci  }
64113498266Sopenharmony_ci
64213498266Sopenharmony_ci  if(status == LDAP_SUCCESS)
64313498266Sopenharmony_ci    status = ldap_search_s(ld, ebase? ebase: "", scope,
64413498266Sopenharmony_ci                           efilter? efilter: "(objectclass=*)",
64513498266Sopenharmony_ci                           eattrs, attrsonly, res);
64613498266Sopenharmony_ci
64713498266Sopenharmony_ci  if(eattrs) {
64813498266Sopenharmony_ci    for(j = 0; eattrs[j]; j++)
64913498266Sopenharmony_ci      free(eattrs[j]);
65013498266Sopenharmony_ci
65113498266Sopenharmony_ci    free(eattrs);
65213498266Sopenharmony_ci  }
65313498266Sopenharmony_ci
65413498266Sopenharmony_ci  free(efilter);
65513498266Sopenharmony_ci  free(ebase);
65613498266Sopenharmony_ci  return status;
65713498266Sopenharmony_ci}
65813498266Sopenharmony_ci
65913498266Sopenharmony_ci
66013498266Sopenharmony_cistruct berval **
66113498266Sopenharmony_ciCurl_ldap_get_values_len_a(void *ld, LDAPMessage *entry, const char *attr)
66213498266Sopenharmony_ci{
66313498266Sopenharmony_ci  char *cp;
66413498266Sopenharmony_ci  struct berval **result;
66513498266Sopenharmony_ci
66613498266Sopenharmony_ci  cp = (char *) NULL;
66713498266Sopenharmony_ci
66813498266Sopenharmony_ci  if(attr) {
66913498266Sopenharmony_ci    int i = strlen(attr);
67013498266Sopenharmony_ci
67113498266Sopenharmony_ci    cp = malloc(i + 1);
67213498266Sopenharmony_ci    if(!cp) {
67313498266Sopenharmony_ci      ldap_set_lderrno(ld, LDAP_NO_MEMORY, NULL,
67413498266Sopenharmony_ci                       ldap_err2string(LDAP_NO_MEMORY));
67513498266Sopenharmony_ci      return (struct berval **) NULL;
67613498266Sopenharmony_ci    }
67713498266Sopenharmony_ci
67813498266Sopenharmony_ci    QadrtConvertA2E(cp, attr, i, i);
67913498266Sopenharmony_ci    cp[i] = '\0';
68013498266Sopenharmony_ci  }
68113498266Sopenharmony_ci
68213498266Sopenharmony_ci  result = ldap_get_values_len(ld, entry, cp);
68313498266Sopenharmony_ci  free(cp);
68413498266Sopenharmony_ci
68513498266Sopenharmony_ci  /* Result data are binary in nature, so they haven't been
68613498266Sopenharmony_ci     converted to EBCDIC. Therefore do not convert. */
68713498266Sopenharmony_ci
68813498266Sopenharmony_ci  return result;
68913498266Sopenharmony_ci}
69013498266Sopenharmony_ci
69113498266Sopenharmony_cichar *
69213498266Sopenharmony_ciCurl_ldap_err2string_a(int error)
69313498266Sopenharmony_ci{
69413498266Sopenharmony_ci  return set_thread_string(LK_LDAP_ERROR, ldap_err2string(error));
69513498266Sopenharmony_ci}
69613498266Sopenharmony_ci
69713498266Sopenharmony_cichar *
69813498266Sopenharmony_ciCurl_ldap_get_dn_a(void *ld, LDAPMessage *entry)
69913498266Sopenharmony_ci{
70013498266Sopenharmony_ci  int i;
70113498266Sopenharmony_ci  char *cp;
70213498266Sopenharmony_ci  char *cp2;
70313498266Sopenharmony_ci
70413498266Sopenharmony_ci  cp = ldap_get_dn(ld, entry);
70513498266Sopenharmony_ci
70613498266Sopenharmony_ci  if(!cp)
70713498266Sopenharmony_ci    return cp;
70813498266Sopenharmony_ci
70913498266Sopenharmony_ci  i = strlen(cp);
71013498266Sopenharmony_ci
71113498266Sopenharmony_ci  cp2 = malloc(i + 1);
71213498266Sopenharmony_ci  if(!cp2)
71313498266Sopenharmony_ci    return cp2;
71413498266Sopenharmony_ci
71513498266Sopenharmony_ci  QadrtConvertE2A(cp2, cp, i, i);
71613498266Sopenharmony_ci  cp2[i] = '\0';
71713498266Sopenharmony_ci
71813498266Sopenharmony_ci  /* No way to allocate a buffer here, because it will be released by
71913498266Sopenharmony_ci     ldap_memfree() and ldap_memalloc() does not exist. The solution is to
72013498266Sopenharmony_ci     overwrite the EBCDIC buffer with ASCII to return it. */
72113498266Sopenharmony_ci
72213498266Sopenharmony_ci  strcpy(cp, cp2);
72313498266Sopenharmony_ci  free(cp2);
72413498266Sopenharmony_ci  return cp;
72513498266Sopenharmony_ci}
72613498266Sopenharmony_ci
72713498266Sopenharmony_cichar *
72813498266Sopenharmony_ciCurl_ldap_first_attribute_a(void *ld,
72913498266Sopenharmony_ci                            LDAPMessage *entry, BerElement **berptr)
73013498266Sopenharmony_ci{
73113498266Sopenharmony_ci  int i;
73213498266Sopenharmony_ci  char *cp;
73313498266Sopenharmony_ci  char *cp2;
73413498266Sopenharmony_ci
73513498266Sopenharmony_ci  cp = ldap_first_attribute(ld, entry, berptr);
73613498266Sopenharmony_ci
73713498266Sopenharmony_ci  if(!cp)
73813498266Sopenharmony_ci    return cp;
73913498266Sopenharmony_ci
74013498266Sopenharmony_ci  i = strlen(cp);
74113498266Sopenharmony_ci
74213498266Sopenharmony_ci  cp2 = malloc(i + 1);
74313498266Sopenharmony_ci  if(!cp2)
74413498266Sopenharmony_ci    return cp2;
74513498266Sopenharmony_ci
74613498266Sopenharmony_ci  QadrtConvertE2A(cp2, cp, i, i);
74713498266Sopenharmony_ci  cp2[i] = '\0';
74813498266Sopenharmony_ci
74913498266Sopenharmony_ci  /* No way to allocate a buffer here, because it will be released by
75013498266Sopenharmony_ci     ldap_memfree() and ldap_memalloc() does not exist. The solution is to
75113498266Sopenharmony_ci     overwrite the EBCDIC buffer with ASCII to return it. */
75213498266Sopenharmony_ci
75313498266Sopenharmony_ci  strcpy(cp, cp2);
75413498266Sopenharmony_ci  free(cp2);
75513498266Sopenharmony_ci  return cp;
75613498266Sopenharmony_ci}
75713498266Sopenharmony_ci
75813498266Sopenharmony_cichar *
75913498266Sopenharmony_ciCurl_ldap_next_attribute_a(void *ld,
76013498266Sopenharmony_ci                           LDAPMessage *entry, BerElement *berptr)
76113498266Sopenharmony_ci{
76213498266Sopenharmony_ci  int i;
76313498266Sopenharmony_ci  char *cp;
76413498266Sopenharmony_ci  char *cp2;
76513498266Sopenharmony_ci
76613498266Sopenharmony_ci  cp = ldap_next_attribute(ld, entry, berptr);
76713498266Sopenharmony_ci
76813498266Sopenharmony_ci  if(!cp)
76913498266Sopenharmony_ci    return cp;
77013498266Sopenharmony_ci
77113498266Sopenharmony_ci  i = strlen(cp);
77213498266Sopenharmony_ci
77313498266Sopenharmony_ci  cp2 = malloc(i + 1);
77413498266Sopenharmony_ci  if(!cp2)
77513498266Sopenharmony_ci    return cp2;
77613498266Sopenharmony_ci
77713498266Sopenharmony_ci  QadrtConvertE2A(cp2, cp, i, i);
77813498266Sopenharmony_ci  cp2[i] = '\0';
77913498266Sopenharmony_ci
78013498266Sopenharmony_ci  /* No way to allocate a buffer here, because it will be released by
78113498266Sopenharmony_ci     ldap_memfree() and ldap_memalloc() does not exist. The solution is to
78213498266Sopenharmony_ci     overwrite the EBCDIC buffer with ASCII to return it. */
78313498266Sopenharmony_ci
78413498266Sopenharmony_ci  strcpy(cp, cp2);
78513498266Sopenharmony_ci  free(cp2);
78613498266Sopenharmony_ci  return cp;
78713498266Sopenharmony_ci}
78813498266Sopenharmony_ci
78913498266Sopenharmony_ci#endif /* CURL_DISABLE_LDAP */
79013498266Sopenharmony_ci
79113498266Sopenharmony_cistatic int
79213498266Sopenharmony_cisockaddr2ebcdic(struct sockaddr_storage *dstaddr,
79313498266Sopenharmony_ci                const struct sockaddr *srcaddr, int srclen)
79413498266Sopenharmony_ci{
79513498266Sopenharmony_ci  const struct sockaddr_un *srcu;
79613498266Sopenharmony_ci  struct sockaddr_un *dstu;
79713498266Sopenharmony_ci  unsigned int i;
79813498266Sopenharmony_ci  unsigned int dstsize;
79913498266Sopenharmony_ci
80013498266Sopenharmony_ci  /* Convert a socket address to job CCSID, if needed. */
80113498266Sopenharmony_ci
80213498266Sopenharmony_ci  if(!srcaddr || srclen < offsetof(struct sockaddr, sa_family) +
80313498266Sopenharmony_ci     sizeof(srcaddr->sa_family) || srclen > sizeof(*dstaddr)) {
80413498266Sopenharmony_ci    errno = EINVAL;
80513498266Sopenharmony_ci    return -1;
80613498266Sopenharmony_ci  }
80713498266Sopenharmony_ci
80813498266Sopenharmony_ci  memcpy((char *) dstaddr, (char *) srcaddr, srclen);
80913498266Sopenharmony_ci
81013498266Sopenharmony_ci  switch(srcaddr->sa_family) {
81113498266Sopenharmony_ci
81213498266Sopenharmony_ci  case AF_UNIX:
81313498266Sopenharmony_ci    srcu = (const struct sockaddr_un *) srcaddr;
81413498266Sopenharmony_ci    dstu = (struct sockaddr_un *) dstaddr;
81513498266Sopenharmony_ci    dstsize = sizeof(*dstaddr) - offsetof(struct sockaddr_un, sun_path);
81613498266Sopenharmony_ci    srclen -= offsetof(struct sockaddr_un, sun_path);
81713498266Sopenharmony_ci    i = QadrtConvertA2E(dstu->sun_path, srcu->sun_path, dstsize - 1, srclen);
81813498266Sopenharmony_ci    dstu->sun_path[i] = '\0';
81913498266Sopenharmony_ci    srclen = i + offsetof(struct sockaddr_un, sun_path);
82013498266Sopenharmony_ci  }
82113498266Sopenharmony_ci
82213498266Sopenharmony_ci  return srclen;
82313498266Sopenharmony_ci}
82413498266Sopenharmony_ci
82513498266Sopenharmony_ci
82613498266Sopenharmony_cistatic int
82713498266Sopenharmony_cisockaddr2ascii(struct sockaddr *dstaddr, int dstlen,
82813498266Sopenharmony_ci               const struct sockaddr_storage *srcaddr, int srclen)
82913498266Sopenharmony_ci{
83013498266Sopenharmony_ci  const struct sockaddr_un *srcu;
83113498266Sopenharmony_ci  struct sockaddr_un *dstu;
83213498266Sopenharmony_ci  unsigned int dstsize;
83313498266Sopenharmony_ci
83413498266Sopenharmony_ci  /* Convert a socket address to ASCII, if needed. */
83513498266Sopenharmony_ci
83613498266Sopenharmony_ci  if(!srclen)
83713498266Sopenharmony_ci    return 0;
83813498266Sopenharmony_ci  if(srclen > dstlen)
83913498266Sopenharmony_ci    srclen = dstlen;
84013498266Sopenharmony_ci  if(!srcaddr || srclen < 0) {
84113498266Sopenharmony_ci    errno = EINVAL;
84213498266Sopenharmony_ci    return -1;
84313498266Sopenharmony_ci  }
84413498266Sopenharmony_ci
84513498266Sopenharmony_ci  memcpy((char *) dstaddr, (char *) srcaddr, srclen);
84613498266Sopenharmony_ci
84713498266Sopenharmony_ci  if(srclen >= offsetof(struct sockaddr_storage, ss_family) +
84813498266Sopenharmony_ci     sizeof(srcaddr->ss_family)) {
84913498266Sopenharmony_ci    switch(srcaddr->ss_family) {
85013498266Sopenharmony_ci
85113498266Sopenharmony_ci    case AF_UNIX:
85213498266Sopenharmony_ci      srcu = (const struct sockaddr_un *) srcaddr;
85313498266Sopenharmony_ci      dstu = (struct sockaddr_un *) dstaddr;
85413498266Sopenharmony_ci      dstsize = dstlen - offsetof(struct sockaddr_un, sun_path);
85513498266Sopenharmony_ci      srclen -= offsetof(struct sockaddr_un, sun_path);
85613498266Sopenharmony_ci      if(dstsize > 0 && srclen > 0) {
85713498266Sopenharmony_ci        srclen = QadrtConvertE2A(dstu->sun_path, srcu->sun_path,
85813498266Sopenharmony_ci                                 dstsize - 1, srclen);
85913498266Sopenharmony_ci        dstu->sun_path[srclen] = '\0';
86013498266Sopenharmony_ci      }
86113498266Sopenharmony_ci      srclen += offsetof(struct sockaddr_un, sun_path);
86213498266Sopenharmony_ci    }
86313498266Sopenharmony_ci  }
86413498266Sopenharmony_ci
86513498266Sopenharmony_ci  return srclen;
86613498266Sopenharmony_ci}
86713498266Sopenharmony_ci
86813498266Sopenharmony_ciint
86913498266Sopenharmony_ciCurl_os400_connect(int sd, struct sockaddr *destaddr, int addrlen)
87013498266Sopenharmony_ci{
87113498266Sopenharmony_ci  int i;
87213498266Sopenharmony_ci  struct sockaddr_storage laddr;
87313498266Sopenharmony_ci
87413498266Sopenharmony_ci  i = sockaddr2ebcdic(&laddr, destaddr, addrlen);
87513498266Sopenharmony_ci
87613498266Sopenharmony_ci  if(i < 0)
87713498266Sopenharmony_ci    return -1;
87813498266Sopenharmony_ci
87913498266Sopenharmony_ci  return connect(sd, (struct sockaddr *) &laddr, i);
88013498266Sopenharmony_ci}
88113498266Sopenharmony_ci
88213498266Sopenharmony_ciint
88313498266Sopenharmony_ciCurl_os400_bind(int sd, struct sockaddr *localaddr, int addrlen)
88413498266Sopenharmony_ci{
88513498266Sopenharmony_ci  int i;
88613498266Sopenharmony_ci  struct sockaddr_storage laddr;
88713498266Sopenharmony_ci
88813498266Sopenharmony_ci  i = sockaddr2ebcdic(&laddr, localaddr, addrlen);
88913498266Sopenharmony_ci
89013498266Sopenharmony_ci  if(i < 0)
89113498266Sopenharmony_ci    return -1;
89213498266Sopenharmony_ci
89313498266Sopenharmony_ci  return bind(sd, (struct sockaddr *) &laddr, i);
89413498266Sopenharmony_ci}
89513498266Sopenharmony_ci
89613498266Sopenharmony_ciint
89713498266Sopenharmony_ciCurl_os400_sendto(int sd, char *buffer, int buflen, int flags,
89813498266Sopenharmony_ci                  const struct sockaddr *dstaddr, int addrlen)
89913498266Sopenharmony_ci{
90013498266Sopenharmony_ci  int i;
90113498266Sopenharmony_ci  struct sockaddr_storage laddr;
90213498266Sopenharmony_ci
90313498266Sopenharmony_ci  i = sockaddr2ebcdic(&laddr, dstaddr, addrlen);
90413498266Sopenharmony_ci
90513498266Sopenharmony_ci  if(i < 0)
90613498266Sopenharmony_ci    return -1;
90713498266Sopenharmony_ci
90813498266Sopenharmony_ci  return sendto(sd, buffer, buflen, flags, (struct sockaddr *) &laddr, i);
90913498266Sopenharmony_ci}
91013498266Sopenharmony_ci
91113498266Sopenharmony_ciint
91213498266Sopenharmony_ciCurl_os400_recvfrom(int sd, char *buffer, int buflen, int flags,
91313498266Sopenharmony_ci                    struct sockaddr *fromaddr, int *addrlen)
91413498266Sopenharmony_ci{
91513498266Sopenharmony_ci  int rcvlen;
91613498266Sopenharmony_ci  struct sockaddr_storage laddr;
91713498266Sopenharmony_ci  int laddrlen = sizeof(laddr);
91813498266Sopenharmony_ci
91913498266Sopenharmony_ci  if(!fromaddr || !addrlen || *addrlen <= 0)
92013498266Sopenharmony_ci    return recvfrom(sd, buffer, buflen, flags, fromaddr, addrlen);
92113498266Sopenharmony_ci
92213498266Sopenharmony_ci  laddr.ss_family = AF_UNSPEC;          /* To detect if unused. */
92313498266Sopenharmony_ci  rcvlen = recvfrom(sd, buffer, buflen, flags,
92413498266Sopenharmony_ci                    (struct sockaddr *) &laddr, &laddrlen);
92513498266Sopenharmony_ci
92613498266Sopenharmony_ci  if(rcvlen < 0)
92713498266Sopenharmony_ci    return rcvlen;
92813498266Sopenharmony_ci
92913498266Sopenharmony_ci  if(laddr.ss_family == AF_UNSPEC)
93013498266Sopenharmony_ci    laddrlen = 0;
93113498266Sopenharmony_ci  else {
93213498266Sopenharmony_ci    laddrlen = sockaddr2ascii(fromaddr, *addrlen, &laddr, laddrlen);
93313498266Sopenharmony_ci    if(laddrlen < 0)
93413498266Sopenharmony_ci      return laddrlen;
93513498266Sopenharmony_ci  }
93613498266Sopenharmony_ci  *addrlen = laddrlen;
93713498266Sopenharmony_ci  return rcvlen;
93813498266Sopenharmony_ci}
93913498266Sopenharmony_ci
94013498266Sopenharmony_ciint
94113498266Sopenharmony_ciCurl_os400_getpeername(int sd, struct sockaddr *addr, int *addrlen)
94213498266Sopenharmony_ci{
94313498266Sopenharmony_ci  struct sockaddr_storage laddr;
94413498266Sopenharmony_ci  int laddrlen = sizeof(laddr);
94513498266Sopenharmony_ci  int retcode = getpeername(sd, (struct sockaddr *) &laddr, &laddrlen);
94613498266Sopenharmony_ci
94713498266Sopenharmony_ci  if(!retcode) {
94813498266Sopenharmony_ci    laddrlen = sockaddr2ascii(addr, *addrlen, &laddr, laddrlen);
94913498266Sopenharmony_ci    if(laddrlen < 0)
95013498266Sopenharmony_ci      return laddrlen;
95113498266Sopenharmony_ci    *addrlen = laddrlen;
95213498266Sopenharmony_ci  }
95313498266Sopenharmony_ci
95413498266Sopenharmony_ci  return retcode;
95513498266Sopenharmony_ci}
95613498266Sopenharmony_ci
95713498266Sopenharmony_ciint
95813498266Sopenharmony_ciCurl_os400_getsockname(int sd, struct sockaddr *addr, int *addrlen)
95913498266Sopenharmony_ci{
96013498266Sopenharmony_ci  struct sockaddr_storage laddr;
96113498266Sopenharmony_ci  int laddrlen = sizeof(laddr);
96213498266Sopenharmony_ci  int retcode = getsockname(sd, (struct sockaddr *) &laddr, &laddrlen);
96313498266Sopenharmony_ci
96413498266Sopenharmony_ci  if(!retcode) {
96513498266Sopenharmony_ci    laddrlen = sockaddr2ascii(addr, *addrlen, &laddr, laddrlen);
96613498266Sopenharmony_ci    if(laddrlen < 0)
96713498266Sopenharmony_ci      return laddrlen;
96813498266Sopenharmony_ci    *addrlen = laddrlen;
96913498266Sopenharmony_ci  }
97013498266Sopenharmony_ci
97113498266Sopenharmony_ci  return retcode;
97213498266Sopenharmony_ci}
97313498266Sopenharmony_ci
97413498266Sopenharmony_ci
97513498266Sopenharmony_ci#ifdef HAVE_LIBZ
97613498266Sopenharmony_ciconst char *
97713498266Sopenharmony_ciCurl_os400_zlibVersion(void)
97813498266Sopenharmony_ci{
97913498266Sopenharmony_ci  return set_thread_string(LK_ZLIB_VERSION, zlibVersion());
98013498266Sopenharmony_ci}
98113498266Sopenharmony_ci
98213498266Sopenharmony_ci
98313498266Sopenharmony_ciint
98413498266Sopenharmony_ciCurl_os400_inflateInit_(z_streamp strm, const char *version, int stream_size)
98513498266Sopenharmony_ci{
98613498266Sopenharmony_ci  z_const char *msgb4 = strm->msg;
98713498266Sopenharmony_ci  int ret;
98813498266Sopenharmony_ci
98913498266Sopenharmony_ci  ret = inflateInit(strm);
99013498266Sopenharmony_ci
99113498266Sopenharmony_ci  if(strm->msg != msgb4)
99213498266Sopenharmony_ci    strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
99313498266Sopenharmony_ci
99413498266Sopenharmony_ci  return ret;
99513498266Sopenharmony_ci}
99613498266Sopenharmony_ci
99713498266Sopenharmony_ciint
99813498266Sopenharmony_ciCurl_os400_inflateInit2_(z_streamp strm, int windowBits,
99913498266Sopenharmony_ci                         const char *version, int stream_size)
100013498266Sopenharmony_ci{
100113498266Sopenharmony_ci  z_const char *msgb4 = strm->msg;
100213498266Sopenharmony_ci  int ret;
100313498266Sopenharmony_ci
100413498266Sopenharmony_ci  ret = inflateInit2(strm, windowBits);
100513498266Sopenharmony_ci
100613498266Sopenharmony_ci  if(strm->msg != msgb4)
100713498266Sopenharmony_ci    strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
100813498266Sopenharmony_ci
100913498266Sopenharmony_ci  return ret;
101013498266Sopenharmony_ci}
101113498266Sopenharmony_ci
101213498266Sopenharmony_ciint
101313498266Sopenharmony_ciCurl_os400_inflate(z_streamp strm, int flush)
101413498266Sopenharmony_ci{
101513498266Sopenharmony_ci  z_const char *msgb4 = strm->msg;
101613498266Sopenharmony_ci  int ret;
101713498266Sopenharmony_ci
101813498266Sopenharmony_ci  ret = inflate(strm, flush);
101913498266Sopenharmony_ci
102013498266Sopenharmony_ci  if(strm->msg != msgb4)
102113498266Sopenharmony_ci    strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
102213498266Sopenharmony_ci
102313498266Sopenharmony_ci  return ret;
102413498266Sopenharmony_ci}
102513498266Sopenharmony_ci
102613498266Sopenharmony_ciint
102713498266Sopenharmony_ciCurl_os400_inflateEnd(z_streamp strm)
102813498266Sopenharmony_ci{
102913498266Sopenharmony_ci  z_const char *msgb4 = strm->msg;
103013498266Sopenharmony_ci  int ret;
103113498266Sopenharmony_ci
103213498266Sopenharmony_ci  ret = inflateEnd(strm);
103313498266Sopenharmony_ci
103413498266Sopenharmony_ci  if(strm->msg != msgb4)
103513498266Sopenharmony_ci    strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
103613498266Sopenharmony_ci
103713498266Sopenharmony_ci  return ret;
103813498266Sopenharmony_ci}
103913498266Sopenharmony_ci
104013498266Sopenharmony_ci#endif
1041