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