os400sys.c 23 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040
  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. /* OS/400 additional support. */
  26. #include <curl/curl.h>
  27. #include "config-os400.h" /* Not curl_setup.h: we only need some defines. */
  28. #include <sys/types.h>
  29. #include <sys/socket.h>
  30. #include <sys/un.h>
  31. #include <stdlib.h>
  32. #include <stddef.h>
  33. #include <string.h>
  34. #include <pthread.h>
  35. #include <netdb.h>
  36. #include <qadrt.h>
  37. #include <errno.h>
  38. #ifdef HAVE_LIBZ
  39. #include <zlib.h>
  40. #endif
  41. #ifdef HAVE_GSSAPI
  42. #include <gssapi.h>
  43. #endif
  44. #ifndef CURL_DISABLE_LDAP
  45. #include <ldap.h>
  46. #endif
  47. #include <netinet/in.h>
  48. #include <arpa/inet.h>
  49. #include "os400sys.h"
  50. /**
  51. *** QADRT OS/400 ASCII runtime defines only the most used procedures, but a
  52. *** lot of them are not supported. This module implements ASCII wrappers for
  53. *** those that are used by libcurl, but not defined by QADRT.
  54. **/
  55. #pragma convert(0) /* Restore EBCDIC. */
  56. #define MIN_BYTE_GAIN 1024 /* Minimum gain when shortening a buffer. */
  57. struct buffer_t {
  58. unsigned long size; /* Buffer size. */
  59. char *buf; /* Buffer address. */
  60. };
  61. static char *buffer_undef(localkey_t key, long size);
  62. static char *buffer_threaded(localkey_t key, long size);
  63. static char *buffer_unthreaded(localkey_t key, long size);
  64. static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  65. static pthread_key_t thdkey;
  66. static struct buffer_t *locbufs;
  67. char *(*Curl_thread_buffer)(localkey_t key, long size) = buffer_undef;
  68. static void thdbufdestroy(void *private)
  69. {
  70. if(private) {
  71. struct buffer_t *p = (struct buffer_t *) private;
  72. localkey_t i;
  73. for(i = (localkey_t) 0; i < LK_LAST; i++) {
  74. free(p->buf);
  75. p++;
  76. }
  77. free(private);
  78. }
  79. }
  80. static void
  81. terminate(void)
  82. {
  83. if(Curl_thread_buffer == buffer_threaded) {
  84. locbufs = pthread_getspecific(thdkey);
  85. pthread_setspecific(thdkey, (void *) NULL);
  86. pthread_key_delete(thdkey);
  87. }
  88. if(Curl_thread_buffer != buffer_undef) {
  89. thdbufdestroy((void *) locbufs);
  90. locbufs = (struct buffer_t *) NULL;
  91. }
  92. Curl_thread_buffer = buffer_undef;
  93. }
  94. static char *
  95. get_buffer(struct buffer_t *buf, long size)
  96. {
  97. char *cp;
  98. /* If `size' >= 0, make sure buffer at `buf' is at least `size'-byte long.
  99. Return the buffer address. */
  100. if(size < 0)
  101. return buf->buf;
  102. if(!buf->buf) {
  103. buf->buf = malloc(size);
  104. if(buf->buf)
  105. buf->size = size;
  106. return buf->buf;
  107. }
  108. if((unsigned long) size <= buf->size) {
  109. /* Shorten the buffer only if it frees a significant byte count. This
  110. avoids some realloc() overhead. */
  111. if(buf->size - size < MIN_BYTE_GAIN)
  112. return buf->buf;
  113. }
  114. /* Resize the buffer. */
  115. cp = realloc(buf->buf, size);
  116. if(cp) {
  117. buf->buf = cp;
  118. buf->size = size;
  119. }
  120. else if(size <= buf->size)
  121. cp = buf->buf;
  122. return cp;
  123. }
  124. static char *
  125. buffer_unthreaded(localkey_t key, long size)
  126. {
  127. return get_buffer(locbufs + key, size);
  128. }
  129. static char *
  130. buffer_threaded(localkey_t key, long size)
  131. {
  132. struct buffer_t *bufs;
  133. /* Get the buffer for the given local key in the current thread, and
  134. make sure it is at least `size'-byte long. Set `size' to < 0 to get
  135. its address only. */
  136. bufs = (struct buffer_t *) pthread_getspecific(thdkey);
  137. if(!bufs) {
  138. if(size < 0)
  139. return (char *) NULL; /* No buffer yet. */
  140. /* Allocate buffer descriptors for the current thread. */
  141. bufs = calloc((size_t) LK_LAST, sizeof(*bufs));
  142. if(!bufs)
  143. return (char *) NULL;
  144. if(pthread_setspecific(thdkey, (void *) bufs)) {
  145. free(bufs);
  146. return (char *) NULL;
  147. }
  148. }
  149. return get_buffer(bufs + key, size);
  150. }
  151. static char *
  152. buffer_undef(localkey_t key, long size)
  153. {
  154. /* Define the buffer system, get the buffer for the given local key in
  155. the current thread, and make sure it is at least `size'-byte long.
  156. Set `size' to < 0 to get its address only. */
  157. pthread_mutex_lock(&mutex);
  158. /* Determine if we can use pthread-specific data. */
  159. if(Curl_thread_buffer == buffer_undef) { /* If unchanged during lock. */
  160. if(!pthread_key_create(&thdkey, thdbufdestroy))
  161. Curl_thread_buffer = buffer_threaded;
  162. else {
  163. locbufs = calloc((size_t) LK_LAST, sizeof(*locbufs));
  164. if(!locbufs) {
  165. pthread_mutex_unlock(&mutex);
  166. return (char *) NULL;
  167. }
  168. else
  169. Curl_thread_buffer = buffer_unthreaded;
  170. }
  171. atexit(terminate);
  172. }
  173. pthread_mutex_unlock(&mutex);
  174. return Curl_thread_buffer(key, size);
  175. }
  176. static char *
  177. set_thread_string(localkey_t key, const char *s)
  178. {
  179. int i;
  180. char *cp;
  181. if(!s)
  182. return (char *) NULL;
  183. i = strlen(s) + 1;
  184. cp = Curl_thread_buffer(key, MAX_CONV_EXPANSION * i + 1);
  185. if(cp) {
  186. i = QadrtConvertE2A(cp, s, MAX_CONV_EXPANSION * i, i);
  187. cp[i] = '\0';
  188. }
  189. return cp;
  190. }
  191. int
  192. Curl_getnameinfo_a(const struct sockaddr *sa, socklen_t salen,
  193. char *nodename, socklen_t nodenamelen,
  194. char *servname, socklen_t servnamelen,
  195. int flags)
  196. {
  197. char *enodename = NULL;
  198. char *eservname = NULL;
  199. int status;
  200. if(nodename && nodenamelen) {
  201. enodename = malloc(nodenamelen);
  202. if(!enodename)
  203. return EAI_MEMORY;
  204. }
  205. if(servname && servnamelen) {
  206. eservname = malloc(servnamelen);
  207. if(!eservname) {
  208. free(enodename);
  209. return EAI_MEMORY;
  210. }
  211. }
  212. status = getnameinfo(sa, salen, enodename, nodenamelen,
  213. eservname, servnamelen, flags);
  214. if(!status) {
  215. int i;
  216. if(enodename) {
  217. i = QadrtConvertE2A(nodename, enodename,
  218. nodenamelen - 1, strlen(enodename));
  219. nodename[i] = '\0';
  220. }
  221. if(eservname) {
  222. i = QadrtConvertE2A(servname, eservname,
  223. servnamelen - 1, strlen(eservname));
  224. servname[i] = '\0';
  225. }
  226. }
  227. free(enodename);
  228. free(eservname);
  229. return status;
  230. }
  231. int
  232. Curl_getaddrinfo_a(const char *nodename, const char *servname,
  233. const struct addrinfo *hints,
  234. struct addrinfo **res)
  235. {
  236. char *enodename;
  237. char *eservname;
  238. int status;
  239. int i;
  240. enodename = (char *) NULL;
  241. eservname = (char *) NULL;
  242. if(nodename) {
  243. i = strlen(nodename);
  244. enodename = malloc(i + 1);
  245. if(!enodename)
  246. return EAI_MEMORY;
  247. i = QadrtConvertA2E(enodename, nodename, i, i);
  248. enodename[i] = '\0';
  249. }
  250. if(servname) {
  251. i = strlen(servname);
  252. eservname = malloc(i + 1);
  253. if(!eservname) {
  254. free(enodename);
  255. return EAI_MEMORY;
  256. }
  257. QadrtConvertA2E(eservname, servname, i, i);
  258. eservname[i] = '\0';
  259. }
  260. status = getaddrinfo(enodename, eservname, hints, res);
  261. free(enodename);
  262. free(eservname);
  263. return status;
  264. }
  265. #ifdef HAVE_GSSAPI
  266. /* ASCII wrappers for the GSSAPI procedures. */
  267. static int
  268. Curl_gss_convert_in_place(OM_uint32 *minor_status, gss_buffer_t buf)
  269. {
  270. unsigned int i = buf->length;
  271. /* Convert `buf' in place, from EBCDIC to ASCII.
  272. If error, release the buffer and return -1. Else return 0. */
  273. if(i) {
  274. char *t = malloc(i);
  275. if(!t) {
  276. gss_release_buffer(minor_status, buf);
  277. if(minor_status)
  278. *minor_status = ENOMEM;
  279. return -1;
  280. }
  281. QadrtConvertE2A(t, buf->value, i, i);
  282. memcpy(buf->value, t, i);
  283. free(t);
  284. }
  285. return 0;
  286. }
  287. OM_uint32
  288. Curl_gss_import_name_a(OM_uint32 *minor_status, gss_buffer_t in_name,
  289. gss_OID in_name_type, gss_name_t *out_name)
  290. {
  291. OM_uint32 rc;
  292. unsigned int i;
  293. gss_buffer_desc in;
  294. if(!in_name || !in_name->value || !in_name->length)
  295. return gss_import_name(minor_status, in_name, in_name_type, out_name);
  296. memcpy((char *) &in, (char *) in_name, sizeof(in));
  297. i = in.length;
  298. in.value = malloc(i + 1);
  299. if(!in.value) {
  300. if(minor_status)
  301. *minor_status = ENOMEM;
  302. return GSS_S_FAILURE;
  303. }
  304. QadrtConvertA2E(in.value, in_name->value, i, i);
  305. ((char *) in.value)[i] = '\0';
  306. rc = gss_import_name(minor_status, &in, in_name_type, out_name);
  307. free(in.value);
  308. return rc;
  309. }
  310. OM_uint32
  311. Curl_gss_display_status_a(OM_uint32 *minor_status, OM_uint32 status_value,
  312. int status_type, gss_OID mech_type,
  313. gss_msg_ctx_t *message_context,
  314. gss_buffer_t status_string)
  315. {
  316. int rc;
  317. rc = gss_display_status(minor_status, status_value, status_type,
  318. mech_type, message_context, status_string);
  319. if(rc != GSS_S_COMPLETE || !status_string ||
  320. !status_string->length || !status_string->value)
  321. return rc;
  322. /* No way to allocate a buffer here, because it will be released by
  323. gss_release_buffer(). The solution is to overwrite the EBCDIC buffer
  324. with ASCII to return it. */
  325. if(Curl_gss_convert_in_place(minor_status, status_string))
  326. return GSS_S_FAILURE;
  327. return rc;
  328. }
  329. OM_uint32
  330. Curl_gss_init_sec_context_a(OM_uint32 *minor_status,
  331. gss_cred_id_t cred_handle,
  332. gss_ctx_id_t *context_handle,
  333. gss_name_t target_name, gss_OID mech_type,
  334. gss_flags_t req_flags, OM_uint32 time_req,
  335. gss_channel_bindings_t input_chan_bindings,
  336. gss_buffer_t input_token,
  337. gss_OID *actual_mech_type,
  338. gss_buffer_t output_token, gss_flags_t *ret_flags,
  339. OM_uint32 *time_rec)
  340. {
  341. int rc;
  342. gss_buffer_desc in;
  343. gss_buffer_t inp;
  344. in.value = NULL;
  345. inp = input_token;
  346. if(inp) {
  347. if(inp->length && inp->value) {
  348. unsigned int i = inp->length;
  349. in.value = malloc(i + 1);
  350. if(!in.value) {
  351. if(minor_status)
  352. *minor_status = ENOMEM;
  353. return GSS_S_FAILURE;
  354. }
  355. QadrtConvertA2E(in.value, input_token->value, i, i);
  356. ((char *) in.value)[i] = '\0';
  357. in.length = i;
  358. inp = &in;
  359. }
  360. }
  361. rc = gss_init_sec_context(minor_status, cred_handle, context_handle,
  362. target_name, mech_type, req_flags, time_req,
  363. input_chan_bindings, inp, actual_mech_type,
  364. output_token, ret_flags, time_rec);
  365. free(in.value);
  366. if(rc != GSS_S_COMPLETE || !output_token ||
  367. !output_token->length || !output_token->value)
  368. return rc;
  369. /* No way to allocate a buffer here, because it will be released by
  370. gss_release_buffer(). The solution is to overwrite the EBCDIC buffer
  371. with ASCII to return it. */
  372. if(Curl_gss_convert_in_place(minor_status, output_token))
  373. return GSS_S_FAILURE;
  374. return rc;
  375. }
  376. OM_uint32
  377. Curl_gss_delete_sec_context_a(OM_uint32 *minor_status,
  378. gss_ctx_id_t *context_handle,
  379. gss_buffer_t output_token)
  380. {
  381. OM_uint32 rc;
  382. rc = gss_delete_sec_context(minor_status, context_handle, output_token);
  383. if(rc != GSS_S_COMPLETE || !output_token ||
  384. !output_token->length || !output_token->value)
  385. return rc;
  386. /* No way to allocate a buffer here, because it will be released by
  387. gss_release_buffer(). The solution is to overwrite the EBCDIC buffer
  388. with ASCII to return it. */
  389. if(Curl_gss_convert_in_place(minor_status, output_token))
  390. return GSS_S_FAILURE;
  391. return rc;
  392. }
  393. #endif /* HAVE_GSSAPI */
  394. #ifndef CURL_DISABLE_LDAP
  395. /* ASCII wrappers for the LDAP procedures. */
  396. void *
  397. Curl_ldap_init_a(char *host, int port)
  398. {
  399. size_t i;
  400. char *ehost;
  401. void *result;
  402. if(!host)
  403. return (void *) ldap_init(host, port);
  404. i = strlen(host);
  405. ehost = malloc(i + 1);
  406. if(!ehost)
  407. return (void *) NULL;
  408. QadrtConvertA2E(ehost, host, i, i);
  409. ehost[i] = '\0';
  410. result = (void *) ldap_init(ehost, port);
  411. free(ehost);
  412. return result;
  413. }
  414. int
  415. Curl_ldap_simple_bind_s_a(void *ld, char *dn, char *passwd)
  416. {
  417. int i;
  418. char *edn;
  419. char *epasswd;
  420. edn = (char *) NULL;
  421. epasswd = (char *) NULL;
  422. if(dn) {
  423. i = strlen(dn);
  424. edn = malloc(i + 1);
  425. if(!edn)
  426. return LDAP_NO_MEMORY;
  427. QadrtConvertA2E(edn, dn, i, i);
  428. edn[i] = '\0';
  429. }
  430. if(passwd) {
  431. i = strlen(passwd);
  432. epasswd = malloc(i + 1);
  433. if(!epasswd) {
  434. free(edn);
  435. return LDAP_NO_MEMORY;
  436. }
  437. QadrtConvertA2E(epasswd, passwd, i, i);
  438. epasswd[i] = '\0';
  439. }
  440. i = ldap_simple_bind_s(ld, edn, epasswd);
  441. free(epasswd);
  442. free(edn);
  443. return i;
  444. }
  445. int
  446. Curl_ldap_search_s_a(void *ld, char *base, int scope, char *filter,
  447. char **attrs, int attrsonly, LDAPMessage **res)
  448. {
  449. int i;
  450. int j;
  451. char *ebase;
  452. char *efilter;
  453. char **eattrs;
  454. int status;
  455. ebase = (char *) NULL;
  456. efilter = (char *) NULL;
  457. eattrs = (char **) NULL;
  458. status = LDAP_SUCCESS;
  459. if(base) {
  460. i = strlen(base);
  461. ebase = malloc(i + 1);
  462. if(!ebase)
  463. status = LDAP_NO_MEMORY;
  464. else {
  465. QadrtConvertA2E(ebase, base, i, i);
  466. ebase[i] = '\0';
  467. }
  468. }
  469. if(filter && status == LDAP_SUCCESS) {
  470. i = strlen(filter);
  471. efilter = malloc(i + 1);
  472. if(!efilter)
  473. status = LDAP_NO_MEMORY;
  474. else {
  475. QadrtConvertA2E(efilter, filter, i, i);
  476. efilter[i] = '\0';
  477. }
  478. }
  479. if(attrs && status == LDAP_SUCCESS) {
  480. for(i = 0; attrs[i++];)
  481. ;
  482. eattrs = calloc(i, sizeof(*eattrs));
  483. if(!eattrs)
  484. status = LDAP_NO_MEMORY;
  485. else {
  486. for(j = 0; attrs[j]; j++) {
  487. i = strlen(attrs[j]);
  488. eattrs[j] = malloc(i + 1);
  489. if(!eattrs[j]) {
  490. status = LDAP_NO_MEMORY;
  491. break;
  492. }
  493. QadrtConvertA2E(eattrs[j], attrs[j], i, i);
  494. eattrs[j][i] = '\0';
  495. }
  496. }
  497. }
  498. if(status == LDAP_SUCCESS)
  499. status = ldap_search_s(ld, ebase ? ebase : "", scope,
  500. efilter ? efilter : "(objectclass=*)",
  501. eattrs, attrsonly, res);
  502. if(eattrs) {
  503. for(j = 0; eattrs[j]; j++)
  504. free(eattrs[j]);
  505. free(eattrs);
  506. }
  507. free(efilter);
  508. free(ebase);
  509. return status;
  510. }
  511. struct berval **
  512. Curl_ldap_get_values_len_a(void *ld, LDAPMessage *entry, const char *attr)
  513. {
  514. char *cp;
  515. struct berval **result;
  516. cp = (char *) NULL;
  517. if(attr) {
  518. int i = strlen(attr);
  519. cp = malloc(i + 1);
  520. if(!cp) {
  521. ldap_set_lderrno(ld, LDAP_NO_MEMORY, NULL,
  522. ldap_err2string(LDAP_NO_MEMORY));
  523. return (struct berval **) NULL;
  524. }
  525. QadrtConvertA2E(cp, attr, i, i);
  526. cp[i] = '\0';
  527. }
  528. result = ldap_get_values_len(ld, entry, cp);
  529. free(cp);
  530. /* Result data are binary in nature, so they haven't been
  531. converted to EBCDIC. Therefore do not convert. */
  532. return result;
  533. }
  534. char *
  535. Curl_ldap_err2string_a(int error)
  536. {
  537. return set_thread_string(LK_LDAP_ERROR, ldap_err2string(error));
  538. }
  539. char *
  540. Curl_ldap_get_dn_a(void *ld, LDAPMessage *entry)
  541. {
  542. int i;
  543. char *cp;
  544. char *cp2;
  545. cp = ldap_get_dn(ld, entry);
  546. if(!cp)
  547. return cp;
  548. i = strlen(cp);
  549. cp2 = malloc(i + 1);
  550. if(!cp2)
  551. return cp2;
  552. QadrtConvertE2A(cp2, cp, i, i);
  553. cp2[i] = '\0';
  554. /* No way to allocate a buffer here, because it will be released by
  555. ldap_memfree() and ldap_memalloc() does not exist. The solution is to
  556. overwrite the EBCDIC buffer with ASCII to return it. */
  557. strcpy(cp, cp2);
  558. free(cp2);
  559. return cp;
  560. }
  561. char *
  562. Curl_ldap_first_attribute_a(void *ld,
  563. LDAPMessage *entry, BerElement **berptr)
  564. {
  565. int i;
  566. char *cp;
  567. char *cp2;
  568. cp = ldap_first_attribute(ld, entry, berptr);
  569. if(!cp)
  570. return cp;
  571. i = strlen(cp);
  572. cp2 = malloc(i + 1);
  573. if(!cp2)
  574. return cp2;
  575. QadrtConvertE2A(cp2, cp, i, i);
  576. cp2[i] = '\0';
  577. /* No way to allocate a buffer here, because it will be released by
  578. ldap_memfree() and ldap_memalloc() does not exist. The solution is to
  579. overwrite the EBCDIC buffer with ASCII to return it. */
  580. strcpy(cp, cp2);
  581. free(cp2);
  582. return cp;
  583. }
  584. char *
  585. Curl_ldap_next_attribute_a(void *ld,
  586. LDAPMessage *entry, BerElement *berptr)
  587. {
  588. int i;
  589. char *cp;
  590. char *cp2;
  591. cp = ldap_next_attribute(ld, entry, berptr);
  592. if(!cp)
  593. return cp;
  594. i = strlen(cp);
  595. cp2 = malloc(i + 1);
  596. if(!cp2)
  597. return cp2;
  598. QadrtConvertE2A(cp2, cp, i, i);
  599. cp2[i] = '\0';
  600. /* No way to allocate a buffer here, because it will be released by
  601. ldap_memfree() and ldap_memalloc() does not exist. The solution is to
  602. overwrite the EBCDIC buffer with ASCII to return it. */
  603. strcpy(cp, cp2);
  604. free(cp2);
  605. return cp;
  606. }
  607. #endif /* CURL_DISABLE_LDAP */
  608. static int
  609. sockaddr2ebcdic(struct sockaddr_storage *dstaddr,
  610. const struct sockaddr *srcaddr, int srclen)
  611. {
  612. const struct sockaddr_un *srcu;
  613. struct sockaddr_un *dstu;
  614. unsigned int i;
  615. unsigned int dstsize;
  616. /* Convert a socket address to job CCSID, if needed. */
  617. if(!srcaddr || srclen < offsetof(struct sockaddr, sa_family) +
  618. sizeof(srcaddr->sa_family) || srclen > sizeof(*dstaddr)) {
  619. errno = EINVAL;
  620. return -1;
  621. }
  622. memcpy((char *) dstaddr, (char *) srcaddr, srclen);
  623. switch(srcaddr->sa_family) {
  624. case AF_UNIX:
  625. srcu = (const struct sockaddr_un *) srcaddr;
  626. dstu = (struct sockaddr_un *) dstaddr;
  627. dstsize = sizeof(*dstaddr) - offsetof(struct sockaddr_un, sun_path);
  628. srclen -= offsetof(struct sockaddr_un, sun_path);
  629. i = QadrtConvertA2E(dstu->sun_path, srcu->sun_path, dstsize - 1, srclen);
  630. dstu->sun_path[i] = '\0';
  631. srclen = i + offsetof(struct sockaddr_un, sun_path);
  632. }
  633. return srclen;
  634. }
  635. static int
  636. sockaddr2ascii(struct sockaddr *dstaddr, int dstlen,
  637. const struct sockaddr_storage *srcaddr, int srclen)
  638. {
  639. const struct sockaddr_un *srcu;
  640. struct sockaddr_un *dstu;
  641. unsigned int dstsize;
  642. /* Convert a socket address to ASCII, if needed. */
  643. if(!srclen)
  644. return 0;
  645. if(srclen > dstlen)
  646. srclen = dstlen;
  647. if(!srcaddr || srclen < 0) {
  648. errno = EINVAL;
  649. return -1;
  650. }
  651. memcpy((char *) dstaddr, (char *) srcaddr, srclen);
  652. if(srclen >= offsetof(struct sockaddr_storage, ss_family) +
  653. sizeof(srcaddr->ss_family)) {
  654. switch(srcaddr->ss_family) {
  655. case AF_UNIX:
  656. srcu = (const struct sockaddr_un *) srcaddr;
  657. dstu = (struct sockaddr_un *) dstaddr;
  658. dstsize = dstlen - offsetof(struct sockaddr_un, sun_path);
  659. srclen -= offsetof(struct sockaddr_un, sun_path);
  660. if(dstsize > 0 && srclen > 0) {
  661. srclen = QadrtConvertE2A(dstu->sun_path, srcu->sun_path,
  662. dstsize - 1, srclen);
  663. dstu->sun_path[srclen] = '\0';
  664. }
  665. srclen += offsetof(struct sockaddr_un, sun_path);
  666. }
  667. }
  668. return srclen;
  669. }
  670. int
  671. Curl_os400_connect(int sd, struct sockaddr *destaddr, int addrlen)
  672. {
  673. int i;
  674. struct sockaddr_storage laddr;
  675. i = sockaddr2ebcdic(&laddr, destaddr, addrlen);
  676. if(i < 0)
  677. return -1;
  678. return connect(sd, (struct sockaddr *) &laddr, i);
  679. }
  680. int
  681. Curl_os400_bind(int sd, struct sockaddr *localaddr, int addrlen)
  682. {
  683. int i;
  684. struct sockaddr_storage laddr;
  685. i = sockaddr2ebcdic(&laddr, localaddr, addrlen);
  686. if(i < 0)
  687. return -1;
  688. return bind(sd, (struct sockaddr *) &laddr, i);
  689. }
  690. int
  691. Curl_os400_sendto(int sd, char *buffer, int buflen, int flags,
  692. const struct sockaddr *dstaddr, int addrlen)
  693. {
  694. int i;
  695. struct sockaddr_storage laddr;
  696. i = sockaddr2ebcdic(&laddr, dstaddr, addrlen);
  697. if(i < 0)
  698. return -1;
  699. return sendto(sd, buffer, buflen, flags, (struct sockaddr *) &laddr, i);
  700. }
  701. int
  702. Curl_os400_recvfrom(int sd, char *buffer, int buflen, int flags,
  703. struct sockaddr *fromaddr, int *addrlen)
  704. {
  705. int rcvlen;
  706. struct sockaddr_storage laddr;
  707. int laddrlen = sizeof(laddr);
  708. if(!fromaddr || !addrlen || *addrlen <= 0)
  709. return recvfrom(sd, buffer, buflen, flags, fromaddr, addrlen);
  710. laddr.ss_family = AF_UNSPEC; /* To detect if unused. */
  711. rcvlen = recvfrom(sd, buffer, buflen, flags,
  712. (struct sockaddr *) &laddr, &laddrlen);
  713. if(rcvlen < 0)
  714. return rcvlen;
  715. if(laddr.ss_family == AF_UNSPEC)
  716. laddrlen = 0;
  717. else {
  718. laddrlen = sockaddr2ascii(fromaddr, *addrlen, &laddr, laddrlen);
  719. if(laddrlen < 0)
  720. return laddrlen;
  721. }
  722. *addrlen = laddrlen;
  723. return rcvlen;
  724. }
  725. int
  726. Curl_os400_getpeername(int sd, struct sockaddr *addr, int *addrlen)
  727. {
  728. struct sockaddr_storage laddr;
  729. int laddrlen = sizeof(laddr);
  730. int retcode = getpeername(sd, (struct sockaddr *) &laddr, &laddrlen);
  731. if(!retcode) {
  732. laddrlen = sockaddr2ascii(addr, *addrlen, &laddr, laddrlen);
  733. if(laddrlen < 0)
  734. return laddrlen;
  735. *addrlen = laddrlen;
  736. }
  737. return retcode;
  738. }
  739. int
  740. Curl_os400_getsockname(int sd, struct sockaddr *addr, int *addrlen)
  741. {
  742. struct sockaddr_storage laddr;
  743. int laddrlen = sizeof(laddr);
  744. int retcode = getsockname(sd, (struct sockaddr *) &laddr, &laddrlen);
  745. if(!retcode) {
  746. laddrlen = sockaddr2ascii(addr, *addrlen, &laddr, laddrlen);
  747. if(laddrlen < 0)
  748. return laddrlen;
  749. *addrlen = laddrlen;
  750. }
  751. return retcode;
  752. }
  753. #ifdef HAVE_LIBZ
  754. const char *
  755. Curl_os400_zlibVersion(void)
  756. {
  757. return set_thread_string(LK_ZLIB_VERSION, zlibVersion());
  758. }
  759. int
  760. Curl_os400_inflateInit_(z_streamp strm, const char *version, int stream_size)
  761. {
  762. z_const char *msgb4 = strm->msg;
  763. int ret;
  764. ret = inflateInit(strm);
  765. if(strm->msg != msgb4)
  766. strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
  767. return ret;
  768. }
  769. int
  770. Curl_os400_inflateInit2_(z_streamp strm, int windowBits,
  771. const char *version, int stream_size)
  772. {
  773. z_const char *msgb4 = strm->msg;
  774. int ret;
  775. ret = inflateInit2(strm, windowBits);
  776. if(strm->msg != msgb4)
  777. strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
  778. return ret;
  779. }
  780. int
  781. Curl_os400_inflate(z_streamp strm, int flush)
  782. {
  783. z_const char *msgb4 = strm->msg;
  784. int ret;
  785. ret = inflate(strm, flush);
  786. if(strm->msg != msgb4)
  787. strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
  788. return ret;
  789. }
  790. int
  791. Curl_os400_inflateEnd(z_streamp strm)
  792. {
  793. z_const char *msgb4 = strm->msg;
  794. int ret;
  795. ret = inflateEnd(strm);
  796. if(strm->msg != msgb4)
  797. strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
  798. return ret;
  799. }
  800. #endif