1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 * SPDX-License-Identifier: curl 22 * 23 * 24 ***************************************************************************/ 25 26/* OS/400 additional support. */ 27 28#include <curl/curl.h> 29#include "config-os400.h" /* Not curl_setup.h: we only need some defines. */ 30 31#include <sys/types.h> 32#include <sys/socket.h> 33#include <sys/un.h> 34 35#include <stdlib.h> 36#include <stddef.h> 37#include <string.h> 38#include <pthread.h> 39#include <netdb.h> 40#include <qadrt.h> 41#include <errno.h> 42 43#ifdef HAVE_LIBZ 44#include <zlib.h> 45#endif 46 47#ifdef HAVE_GSSAPI 48#include <gssapi.h> 49#endif 50 51#ifndef CURL_DISABLE_LDAP 52#include <ldap.h> 53#endif 54 55#include <netinet/in.h> 56#include <arpa/inet.h> 57 58#include "os400sys.h" 59 60/** 61*** QADRT OS/400 ASCII runtime defines only the most used procedures, but a 62*** lot of them are not supported. This module implements ASCII wrappers for 63*** those that are used by libcurl, but not defined by QADRT. 64**/ 65 66#pragma convert(0) /* Restore EBCDIC. */ 67 68#define MIN_BYTE_GAIN 1024 /* Minimum gain when shortening a buffer. */ 69 70struct buffer_t { 71 unsigned long size; /* Buffer size. */ 72 char *buf; /* Buffer address. */ 73}; 74 75 76static char *buffer_undef(localkey_t key, long size); 77static char *buffer_threaded(localkey_t key, long size); 78static char *buffer_unthreaded(localkey_t key, long size); 79 80static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 81static pthread_key_t thdkey; 82static struct buffer_t *locbufs; 83 84char *(*Curl_thread_buffer)(localkey_t key, long size) = buffer_undef; 85 86static void thdbufdestroy(void *private) 87{ 88 if(private) { 89 struct buffer_t *p = (struct buffer_t *) private; 90 localkey_t i; 91 92 for(i = (localkey_t) 0; i < LK_LAST; i++) { 93 free(p->buf); 94 p++; 95 } 96 97 free(private); 98 } 99} 100 101 102static void 103terminate(void) 104{ 105 if(Curl_thread_buffer == buffer_threaded) { 106 locbufs = pthread_getspecific(thdkey); 107 pthread_setspecific(thdkey, (void *) NULL); 108 pthread_key_delete(thdkey); 109 } 110 111 if(Curl_thread_buffer != buffer_undef) { 112 thdbufdestroy((void *) locbufs); 113 locbufs = (struct buffer_t *) NULL; 114 } 115 116 Curl_thread_buffer = buffer_undef; 117} 118 119 120static char * 121get_buffer(struct buffer_t *buf, long size) 122{ 123 char *cp; 124 125 /* If `size' >= 0, make sure buffer at `buf' is at least `size'-byte long. 126 Return the buffer address. */ 127 128 if(size < 0) 129 return buf->buf; 130 131 if(!buf->buf) { 132 buf->buf = malloc(size); 133 if(buf->buf) 134 buf->size = size; 135 136 return buf->buf; 137 } 138 139 if((unsigned long) size <= buf->size) { 140 /* Shorten the buffer only if it frees a significant byte count. This 141 avoids some realloc() overhead. */ 142 143 if(buf->size - size < MIN_BYTE_GAIN) 144 return buf->buf; 145 } 146 147 /* Resize the buffer. */ 148 149 cp = realloc(buf->buf, size); 150 if(cp) { 151 buf->buf = cp; 152 buf->size = size; 153 } 154 else if(size <= buf->size) 155 cp = buf->buf; 156 157 return cp; 158} 159 160 161static char * 162buffer_unthreaded(localkey_t key, long size) 163{ 164 return get_buffer(locbufs + key, size); 165} 166 167 168static char * 169buffer_threaded(localkey_t key, long size) 170{ 171 struct buffer_t *bufs; 172 173 /* Get the buffer for the given local key in the current thread, and 174 make sure it is at least `size'-byte long. Set `size' to < 0 to get 175 its address only. */ 176 177 bufs = (struct buffer_t *) pthread_getspecific(thdkey); 178 179 if(!bufs) { 180 if(size < 0) 181 return (char *) NULL; /* No buffer yet. */ 182 183 /* Allocate buffer descriptors for the current thread. */ 184 185 bufs = calloc((size_t) LK_LAST, sizeof(*bufs)); 186 if(!bufs) 187 return (char *) NULL; 188 189 if(pthread_setspecific(thdkey, (void *) bufs)) { 190 free(bufs); 191 return (char *) NULL; 192 } 193 } 194 195 return get_buffer(bufs + key, size); 196} 197 198 199static char * 200buffer_undef(localkey_t key, long size) 201{ 202 /* Define the buffer system, get the buffer for the given local key in 203 the current thread, and make sure it is at least `size'-byte long. 204 Set `size' to < 0 to get its address only. */ 205 206 pthread_mutex_lock(&mutex); 207 208 /* Determine if we can use pthread-specific data. */ 209 210 if(Curl_thread_buffer == buffer_undef) { /* If unchanged during lock. */ 211 if(!pthread_key_create(&thdkey, thdbufdestroy)) 212 Curl_thread_buffer = buffer_threaded; 213 else { 214 locbufs = calloc((size_t) LK_LAST, sizeof(*locbufs)); 215 if(!locbufs) { 216 pthread_mutex_unlock(&mutex); 217 return (char *) NULL; 218 } 219 else 220 Curl_thread_buffer = buffer_unthreaded; 221 } 222 223 atexit(terminate); 224 } 225 226 pthread_mutex_unlock(&mutex); 227 return Curl_thread_buffer(key, size); 228} 229 230 231static char * 232set_thread_string(localkey_t key, const char *s) 233{ 234 int i; 235 char *cp; 236 237 if(!s) 238 return (char *) NULL; 239 240 i = strlen(s) + 1; 241 cp = Curl_thread_buffer(key, MAX_CONV_EXPANSION * i + 1); 242 243 if(cp) { 244 i = QadrtConvertE2A(cp, s, MAX_CONV_EXPANSION * i, i); 245 cp[i] = '\0'; 246 } 247 248 return cp; 249} 250 251 252int 253Curl_getnameinfo_a(const struct sockaddr *sa, socklen_t salen, 254 char *nodename, socklen_t nodenamelen, 255 char *servname, socklen_t servnamelen, 256 int flags) 257{ 258 char *enodename = NULL; 259 char *eservname = NULL; 260 int status; 261 262 if(nodename && nodenamelen) { 263 enodename = malloc(nodenamelen); 264 if(!enodename) 265 return EAI_MEMORY; 266 } 267 268 if(servname && servnamelen) { 269 eservname = malloc(servnamelen); 270 if(!eservname) { 271 free(enodename); 272 return EAI_MEMORY; 273 } 274 } 275 276 status = getnameinfo(sa, salen, enodename, nodenamelen, 277 eservname, servnamelen, flags); 278 279 if(!status) { 280 int i; 281 if(enodename) { 282 i = QadrtConvertE2A(nodename, enodename, 283 nodenamelen - 1, strlen(enodename)); 284 nodename[i] = '\0'; 285 } 286 287 if(eservname) { 288 i = QadrtConvertE2A(servname, eservname, 289 servnamelen - 1, strlen(eservname)); 290 servname[i] = '\0'; 291 } 292 } 293 294 free(enodename); 295 free(eservname); 296 return status; 297} 298 299int 300Curl_getaddrinfo_a(const char *nodename, const char *servname, 301 const struct addrinfo *hints, 302 struct addrinfo **res) 303{ 304 char *enodename; 305 char *eservname; 306 int status; 307 int i; 308 309 enodename = (char *) NULL; 310 eservname = (char *) NULL; 311 312 if(nodename) { 313 i = strlen(nodename); 314 315 enodename = malloc(i + 1); 316 if(!enodename) 317 return EAI_MEMORY; 318 319 i = QadrtConvertA2E(enodename, nodename, i, i); 320 enodename[i] = '\0'; 321 } 322 323 if(servname) { 324 i = strlen(servname); 325 326 eservname = malloc(i + 1); 327 if(!eservname) { 328 free(enodename); 329 return EAI_MEMORY; 330 } 331 332 QadrtConvertA2E(eservname, servname, i, i); 333 eservname[i] = '\0'; 334 } 335 336 status = getaddrinfo(enodename, eservname, hints, res); 337 free(enodename); 338 free(eservname); 339 return status; 340} 341 342#ifdef HAVE_GSSAPI 343 344/* ASCII wrappers for the GSSAPI procedures. */ 345 346static int 347Curl_gss_convert_in_place(OM_uint32 *minor_status, gss_buffer_t buf) 348{ 349 unsigned int i = buf->length; 350 351 /* Convert `buf' in place, from EBCDIC to ASCII. 352 If error, release the buffer and return -1. Else return 0. */ 353 354 if(i) { 355 char *t = malloc(i); 356 if(!t) { 357 gss_release_buffer(minor_status, buf); 358 359 if(minor_status) 360 *minor_status = ENOMEM; 361 362 return -1; 363 } 364 365 QadrtConvertE2A(t, buf->value, i, i); 366 memcpy(buf->value, t, i); 367 free(t); 368 } 369 370 return 0; 371} 372 373 374OM_uint32 375Curl_gss_import_name_a(OM_uint32 *minor_status, gss_buffer_t in_name, 376 gss_OID in_name_type, gss_name_t *out_name) 377{ 378 OM_uint32 rc; 379 unsigned int i; 380 gss_buffer_desc in; 381 382 if(!in_name || !in_name->value || !in_name->length) 383 return gss_import_name(minor_status, in_name, in_name_type, out_name); 384 385 memcpy((char *) &in, (char *) in_name, sizeof(in)); 386 i = in.length; 387 388 in.value = malloc(i + 1); 389 if(!in.value) { 390 if(minor_status) 391 *minor_status = ENOMEM; 392 393 return GSS_S_FAILURE; 394 } 395 396 QadrtConvertA2E(in.value, in_name->value, i, i); 397 ((char *) in.value)[i] = '\0'; 398 rc = gss_import_name(minor_status, &in, in_name_type, out_name); 399 free(in.value); 400 return rc; 401} 402 403OM_uint32 404Curl_gss_display_status_a(OM_uint32 *minor_status, OM_uint32 status_value, 405 int status_type, gss_OID mech_type, 406 gss_msg_ctx_t *message_context, 407 gss_buffer_t status_string) 408{ 409 int rc; 410 411 rc = gss_display_status(minor_status, status_value, status_type, 412 mech_type, message_context, status_string); 413 414 if(rc != GSS_S_COMPLETE || !status_string || 415 !status_string->length || !status_string->value) 416 return rc; 417 418 /* No way to allocate a buffer here, because it will be released by 419 gss_release_buffer(). The solution is to overwrite the EBCDIC buffer 420 with ASCII to return it. */ 421 422 if(Curl_gss_convert_in_place(minor_status, status_string)) 423 return GSS_S_FAILURE; 424 425 return rc; 426} 427 428OM_uint32 429Curl_gss_init_sec_context_a(OM_uint32 *minor_status, 430 gss_cred_id_t cred_handle, 431 gss_ctx_id_t *context_handle, 432 gss_name_t target_name, gss_OID mech_type, 433 gss_flags_t req_flags, OM_uint32 time_req, 434 gss_channel_bindings_t input_chan_bindings, 435 gss_buffer_t input_token, 436 gss_OID *actual_mech_type, 437 gss_buffer_t output_token, gss_flags_t *ret_flags, 438 OM_uint32 *time_rec) 439{ 440 int rc; 441 gss_buffer_desc in; 442 gss_buffer_t inp; 443 444 in.value = NULL; 445 inp = input_token; 446 447 if(inp) { 448 if(inp->length && inp->value) { 449 unsigned int i = inp->length; 450 451 in.value = malloc(i + 1); 452 if(!in.value) { 453 if(minor_status) 454 *minor_status = ENOMEM; 455 456 return GSS_S_FAILURE; 457 } 458 459 QadrtConvertA2E(in.value, input_token->value, i, i); 460 ((char *) in.value)[i] = '\0'; 461 in.length = i; 462 inp = ∈ 463 } 464 } 465 466 rc = gss_init_sec_context(minor_status, cred_handle, context_handle, 467 target_name, mech_type, req_flags, time_req, 468 input_chan_bindings, inp, actual_mech_type, 469 output_token, ret_flags, time_rec); 470 free(in.value); 471 472 if(rc != GSS_S_COMPLETE || !output_token || 473 !output_token->length || !output_token->value) 474 return rc; 475 476 /* No way to allocate a buffer here, because it will be released by 477 gss_release_buffer(). The solution is to overwrite the EBCDIC buffer 478 with ASCII to return it. */ 479 480 if(Curl_gss_convert_in_place(minor_status, output_token)) 481 return GSS_S_FAILURE; 482 483 return rc; 484} 485 486 487OM_uint32 488Curl_gss_delete_sec_context_a(OM_uint32 *minor_status, 489 gss_ctx_id_t *context_handle, 490 gss_buffer_t output_token) 491{ 492 OM_uint32 rc; 493 494 rc = gss_delete_sec_context(minor_status, context_handle, output_token); 495 496 if(rc != GSS_S_COMPLETE || !output_token || 497 !output_token->length || !output_token->value) 498 return rc; 499 500 /* No way to allocate a buffer here, because it will be released by 501 gss_release_buffer(). The solution is to overwrite the EBCDIC buffer 502 with ASCII to return it. */ 503 504 if(Curl_gss_convert_in_place(minor_status, output_token)) 505 return GSS_S_FAILURE; 506 507 return rc; 508} 509 510#endif /* HAVE_GSSAPI */ 511 512#ifndef CURL_DISABLE_LDAP 513 514/* ASCII wrappers for the LDAP procedures. */ 515 516void * 517Curl_ldap_init_a(char *host, int port) 518{ 519 size_t i; 520 char *ehost; 521 void *result; 522 523 if(!host) 524 return (void *) ldap_init(host, port); 525 526 i = strlen(host); 527 528 ehost = malloc(i + 1); 529 if(!ehost) 530 return (void *) NULL; 531 532 QadrtConvertA2E(ehost, host, i, i); 533 ehost[i] = '\0'; 534 result = (void *) ldap_init(ehost, port); 535 free(ehost); 536 return result; 537} 538 539int 540Curl_ldap_simple_bind_s_a(void *ld, char *dn, char *passwd) 541{ 542 int i; 543 char *edn; 544 char *epasswd; 545 546 edn = (char *) NULL; 547 epasswd = (char *) NULL; 548 549 if(dn) { 550 i = strlen(dn); 551 552 edn = malloc(i + 1); 553 if(!edn) 554 return LDAP_NO_MEMORY; 555 556 QadrtConvertA2E(edn, dn, i, i); 557 edn[i] = '\0'; 558 } 559 560 if(passwd) { 561 i = strlen(passwd); 562 563 epasswd = malloc(i + 1); 564 if(!epasswd) { 565 free(edn); 566 return LDAP_NO_MEMORY; 567 } 568 569 QadrtConvertA2E(epasswd, passwd, i, i); 570 epasswd[i] = '\0'; 571 } 572 573 i = ldap_simple_bind_s(ld, edn, epasswd); 574 free(epasswd); 575 free(edn); 576 return i; 577} 578 579int 580Curl_ldap_search_s_a(void *ld, char *base, int scope, char *filter, 581 char **attrs, int attrsonly, LDAPMessage **res) 582{ 583 int i; 584 int j; 585 char *ebase; 586 char *efilter; 587 char **eattrs; 588 int status; 589 590 ebase = (char *) NULL; 591 efilter = (char *) NULL; 592 eattrs = (char **) NULL; 593 status = LDAP_SUCCESS; 594 595 if(base) { 596 i = strlen(base); 597 598 ebase = malloc(i + 1); 599 if(!ebase) 600 status = LDAP_NO_MEMORY; 601 else { 602 QadrtConvertA2E(ebase, base, i, i); 603 ebase[i] = '\0'; 604 } 605 } 606 607 if(filter && status == LDAP_SUCCESS) { 608 i = strlen(filter); 609 610 efilter = malloc(i + 1); 611 if(!efilter) 612 status = LDAP_NO_MEMORY; 613 else { 614 QadrtConvertA2E(efilter, filter, i, i); 615 efilter[i] = '\0'; 616 } 617 } 618 619 if(attrs && status == LDAP_SUCCESS) { 620 for(i = 0; attrs[i++];) 621 ; 622 623 eattrs = calloc(i, sizeof(*eattrs)); 624 if(!eattrs) 625 status = LDAP_NO_MEMORY; 626 else { 627 for(j = 0; attrs[j]; j++) { 628 i = strlen(attrs[j]); 629 630 eattrs[j] = malloc(i + 1); 631 if(!eattrs[j]) { 632 status = LDAP_NO_MEMORY; 633 break; 634 } 635 636 QadrtConvertA2E(eattrs[j], attrs[j], i, i); 637 eattrs[j][i] = '\0'; 638 } 639 } 640 } 641 642 if(status == LDAP_SUCCESS) 643 status = ldap_search_s(ld, ebase? ebase: "", scope, 644 efilter? efilter: "(objectclass=*)", 645 eattrs, attrsonly, res); 646 647 if(eattrs) { 648 for(j = 0; eattrs[j]; j++) 649 free(eattrs[j]); 650 651 free(eattrs); 652 } 653 654 free(efilter); 655 free(ebase); 656 return status; 657} 658 659 660struct berval ** 661Curl_ldap_get_values_len_a(void *ld, LDAPMessage *entry, const char *attr) 662{ 663 char *cp; 664 struct berval **result; 665 666 cp = (char *) NULL; 667 668 if(attr) { 669 int i = strlen(attr); 670 671 cp = malloc(i + 1); 672 if(!cp) { 673 ldap_set_lderrno(ld, LDAP_NO_MEMORY, NULL, 674 ldap_err2string(LDAP_NO_MEMORY)); 675 return (struct berval **) NULL; 676 } 677 678 QadrtConvertA2E(cp, attr, i, i); 679 cp[i] = '\0'; 680 } 681 682 result = ldap_get_values_len(ld, entry, cp); 683 free(cp); 684 685 /* Result data are binary in nature, so they haven't been 686 converted to EBCDIC. Therefore do not convert. */ 687 688 return result; 689} 690 691char * 692Curl_ldap_err2string_a(int error) 693{ 694 return set_thread_string(LK_LDAP_ERROR, ldap_err2string(error)); 695} 696 697char * 698Curl_ldap_get_dn_a(void *ld, LDAPMessage *entry) 699{ 700 int i; 701 char *cp; 702 char *cp2; 703 704 cp = ldap_get_dn(ld, entry); 705 706 if(!cp) 707 return cp; 708 709 i = strlen(cp); 710 711 cp2 = malloc(i + 1); 712 if(!cp2) 713 return cp2; 714 715 QadrtConvertE2A(cp2, cp, i, i); 716 cp2[i] = '\0'; 717 718 /* No way to allocate a buffer here, because it will be released by 719 ldap_memfree() and ldap_memalloc() does not exist. The solution is to 720 overwrite the EBCDIC buffer with ASCII to return it. */ 721 722 strcpy(cp, cp2); 723 free(cp2); 724 return cp; 725} 726 727char * 728Curl_ldap_first_attribute_a(void *ld, 729 LDAPMessage *entry, BerElement **berptr) 730{ 731 int i; 732 char *cp; 733 char *cp2; 734 735 cp = ldap_first_attribute(ld, entry, berptr); 736 737 if(!cp) 738 return cp; 739 740 i = strlen(cp); 741 742 cp2 = malloc(i + 1); 743 if(!cp2) 744 return cp2; 745 746 QadrtConvertE2A(cp2, cp, i, i); 747 cp2[i] = '\0'; 748 749 /* No way to allocate a buffer here, because it will be released by 750 ldap_memfree() and ldap_memalloc() does not exist. The solution is to 751 overwrite the EBCDIC buffer with ASCII to return it. */ 752 753 strcpy(cp, cp2); 754 free(cp2); 755 return cp; 756} 757 758char * 759Curl_ldap_next_attribute_a(void *ld, 760 LDAPMessage *entry, BerElement *berptr) 761{ 762 int i; 763 char *cp; 764 char *cp2; 765 766 cp = ldap_next_attribute(ld, entry, berptr); 767 768 if(!cp) 769 return cp; 770 771 i = strlen(cp); 772 773 cp2 = malloc(i + 1); 774 if(!cp2) 775 return cp2; 776 777 QadrtConvertE2A(cp2, cp, i, i); 778 cp2[i] = '\0'; 779 780 /* No way to allocate a buffer here, because it will be released by 781 ldap_memfree() and ldap_memalloc() does not exist. The solution is to 782 overwrite the EBCDIC buffer with ASCII to return it. */ 783 784 strcpy(cp, cp2); 785 free(cp2); 786 return cp; 787} 788 789#endif /* CURL_DISABLE_LDAP */ 790 791static int 792sockaddr2ebcdic(struct sockaddr_storage *dstaddr, 793 const struct sockaddr *srcaddr, int srclen) 794{ 795 const struct sockaddr_un *srcu; 796 struct sockaddr_un *dstu; 797 unsigned int i; 798 unsigned int dstsize; 799 800 /* Convert a socket address to job CCSID, if needed. */ 801 802 if(!srcaddr || srclen < offsetof(struct sockaddr, sa_family) + 803 sizeof(srcaddr->sa_family) || srclen > sizeof(*dstaddr)) { 804 errno = EINVAL; 805 return -1; 806 } 807 808 memcpy((char *) dstaddr, (char *) srcaddr, srclen); 809 810 switch(srcaddr->sa_family) { 811 812 case AF_UNIX: 813 srcu = (const struct sockaddr_un *) srcaddr; 814 dstu = (struct sockaddr_un *) dstaddr; 815 dstsize = sizeof(*dstaddr) - offsetof(struct sockaddr_un, sun_path); 816 srclen -= offsetof(struct sockaddr_un, sun_path); 817 i = QadrtConvertA2E(dstu->sun_path, srcu->sun_path, dstsize - 1, srclen); 818 dstu->sun_path[i] = '\0'; 819 srclen = i + offsetof(struct sockaddr_un, sun_path); 820 } 821 822 return srclen; 823} 824 825 826static int 827sockaddr2ascii(struct sockaddr *dstaddr, int dstlen, 828 const struct sockaddr_storage *srcaddr, int srclen) 829{ 830 const struct sockaddr_un *srcu; 831 struct sockaddr_un *dstu; 832 unsigned int dstsize; 833 834 /* Convert a socket address to ASCII, if needed. */ 835 836 if(!srclen) 837 return 0; 838 if(srclen > dstlen) 839 srclen = dstlen; 840 if(!srcaddr || srclen < 0) { 841 errno = EINVAL; 842 return -1; 843 } 844 845 memcpy((char *) dstaddr, (char *) srcaddr, srclen); 846 847 if(srclen >= offsetof(struct sockaddr_storage, ss_family) + 848 sizeof(srcaddr->ss_family)) { 849 switch(srcaddr->ss_family) { 850 851 case AF_UNIX: 852 srcu = (const struct sockaddr_un *) srcaddr; 853 dstu = (struct sockaddr_un *) dstaddr; 854 dstsize = dstlen - offsetof(struct sockaddr_un, sun_path); 855 srclen -= offsetof(struct sockaddr_un, sun_path); 856 if(dstsize > 0 && srclen > 0) { 857 srclen = QadrtConvertE2A(dstu->sun_path, srcu->sun_path, 858 dstsize - 1, srclen); 859 dstu->sun_path[srclen] = '\0'; 860 } 861 srclen += offsetof(struct sockaddr_un, sun_path); 862 } 863 } 864 865 return srclen; 866} 867 868int 869Curl_os400_connect(int sd, struct sockaddr *destaddr, int addrlen) 870{ 871 int i; 872 struct sockaddr_storage laddr; 873 874 i = sockaddr2ebcdic(&laddr, destaddr, addrlen); 875 876 if(i < 0) 877 return -1; 878 879 return connect(sd, (struct sockaddr *) &laddr, i); 880} 881 882int 883Curl_os400_bind(int sd, struct sockaddr *localaddr, int addrlen) 884{ 885 int i; 886 struct sockaddr_storage laddr; 887 888 i = sockaddr2ebcdic(&laddr, localaddr, addrlen); 889 890 if(i < 0) 891 return -1; 892 893 return bind(sd, (struct sockaddr *) &laddr, i); 894} 895 896int 897Curl_os400_sendto(int sd, char *buffer, int buflen, int flags, 898 const struct sockaddr *dstaddr, int addrlen) 899{ 900 int i; 901 struct sockaddr_storage laddr; 902 903 i = sockaddr2ebcdic(&laddr, dstaddr, addrlen); 904 905 if(i < 0) 906 return -1; 907 908 return sendto(sd, buffer, buflen, flags, (struct sockaddr *) &laddr, i); 909} 910 911int 912Curl_os400_recvfrom(int sd, char *buffer, int buflen, int flags, 913 struct sockaddr *fromaddr, int *addrlen) 914{ 915 int rcvlen; 916 struct sockaddr_storage laddr; 917 int laddrlen = sizeof(laddr); 918 919 if(!fromaddr || !addrlen || *addrlen <= 0) 920 return recvfrom(sd, buffer, buflen, flags, fromaddr, addrlen); 921 922 laddr.ss_family = AF_UNSPEC; /* To detect if unused. */ 923 rcvlen = recvfrom(sd, buffer, buflen, flags, 924 (struct sockaddr *) &laddr, &laddrlen); 925 926 if(rcvlen < 0) 927 return rcvlen; 928 929 if(laddr.ss_family == AF_UNSPEC) 930 laddrlen = 0; 931 else { 932 laddrlen = sockaddr2ascii(fromaddr, *addrlen, &laddr, laddrlen); 933 if(laddrlen < 0) 934 return laddrlen; 935 } 936 *addrlen = laddrlen; 937 return rcvlen; 938} 939 940int 941Curl_os400_getpeername(int sd, struct sockaddr *addr, int *addrlen) 942{ 943 struct sockaddr_storage laddr; 944 int laddrlen = sizeof(laddr); 945 int retcode = getpeername(sd, (struct sockaddr *) &laddr, &laddrlen); 946 947 if(!retcode) { 948 laddrlen = sockaddr2ascii(addr, *addrlen, &laddr, laddrlen); 949 if(laddrlen < 0) 950 return laddrlen; 951 *addrlen = laddrlen; 952 } 953 954 return retcode; 955} 956 957int 958Curl_os400_getsockname(int sd, struct sockaddr *addr, int *addrlen) 959{ 960 struct sockaddr_storage laddr; 961 int laddrlen = sizeof(laddr); 962 int retcode = getsockname(sd, (struct sockaddr *) &laddr, &laddrlen); 963 964 if(!retcode) { 965 laddrlen = sockaddr2ascii(addr, *addrlen, &laddr, laddrlen); 966 if(laddrlen < 0) 967 return laddrlen; 968 *addrlen = laddrlen; 969 } 970 971 return retcode; 972} 973 974 975#ifdef HAVE_LIBZ 976const char * 977Curl_os400_zlibVersion(void) 978{ 979 return set_thread_string(LK_ZLIB_VERSION, zlibVersion()); 980} 981 982 983int 984Curl_os400_inflateInit_(z_streamp strm, const char *version, int stream_size) 985{ 986 z_const char *msgb4 = strm->msg; 987 int ret; 988 989 ret = inflateInit(strm); 990 991 if(strm->msg != msgb4) 992 strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg); 993 994 return ret; 995} 996 997int 998Curl_os400_inflateInit2_(z_streamp strm, int windowBits, 999 const char *version, int stream_size) 1000{ 1001 z_const char *msgb4 = strm->msg; 1002 int ret; 1003 1004 ret = inflateInit2(strm, windowBits); 1005 1006 if(strm->msg != msgb4) 1007 strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg); 1008 1009 return ret; 1010} 1011 1012int 1013Curl_os400_inflate(z_streamp strm, int flush) 1014{ 1015 z_const char *msgb4 = strm->msg; 1016 int ret; 1017 1018 ret = inflate(strm, flush); 1019 1020 if(strm->msg != msgb4) 1021 strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg); 1022 1023 return ret; 1024} 1025 1026int 1027Curl_os400_inflateEnd(z_streamp strm) 1028{ 1029 z_const char *msgb4 = strm->msg; 1030 int ret; 1031 1032 ret = inflateEnd(strm); 1033 1034 if(strm->msg != msgb4) 1035 strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg); 1036 1037 return ret; 1038} 1039 1040#endif 1041