]> jfr.im git - irc/quakenet/newserv.git/blob - nterface/nterfaced_uds.c
Modified strlcat.c -> strlfunc.c and added strlcpy
[irc/quakenet/newserv.git] / nterface / nterfaced_uds.c
1 /*
2 nterfaced UNIX domain socket module
3 Copyright (C) 2003-2004 Chris Porter.
4 */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <errno.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <sys/socket.h>
12 #include <sys/stat.h>
13 #include <sys/un.h>
14 #include <sys/ioctl.h>
15
16 #include "../core/config.h"
17 #include "../core/events.h"
18
19 #include "nterfaced_uds.h"
20 #include "nterfaced.h"
21 #include "logging.h"
22 #include "library.h"
23 #include "transports.h"
24 #include "requests.h"
25
26 struct transport *otu;
27 struct esocket_events uds_events;
28 unsigned short uds_token;
29
30 void _init(void) {
31 otu = register_transport("uds");
32 MemCheck(otu);
33
34 otu->on_line = uds_transport_line_event;
35 otu->on_disconnect = uds_transport_disconnect_event;
36 otu->type = TT_INPUT;
37
38 socket_path = getcopyconfigitem("nterfaced", "socketpath", "/tmp/nterfaced", 100);
39 MemCheck(socket_path);
40
41 uds = create_uds();
42 if(uds < 0) {
43 nterface_log(ndl, NL_ERROR, "UDS: Unable to create domain socket!");
44
45 freesstring(socket_path);
46 socket_path = NULL;
47
48 uds = -1;
49 return;
50 }
51
52 uds_events.on_line = uds_buffer_line_event;
53 uds_events.on_accept = uds_buffer_accept_event;
54 uds_events.on_disconnect = NULL;
55
56 uds_token = esocket_token();
57 esocket_add(uds, ESOCKET_UNIX_DOMAIN, &uds_events, uds_token);
58
59 /* UDS must not have a disconnect event */
60 uds_events.on_disconnect = uds_buffer_disconnect_event;
61 }
62
63 void _fini(void) {
64 if(uds != -1) {
65 esocket_clean_by_token(uds_token);
66
67 if(socket_path && (unlink(socket_path->content) == -1))
68 nterface_log(ndl, NL_WARNING, "UDS: Unable to delete socket %s.", socket_path->content);
69 }
70
71 if(socket_path)
72 freesstring(socket_path);
73
74 if(otu)
75 deregister_transport(otu);
76
77 }
78
79 int create_uds(void) {
80 int sock;
81 struct sockaddr_un sa;
82
83 sock = socket(PF_UNIX, SOCK_STREAM, 0);
84
85 if(sock < 0) {
86 nterface_log(ndl, NL_ERROR, "UDS: Unable to create UNIX domain socket!");
87 return -1;
88 }
89
90 memset(&sa, 0, sizeof(sa));
91 sa.sun_family = AF_UNIX;
92 strncpy(sa.sun_path, socket_path->content, sizeof(sa.sun_path) - 1);
93 sa.sun_path[sizeof(sa.sun_path) - 1] = '\0';
94
95 if((unlink(socket_path->content) == -1) && (errno != ENOENT)) {
96 nterface_log(ndl, NL_ERROR, "UDS: Unable to delete already existing socket (%s)!", socket_path->content);
97 close(sock);
98 return -1;
99 }
100
101 if(bind(sock, (struct sockaddr *)&sa, sizeof(sa))) {
102 nterface_log(ndl, NL_ERROR, "UDS: Unable to bind socket to %s!", socket_path->content);
103 close(sock);
104 return -1;
105 }
106
107 if(chmod(socket_path->content, S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH) == -1) {
108 nterface_log(ndl, NL_ERROR, "UDS: Unable to change permissions of socket %s!", socket_path->content);
109 close(sock);
110 if(unlink(socket_path->content) == -1)
111 nterface_log(ndl, NL_WARNING, "UDS: Unable to delete socket %s.", socket_path->content);
112 return -1;
113 }
114
115 if(listen(sock, 5)) {
116 nterface_log(ndl, NL_ERROR, "UDS: Unable to listen on socket!");
117 close(sock);
118 if(unlink(socket_path->content) == -1)
119 nterface_log(ndl, NL_WARNING, "UDS: Unable to delete socket %s.", socket_path->content);
120 return -1;
121 }
122
123 return sock;
124 }
125
126 void uds_buffer_accept_event(struct esocket *active) {
127 int newfd = accept(active->fd, NULL, 0);
128 unsigned short opt = 1;
129 if(!newfd == -1) {
130 nterface_log(ndl, NL_WARNING, "UDS: Unable to accept new UNIX domain socket!");
131 return;
132 }
133
134 nterface_log(ndl, NL_INFO|NL_LOG_ONLY, "UDS: New connection");
135 if(ioctl(newfd, FIONBIO, &opt)) {
136 close(newfd);
137 return;
138 }
139
140 if(!esocket_add(newfd, ESOCKET_UNIX_DOMAIN_CONNECTED, &uds_events, uds_token)) {
141 close(newfd);
142 return;
143 }
144 }
145
146 int uds_buffer_line_event(struct esocket *socket, char *newline) {
147 int number, reason;
148
149 nterface_log(ndl, NL_INFO|NL_LOG_ONLY, "UDS: L: %s", newline);
150 reason = new_request(otu, socket->fd, newline, &number);
151 if(reason) {
152 if(reason == RE_BAD_LINE) {
153 return 1;
154 } else {
155 int ret = esocket_write_line(socket, "%s,%d,E%d,%s", newline, number, reason, request_error(reason));
156 if(ret)
157 return ret;
158 }
159 }
160 return 0;
161 }
162
163 int uds_transport_line_event(struct request *request, char *buf) {
164 struct esocket *es;
165 es = find_esocket_from_fd(request->input.tag);
166
167 if(!es)
168 return 1;
169
170 return esocket_write_line(es, "%s,%d,%s", request->service->service->content, request->input.token, buf);
171 }
172
173 void uds_transport_disconnect_event(struct request *req) {
174 struct esocket *es = find_esocket_from_fd(req->input.tag);
175 if(!es)
176 return;
177
178 esocket_write_line(es, "%s,%d,E%d,%s", req->service->service->content, req->input.token, RE_CONNECTION_CLOSED, request_error(RE_CONNECTION_CLOSED));
179 }
180
181 void uds_buffer_disconnect_event(struct esocket *socket) {
182 transport_disconnect(otu, socket->fd);
183 }