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