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: dk4sock13.ctr
12 */
13 
14 /**	@file dk4sock13.c The dk4sock13 module.
15 */
16 
17 
18 #include "dk4conf.h"
19 #include <libdk4sock/dk4sock.h>
20 
21 #include <stdio.h>
22 
23 #if DK4_HAVE_ERRNO_H
24 #ifndef ERRNO_H_INCLUDED
25 #include <errno.h>
26 #define	ERRNO_H_INCLUDED 1
27 #endif
28 #endif
29 
30 #if DK4_HAVE_UNISTD_H
31 #ifndef	UNISTD_H_INCLUDED
32 #include <unistd.h>
33 #define	UNISTD_H_INCLUDED 1
34 #endif
35 #endif
36 
37 #if DK4_HAVE_IO_H
38 #ifndef	IO_H_INCLUDED
39 #include <io.h>
40 #define	IO_H_INCLUDED 1
41 #endif
42 #endif
43 
44 #if DK4_HAVE_STRINGS_H
45 #ifndef	STRINGS_H_INCLUDED
46 #include <strings.h>
47 #define	STRINGS_H_INCLUDED 1
48 #endif
49 #endif
50 
51 #include <libdk4base/dk4mem.h>
52 #include <libdk4c/dk4stat.h>
53 #include <libdk4c/dk4stat8.h>
54 #include <libdk4c/dk4delfile08.h>
55 
56 #if DK4_HAVE_ASSERT_H
57 #ifndef	ASSERT_H_INCLUDED
58 #include <assert.h>
59 #define	ASSERT_H_INCLUDED 1
60 #endif
61 #endif
62 
63 
64 
65 
66 
67 
68 
69 int
dk4socket_listen(dk4_socket_t sock,int bl,dk4_er_t * erp)70 dk4socket_listen(
71   dk4_socket_t		 sock,
72   int			 bl,
73   dk4_er_t		*erp
74 )
75 {
76   int		 back = DK4_SOCKET_RESULT_FAILED;
77 #if	DK4_USE_ASSERT
78   assert(INVALID_SOCKET != sock);
79 #endif
80   if ((INVALID_SOCKET != sock) && (0 < bl)) {
81     dk4socket_error_reset();
82     if (0 == listen(sock, bl)) {
83       back = DK4_SOCKET_RESULT_SUCCESS;
84     } else {
85       dk4socket_error_report(erp, DK4_E_SOCKET_LISTEN);
86     }
87   } else {
88     dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
89   }
90   return back;
91 }
92 
93 
94 
95 dk4_socket_t
dk4socket_accept(dk4_socket_t sock,struct sockaddr * pAddr,size_t * pSzAddr,dk4_er_t * erp)96 dk4socket_accept(
97   dk4_socket_t		 sock,
98   struct sockaddr	*pAddr,
99   size_t		*pSzAddr,
100   dk4_er_t		*erp
101 )
102 {
103   dk4_socket_t	 back	= INVALID_SOCKET;
104 #if DK4_HAVE_SOCKLEN_T
105   socklen_t	 sz;
106 #else
107   int		 sz;
108 #endif
109 
110 #if	DK4_USE_ASSERT
111   assert(INVALID_SOCKET != sock);
112   assert(NULL != pAddr);
113   assert(NULL != pSzAddr);
114   assert(0 < *pSzAddr);
115 #endif
116   if (INVALID_SOCKET != sock) {
117     if (NULL != pAddr) {
118       if (NULL != pSzAddr) {
119         if (0 < *pSzAddr) {
120 #if DK4_HAVE_SOCKLEN_T
121           sz = (socklen_t)(*pSzAddr);
122 #else
123           sz = (int)(*pSzAddr);
124 #endif
125           dk4socket_error_reset();
126           back = accept(sock, pAddr, &sz);
127           if (INVALID_SOCKET != back) {
128             *pSzAddr = (size_t)sz;
129           } else {
130             dk4socket_error_report(erp, DK4_E_SOCKET_ACCEPT);
131             *pSzAddr = 0;
132           }
133 	} else {
134 	  dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
135 	}
136       } else {
137         dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
138       }
139     } else {
140       /* ACCEPT */
141       dk4socket_error_reset();
142       back = accept(sock, NULL, NULL);
143       if (INVALID_SOCKET == back) {
144         dk4socket_error_report(erp, DK4_E_SOCKET_ACCEPT);
145       }
146     }
147   } else {
148     dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
149   }
150   return back;
151 }
152 
153 #if DK4_HAVE_STRUCT_SOCKADDR_UN
154 
155 
156 /**	Change mode and optionally owner and group for a socket.
157 	@param	sock		Socket file descriptor.
158 	@param	filename	Socket file name.
159 	@param	owner		New owner.
160 	@param	group		New group.
161 	@param	mode		New file mode.
162 	@param	cog		Flag: Also change owner and group.
163 	@param	erp		Error report, may be NULL
164 */
165 static
166 int
dk4socket_i_change_owner_group_mode(dk4_socket_t sock,const char * filename,uid_t owner,gid_t group,mode_t mode,int cog,dk4_er_t * erp)167 dk4socket_i_change_owner_group_mode(
168   dk4_socket_t		 sock,
169   const char		*filename,
170   uid_t			 owner,
171   gid_t			 group,
172   mode_t		 mode,
173   int			 cog,
174   dk4_er_t		*erp
175 )
176 {
177   int		 errval;
178   int		 back	= 1;
179 #if	DK4_USE_ASSERT
180   assert(INVALID_SOCKET != sock);
181   assert(NULL != filename);
182   assert(108 > strlen(filename));
183 #endif
184 
185   if (0 != cog) {
186     errno = 0;
187     if (0 != chown(filename, owner, group)) {
188       errval = errno;
189       if (0 != fchown(sock, owner, group)) {
190         back = 0;
191 	dk4error_set_idetails(erp, DK4_E_CHOWN_FAILED, errval);
192       }
193     }
194   }
195   errno = 0;
196   if (0 != chmod(filename, mode)) {
197     errval = errno;
198     if (0 != fchmod(sock, mode)) {
199       back = 0;
200       dk4error_set_idetails(erp, DK4_E_CHMOD_FAILED, errval);
201     }
202   }
203 
204   return back;
205 }
206 
207 
208 
209 static
210 dk4_socket_t
dk4socket_i_c8_unix_listener_ogm(const char * filename,int backlog,uid_t owner,gid_t group,mode_t mode,int change,dk4_er_t * erp)211 dk4socket_i_c8_unix_listener_ogm(
212   const char		*filename,
213   int			 backlog,
214   uid_t			 owner,
215   gid_t			 group,
216   mode_t		 mode,
217   int			 change,
218   dk4_er_t		*erp
219 )
220 {
221   struct sockaddr_un	soun;
222   dk4_stat_t		stb;
223   size_t		slen;
224   dk4_socket_t		back	= INVALID_SOCKET;
225   int			md	= 0;
226   int			res;
227   int			ogm1;
228   int			ogm2;
229 #if	DK4_USE_ASSERT
230   assert(NULL != filename);
231   assert(108 > strlen(filename));
232   assert(0 < backlog);
233 #endif
234   if ((NULL != filename) && (0 < backlog)) {
235     if (108 > strlen(filename)) {
236       /*	Attempt to remove existing socket.
237       */
238       res = 1;
239       if (0 != dk4stat_c8(&stb, filename, NULL)) {
240         res = 0;
241         if (0 != dk4stat_is_unix_domain_socket(&stb, NULL)) {
242 	  if (0 != dk4delete_file_c8(filename, NULL)) {
243 	    res = 1;
244 	  } else {
245 	    /* ERROR: Failed to remove old socket */
246 	    dk4error_set_simple_error_code(erp, DK4_E_UNLINK_FAILED);
247 	  }
248 	} else {
249 	  /* ERROR: Not a socket */
250 	  dk4error_set_simple_error_code(erp, DK4_E_NON_SOCKET);
251 	}
252       }
253       /*	Open and bind new socket.
254       */
255       if (0 != res) {
256         DK4_MEMRES(&soun, sizeof(soun));
257         soun.sun_family = AF_UNIX;
258         strcpy(soun.sun_path, filename);
259         slen = dk4socket_unix_length(&soun);
260         back = dk4socket_open(AF_UNIX, SOCK_STREAM, 0, erp);
261         if (INVALID_SOCKET != back) {
262           (void)dk4socket_option_set_reuse(back, 1, NULL);
263 	  res = dk4socket_bind(
264 	    back, (const struct sockaddr *)(&soun), slen, erp
265 	  );
266 	  if (DK4_SOCKET_RESULT_SUCCESS == res) {
267 	    ogm1 = dk4socket_i_change_owner_group_mode(
268 	      back, filename, owner, group, mode, change, erp
269 	    );
270 	    res = dk4socket_listen(back, backlog, erp);
271 	    if (DK4_SOCKET_RESULT_SUCCESS == res) {
272 	      ogm2 = dk4socket_i_change_owner_group_mode(
273 		back, filename, owner, group, mode, change, erp
274 	      );
275 	      if ((0 == ogm1) && (0 == ogm2)) {
276 	        (void)dk4socket_close(back, NULL);
277 		back = INVALID_SOCKET;
278 		md = 1;
279 	      }
280 	    } else {
281 	      (void)dk4socket_close(back, NULL);
282 	      back = INVALID_SOCKET;
283 	      md = 1;
284 	    }
285 	  } else {
286 	    (void)dk4socket_close(back, NULL);
287 	    back = INVALID_SOCKET;
288 	  }
289 	  if ((INVALID_SOCKET == back) && (0 != md)) {
290 	    (void)dk4delete_file_c8(filename, NULL);
291 	  }
292         }
293       } else {
294       }
295     } else {
296       dk4error_set_simple_error_code(erp, DK4_E_SYNTAX);
297     }
298   } else {
299     dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
300   }
301   return back;
302 }
303 
304 
305 
306 dk4_socket_t
dk4socket_c8_unix_listener(const char * filename,int backlog,dk4_er_t * erp)307 dk4socket_c8_unix_listener(
308   const char		*filename,
309   int			 backlog,
310   dk4_er_t		*erp
311 )
312 {
313 #if	DK4_USE_ASSERT
314   assert(NULL != filename);
315   assert(108 > strlen(filename));
316 #endif
317   return (
318     dk4socket_i_c8_unix_listener_ogm(filename, backlog, 0, 0, 0660, 0, erp)
319   );
320 }
321 
322 
323 
324 dk4_socket_t
dk4socket_c8_unix_listener_owner_group_mode(const char * filename,int backlog,uid_t owner,gid_t group,mode_t mode,dk4_er_t * erp)325 dk4socket_c8_unix_listener_owner_group_mode(
326   const char		*filename,
327   int			 backlog,
328   uid_t			 owner,
329   gid_t			 group,
330   mode_t		 mode,
331   dk4_er_t		*erp
332 )
333 {
334 #if	DK4_USE_ASSERT
335   assert(NULL != filename);
336   assert(108 > strlen(filename));
337 #endif
338   return (
339     dk4socket_i_c8_unix_listener_ogm(
340       filename, backlog, owner, group, mode, 1, erp
341     )
342   );
343 }
344 
345 
346 
347 
348 #endif
349