1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
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.
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.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
23 ***************************************************************************/
25 /* OS/400 additional support. */
27 #include "config-os400.h" /* Not setup.h: we only need some defines. */
29 #include <sys/types.h>
30 #include <sys/socket.h>
49 #ifndef CURL_DISABLE_LDAP
53 #include <netinet/in.h>
54 #include <arpa/inet.h>
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
66 #pragma convert(0) /* Restore EBCDIC. */
69 #define MIN_BYTE_GAIN 1024 /* Minimum gain when shortening a buffer. */
72 unsigned long size; /* Buffer size. */
73 char * buf; /* Buffer address. */
77 static char * buffer_undef(localkey_t key, long size);
78 static char * buffer_threaded(localkey_t key, long size);
79 static char * buffer_unthreaded(localkey_t key, long size);
81 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
82 static pthread_key_t thdkey;
83 static buffer_t * locbufs;
85 char * (* Curl_thread_buffer)(localkey_t key, long size) = buffer_undef;
89 thdbufdestroy(void * private)
96 p = (buffer_t *) private;
98 for (i = (localkey_t) 0; i < LK_LAST; i++) {
114 if (Curl_thread_buffer == buffer_threaded) {
115 locbufs = pthread_getspecific(thdkey);
116 pthread_setspecific(thdkey, (void *) NULL);
117 pthread_key_delete(thdkey);
120 if (Curl_thread_buffer != buffer_undef) {
121 thdbufdestroy((void *) locbufs);
122 locbufs = (buffer_t *) NULL;
125 Curl_thread_buffer = buffer_undef;
130 get_buffer(buffer_t * buf, long size)
135 /* If `size' >= 0, make sure buffer at `buf' is at least `size'-byte long.
136 Return the buffer address. */
142 if ((buf->buf = malloc(size)))
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. */
152 if (buf->size - size < MIN_BYTE_GAIN)
156 /* Resize the buffer. */
158 if ((cp = realloc(buf->buf, size))) {
162 else if (size <= buf->size)
170 buffer_unthreaded(localkey_t key, long size)
173 return get_buffer(locbufs + key, size);
178 buffer_threaded(localkey_t key, long size)
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
187 bufs = (buffer_t *) pthread_getspecific(thdkey);
191 return (char *) NULL; /* No buffer yet. */
193 /* Allocate buffer descriptors for the current thread. */
195 if (!(bufs = (buffer_t *) calloc((size_t) LK_LAST, sizeof *bufs)))
196 return (char *) NULL;
198 if (pthread_setspecific(thdkey, (void *) bufs)) {
200 return (char *) NULL;
204 return get_buffer(bufs + key, size);
209 buffer_undef(localkey_t key, long size)
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. */
216 pthread_mutex_lock(&mutex);
218 /* Determine if we can use pthread-specific data. */
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 = (buffer_t *) calloc((size_t) LK_LAST,
225 pthread_mutex_unlock(&mutex);
226 return (char *) NULL;
229 Curl_thread_buffer = buffer_unthreaded;
234 pthread_mutex_unlock(&mutex);
235 return Curl_thread_buffer(key, size);
240 Curl_getnameinfo_a(const struct sockaddr * sa, socklen_t salen,
241 char * nodename, socklen_t nodenamelen,
242 char * servname, socklen_t servnamelen,
251 enodename = (char *) NULL;
252 eservname = (char *) NULL;
254 if (nodename && nodenamelen)
255 if (!(enodename = malloc(nodenamelen)))
258 if (servname && servnamelen)
259 if (!(eservname = malloc(servnamelen))) {
266 status = getnameinfo(sa, salen, enodename, nodenamelen,
267 eservname, servnamelen, flags);
271 i = QadrtConvertE2A(nodename, enodename,
272 nodenamelen - 1, strlen(enodename));
277 i = QadrtConvertE2A(servname, eservname,
278 servnamelen - 1, strlen(eservname));
294 Curl_getaddrinfo_a(const char * nodename, const char * servname,
295 const struct addrinfo * hints,
296 struct addrinfo * * res)
304 enodename = (char *) NULL;
305 eservname = (char *) NULL;
308 i = strlen(nodename);
310 if (!(enodename = malloc(i + 1)))
313 i = QadrtConvertA2E(enodename, nodename, i, i);
318 i = strlen(servname);
320 if (!(eservname = malloc(i + 1))) {
327 QadrtConvertA2E(eservname, servname, i, i);
331 status = getaddrinfo(enodename, eservname, hints, res);
344 Curl_inet_ntoa_r_a(struct in_addr internet_address,
345 char * output_buffer, int output_buffer_length)
352 if (!output_buffer || output_buffer_length < 16)
353 return inet_ntoa_r(internet_address, output_buffer, output_buffer_length);
355 if (!(cp = malloc(output_buffer_length + 1)))
358 rc = inet_ntoa_r(internet_address, cp, output_buffer_length);
365 cp[output_buffer_length - 1] = '\0';
367 QadrtConvertE2A(output_buffer, cp, i, i);
368 output_buffer[i] = '\0';
376 /* ASCII wrappers for the SSL procedures. */
379 Curl_SSL_Init_Application_a(SSLInitApp * init_app)
386 if (!init_app || !init_app->applicationID || !init_app->applicationIDLen)
387 return SSL_Init_Application(init_app);
389 memcpy((char *) &ia, (char *) init_app, sizeof ia);
390 i = ia.applicationIDLen;
392 if (!(ia.applicationID = malloc(i + 1))) {
397 QadrtConvertA2E(ia.applicationID, init_app->applicationID, i, i);
398 ia.applicationID[i] = '\0';
399 rc = SSL_Init_Application(&ia);
400 free(ia.applicationID);
401 init_app->localCertificateLen = ia.localCertificateLen;
402 init_app->sessionType = ia.sessionType;
408 Curl_SSL_Init_a(SSLInit * init)
415 if (!init || (!init->keyringFileName && !init->keyringPassword))
416 return SSL_Init(init);
418 memcpy((char *) &ia, (char *) init, sizeof ia);
420 if (ia.keyringFileName) {
421 i = strlen(ia.keyringFileName);
423 if (!(ia.keyringFileName = malloc(i + 1))) {
428 QadrtConvertA2E(ia.keyringFileName, init->keyringFileName, i, i);
429 ia.keyringFileName[i] = '\0';
432 if (ia.keyringPassword) {
433 i = strlen(ia.keyringPassword);
435 if (!(ia.keyringPassword = malloc(i + 1))) {
436 if (ia.keyringFileName)
437 free(ia.keyringFileName);
443 QadrtConvertA2E(ia.keyringPassword, init->keyringPassword, i, i);
444 ia.keyringPassword[i] = '\0';
449 if (ia.keyringFileName)
450 free(ia.keyringFileName);
452 if (ia.keyringPassword)
453 free(ia.keyringPassword);
460 Curl_SSL_Strerror_a(int sslreturnvalue, SSLErrorMsg * serrmsgp)
467 cp = SSL_Strerror(sslreturnvalue, serrmsgp);
474 if (!(cp2 = Curl_thread_buffer(LK_SSL_ERROR, MAX_CONV_EXPANSION * i + 1)))
477 i = QadrtConvertE2A(cp2, cp, MAX_CONV_EXPANSION * i, i);
482 #endif /* USE_QSOSSL */
487 /* ASCII wrappers for the GSSAPI procedures. */
490 Curl_gss_convert_in_place(OM_uint32 * minor_status, gss_buffer_t buf)
496 /* Convert `buf' in place, from EBCDIC to ASCII.
497 If error, release the buffer and return -1. Else return 0. */
502 if (!(t = malloc(i))) {
503 gss_release_buffer(minor_status, buf);
506 *minor_status = ENOMEM;
511 QadrtConvertE2A(t, buf->value, i, i);
512 memcpy(buf->value, t, i);
521 Curl_gss_import_name_a(OM_uint32 * minor_status, gss_buffer_t in_name,
522 gss_OID in_name_type, gss_name_t * out_name)
529 if (!in_name || !in_name->value || !in_name->length)
530 return gss_import_name(minor_status, in_name, in_name_type, out_name);
532 memcpy((char *) &in, (char *) in_name, sizeof in);
535 if (!(in.value = malloc(i + 1))) {
537 *minor_status = ENOMEM;
539 return GSS_S_FAILURE;
542 QadrtConvertA2E(in.value, in_name->value, i, i);
543 ((char *) in.value)[i] = '\0';
544 rc = gss_import_name(minor_status, &in, in_name_type, out_name);
551 Curl_gss_display_status_a(OM_uint32 * minor_status, OM_uint32 status_value,
552 int status_type, gss_OID mech_type,
553 gss_msg_ctx_t * message_context, gss_buffer_t status_string)
558 rc = gss_display_status(minor_status, status_value, status_type,
559 mech_type, message_context, status_string);
561 if (rc != GSS_S_COMPLETE || !status_string ||
562 !status_string->length || !status_string->value)
565 /* No way to allocate a buffer here, because it will be released by
566 gss_release_buffer(). The solution is to overwrite the EBCDIC buffer
567 with ASCII to return it. */
569 if (Curl_gss_convert_in_place(minor_status, status_string))
570 return GSS_S_FAILURE;
577 Curl_gss_init_sec_context_a(OM_uint32 * minor_status, gss_cred_id_t cred_handle,
578 gss_ctx_id_t * context_handle,
579 gss_name_t target_name, gss_OID mech_type,
580 gss_flags_t req_flags, OM_uint32 time_req,
581 gss_channel_bindings_t input_chan_bindings,
582 gss_buffer_t input_token,
583 gss_OID * actual_mech_type,
584 gss_buffer_t output_token, gss_flags_t * ret_flags,
585 OM_uint32 * time_rec)
595 if ((inp = input_token))
596 if (inp->length && inp->value) {
599 if (!(in.value = malloc(i + 1))) {
601 *minor_status = ENOMEM;
603 return GSS_S_FAILURE;
606 QadrtConvertA2E(in.value, input_token->value, i, i);
607 ((char *) in.value)[i] = '\0';
612 rc = gss_init_sec_context(minor_status, cred_handle, context_handle,
613 target_name, mech_type, req_flags, time_req,
614 input_chan_bindings, inp, actual_mech_type,
615 output_token, ret_flags, time_rec);
620 if (rc != GSS_S_COMPLETE || !output_token ||
621 !output_token->length || !output_token->value)
624 /* No way to allocate a buffer here, because it will be released by
625 gss_release_buffer(). The solution is to overwrite the EBCDIC buffer
626 with ASCII to return it. */
628 if (Curl_gss_convert_in_place(minor_status, output_token))
629 return GSS_S_FAILURE;
636 Curl_gss_delete_sec_context_a(OM_uint32 * minor_status,
637 gss_ctx_id_t * context_handle,
638 gss_buffer_t output_token)
643 rc = gss_delete_sec_context(minor_status, context_handle, output_token);
645 if (rc != GSS_S_COMPLETE || !output_token ||
646 !output_token->length || !output_token->value)
649 /* No way to allocate a buffer here, because it will be released by
650 gss_release_buffer(). The solution is to overwrite the EBCDIC buffer
651 with ASCII to return it. */
653 if (Curl_gss_convert_in_place(minor_status, output_token))
654 return GSS_S_FAILURE;
659 #endif /* HAVE_GSSAPI */
662 #ifndef CURL_DISABLE_LDAP
664 /* ASCII wrappers for the LDAP procedures. */
667 Curl_ldap_init_a(char * host, int port)
675 return (void *) ldap_init(host, port);
679 if (!(ehost = malloc(i + 1)))
680 return (void *) NULL;
682 QadrtConvertA2E(ehost, host, i, i);
684 result = (void *) ldap_init(ehost, port);
691 Curl_ldap_simple_bind_s_a(void * ld, char * dn, char * passwd)
699 epasswd = (char *) NULL;
704 if (!(edn = malloc(i + 1)))
705 return LDAP_NO_MEMORY;
707 QadrtConvertA2E(edn, dn, i, i);
714 if (!(epasswd = malloc(i + 1))) {
718 return LDAP_NO_MEMORY;
721 QadrtConvertA2E(epasswd, passwd, i, i);
725 i = ldap_simple_bind_s(ld, edn, epasswd);
738 Curl_ldap_search_s_a(void * ld, char * base, int scope, char * filter,
739 char * * attrs, int attrsonly, LDAPMessage * * res)
749 ebase = (char *) NULL;
750 efilter = (char *) NULL;
751 eattrs = (char * *) NULL;
752 status = LDAP_SUCCESS;
757 if (!(ebase = malloc(i + 1)))
758 status = LDAP_NO_MEMORY;
760 QadrtConvertA2E(ebase, base, i, i);
765 if (filter && status == LDAP_SUCCESS) {
768 if (!(efilter = malloc(i + 1)))
769 status = LDAP_NO_MEMORY;
771 QadrtConvertA2E(efilter, filter, i, i);
776 if (attrs && status == LDAP_SUCCESS) {
777 for (i = 0; attrs[i++];)
780 if (!(eattrs = (char * *) calloc(i, sizeof *eattrs)))
781 status = LDAP_NO_MEMORY;
783 for (j = 0; attrs[j]; j++) {
784 i = strlen(attrs[j]);
786 if (!(eattrs[j] = malloc(i + 1))) {
787 status = LDAP_NO_MEMORY;
791 QadrtConvertA2E(eattrs[j], attrs[j], i, i);
797 if (status == LDAP_SUCCESS)
798 status = ldap_search_s(ld, ebase? ebase: "", scope,
799 efilter? efilter: "(objectclass=*)",
800 eattrs, attrsonly, res);
803 for (j = 0; eattrs[j]; j++)
820 Curl_ldap_get_values_len_a(void * ld, LDAPMessage * entry, const char * attr)
825 struct berval * * result;
832 if (!(cp = malloc(i + 1))) {
833 ldap_set_lderrno(ld, LDAP_NO_MEMORY, NULL,
834 ldap_err2string(LDAP_NO_MEMORY));
835 return (struct berval * *) NULL;
838 QadrtConvertA2E(cp, attr, i, i);
842 result = ldap_get_values_len(ld, entry, cp);
847 /* Result data are binary in nature, so they haven't been converted to EBCDIC.
848 Therefore do not convert. */
855 Curl_ldap_err2string_a(int error)
862 cp = ldap_err2string(error);
869 if (!(cp2 = Curl_thread_buffer(LK_LDAP_ERROR, MAX_CONV_EXPANSION * i + 1)))
872 i = QadrtConvertE2A(cp2, cp, MAX_CONV_EXPANSION * i, i);
879 Curl_ldap_get_dn_a(void * ld, LDAPMessage * entry)
886 cp = ldap_get_dn(ld, entry);
893 if (!(cp2 = malloc(i + 1)))
896 QadrtConvertE2A(cp2, cp, i, i);
898 /* No way to allocate a buffer here, because it will be released by
899 ldap_memfree() and ldap_memalloc() does not exist. The solution is to
900 overwrite the EBCDIC buffer with ASCII to return it. */
909 Curl_ldap_first_attribute_a(void * ld,
910 LDAPMessage * entry, BerElement * * berptr)
917 cp = ldap_first_attribute(ld, entry, berptr);
924 if (!(cp2 = malloc(i + 1)))
927 QadrtConvertE2A(cp2, cp, i, i);
929 /* No way to allocate a buffer here, because it will be released by
930 ldap_memfree() and ldap_memalloc() does not exist. The solution is to
931 overwrite the EBCDIC buffer with ASCII to return it. */
940 Curl_ldap_next_attribute_a(void * ld,
941 LDAPMessage * entry, BerElement * berptr)
948 cp = ldap_next_attribute(ld, entry, berptr);
955 if (!(cp2 = malloc(i + 1)))
958 QadrtConvertE2A(cp2, cp, i, i);
960 /* No way to allocate a buffer here, because it will be released by
961 ldap_memfree() and ldap_memalloc() does not exist. The solution is to
962 overwrite the EBCDIC buffer with ASCII to return it. */
969 #endif /* CURL_DISABLE_LDAP */
973 convert_sockaddr(struct sockaddr_storage * dstaddr,
974 const struct sockaddr * srcaddr, int srclen)
977 const struct sockaddr_un * srcu;
978 struct sockaddr_un * dstu;
980 unsigned int dstsize;
982 /* Convert a socket address into job CCSID, if needed. */
984 if (!srcaddr || srclen < offsetof(struct sockaddr, sa_family) +
985 sizeof srcaddr->sa_family || srclen > sizeof *dstaddr) {
990 memcpy((char *) dstaddr, (char *) srcaddr, srclen);
992 switch (srcaddr->sa_family) {
995 srcu = (const struct sockaddr_un *) srcaddr;
996 dstu = (struct sockaddr_un *) dstaddr;
997 dstsize = sizeof *dstaddr - offsetof(struct sockaddr_un, sun_path);
998 srclen -= offsetof(struct sockaddr_un, sun_path);
999 i = QadrtConvertA2E(dstu->sun_path, srcu->sun_path, dstsize - 1, srclen);
1000 dstu->sun_path[i] = '\0';
1001 i += offsetof(struct sockaddr_un, sun_path);
1010 Curl_os400_connect(int sd, struct sockaddr * destaddr, int addrlen)
1014 struct sockaddr_storage laddr;
1016 i = convert_sockaddr(&laddr, destaddr, addrlen);
1021 return connect(sd, (struct sockaddr *) &laddr, i);
1026 Curl_os400_bind(int sd, struct sockaddr * localaddr, int addrlen)
1030 struct sockaddr_storage laddr;
1032 i = convert_sockaddr(&laddr, localaddr, addrlen);
1037 return bind(sd, (struct sockaddr *) &laddr, i);
1042 Curl_os400_sendto(int sd, char * buffer, int buflen, int flags,
1043 struct sockaddr * dstaddr, int addrlen)
1047 struct sockaddr_storage laddr;
1049 i = convert_sockaddr(&laddr, dstaddr, addrlen);
1054 return sendto(sd, buffer, buflen, flags, (struct sockaddr *) &laddr, i);
1059 Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags,
1060 struct sockaddr * fromaddr, int * addrlen)
1066 const struct sockaddr_un * srcu;
1067 struct sockaddr_un * dstu;
1068 struct sockaddr_storage laddr;
1070 if (!fromaddr || !addrlen || *addrlen <= 0)
1071 return recvfrom(sd, buffer, buflen, flags, fromaddr, addrlen);
1073 laddrlen = sizeof laddr;
1074 laddr.ss_family = AF_UNSPEC; /* To detect if unused. */
1075 rcvlen = recvfrom(sd, buffer, buflen, flags,
1076 (struct sockaddr *) &laddr, &laddrlen);
1081 switch (laddr.ss_family) {
1084 srcu = (const struct sockaddr_un *) &laddr;
1085 dstu = (struct sockaddr_un *) fromaddr;
1086 i = *addrlen - offsetof(struct sockaddr_un, sun_path);
1087 laddrlen -= offsetof(struct sockaddr_un, sun_path);
1088 i = QadrtConvertE2A(dstu->sun_path, srcu->sun_path, i, laddrlen);
1089 laddrlen = i + offsetof(struct sockaddr_un, sun_path);
1091 if (laddrlen < *addrlen)
1092 dstu->sun_path[i] = '\0';
1100 if (laddrlen > *addrlen)
1101 laddrlen = *addrlen;
1104 memcpy((char *) fromaddr, (char *) &laddr, laddrlen);
1109 *addrlen = laddrlen;