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