Annotation of src/usr.bin/aucat/listen.c, Revision 1.15
1.15 ! ratchov 1: /* $OpenBSD: listen.c,v 1.14 2011/04/28 06:19:57 ratchov Exp $ */
1.1 ratchov 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: #include <sys/types.h>
18: #include <sys/socket.h>
1.13 deraadt 19: #include <sys/signal.h>
1.2 ratchov 20: #include <sys/stat.h>
1.1 ratchov 21: #include <sys/un.h>
1.14 ratchov 22:
23: #include <netinet/in.h>
1.15 ! ratchov 24: #include <netinet/tcp.h>
1.14 ratchov 25: #include <netdb.h>
26:
1.1 ratchov 27: #include <err.h>
28: #include <errno.h>
29: #include <fcntl.h>
30: #include <poll.h>
31: #include <stdio.h>
32: #include <stdlib.h>
33: #include <string.h>
34: #include <unistd.h>
35:
36: #include "conf.h"
1.10 ratchov 37: #include "listen.h"
1.1 ratchov 38: #include "sock.h"
39:
40: struct fileops listen_ops = {
41: "listen",
42: sizeof(struct listen),
43: listen_close,
44: NULL, /* read */
45: NULL, /* write */
46: NULL, /* start */
47: NULL, /* stop */
48: listen_nfds,
49: listen_pollfd,
50: listen_revents
51: };
52:
1.12 ratchov 53: void
54: listen_new_un(char *path)
1.1 ratchov 55: {
1.7 ratchov 56: int sock, oldumask;
1.1 ratchov 57: struct sockaddr_un sockname;
58: struct listen *f;
59:
60: sock = socket(AF_UNIX, SOCK_STREAM, 0);
61: if (sock < 0) {
62: perror("socket");
1.12 ratchov 63: exit(1);
1.1 ratchov 64: }
65: if (unlink(path) < 0 && errno != ENOENT) {
66: perror("unlink");
1.8 ratchov 67: goto bad_close;
1.1 ratchov 68: }
69: sockname.sun_family = AF_UNIX;
70: strlcpy(sockname.sun_path, path, sizeof(sockname.sun_path));
1.7 ratchov 71: oldumask = umask(0111);
1.6 ratchov 72: if (bind(sock, (struct sockaddr *)&sockname,
73: sizeof(struct sockaddr_un)) < 0) {
1.1 ratchov 74: perror("bind");
1.8 ratchov 75: goto bad_close;
1.2 ratchov 76: }
1.7 ratchov 77: umask(oldumask);
1.1 ratchov 78: if (listen(sock, 1) < 0) {
79: perror("listen");
1.8 ratchov 80: goto bad_close;
1.1 ratchov 81: }
1.12 ratchov 82: f = (struct listen *)file_new(&listen_ops, path, 1);
1.8 ratchov 83: if (f == NULL)
84: goto bad_close;
1.1 ratchov 85: f->path = strdup(path);
86: if (f->path == NULL) {
87: perror("strdup");
88: exit(1);
89: }
90: f->fd = sock;
1.12 ratchov 91: return;
1.8 ratchov 92: bad_close:
93: close(sock);
1.12 ratchov 94: exit(1);
1.14 ratchov 95: }
96:
97: void
98: listen_new_tcp(char *addr, unsigned port)
99: {
100: char *host, serv[sizeof(unsigned) * 3 + 1];
101: struct addrinfo *ailist, *ai, aihints;
102: struct listen *f;
103: int s, error, opt = 1, n = 0;
104:
105: /*
106: * obtain a list of possible addresses for the host/port
107: */
108: memset(&aihints, 0, sizeof(struct addrinfo));
109: snprintf(serv, sizeof(serv), "%u", port);
110: host = strcmp(addr, "*") == 0 ? NULL : addr;
111: aihints.ai_flags |= AI_PASSIVE;
112: aihints.ai_socktype = SOCK_STREAM;
113: aihints.ai_protocol = IPPROTO_TCP;
114: error = getaddrinfo(host, serv, &aihints, &ailist);
115: if (error) {
116: fprintf(stderr, "%s: %s\n", addr, gai_strerror(error));
117: exit(1);
118: }
119:
120: /*
121: * for each address, try create a listening socket bound on
122: * that address
123: */
124: for (ai = ailist; ai != NULL; ai = ai->ai_next) {
125: s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
126: if (s < 0) {
127: perror("socket");
128: continue;
129: }
130: opt = 1;
131: if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)) < 0) {
132: perror("setsockopt");
133: goto bad_close;
134: }
135: if (bind(s, ai->ai_addr, ai->ai_addrlen) < 0) {
136: perror("bind");
137: goto bad_close;
138: }
139: if (listen(s, 1) < 0) {
140: perror("listen");
141: goto bad_close;
142: }
143: f = (struct listen *)file_new(&listen_ops, addr, 1);
144: if (f == NULL) {
145: bad_close:
146: close(s);
147: continue;
148: }
149: f->path = NULL;
150: f->fd = s;
151: n++;
152: }
153: freeaddrinfo(ailist);
154: if (n == 0)
155: exit(1);
1.1 ratchov 156: }
157:
158: int
159: listen_nfds(struct file *f) {
160: return 1;
161: }
162:
163: int
164: listen_pollfd(struct file *file, struct pollfd *pfd, int events)
165: {
166: struct listen *f = (struct listen *)file;
167:
168: pfd->fd = f->fd;
169: pfd->events = POLLIN;
170: return 1;
171: }
172:
173: int
174: listen_revents(struct file *file, struct pollfd *pfd)
175: {
176: struct listen *f = (struct listen *)file;
177: struct sockaddr caddr;
178: socklen_t caddrlen;
1.15 ! ratchov 179: int sock, opt;
1.1 ratchov 180:
181: if (pfd->revents & POLLIN) {
182: caddrlen = sizeof(caddrlen);
183: sock = accept(f->fd, &caddr, &caddrlen);
184: if (sock < 0) {
1.12 ratchov 185: /* XXX: should we kill the socket here ? */
1.1 ratchov 186: perror("accept");
187: return 0;
188: }
189: if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
190: perror("fcntl(sock, O_NONBLOCK)");
191: close(sock);
192: return 0;
1.15 ! ratchov 193: }
! 194: if (f->path == NULL) {
! 195: opt = 1;
! 196: if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
! 197: &opt, sizeof(int)) < 0) {
! 198: perror("setsockopt");
! 199: close(sock);
! 200: return 0;
! 201: }
1.1 ratchov 202: }
1.9 ratchov 203: if (sock_new(&sock_ops, sock) == NULL) {
1.8 ratchov 204: close(sock);
205: return 0;
206: }
1.1 ratchov 207: }
208: return 0;
209: }
210:
211: void
212: listen_close(struct file *file)
213: {
214: struct listen *f = (struct listen *)file;
215:
1.12 ratchov 216: if (f->path != NULL) {
217: unlink(f->path);
218: free(f->path);
219: }
1.10 ratchov 220: close(f->fd);
1.12 ratchov 221: }
222:
223: void
224: listen_closeall(void)
225: {
226: struct file *f, *fnext;
227:
228: for (f = LIST_FIRST(&file_list); f != NULL; f = fnext) {
229: fnext = LIST_NEXT(f, entry);
230: if (f->ops == &listen_ops)
231: file_close(f);
232: }
1.1 ratchov 233: }