1 /*
2 Copyright (C) 2015-2021, Dirk Krause
3 SPDX-License-Identifier: BSD-3-Clause
4 */
5
6 /*
7 WARNING: This file was generated by the dkct program (see
8 http://dktools.sourceforge.net/ for details).
9 Changes you make here will be lost if dkct is run again!
10 You should modify the original source and run dkct on it.
11 Original source: dk4sock18.ctr
12 */
13
14 /** @file dk4sock18.c The dk4sock18 module.
15 */
16
17
18 #include "dk4conf.h"
19 #include <libdk4sock/dk4sock.h>
20 #include <libdk4base/dk4mem.h>
21 #include <libdk4maiodd/dk4maodd.h>
22
23 #if !DK4_HAVE_GETADDRINFO
24 #include <libdk4c/dk4rec24.h>
25 #endif
26
27 #include <libdk4maiodd/dk4maiddus.h>
28
29 #include <libdk4base/dk4unused.h>
30
31 #if DK4_HAVE_ASSERT_H
32 #ifndef ASSERT_H_INCLUDED
33 #include <assert.h>
34 #define ASSERT_H_INCLUDED 1
35 #endif
36 #endif
37
38
39
40
41
42
43 #if DK4_ON_WINDOWS
44 #if DK4_HAVE_GETADDRINFO
45
46 static
47 dk4_socket_t
dk4socket_wc_tcp_client_addresses(ADDRINFOW * raddrst,ADDRINFOW * laddrst,long secs,long usecs,dk4_er_t * erp)48 dk4socket_wc_tcp_client_addresses(
49 ADDRINFOW *raddrst,
50 ADDRINFOW *laddrst,
51 long secs,
52 long usecs,
53 dk4_er_t *erp
54 )
55 {
56 ADDRINFOW *ra;
57 ADDRINFOW *la;
58 dk4_socket_t back = INVALID_SOCKET;
59
60 ra = raddrst;
61 while ((INVALID_SOCKET == back) && (NULL != ra)) {
62 if (NULL != laddrst) {
63 la = laddrst;
64 while ((INVALID_SOCKET == back) && (NULL != la)) {
65 if (la->ai_family == ra->ai_family) {
66
67
68
69
70 back = dk4socket_tcp_client_for_addr(
71 ra->ai_family, ra->ai_addr, ra->ai_addrlen,
72 la->ai_addr, la->ai_addrlen, secs, usecs, erp
73 );
74 if (INVALID_SOCKET != back) {
75 la = NULL; ra = NULL;
76 }
77 }
78 if (NULL != la) { la = la->ai_next; }
79 }
80 } else {
81 back = dk4socket_tcp_client_for_addr(
82 ra->ai_family, ra->ai_addr, ra->ai_addrlen, NULL, 0,
83 secs, usecs, erp
84 );
85 if (INVALID_SOCKET != back) {
86 ra = NULL;
87 }
88 }
89 if (NULL != ra) { ra = ra->ai_next; }
90 }
91
92 return back;
93 }
94
95 #else
96
97 #endif
98 #endif
99
100
101
102 dk4_socket_t
dk4socket_wc_tcp_client_host_num_srv(const wchar_t * hostname,const wchar_t * svcname,const wchar_t * lsvcname,long secs,long usecs,int nsrv,dk4_er_t * erp)103 dk4socket_wc_tcp_client_host_num_srv(
104 #if DK4_ON_WINDOWS
105 const wchar_t *hostname,
106 const wchar_t *svcname,
107 const wchar_t *lsvcname,
108 long secs,
109 long usecs,
110 int nsrv,
111 #else
112 const wchar_t * DK4_ARG_UNUSED(hostname),
113 const wchar_t * DK4_ARG_UNUSED(svcname),
114 const wchar_t * DK4_ARG_UNUSED(lsvcname),
115 long DK4_ARG_UNUSED(secs),
116 long DK4_ARG_UNUSED(usecs),
117 int DK4_ARG_UNUSED(nsrv),
118 #endif
119 dk4_er_t *erp
120 )
121 {
122 #if DK4_ON_WINDOWS
123 #if DK4_HAVE_GETADDRINFO
124 /* +++++ +getaddrinfo */
125 ADDRINFOW rhints;
126 ADDRINFOW lhints;
127 ADDRINFOW *raddrst = NULL;
128 ADDRINFOW *laddrst = NULL;
129 dk4_socket_t back = INVALID_SOCKET;
130 int res;
131
132 #if DK4_USE_ASSERT
133 assert(NULL != hostname);
134 assert(NULL != svcname);
135 #endif
136 if ((NULL != hostname) && (NULL != svcname)) {
137 DK4_MEMRES(&rhints, sizeof(rhints));
138 rhints.ai_family = AF_UNSPEC;
139 rhints.ai_socktype = SOCK_STREAM;
140 if (0 != nsrv) { rhints.ai_flags = AI_NUMERICSERV; }
141 rhints.ai_protocol = 0;
142 res = GetAddrInfoW(hostname, svcname, &rhints, &raddrst);
143 if ((0 == res) && (NULL != raddrst)) {
144 if (NULL != lsvcname) {
145 DK4_MEMRES(&lhints, sizeof(lhints));
146 lhints.ai_family = AF_UNSPEC;
147 lhints.ai_socktype = SOCK_STREAM;
148 lhints.ai_flags = AI_PASSIVE;
149 if (0 != nsrv) { lhints.ai_flags |= AI_NUMERICSERV; }
150 lhints.ai_protocol = 0;
151 res = GetAddrInfoW(NULL, lsvcname, &lhints, &laddrst);
152 if ((0 == res) && (NULL != laddrst)) {
153 back = dk4socket_wc_tcp_client_addresses(
154 raddrst, laddrst, secs, usecs, erp
155 );
156 if (NULL != laddrst) { FreeAddrInfoW(laddrst); }
157 } else {
158 /* ERROR: getaddrinfo failed */
159 dk4error_set_idetails(erp, DK4_E_SOCKET_GETADDRLOC, res);
160 }
161 } else {
162 back = dk4socket_wc_tcp_client_addresses(
163 raddrst, NULL, secs, usecs, erp
164 );
165 }
166 } else {
167 /* ERROR: getaddrinfo failed */
168 dk4error_set_idetails(erp, DK4_E_SOCKET_GETADDRINFO, res);
169 }
170 if (NULL != laddrst) { FreeAddrInfoW(laddrst); }
171 } else {
172 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
173 }
174
175 return back;
176 /* ----- +getaddrinfo */
177 #else
178 /* +++++ -getaddrinfo */
179 char cppt[48];
180 char cplp[48];
181 struct servent *serv = NULL;
182 const wchar_t *endptr = NULL;
183 dk4_socket_t back = INVALID_SOCKET;
184 int res = 0;
185 unsigned short rport = 0U;
186 unsigned short lport = 0U;
187 unsigned short iport = 0U;
188 #if DK4_USE_ASSERT
189 assert(NULL != hostname);
190 assert(NULL != svcname);
191 #endif
192 if ((NULL != hostname) && (NULL != svcname)) {
193 res = dk4ma_input_dk_dec_ushort(&rport, svcname, &endptr, 1, erp);
194 if (0 == res) {
195 if (0 != dk4recode_wchar_t_to_char(cppt, sizeof(cppt), svcname, erp)) {
196 dk4socket_error_reset();
197 serv = getservbyname(cppt, NULL);
198 if (NULL != serv) {
199 iport = serv->s_port;
200 dk4socket_swap_bytes_if_not_bigendian((void *)(&iport),sizeof(iport));
201 rport = (unsigned short)iport;
202 } else {
203 dk4socket_error_report(erp, DK4_E_SOCKET_GETSERVBYNAME);
204 }
205 }
206 }
207 if (0 != rport) {
208 if (NULL != lsvcname) {
209 endptr = NULL;
210 res = dk4ma_input_dk_dec_ushort(&lport, lsvcname, &endptr, 1, erp);
211 if (0 == res) {
212 if (0 != dk4recode_wchar_t_to_char(cplp,sizeof(cplp),lsvcname,erp)) {
213 dk4socket_error_reset();
214 serv = getservbyname(cplp, NULL);
215 if (NULL != serv) {
216 iport = serv->s_port;
217 dk4socket_swap_bytes_if_not_bigendian(
218 (void *)(&iport), sizeof(iport)
219 );
220 lport = (unsigned short)iport;
221 } else {
222 dk4socket_error_report(erp, DK4_E_SOCKET_GETSERVBYNAME);
223 }
224 } else {
225 /* ERROR: Text conversion failed, already reported */
226 }
227 }
228 if (0 != lport) {
229 back = dk4socket_wc_tcp_client_host_port(
230 hostname, rport, lport, secs, usecs, erp
231 );
232 }
233 } else {
234 back = dk4socket_wc_tcp_client_host_port(
235 hostname, rport, (unsigned short)0, secs, usecs, erp
236 );
237 }
238 }
239 } else {
240 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
241 }
242 return back;
243 /* ----- -getaddrinfo */
244 #endif
245 #else
246 DK4_UNUSED_ARG(hostname)
247 DK4_UNUSED_ARG(svcname)
248 DK4_UNUSED_ARG(lsvcname)
249 DK4_UNUSED_ARG(secs)
250 DK4_UNUSED_ARG(usecs)
251 DK4_UNUSED_ARG(nsrv)
252 dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED);
253 return (DK4_SOCKET_RESULT_FAILED);
254 #endif
255 }
256
257
258
259 dk4_socket_t
dk4socket_wc_tcp_client_host_srv(const wchar_t * hostname,const wchar_t * svcname,const wchar_t * lsvcname,long secs,long usecs,dk4_er_t * erp)260 dk4socket_wc_tcp_client_host_srv(
261 const wchar_t *hostname,
262 const wchar_t *svcname,
263 const wchar_t *lsvcname,
264 long secs,
265 long usecs,
266 dk4_er_t *erp
267 )
268 {
269 return (
270 dk4socket_wc_tcp_client_host_num_srv(
271 hostname, svcname, lsvcname, secs, usecs, 0, erp
272 )
273 );
274 }
275
276
277
278 #if (DK4_HAVE_STRUCT_SOCKADDR_IN6) && (!(DK4_HAVE_GETADDRINFO))
279 /** used to initialize IPv6 address for binding local ports.
280 */
281 static const IN6_ADDR dk4sock18_any6 = IN6ADDR_ANY_INIT ;
282 #endif
283
284
285
286 dk4_socket_t
dk4socket_wc_tcp_client_host_port(const wchar_t * hostname,unsigned short portno,unsigned short lportno,long secs,long usecs,dk4_er_t * erp)287 dk4socket_wc_tcp_client_host_port(
288 #if DK4_ON_WINDOWS
289 const wchar_t *hostname,
290 unsigned short portno,
291 unsigned short lportno,
292 long secs,
293 long usecs,
294 #else
295 const wchar_t * DK4_ARG_UNUSED(hostname),
296 unsigned short DK4_ARG_UNUSED(portno),
297 unsigned short DK4_ARG_UNUSED(lportno),
298 long DK4_ARG_UNUSED(secs),
299 long DK4_ARG_UNUSED(usecs),
300 #endif
301 dk4_er_t *erp
302 )
303 {
304 #if DK4_ON_WINDOWS
305 #if DK4_HAVE_GETADDRINFO
306 /* +++++ +getaddrinfo */
307 wchar_t rpnb[16*sizeof(dk4_um_t)];
308 wchar_t lpnb[16*sizeof(dk4_um_t)];
309 const size_t szrpbn = DK4_SIZEOF(rpnb,wchar_t);
310 const size_t szlpnb = DK4_SIZEOF(lpnb,wchar_t);
311 dk4_socket_t back = INVALID_SOCKET;
312 int res;
313
314 #if DK4_USE_ASSERT
315 assert(NULL != hostname);
316 assert(0 < portno);
317 #endif
318 if ((NULL != hostname) && (0 < portno)) {
319 res = dk4ma_write_decimal_unsigned(rpnb, szrpbn, (dk4_um_t)portno, 0, erp);
320 if (0 != res) {
321 if (0 < lportno) {
322 res = dk4ma_write_decimal_unsigned(lpnb,szlpnb,(dk4_um_t)lportno,0,erp);
323 if (0 != res) {
324 back = dk4socket_wc_tcp_client_host_num_srv(
325 hostname, rpnb, lpnb, secs, usecs, 1, erp
326 );
327 } else {
328 }
329 } else {
330 back = dk4socket_wc_tcp_client_host_num_srv(
331 hostname, rpnb, NULL, secs, usecs, 1, erp
332 );
333 }
334 } else {
335 }
336 } else {
337 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
338 }
339
340 return back;
341 /* ----- +getaddrinfo */
342 #else
343 /* +++++ -getaddrinfo */
344 char hona[1040];
345 #if DK4_HAVE_STRUCT_SOCKADDR_IN6
346 struct sockaddr_in6 sr6;
347 struct sockaddr_in6 sl6;
348 #endif
349 struct sockaddr_in sr4;
350 struct sockaddr_in sl4;
351 char **addrptr;
352 struct hostent *hep;
353 dk4_socket_t back = INVALID_SOCKET;
354
355 #if DK4_USE_ASSERT
356 assert(NULL != hostname);
357 assert(0 < portno);
358 #endif
359 if ((NULL != hostname) && (0 < portno)) {
360 if (0 != dk4recode_wchar_t_to_char(hona, sizeof(hona), hostname, erp)) {
361 dk4socket_error_reset();
362 hep = gethostbyname(hona);
363 if (NULL != hep) {
364 if (NULL != hep->h_addr_list) {
365 switch (hep->h_addrtype) {
366 case AF_INET : {
367 if (4 == hep->h_length) {
368 addrptr = hep->h_addr_list;
369 while ((INVALID_SOCKET == back) && (NULL != *addrptr)) {
370 DK4_MEMRES(&sr4, sizeof(sr4));
371 sr4.sin_family = AF_INET;
372 sr4.sin_port = dk4socket_htons(portno);
373 DK4_MEMCPY(&(sr4.sin_addr), *addrptr, sizeof(IN_ADDR));
374
375 if (0 != lportno) {
376 DK4_MEMRES(&sl4, sizeof(sl4));
377 sl4.sin_family = AF_INET;
378 sl4.sin_port = dk4socket_htons(lportno);
379 sl4.sin_addr.s_addr = dk4socket_htonl(INADDR_ANY);
380
381 back = dk4socket_tcp_client_for_addr(
382 AF_INET, (struct sockaddr *)(&sr4), sizeof(sr4),
383 (struct sockaddr *)(&sl4), sizeof(sl4),
384 secs, usecs, erp
385 );
386 } else {
387 back = dk4socket_tcp_client_for_addr(
388 AF_INET, (struct sockaddr *)(&sr4), sizeof(sr4),
389 NULL, 0, secs, usecs, erp
390 );
391 }
392 addrptr++;
393 }
394 } else {
395 dk4error_set_simple_error_code(erp, DK4_E_BUG);
396 }
397 } break;
398 #if DK4_HAVE_STRUCT_SOCKADDR_IN6
399 case AF_INET6 : {
400 if (16 == hep->h_length) {
401 addrptr = hep->h_addr_list;
402 while ((INVALID_SOCKET == back) && (NULL != *addrptr)) {
403 DK4_MEMRES(&sr6, sizeof(sr6));
404 sr6.sin6_family = AF_INET6;
405 sr6.sin6_port = dk4socket_htons(portno);
406 DK4_MEMCPY(&(sr6.sin6_addr), *addrptr, sizeof(IN6_ADDR));
407 if (0 != lportno) {
408 DK4_MEMRES(&sl6, sizeof(sl6));
409 sl6.sin6_family = AF_INET6;
410 sl6.sin6_port = dk4socket_htons(lportno);
411 DK4_MEMCPY(&(sl6.sin6_addr), &dk4sock18_any6, sizeof(IN6_ADDR));
412 back = dk4socket_tcp_client_for_addr(
413 AF_INET6, (struct sockaddr *)(&sr6), sizeof(sr6),
414 (struct sockaddr *)(&sl6), sizeof(sl6),
415 secs, usecs, erp
416 );
417 } else {
418 back = dk4socket_tcp_client_for_addr(
419 AF_INET6, (struct sockaddr *)(&sr6), sizeof(sr6),
420 NULL, 0, secs, usecs, erp
421 );
422 }
423 addrptr++;
424 }
425 } else {
426 /* ERROR: Address length mismatch */
427 dk4error_set_simple_error_code(erp, DK4_E_BUG);
428 }
429 } break;
430 #endif
431 default : {
432 /* ERROR: Unknown protocol */
433 dk4error_set_simple_error_code(erp, DK4_E_BUG);
434 } break;
435 }
436 } else {
437 /* ERROR: List empty */
438 dk4error_set_simple_error_code(erp, DK4_E_BUG);
439 }
440 } else {
441 /* ERROR: Host not found */
442 dk4socket_error_report(erp, DK4_E_SOCKET_GETHOSTBYNAME);
443 }
444 } else {
445 /* ERROR: Failed to convert hostname to ASCII, already reported */
446 }
447 } else {
448 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
449 }
450
451 return back;
452 /* ----- -getaddrinfo */
453 #endif
454 #else
455 DK4_UNUSED_ARG(hostname)
456 DK4_UNUSED_ARG(portno)
457 DK4_UNUSED_ARG(lportno)
458 DK4_UNUSED_ARG(secs)
459 DK4_UNUSED_ARG(usecs)
460 dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED);
461 return (DK4_SOCKET_RESULT_FAILED);
462 #endif
463 }
464
465