File: | src/lib/libossaudio/../libsndio/aucat.c |
Warning: | line 282, column 2 Null pointer passed as 2nd argument to memory copy function |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: aucat.c,v 1.79 2021/11/07 20:51:47 ratchov Exp $ */ | |||
2 | /* | |||
3 | * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> | |||
4 | * | |||
5 | * Permission to use, copy, modify, and distribute this software for any | |||
6 | * purpose with or without fee is hereby granted, provided that the above | |||
7 | * copyright notice and this permission notice appear in all copies. | |||
8 | * | |||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
16 | */ | |||
17 | ||||
18 | #include <sys/types.h> | |||
19 | #include <sys/socket.h> | |||
20 | #include <sys/stat.h> | |||
21 | #include <sys/un.h> | |||
22 | ||||
23 | #include <netinet/in.h> | |||
24 | #include <netinet/tcp.h> | |||
25 | #include <netdb.h> | |||
26 | ||||
27 | #include <errno(*__errno()).h> | |||
28 | #include <fcntl.h> | |||
29 | #include <limits.h> | |||
30 | #include <poll.h> | |||
31 | #include <stdio.h> | |||
32 | #include <stdlib.h> | |||
33 | #include <string.h> | |||
34 | #include <unistd.h> | |||
35 | ||||
36 | #include "aucat.h" | |||
37 | #include "debug.h" | |||
38 | ||||
39 | ||||
40 | /* | |||
41 | * read a message, return 0 if not completed | |||
42 | */ | |||
43 | int | |||
44 | _aucat_rmsg(struct aucat *hdl, int *eof) | |||
45 | { | |||
46 | ssize_t n; | |||
47 | unsigned char *data; | |||
48 | ||||
49 | if (hdl->rstate != RSTATE_MSG0) { | |||
50 | DPRINTF("_aucat_rmsg: bad state\n")do {} while(0); | |||
51 | abort(); | |||
52 | } | |||
53 | while (hdl->rtodo > 0) { | |||
54 | data = (unsigned char *)&hdl->rmsg; | |||
55 | data += sizeof(struct amsg) - hdl->rtodo; | |||
56 | while ((n = read(hdl->fd, data, hdl->rtodo)) == -1) { | |||
57 | if (errno(*__errno()) == EINTR4) | |||
58 | continue; | |||
59 | if (errno(*__errno()) != EAGAIN35) { | |||
60 | *eof = 1; | |||
61 | DPERROR("_aucat_rmsg: read")do {} while(0); | |||
62 | } | |||
63 | return 0; | |||
64 | } | |||
65 | if (n == 0) { | |||
66 | DPRINTF("_aucat_rmsg: eof\n")do {} while(0); | |||
67 | *eof = 1; | |||
68 | return 0; | |||
69 | } | |||
70 | hdl->rtodo -= n; | |||
71 | } | |||
72 | if (ntohl(hdl->rmsg.cmd)(__uint32_t)(__builtin_constant_p(hdl->rmsg.cmd) ? (__uint32_t )(((__uint32_t)(hdl->rmsg.cmd) & 0xff) << 24 | ( (__uint32_t)(hdl->rmsg.cmd) & 0xff00) << 8 | ((__uint32_t )(hdl->rmsg.cmd) & 0xff0000) >> 8 | ((__uint32_t )(hdl->rmsg.cmd) & 0xff000000) >> 24) : __swap32md (hdl->rmsg.cmd)) == AMSG_DATA5) { | |||
73 | hdl->rtodo = ntohl(hdl->rmsg.u.data.size)(__uint32_t)(__builtin_constant_p(hdl->rmsg.u.data.size) ? (__uint32_t)(((__uint32_t)(hdl->rmsg.u.data.size) & 0xff ) << 24 | ((__uint32_t)(hdl->rmsg.u.data.size) & 0xff00) << 8 | ((__uint32_t)(hdl->rmsg.u.data.size) & 0xff0000) >> 8 | ((__uint32_t)(hdl->rmsg.u.data .size) & 0xff000000) >> 24) : __swap32md(hdl->rmsg .u.data.size)); | |||
74 | hdl->rstate = RSTATE_DATA1; | |||
75 | } else { | |||
76 | hdl->rtodo = sizeof(struct amsg); | |||
77 | hdl->rstate = RSTATE_MSG0; | |||
78 | } | |||
79 | return 1; | |||
80 | } | |||
81 | ||||
82 | /* | |||
83 | * write a message, return 0 if not completed | |||
84 | */ | |||
85 | int | |||
86 | _aucat_wmsg(struct aucat *hdl, int *eof) | |||
87 | { | |||
88 | ssize_t n; | |||
89 | unsigned char *data; | |||
90 | ||||
91 | if (hdl->wstate == WSTATE_IDLE2) { | |||
92 | hdl->wstate = WSTATE_MSG3; | |||
93 | hdl->wtodo = sizeof(struct amsg); | |||
94 | } | |||
95 | if (hdl->wstate != WSTATE_MSG3) { | |||
96 | DPRINTF("_aucat_wmsg: bad state\n")do {} while(0); | |||
97 | abort(); | |||
98 | } | |||
99 | while (hdl->wtodo > 0) { | |||
100 | data = (unsigned char *)&hdl->wmsg; | |||
101 | data += sizeof(struct amsg) - hdl->wtodo; | |||
102 | while ((n = write(hdl->fd, data, hdl->wtodo)) == -1) { | |||
103 | if (errno(*__errno()) == EINTR4) | |||
104 | continue; | |||
105 | if (errno(*__errno()) != EAGAIN35) { | |||
106 | *eof = 1; | |||
107 | DPERROR("_aucat_wmsg: write")do {} while(0); | |||
108 | } | |||
109 | return 0; | |||
110 | } | |||
111 | hdl->wtodo -= n; | |||
112 | } | |||
113 | if (ntohl(hdl->wmsg.cmd)(__uint32_t)(__builtin_constant_p(hdl->wmsg.cmd) ? (__uint32_t )(((__uint32_t)(hdl->wmsg.cmd) & 0xff) << 24 | ( (__uint32_t)(hdl->wmsg.cmd) & 0xff00) << 8 | ((__uint32_t )(hdl->wmsg.cmd) & 0xff0000) >> 8 | ((__uint32_t )(hdl->wmsg.cmd) & 0xff000000) >> 24) : __swap32md (hdl->wmsg.cmd)) == AMSG_DATA5) { | |||
114 | hdl->wtodo = ntohl(hdl->wmsg.u.data.size)(__uint32_t)(__builtin_constant_p(hdl->wmsg.u.data.size) ? (__uint32_t)(((__uint32_t)(hdl->wmsg.u.data.size) & 0xff ) << 24 | ((__uint32_t)(hdl->wmsg.u.data.size) & 0xff00) << 8 | ((__uint32_t)(hdl->wmsg.u.data.size) & 0xff0000) >> 8 | ((__uint32_t)(hdl->wmsg.u.data .size) & 0xff000000) >> 24) : __swap32md(hdl->wmsg .u.data.size)); | |||
115 | hdl->wstate = WSTATE_DATA4; | |||
116 | } else { | |||
117 | hdl->wtodo = 0xdeadbeef; | |||
118 | hdl->wstate = WSTATE_IDLE2; | |||
119 | } | |||
120 | return 1; | |||
121 | } | |||
122 | ||||
123 | size_t | |||
124 | _aucat_rdata(struct aucat *hdl, void *buf, size_t len, int *eof) | |||
125 | { | |||
126 | ssize_t n; | |||
127 | ||||
128 | if (hdl->rstate != RSTATE_DATA1) { | |||
129 | DPRINTF("_aucat_rdata: bad state\n")do {} while(0); | |||
130 | abort(); | |||
131 | } | |||
132 | if (len > hdl->rtodo) | |||
133 | len = hdl->rtodo; | |||
134 | while ((n = read(hdl->fd, buf, len)) == -1) { | |||
135 | if (errno(*__errno()) == EINTR4) | |||
136 | continue; | |||
137 | if (errno(*__errno()) != EAGAIN35) { | |||
138 | *eof = 1; | |||
139 | DPERROR("_aucat_rdata: read")do {} while(0); | |||
140 | } | |||
141 | return 0; | |||
142 | } | |||
143 | if (n == 0) { | |||
144 | DPRINTF("_aucat_rdata: eof\n")do {} while(0); | |||
145 | *eof = 1; | |||
146 | return 0; | |||
147 | } | |||
148 | hdl->rtodo -= n; | |||
149 | if (hdl->rtodo == 0) { | |||
150 | hdl->rstate = RSTATE_MSG0; | |||
151 | hdl->rtodo = sizeof(struct amsg); | |||
152 | } | |||
153 | DPRINTFN(2, "_aucat_rdata: read: n = %zd\n", n)do {} while(0); | |||
154 | return n; | |||
155 | } | |||
156 | ||||
157 | size_t | |||
158 | _aucat_wdata(struct aucat *hdl, const void *buf, size_t len, | |||
159 | unsigned int wbpf, int *eof) | |||
160 | { | |||
161 | ssize_t n; | |||
162 | size_t datasize; | |||
163 | ||||
164 | switch (hdl->wstate) { | |||
165 | case WSTATE_IDLE2: | |||
166 | datasize = len; | |||
167 | if (datasize > AMSG_DATAMAX0x1000) | |||
168 | datasize = AMSG_DATAMAX0x1000; | |||
169 | datasize -= datasize % wbpf; | |||
170 | if (datasize == 0) | |||
171 | datasize = wbpf; | |||
172 | hdl->wmsg.cmd = htonl(AMSG_DATA)(__uint32_t)(__builtin_constant_p(5) ? (__uint32_t)(((__uint32_t )(5) & 0xff) << 24 | ((__uint32_t)(5) & 0xff00) << 8 | ((__uint32_t)(5) & 0xff0000) >> 8 | ( (__uint32_t)(5) & 0xff000000) >> 24) : __swap32md(5 )); | |||
173 | hdl->wmsg.u.data.size = htonl(datasize)(__uint32_t)(__builtin_constant_p(datasize) ? (__uint32_t)((( __uint32_t)(datasize) & 0xff) << 24 | ((__uint32_t) (datasize) & 0xff00) << 8 | ((__uint32_t)(datasize) & 0xff0000) >> 8 | ((__uint32_t)(datasize) & 0xff000000 ) >> 24) : __swap32md(datasize)); | |||
174 | hdl->wtodo = sizeof(struct amsg); | |||
175 | hdl->wstate = WSTATE_MSG3; | |||
176 | /* FALLTHROUGH */ | |||
177 | case WSTATE_MSG3: | |||
178 | if (!_aucat_wmsg(hdl, eof)) | |||
179 | return 0; | |||
180 | } | |||
181 | if (len > hdl->wtodo) | |||
182 | len = hdl->wtodo; | |||
183 | if (len == 0) { | |||
184 | DPRINTF("_aucat_wdata: len == 0\n")do {} while(0); | |||
185 | abort(); | |||
186 | } | |||
187 | while ((n = write(hdl->fd, buf, len)) == -1) { | |||
188 | if (errno(*__errno()) == EINTR4) | |||
189 | continue; | |||
190 | if (errno(*__errno()) != EAGAIN35) { | |||
191 | *eof = 1; | |||
192 | DPERROR("_aucat_wdata: write")do {} while(0); | |||
193 | } | |||
194 | return 0; | |||
195 | } | |||
196 | DPRINTFN(2, "_aucat_wdata: write: n = %zd\n", n)do {} while(0); | |||
197 | hdl->wtodo -= n; | |||
198 | if (hdl->wtodo == 0) { | |||
199 | hdl->wstate = WSTATE_IDLE2; | |||
200 | hdl->wtodo = 0xdeadbeef; | |||
201 | } | |||
202 | return n; | |||
203 | } | |||
204 | ||||
205 | static int | |||
206 | aucat_mkcookie(unsigned char *cookie) | |||
207 | { | |||
208 | #define COOKIE_DIR"/.sndio" "/.sndio" | |||
209 | #define COOKIE_SUFFIX"/.sndio/cookie" "/.sndio/cookie" | |||
210 | #define TEMPL_SUFFIX".XXXXXXXX" ".XXXXXXXX" | |||
211 | struct stat sb; | |||
212 | char *home, *path = NULL((void *)0), *tmp = NULL((void *)0); | |||
213 | size_t home_len, path_len; | |||
214 | int fd, len; | |||
215 | ||||
216 | /* please gcc */ | |||
217 | path_len = 0xdeadbeef; | |||
218 | ||||
219 | /* | |||
220 | * try to load the cookie | |||
221 | */ | |||
222 | home = issetugid() ? NULL((void *)0) : getenv("HOME"); | |||
223 | if (home == NULL((void *)0)) | |||
224 | goto bad_gen; | |||
225 | home_len = strlen(home); | |||
226 | path = malloc(home_len + sizeof(COOKIE_SUFFIX"/.sndio/cookie")); | |||
227 | if (path == NULL((void *)0)) | |||
228 | goto bad_gen; | |||
229 | memcpy(path, home, home_len); | |||
230 | memcpy(path + home_len, COOKIE_SUFFIX"/.sndio/cookie", sizeof(COOKIE_SUFFIX"/.sndio/cookie")); | |||
231 | path_len = home_len + sizeof(COOKIE_SUFFIX"/.sndio/cookie") - 1; | |||
232 | fd = open(path, O_RDONLY0x0000); | |||
233 | if (fd == -1) { | |||
234 | if (errno(*__errno()) != ENOENT2) | |||
235 | DPERROR(path)do {} while(0); | |||
236 | goto bad_gen; | |||
237 | } | |||
238 | if (fstat(fd, &sb) == -1) { | |||
239 | DPERROR(path)do {} while(0); | |||
240 | goto bad_close; | |||
241 | } | |||
242 | if (sb.st_mode & 0077) { | |||
243 | DPRINTF("%s has wrong permissions\n", path)do {} while(0); | |||
244 | goto bad_close; | |||
245 | } | |||
246 | len = read(fd, cookie, AMSG_COOKIELEN16); | |||
247 | if (len == -1) { | |||
248 | DPERROR(path)do {} while(0); | |||
249 | goto bad_close; | |||
250 | } | |||
251 | if (len != AMSG_COOKIELEN16) { | |||
252 | DPRINTF("%s: short read\n", path)do {} while(0); | |||
253 | goto bad_close; | |||
254 | } | |||
255 | close(fd); | |||
256 | goto done; | |||
257 | bad_close: | |||
258 | close(fd); | |||
259 | bad_gen: | |||
260 | /* | |||
261 | * generate a new cookie | |||
262 | */ | |||
263 | arc4random_buf(cookie, AMSG_COOKIELEN16); | |||
264 | ||||
265 | /* | |||
266 | * try to save the cookie | |||
267 | */ | |||
268 | ||||
269 | if (home
| |||
270 | goto done; | |||
271 | tmp = malloc(path_len + sizeof(TEMPL_SUFFIX".XXXXXXXX")); | |||
272 | if (tmp == NULL((void *)0)) | |||
273 | goto done; | |||
274 | ||||
275 | /* create ~/.sndio directory */ | |||
276 | memcpy(tmp, home, home_len); | |||
277 | memcpy(tmp + home_len, COOKIE_DIR"/.sndio", sizeof(COOKIE_DIR"/.sndio")); | |||
278 | if (mkdir(tmp, 0755) == -1 && errno(*__errno()) != EEXIST17) | |||
279 | goto done; | |||
280 | ||||
281 | /* create cookie file in it */ | |||
282 | memcpy(tmp, path, path_len); | |||
| ||||
283 | memcpy(tmp + path_len, TEMPL_SUFFIX".XXXXXXXX", sizeof(TEMPL_SUFFIX".XXXXXXXX")); | |||
284 | fd = mkstemp(tmp); | |||
285 | if (fd == -1) { | |||
286 | DPERROR(tmp)do {} while(0); | |||
287 | goto done; | |||
288 | } | |||
289 | if (write(fd, cookie, AMSG_COOKIELEN16) == -1) { | |||
290 | DPERROR(tmp)do {} while(0); | |||
291 | unlink(tmp); | |||
292 | close(fd); | |||
293 | goto done; | |||
294 | } | |||
295 | close(fd); | |||
296 | if (rename(tmp, path) == -1) { | |||
297 | DPERROR(tmp)do {} while(0); | |||
298 | unlink(tmp); | |||
299 | } | |||
300 | done: | |||
301 | free(tmp); | |||
302 | free(path); | |||
303 | return 1; | |||
304 | } | |||
305 | ||||
306 | static int | |||
307 | aucat_connect_tcp(struct aucat *hdl, char *host, unsigned int unit) | |||
308 | { | |||
309 | int s, error, opt; | |||
310 | struct addrinfo *ailist, *ai, aihints; | |||
311 | char serv[NI_MAXSERV32]; | |||
312 | ||||
313 | snprintf(serv, sizeof(serv), "%u", unit + AUCAT_PORT11025); | |||
314 | memset(&aihints, 0, sizeof(struct addrinfo)); | |||
315 | aihints.ai_socktype = SOCK_STREAM1; | |||
316 | aihints.ai_protocol = IPPROTO_TCP6; | |||
317 | error = getaddrinfo(host, serv, &aihints, &ailist); | |||
318 | if (error) { | |||
319 | DPRINTF("%s: %s\n", host, gai_strerror(error))do {} while(0); | |||
320 | return 0; | |||
321 | } | |||
322 | s = -1; | |||
323 | for (ai = ailist; ai != NULL((void *)0); ai = ai->ai_next) { | |||
324 | s = socket(ai->ai_family, ai->ai_socktype | SOCK_CLOEXEC0x8000, | |||
325 | ai->ai_protocol); | |||
326 | if (s == -1) { | |||
327 | DPERROR("socket")do {} while(0); | |||
328 | continue; | |||
329 | } | |||
330 | restart: | |||
331 | if (connect(s, ai->ai_addr, ai->ai_addrlen) == -1) { | |||
332 | if (errno(*__errno()) == EINTR4) | |||
333 | goto restart; | |||
334 | DPERROR("connect")do {} while(0); | |||
335 | close(s); | |||
336 | s = -1; | |||
337 | continue; | |||
338 | } | |||
339 | break; | |||
340 | } | |||
341 | freeaddrinfo(ailist); | |||
342 | if (s == -1) | |||
343 | return 0; | |||
344 | opt = 1; | |||
345 | if (setsockopt(s, IPPROTO_TCP6, TCP_NODELAY0x01, &opt, sizeof(int)) == -1) { | |||
346 | DPERROR("setsockopt")do {} while(0); | |||
347 | close(s); | |||
348 | return 0; | |||
349 | } | |||
350 | hdl->fd = s; | |||
351 | return 1; | |||
352 | } | |||
353 | ||||
354 | static int | |||
355 | aucat_connect_un(struct aucat *hdl, unsigned int unit) | |||
356 | { | |||
357 | struct sockaddr_un ca; | |||
358 | socklen_t len = sizeof(struct sockaddr_un); | |||
359 | uid_t uid; | |||
360 | int s; | |||
361 | ||||
362 | uid = geteuid(); | |||
363 | snprintf(ca.sun_path, sizeof(ca.sun_path), | |||
364 | SOCKPATH_DIR"/tmp/sndio" "-%u/" SOCKPATH_FILE"sock" "%u", uid, unit); | |||
365 | ca.sun_family = AF_UNIX1; | |||
366 | s = socket(AF_UNIX1, SOCK_STREAM1 | SOCK_CLOEXEC0x8000, 0); | |||
367 | if (s == -1) | |||
368 | return 0; | |||
369 | while (connect(s, (struct sockaddr *)&ca, len) == -1) { | |||
370 | if (errno(*__errno()) == EINTR4) | |||
371 | continue; | |||
372 | DPERROR(ca.sun_path)do {} while(0); | |||
373 | /* try shared server */ | |||
374 | snprintf(ca.sun_path, sizeof(ca.sun_path), | |||
375 | SOCKPATH_DIR"/tmp/sndio" "/" SOCKPATH_FILE"sock" "%u", unit); | |||
376 | while (connect(s, (struct sockaddr *)&ca, len) == -1) { | |||
377 | if (errno(*__errno()) == EINTR4) | |||
378 | continue; | |||
379 | DPERROR(ca.sun_path)do {} while(0); | |||
380 | close(s); | |||
381 | return 0; | |||
382 | } | |||
383 | break; | |||
384 | } | |||
385 | hdl->fd = s; | |||
386 | DPRINTFN(2, "%s: connected\n", ca.sun_path)do {} while(0); | |||
387 | return 1; | |||
388 | } | |||
389 | ||||
390 | static const char * | |||
391 | parsestr(const char *str, char *rstr, unsigned int max) | |||
392 | { | |||
393 | const char *p = str; | |||
394 | ||||
395 | while (*p != '\0' && *p != ',' && *p != '/') { | |||
396 | if (--max == 0) { | |||
397 | DPRINTF("%s: string too long\n", str)do {} while(0); | |||
398 | return NULL((void *)0); | |||
399 | } | |||
400 | *rstr++ = *p++; | |||
401 | } | |||
402 | if (str == p) { | |||
403 | DPRINTF("%s: string expected\n", str)do {} while(0); | |||
404 | return NULL((void *)0); | |||
405 | } | |||
406 | *rstr = '\0'; | |||
407 | return p; | |||
408 | } | |||
409 | ||||
410 | int | |||
411 | _aucat_open(struct aucat *hdl, const char *str, unsigned int mode) | |||
412 | { | |||
413 | extern char *__progname; | |||
414 | int eof; | |||
415 | char host[NI_MAXHOST256], opt[AMSG_OPTMAX12]; | |||
416 | const char *p; | |||
417 | unsigned int unit, devnum, type; | |||
418 | ||||
419 | if ((p = _sndio_parsetype(str, "snd")) != NULL((void *)0)) | |||
| ||||
420 | type = 0; | |||
421 | else if ((p = _sndio_parsetype(str, "midithru")) != NULL((void *)0)) | |||
422 | type = 1; | |||
423 | else if ((p = _sndio_parsetype(str, "midi")) != NULL((void *)0)) | |||
424 | type = 2; | |||
425 | else { | |||
426 | DPRINTF("%s: unsupported device type\n", str)do {} while(0); | |||
427 | return -1; | |||
428 | } | |||
429 | if (*p == '@') { | |||
430 | p = parsestr(++p, host, NI_MAXHOST256); | |||
431 | if (p == NULL((void *)0)) | |||
432 | return 0; | |||
433 | } else | |||
434 | *host = '\0'; | |||
435 | if (*p == ',') { | |||
436 | p = _sndio_parsenum(++p, &unit, 15); | |||
437 | if (p == NULL((void *)0)) | |||
438 | return 0; | |||
439 | } else | |||
440 | unit = 0; | |||
441 | if (*p != '/') { | |||
442 | DPRINTF("%s: '/' expected\n", str)do {} while(0); | |||
443 | return 0; | |||
444 | } | |||
445 | p++; | |||
446 | if (type
| |||
447 | if (*p < '0' || *p > '9') { | |||
448 | devnum = AMSG_NODEV255; | |||
449 | p = parsestr(p, opt, AMSG_OPTMAX12); | |||
450 | if (p == NULL((void *)0)) | |||
451 | return 0; | |||
452 | } else { | |||
453 | p = _sndio_parsenum(p, &devnum, 15); | |||
454 | if (p == NULL((void *)0)) | |||
455 | return 0; | |||
456 | if (*p == '.') { | |||
457 | p = parsestr(++p, opt, AMSG_OPTMAX12); | |||
458 | if (p == NULL((void *)0)) | |||
459 | return 0; | |||
460 | } else | |||
461 | strlcpy(opt, "default", AMSG_OPTMAX12); | |||
462 | } | |||
463 | } else { | |||
464 | p = _sndio_parsenum(p, &devnum, 15); | |||
465 | if (p == NULL((void *)0)) | |||
466 | return 0; | |||
467 | memset(opt, 0, sizeof(opt)); | |||
468 | } | |||
469 | if (*p != '\0') { | |||
470 | DPRINTF("%s: junk at end of dev name\n", p)do {} while(0); | |||
471 | return 0; | |||
472 | } | |||
473 | devnum += type * 16; /* XXX */ | |||
474 | DPRINTFN(2, "_aucat_open: host=%s unit=%u devnum=%u opt=%s\n",do {} while(0) | |||
475 | host, unit, devnum, opt)do {} while(0); | |||
476 | if (host[0] != '\0') { | |||
477 | if (!aucat_connect_tcp(hdl, host, unit)) | |||
478 | return 0; | |||
479 | } else { | |||
480 | if (!aucat_connect_un(hdl, unit)) | |||
481 | return 0; | |||
482 | } | |||
483 | hdl->rstate = RSTATE_MSG0; | |||
484 | hdl->rtodo = sizeof(struct amsg); | |||
485 | hdl->wstate = WSTATE_IDLE2; | |||
486 | hdl->wtodo = 0xdeadbeef; | |||
487 | hdl->maxwrite = 0; | |||
488 | ||||
489 | /* | |||
490 | * say hello to server | |||
491 | */ | |||
492 | AMSG_INIT(&hdl->wmsg)do { memset((&hdl->wmsg), 0xff, sizeof(struct amsg)); } while (0); | |||
493 | hdl->wmsg.cmd = htonl(AMSG_AUTH)(__uint32_t)(__builtin_constant_p(12) ? (__uint32_t)(((__uint32_t )(12) & 0xff) << 24 | ((__uint32_t)(12) & 0xff00 ) << 8 | ((__uint32_t)(12) & 0xff0000) >> 8 | ((__uint32_t)(12) & 0xff000000) >> 24) : __swap32md (12)); | |||
494 | if (!aucat_mkcookie(hdl->wmsg.u.auth.cookie)) | |||
495 | goto bad_connect; | |||
496 | hdl->wtodo = sizeof(struct amsg); | |||
497 | if (!_aucat_wmsg(hdl, &eof)) | |||
498 | goto bad_connect; | |||
499 | AMSG_INIT(&hdl->wmsg)do { memset((&hdl->wmsg), 0xff, sizeof(struct amsg)); } while (0); | |||
500 | hdl->wmsg.cmd = htonl(AMSG_HELLO)(__uint32_t)(__builtin_constant_p(10) ? (__uint32_t)(((__uint32_t )(10) & 0xff) << 24 | ((__uint32_t)(10) & 0xff00 ) << 8 | ((__uint32_t)(10) & 0xff0000) >> 8 | ((__uint32_t)(10) & 0xff000000) >> 24) : __swap32md (10)); | |||
501 | hdl->wmsg.u.hello.version = AMSG_VERSION7; | |||
502 | hdl->wmsg.u.hello.mode = htons(mode)(__uint16_t)(__builtin_constant_p(mode) ? (__uint16_t)(((__uint16_t )(mode) & 0xffU) << 8 | ((__uint16_t)(mode) & 0xff00U ) >> 8) : __swap16md(mode)); | |||
503 | hdl->wmsg.u.hello.devnum = devnum; | |||
504 | hdl->wmsg.u.hello.id = htonl(getpid())(__uint32_t)(__builtin_constant_p(getpid()) ? (__uint32_t)((( __uint32_t)(getpid()) & 0xff) << 24 | ((__uint32_t) (getpid()) & 0xff00) << 8 | ((__uint32_t)(getpid()) & 0xff0000) >> 8 | ((__uint32_t)(getpid()) & 0xff000000 ) >> 24) : __swap32md(getpid())); | |||
505 | strlcpy(hdl->wmsg.u.hello.who, __progname, | |||
506 | sizeof(hdl->wmsg.u.hello.who)); | |||
507 | strlcpy(hdl->wmsg.u.hello.opt, opt, | |||
508 | sizeof(hdl->wmsg.u.hello.opt)); | |||
509 | hdl->wtodo = sizeof(struct amsg); | |||
510 | if (!_aucat_wmsg(hdl, &eof)) | |||
511 | goto bad_connect; | |||
512 | hdl->rtodo = sizeof(struct amsg); | |||
513 | if (!_aucat_rmsg(hdl, &eof)) { | |||
514 | DPRINTF("aucat_init: mode refused\n")do {} while(0); | |||
515 | goto bad_connect; | |||
516 | } | |||
517 | if (ntohl(hdl->rmsg.cmd)(__uint32_t)(__builtin_constant_p(hdl->rmsg.cmd) ? (__uint32_t )(((__uint32_t)(hdl->rmsg.cmd) & 0xff) << 24 | ( (__uint32_t)(hdl->rmsg.cmd) & 0xff00) << 8 | ((__uint32_t )(hdl->rmsg.cmd) & 0xff0000) >> 8 | ((__uint32_t )(hdl->rmsg.cmd) & 0xff000000) >> 24) : __swap32md (hdl->rmsg.cmd)) != AMSG_ACK0) { | |||
518 | DPRINTF("aucat_init: protocol err\n")do {} while(0); | |||
519 | goto bad_connect; | |||
520 | } | |||
521 | return 1; | |||
522 | bad_connect: | |||
523 | while (close(hdl->fd) == -1 && errno(*__errno()) == EINTR4) | |||
524 | ; /* retry */ | |||
525 | return 0; | |||
526 | } | |||
527 | ||||
528 | void | |||
529 | _aucat_close(struct aucat *hdl, int eof) | |||
530 | { | |||
531 | char dummy[sizeof(struct amsg)]; | |||
532 | ssize_t n; | |||
533 | ||||
534 | if (!eof) { | |||
535 | AMSG_INIT(&hdl->wmsg)do { memset((&hdl->wmsg), 0xff, sizeof(struct amsg)); } while (0); | |||
536 | hdl->wmsg.cmd = htonl(AMSG_BYE)(__uint32_t)(__builtin_constant_p(11) ? (__uint32_t)(((__uint32_t )(11) & 0xff) << 24 | ((__uint32_t)(11) & 0xff00 ) << 8 | ((__uint32_t)(11) & 0xff0000) >> 8 | ((__uint32_t)(11) & 0xff000000) >> 24) : __swap32md (11)); | |||
537 | hdl->wtodo = sizeof(struct amsg); | |||
538 | if (!_aucat_wmsg(hdl, &eof)) | |||
539 | goto bad_close; | |||
540 | ||||
541 | /* | |||
542 | * block until the peer disconnects | |||
543 | */ | |||
544 | while (1) { | |||
545 | n = read(hdl->fd, dummy, sizeof(dummy)); | |||
546 | if (n == -1) { | |||
547 | if (errno(*__errno()) == EINTR4) | |||
548 | continue; | |||
549 | break; | |||
550 | } | |||
551 | if (n == 0) | |||
552 | break; | |||
553 | } | |||
554 | } | |||
555 | bad_close: | |||
556 | while (close(hdl->fd) == -1 && errno(*__errno()) == EINTR4) | |||
557 | ; /* nothing */ | |||
558 | } | |||
559 | ||||
560 | int | |||
561 | _aucat_setfl(struct aucat *hdl, int nbio, int *eof) | |||
562 | { | |||
563 | if (fcntl(hdl->fd, F_SETFL4, nbio ? O_NONBLOCK0x0004 : 0) == -1) { | |||
564 | DPERROR("_aucat_setfl: fcntl")do {} while(0); | |||
565 | *eof = 1; | |||
566 | return 0; | |||
567 | } | |||
568 | return 1; | |||
569 | } | |||
570 | ||||
571 | int | |||
572 | _aucat_pollfd(struct aucat *hdl, struct pollfd *pfd, int events) | |||
573 | { | |||
574 | if (hdl->rstate == RSTATE_MSG0) | |||
575 | events |= POLLIN0x0001; | |||
576 | pfd->fd = hdl->fd; | |||
577 | pfd->events = events; | |||
578 | return 1; | |||
579 | } | |||
580 | ||||
581 | int | |||
582 | _aucat_revents(struct aucat *hdl, struct pollfd *pfd) | |||
583 | { | |||
584 | int revents = pfd->revents; | |||
585 | ||||
586 | DPRINTFN(2, "_aucat_revents: revents: %x\n", revents)do {} while(0); | |||
587 | return revents; | |||
588 | } |