Various changes, see Changelog
[revinetd.git] / misc.c
blob42e5098cfeb21c9946734891669af97e93a08145
1 /*
2 * misc.c
4 * This file is a part of the revinetd project
6 * Revinetd is copyright (c) 2003-2008 by Steven M. Gill
7 * and distributed under the GPL.
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
22 * USA.
24 * */
26 #include "includes.h"
27 #include "revinetd.h"
28 #include "misc.h"
30 static const char cvsid[] = "$Id: misc.c,v 1.26 2008/08/28 03:24:59 necrotaur Exp $";
32 int
33 read_from_client(int filedes)
35 char buffer[1024];
36 int nbytes;
38 nbytes = read(filedes, buffer, 1024);
39 if (nbytes < 0) {
40 /* Read error. */
41 perror("read");
42 exit(EXIT_FAILURE);
43 } else if (nbytes == 0) {
44 return -1;
45 } else {
46 /* Data read. */
47 fprintf(stderr, "Server: got message: `%s'\n", buffer);
48 return 0;
52 int
53 copy_between_ports(int src_file, int dst_file)
55 char buffer[SZ_READ_BUFFER];
56 int nbytes;
58 nbytes = read(src_file, buffer, SZ_READ_BUFFER);
59 if (nbytes < 0) {
60 /* Read error. */
61 perror("read");
62 //old: exit(EXIT_FAILURE);
63 return -1;
64 } else if (nbytes == 0) {
65 return -1;
66 } else {
67 /* Data read. */
68 /* fprintf (stderr, "Server: got message: `%s'\n", buffer); */
69 write(dst_file, buffer, nbytes);
70 return 0;
74 int
75 get_comm_message(int src_file)
77 char buffer[SZ_READ_BUFFER];
78 int nbytes;
80 nbytes = read(src_file, buffer, SZ_READ_BUFFER);
81 if (nbytes < 0) {
82 /* Read error. */
83 perror("read");
84 exit(EXIT_FAILURE);
85 } else if (nbytes == 0) {
86 return -1;
87 } else {
88 /* Data read. */
89 /* fprintf (stderr, "Server: got message: `%s'\n", buffer); */
90 return (int)*buffer;
94 int
95 send_comm_message(int dst_file, int message)
97 char *buffer = (char*)&message;
98 int nbytes = sizeof(buffer);
100 write(dst_file, buffer, nbytes);
102 return 0;
106 make_socket_IPv4(const char *hostname, unsigned short port)
108 int sock, sock_opt = 1;
109 struct sockaddr_in name;
110 struct hostent *hostinfo;
111 struct in_addr saddr;
113 /* Create the socket. */
114 sock = socket(PF_INET, SOCK_STREAM, 0);
115 if (sock < 0) {
116 perror("socket");
117 exit(EXIT_FAILURE);
120 /* Set SO_REUSEADDR */
121 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sock_opt, sizeof(sock_opt));
124 /* Give the socket a name. */
125 name.sin_family = AF_INET;
126 name.sin_port = htons(port);
127 /* check if ip address or resolve hostname */
128 #ifdef HAVE_INET_ATON
129 if (!inet_aton(hostname, &saddr)) {
130 #else
131 saddr.s_addr = inet_addr(hostname);
132 if (saddr.s_addr == -1) {
133 #endif
134 hostinfo = gethostbyname(hostname);
135 if (hostinfo == NULL) {
136 fprintf(stderr, "Unknown host %s.\n", hostname);
137 exit(EXIT_FAILURE);
139 name.sin_addr = *(struct in_addr *)hostinfo->h_addr;
140 } else {
141 name.sin_addr = saddr;
143 /* name.sin_addr.s_addr = htonl(INADDR_ANY); */
144 if (bind(sock, (struct sockaddr *)&name, sizeof(name)) < 0) {
145 perror("bind");
146 exit(EXIT_FAILURE);
149 return sock;
153 make_socket_IPv6(const char *hostname, unsigned short port)
155 int sock6, sock_opt = 1;
156 struct sockaddr_in6 name;
157 //struct hostent *hostinfo;
158 struct in6_addr saddr;
159 // char str[INET6_ADDRSTRLEN];
161 /* Create the socket. */
162 sock6 = socket(AF_INET6, SOCK_STREAM, 0);
163 if (sock6 < 0) {
164 perror("socket");
165 exit(EXIT_FAILURE);
168 /* Set SO_REUSEADDR */
169 setsockopt(sock6, SOL_SOCKET, SO_REUSEADDR, &sock_opt, sizeof(sock_opt));
172 /* Give the socket a name. */
173 //name.sin6_len = sizeof(name);
174 name.sin6_family = AF_INET6;
175 name.sin6_flowinfo = 0;
176 name.sin6_port = htons(port);
178 /* check if ip address or resolve hostname */
179 // https://man7.org/linux/man-pages/man3/inet_pton.3.html
180 if (inet_pton(AF_INET6, hostname, &saddr) == 0)
182 //#ifdef HAVE_INET_ATON
183 // if (!inet_aton(hostname, &saddr)) {
184 //#else
185 // saddr.s_addr = inet_addr(hostname);
186 // if (saddr.s_addr == -1) {
187 //#endif
188 fprintf(stderr, "Not a valid IPv6 numeric address, and address lookup not implemented for supposed IPv6 hostname %s.\n", hostname);
189 exit(EXIT_FAILURE);
190 //hostinfo = gethostbyname(hostname);
191 //if (hostinfo == NULL) {
192 // fprintf(stderr, "Unknown host %s.\n", hostname);
193 // exit(EXIT_FAILURE);
195 //name.sin6_addr = *(struct in6_addr *)hostinfo->h_addr;
196 } else {
197 name.sin6_addr = saddr;
199 /* name.sin_addr.s_addr = htonl(INADDR_ANY); */
200 if (bind(sock6, (struct sockaddr *)&name, sizeof(name)) < 0) {
201 perror("bind");
202 exit(EXIT_FAILURE);
205 return sock6;
208 // Returns AF_INET6 if hostname is a string of format "[...]" (i.e.
209 // something enclosed in square brackets, or AF_INET if not
210 // enclosed in square brackets. Returns -1 if the format is ambiguous
211 // due to only one bracket occuring.
212 // If AF_INET6 is returned, the hostname_stripped will contain the
213 // string value of hostname without the brackets. (Must have been allocated
214 // of sufficient size.)
215 int
216 detect_address_family(const char *hostname, char *hostname_stripped)
218 size_t x;
219 if ((x=strlen(hostname)) > 2) {
220 if (hostname[0] == '[') {
221 if (hostname[x-1] == ']') {
222 strncpy(hostname_stripped, &(hostname[1]), x-2);
223 hostname_stripped[x-2] = '\0';
224 return AF_INET6;
226 else {
227 return -1;
231 return AF_INET;
235 init_sockaddr(struct sockaddr_in *name, const char *hostname,
236 unsigned short port)
238 int sock;
239 struct hostent *hostinfo;
240 struct in_addr saddr;
242 /* Create the socket. */
243 sock = socket(PF_INET, SOCK_STREAM, 0);
244 if (sock < 0) {
245 perror("socket");
246 exit(EXIT_FAILURE);
249 name->sin_family = AF_INET;
250 name->sin_port = htons(port);
251 #ifdef HAVE_INET_ATON
252 if (!inet_aton(hostname, &saddr)) {
253 #else
254 saddr.s_addr = inet_addr(hostname);
255 if (saddr.s_addr == -1) {
256 #endif
257 hostinfo = gethostbyname(hostname);
258 if (hostinfo == NULL) {
259 fprintf(stderr, "Unknown host %s.\n", hostname);
260 exit(EXIT_FAILURE);
262 name->sin_addr = *(struct in_addr *)hostinfo->h_addr;
263 } else {
264 name->sin_addr = saddr;
266 memset(name->sin_zero, '\0', 8);
268 return sock;
271 void
272 register_sock(int sock)
274 OpenSockets *open_sock;
276 /* Get a new OpenSockets struct. */
277 open_sock = malloc(sizeof(OpenSockets));
278 if (open_sock == NULL) {
279 perror("malloc");
280 exit(EXIT_FAILURE);
282 memset(open_sock, 0, sizeof(OpenSockets));
284 /* Fill the struct. */
285 open_sock->sock = sock;
287 /* Insert the struct. */
288 open_sock->prev = NULL;
289 open_sock->next = conf.open_sock;
290 if (conf.open_sock != NULL) {
291 conf.open_sock->prev = open_sock;
293 conf.open_sock = open_sock;
295 return;
299 unregister_sock(int sock)
301 OpenSockets *open_sock;
303 open_sock = conf.open_sock;
304 while (open_sock != NULL) {
305 if (open_sock->sock == sock) {
306 /* Remove link from previous or first entry. */
307 if (open_sock->prev != NULL)
308 open_sock->prev->next = open_sock->next;
309 else
310 conf.open_sock = open_sock->next;
311 /* Remove link from next entry. */
312 if (open_sock->next != NULL)
313 open_sock->next->prev = open_sock->prev;
314 /* Free OpenSockets struct. */
315 free(open_sock);
316 /* Close sock. */
317 if (shutdown(sock, SHUT_RDWR) == -1)
318 return 0; /* Socket couldn't be closed. */
319 close(sock);
320 /* Return success. */
321 return 1;
323 open_sock = open_sock->next;
326 /* Socket not found. */
327 return 0;