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