TCP port forwarding implemented.
[udpgate.git] / src / network.c
1 /* $Id$
2  * UDP Gateway utility network layer
3  * Copyright (C) 2004 Jan Kratochvil <project-udpgate@jankratochvil.net>
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; exactly version 2 of June 1991 is required
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19
20 #include "config.h"
21
22 #include <glib/gmessages.h>
23 #include <glib/gmain.h>
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <glib/glist.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <sys/types.h>
30 #include <signal.h>
31 #include <errno.h>
32 #include <glib/giochannel.h>
33 #include <sys/ioctl.h>
34 #include <string.h>
35 #include <glib/galloca.h>
36 #include <glib/gprintf.h>
37 #include <glib/grand.h>
38 #include <glib/gutils.h>
39
40 #include "network.h"
41 #include "packet.h"
42 #include "main.h"       /* for optarg_verbose */
43 #include "pathname.h"
44
45
46 /* Config: */
47 #define SOCK_SOURCE_CHECK_REVENTS (G_IO_IN|G_IO_OUT)    /* |G_IO_ERR|G_IO_HUP|G_IO_NVAL */
48 #define SERVER_INADDR 0xC37AD054        /* mms2.org = 195.122.208.84; host order */
49 #define SERVER_PORT   9201      /* host order */
50 #define PROBE_INADDR  SERVER_INADDR     /* host order */
51 #define PROBE_PORT    8201      /* host order */
52 #define CLIENT_TIMEOUT_SEC (5*60)
53 #define PROBE_TIMEOUT_SEC_BASE 5
54 #define PROBE_TIMEOUT_SEC_MAX 3500
55 #define TCP_BACKLOG 5
56 #define GSTRING_TO_SEND_MAX 1500*6      /* maximum data buffered per TCP client */
57
58
59 void (*network_notify_hostip)(guint32 hostip_guint32);
60
61
62 static G_CONST_RETURN gchar *pid_pathname(void)
63 {
64 static const gchar *static_pathname;
65 static const char *user_val;
66
67         if (!static_pathname)
68                 user_val=g_get_user_name();
69         return pathname_find(&static_pathname,
70                         G_STRINGIFY(LOCALSTATEDIR) "/run",PACKAGE ".pid",
71                         (!user_val ? NULL : g_get_tmp_dir()),
72                                         (!user_val ? NULL : udpgate_printf_alloca(".%s-%s.pid",user_val,PACKAGE)),
73                         NULL);
74 }
75
76
77 struct client {
78         GPollFD gpollfd;
79         struct sockaddr_in sockaddr_in_from;
80         guint timeout_id;
81         struct client *bound;
82         unsigned connect_pending:1;     /* for TCP connection to the server; activated by: G_IO_OUT */
83         unsigned server_only:1; /* nonimportant connect - the server side */
84         unsigned done:1;        /* temporary marker */
85         GString *gstring_to_send;       /* for TCP connections; data to be sent to this socket */
86         };
87
88 static GSource *sock_gsource;
89
90 static GList *sock_client_list; /* of 'struct client *', incl. 'master' and 'probe' */
91 static struct client *master_udp;       /* no 'timeout' permitted */
92 static struct client *master_tcp;       /* no 'timeout' permitted */
93 static struct client *probe;    /* 'timeout' permitted */
94 static guint32 probe_unique;
95 static guint probe_timeout_sec_now;
96 guint probe_timeout_sec_max=G_MAXUINT;
97 static gint port_local; /* for 'probe' resends */
98
99 static gboolean write_daemon_running(pid_t pid);
100
101 pid_t is_daemon_running(void)
102 {
103 FILE *f;
104 char buf[LINE_MAX],*got;
105 int pid_int;
106
107         if (sock_gsource)
108                 return getpid();
109
110         if (!(f=fopen(pid_pathname(),"r")))
111                 goto err;
112         got=fgets(buf,sizeof(buf),f);
113         fclose(f);      /* FIXME: error ignored */
114         if (got!=buf) {
115 err_unlink:
116                 write_daemon_running((pid_t)-1);        /* unlink */
117 err:
118                 return (pid_t)-1;
119                 }
120         pid_int=atoi(buf);
121         if (pid_int<=1)
122                 goto err_unlink;
123         if (kill((pid_t)pid_int,0)) {
124                 if (errno==ESRCH)
125                         goto err_unlink;
126                 goto err;
127                 }
128         return (pid_t)pid_int;
129 }
130
131 static gboolean write_daemon_running(pid_t pid)
132 {
133 FILE *f;
134
135         if (pid==(pid_t)-1) {
136                 if (unlink(pid_pathname())) {
137                         if (errno!=ENOENT)
138                                 g_warning(_("Error removing PID file \"%s\": %m"),pid_pathname());
139                         return FALSE;
140                         }
141                 return TRUE;
142                 }
143         if (!(f=fopen(pid_pathname(),"w"))) {
144 static gboolean once=TRUE;
145
146                 if (once) {
147                         once=FALSE;
148                         g_warning(_("Error writing PID %d to \"%s\": %m"),(int)pid,pid_pathname());
149                         }
150                 return FALSE;
151                 }
152         fprintf(f,"%d\n",(int)pid);     /* errors ignored */
153         fclose(f);      /* FIXME: error ignored */
154         return TRUE;
155 }
156
157 static void client_timeout_remove(struct client *client)
158 {
159         g_return_if_fail(client!=NULL);
160         g_return_if_fail(client!=master_udp);
161         g_return_if_fail(client!=master_tcp);
162
163         if (client->timeout_id) {
164 gboolean errgboolean;
165
166                 if (optarg_verbose)
167                         g_message(_("Client fd %d removed timeout id %d"),client->gpollfd.fd,client->timeout_id);
168                 errgboolean=g_source_remove(client->timeout_id);
169                 g_assert(errgboolean==TRUE);
170                 client->timeout_id=0;
171                 }
172 }
173
174 static gboolean client_touch_timeout(struct client *client);
175
176 static void client_touch(struct client *client,guint timeout_sec)
177 {
178         g_return_if_fail(client!=NULL);
179         g_return_if_fail(client!=master_udp);
180         g_return_if_fail(client!=master_tcp);
181         g_return_if_fail(timeout_sec>0);
182
183         client_timeout_remove(client);
184         client->timeout_id=g_timeout_add(
185                         timeout_sec*1000,       /* interval; msec */
186                         (GSourceFunc)client_touch_timeout,      /* function */
187                         client);        /* data */
188         if (optarg_verbose)
189                 g_message(_("Client fd %d new timeout id %d"),client->gpollfd.fd,client->timeout_id);
190         g_assert(client->timeout_id!=0);
191 }
192
193 static void client_destroy(struct client *client);
194 static gboolean probe_send(struct client *probe,gint port_local);
195
196 static gboolean client_touch_timeout(struct client *client)
197 {
198         g_return_val_if_fail(client!=NULL,FALSE);       /* FALSE=>should be removed */
199         g_return_val_if_fail(client!=master_udp,FALSE); /* FALSE=>should be removed */
200         g_return_val_if_fail(client!=master_tcp,FALSE); /* FALSE=>should be removed */
201
202         if (optarg_verbose)
203                 g_message(_("Client fd %d timeout id %d occured/entered"),client->gpollfd.fd,client->timeout_id);
204
205         /* Do not destroy the timeout in client_destroy().
206          * It would crash GLib - we remove it be returning FALSE from here.
207          */
208         g_assert(client->timeout_id!=0);
209         client->timeout_id=0;
210
211         if (client==probe) {
212                 if (probe_timeout_sec_now<probe_timeout_sec_max) {
213                         probe_timeout_sec_now*=PROBE_TIMEOUT_SEC_BASE;
214                         g_assert(probe_timeout_sec_max==G_MAXUINT || probe_timeout_sec_max<PROBE_TIMEOUT_SEC_MAX);
215                         probe_timeout_sec_now=MIN(probe_timeout_sec_now,probe_timeout_sec_max);
216                         probe_timeout_sec_now=MIN(probe_timeout_sec_now,PROBE_TIMEOUT_SEC_MAX);
217                         if (probe_send(probe,port_local)) {
218                                 client_touch(probe,probe_timeout_sec_now);      /* timeout */
219                                 return FALSE;   /* GSource should be removed */
220                                 }
221                         /* failure FALLTHRU */
222                         }
223                 network_stop();
224                 /* Never destroy 'client' now - it has been destroyed by network_stop()! */
225                 g_warning(_("No probe response from the server, stopping the daemon. Please check your public Internet connectivity."));
226                 }
227         else {
228                 client_destroy(client);
229                 }
230
231         if (optarg_verbose)
232                 g_message(_("Client timeout occurance finish"));
233
234         return FALSE;   /* GSource should be removed */
235 }
236
237 static void handle_master_probe(const void *packet,size_t gotlen,const struct sockaddr_in *sockaddr_in_from)
238 {
239 GHashTable *got_hash;
240 gpointer got_unique_gpointer;
241 gpointer hostip_gpointer;
242 guint32 hostip_guint32;
243
244         g_return_if_fail(packet!=NULL);
245         g_return_if_fail(sockaddr_in_from!=NULL);
246
247         if (!probe)
248                 return;
249
250         if (!(got_hash=packet_disassembly(packet,gotlen)))
251                 return;
252         if (!(g_hash_table_lookup_extended(
253                         got_hash,       /* hash_table */
254                         GUINT_TO_POINTER(PACKET_ELEM_TYPE_DATA_GUINT32),        /* lookup_key */
255                         NULL,   /* orig_key */
256                         &got_unique_gpointer))) {
257 err_packet_disassembly_destroy_got_hash:
258                 packet_disassembly_destroy(got_hash);
259                 return;
260                 }
261         if (GPOINTER_TO_UINT(got_unique_gpointer)!=probe_unique)
262                 goto err_packet_disassembly_destroy_got_hash;
263         if (!(g_hash_table_lookup_extended(
264                         got_hash,       /* hash_table */
265                         GUINT_TO_POINTER(PACKET_ELEM_TYPE_CLIENT_INADDR),       /* lookup_key */
266                         NULL,   /* orig_key */
267                         &hostip_gpointer)))
268                 goto err_packet_disassembly_destroy_got_hash;
269         hostip_guint32=GPOINTER_TO_UINT(hostip_gpointer);
270         packet_disassembly_destroy(got_hash);
271
272         client_destroy(probe);
273         if (network_notify_hostip)
274                 (*network_notify_hostip)(hostip_guint32);
275 }
276
277 enum client_new_type {
278         CLIENT_NEW_TYPE_UDP,
279         CLIENT_NEW_TYPE_TCP,
280         };
281
282 static struct client *client_new(enum client_new_type type);
283 static struct client *client_new_from_sock(int sock);
284
285 static void clients_bind(struct client *client0,struct client *client1)
286 {
287         g_return_if_fail(client0!=NULL);
288         g_return_if_fail(client0->bound==NULL);
289         g_return_if_fail(client0->gstring_to_send==NULL);
290         g_return_if_fail(client1!=NULL);
291         g_return_if_fail(client1->bound==NULL);
292         g_return_if_fail(client1->gstring_to_send==NULL);
293         g_return_if_fail(client0!=client1);
294
295         client0->bound=client1;
296         client1->bound=client0;
297
298         client0->gstring_to_send=g_string_sized_new(GSTRING_TO_SEND_MAX);
299         client1->gstring_to_send=g_string_sized_new(GSTRING_TO_SEND_MAX);
300 }
301
302 static void client_split(struct client *client)
303 {
304         g_return_if_fail(client!=NULL);
305         g_return_if_fail(client->bound!=NULL);
306         g_return_if_fail(client->bound!=client);
307         g_return_if_fail(client->bound->bound==client);
308         g_return_if_fail(client->gstring_to_send!=NULL);
309
310         client->bound->bound=NULL;
311         client->bound=NULL;
312 }
313
314 static struct sockaddr_in sockaddr_in_server;
315
316 static void handle_master_udp(struct client *master_udp)
317 {
318         g_return_if_fail(master_udp!=NULL);
319
320         for (;;) {
321 char packet[0x10000];
322 ssize_t gotlen;
323 struct sockaddr_in sockaddr_in_from;
324 struct client *client=NULL      /* Prevent false positive: might be used uninitialized */;
325 socklen_t sockaddr_in_from_length;
326 GList *clientl;
327
328                 sockaddr_in_from_length=sizeof(sockaddr_in_from);
329                 if (-1==(gotlen=recvfrom(
330                                 master_udp->gpollfd.fd, /* s */
331                                 packet, /* buf */
332                                 sizeof(packet), /* len */
333                                 0,      /* flags */
334                                 (struct sockaddr *)&sockaddr_in_from,   /* from */
335                                 &sockaddr_in_from_length)))     /* fromlen */
336                         break;
337
338                 if (sockaddr_in_from_length!=sizeof(sockaddr_in_from))  /* FIXME: errors reporting */
339                         continue;
340
341                 if (packet_recognized(packet,gotlen)) {
342                         handle_master_probe(packet,gotlen,&sockaddr_in_from);
343                         continue;
344                         }
345                 /* Not yet initialized by 'probe' reply - drop it. */
346                 if (probe) {
347                         if (optarg_verbose)
348                                 g_message(_("Data packet received from %s but no probe reply yet; dropping packet."),
349                                                 SOCKADDR_IN_TO_STRING(&sockaddr_in_from));
350                         continue;
351                         }
352
353                 /* FIXME: Performance: Ugly search... */
354                 for (clientl=sock_client_list;clientl;clientl=clientl->next) {
355                         client=clientl->data;
356                         if (client==master_udp)
357                                 continue;
358                         if (1
359                                         && client->sockaddr_in_from.sin_family     ==sockaddr_in_from.sin_family
360                                         && client->sockaddr_in_from.sin_port       ==sockaddr_in_from.sin_port
361                                         && client->sockaddr_in_from.sin_addr.s_addr==sockaddr_in_from.sin_addr.s_addr)
362                                 break;
363                         }
364                 if (!clientl) {
365                         client=client_new(CLIENT_NEW_TYPE_UDP);
366                         client->sockaddr_in_from=sockaddr_in_from;
367                         }
368                 client_touch(client,CLIENT_TIMEOUT_SEC);
369                 /* FIXME: errors checking */
370                 sendto(
371                                 client->gpollfd.fd,     /* s */
372                                 packet, /* msg */
373                                 gotlen, /* len */
374                                 0,      /* flags */
375                                 (struct sockaddr *)&sockaddr_in_server, /* to */
376                                 sizeof(sockaddr_in_server));    /* tolen */
377                 }
378 }
379
380 static void handle_master_tcp(struct client *master_tcp)
381 {
382         g_return_if_fail(master_tcp!=NULL);
383
384         for (;;) {
385 int sock_new;
386 struct sockaddr_in sockaddr_in_from;
387 struct client *client=NULL      /* Prevent false positive: might be used uninitialized */;
388 socklen_t sockaddr_in_from_length;
389 int connect_got;
390 struct client *server;
391
392                 sockaddr_in_from_length=sizeof(sockaddr_in_from);
393                 if (-1==(sock_new=accept(
394                                 master_tcp->gpollfd.fd, /* s */
395                                 (struct sockaddr *)&sockaddr_in_from,   /* from */
396                                 &sockaddr_in_from_length)))     /* fromlen */
397                         break;
398
399                 if (sockaddr_in_from_length!=sizeof(sockaddr_in_from))  /* FIXME: errors reporting */
400                         continue;
401
402                 /* Not yet initialized by 'probe' reply - drop it. */
403                 if (probe) {
404                         if (optarg_verbose)
405                                 g_message(_("Incoming connection received from %s but no probe reply yet; dropping connection."),
406                                                 SOCKADDR_IN_TO_STRING(&sockaddr_in_from));
407                         close(sock_new);        /* FIXME: errors reporting */
408                         continue;
409                         }
410
411                 if (!(client=client_new_from_sock(sock_new)))
412                         continue;
413                 client->sockaddr_in_from=sockaddr_in_from;
414
415                 if (!(server=client_new(CLIENT_NEW_TYPE_TCP))) {
416                         client_destroy(client);
417                         continue;
418                         }
419                 server->server_only=1;
420                 server->sockaddr_in_from=sockaddr_in_server;
421                 clients_bind(client,server);
422                 /* Currently only one of 'client' or 'server' needs to be destroyed. */
423
424                 errno=0;
425                 connect_got=connect(
426                                 server->gpollfd.fd,     /* sockfd */
427                                 (struct sockaddr *)&sockaddr_in_server, /* to */
428                                 sizeof(sockaddr_in_server));    /* tolen */
429                 if (connect_got!=-1 || errno!=EINPROGRESS) {
430                         g_warning(_("Error establishing server TCP connection: %m"));
431                         client_destroy(server);
432                         continue;
433                         }
434                 g_assert(!server->connect_pending);
435                 server->connect_pending=1;
436                 }
437 }
438
439 static void handle_probe(struct client *probe)
440 {
441         g_return_if_fail(probe!=NULL);
442
443         for (;;) {
444 ssize_t gotlen;
445 struct sockaddr_in sockaddr_in_from;
446 char packet[0x10000];
447 socklen_t sockaddr_in_from_length;
448
449                 sockaddr_in_from_length=sizeof(sockaddr_in_from);
450                 if (-1==(gotlen=recvfrom(
451                                 master_udp->gpollfd.fd, /* s */
452                                 packet, /* buf */
453                                 sizeof(packet), /* len */
454                                 0,      /* flags */
455                                 (struct sockaddr *)&sockaddr_in_from,   /* from */
456                                 &sockaddr_in_from_length)))     /* fromlen */
457                         break;
458                 if (sockaddr_in_from_length!=sizeof(sockaddr_in_from))  /* FIXME: errors reporting */
459                         continue;
460
461                 /* Probe socket should have no response; maybe some ICMP errors - ignored. */
462                 }
463 }
464
465 static void handle_client_udp(struct client *client)
466 {
467         g_return_if_fail(client!=NULL);
468         g_return_if_fail(master_udp!=NULL);
469
470         for (;;) {
471 ssize_t gotlen;
472 struct sockaddr_in sockaddr_in_from;
473 char packet[0x10000];
474 socklen_t sockaddr_in_from_length;
475
476                 sockaddr_in_from_length=sizeof(sockaddr_in_from);
477                 if (-1==(gotlen=recvfrom(
478                                 client->gpollfd.fd,     /* s */
479                                 packet, /* buf */
480                                 sizeof(packet), /* len */
481                                 0,      /* flags */
482                                 (struct sockaddr *)&sockaddr_in_from,   /* from */
483                                 &sockaddr_in_from_length)))     /* fromlen */
484                         break;
485                 if (sockaddr_in_from_length!=sizeof(sockaddr_in_from))  /* FIXME: errors reporting */
486                         continue;
487                 client_touch(client,CLIENT_TIMEOUT_SEC);
488                 /* FIXME: errors checking */
489                 sendto(
490                                 master_udp->gpollfd.fd, /* s */
491                                 packet, /* msg */
492                                 gotlen, /* len */
493                                 0,      /* flags */
494                                 (struct sockaddr *)&client->sockaddr_in_from,   /* to */
495                                 sizeof(client->sockaddr_in_from));      /* tolen */
496                 }
497 }
498
499 static void handle_client_tcp_connect(struct client *server)
500 {
501         g_return_if_fail(server!=NULL);
502         g_return_if_fail(server->connect_pending);
503         g_return_if_fail(master_tcp!=NULL);
504
505         errno=0;
506         if (connect(
507                         server->gpollfd.fd,     /* sockfd */
508                         (struct sockaddr *)&sockaddr_in_server, /* to */
509                         sizeof(sockaddr_in_server))) {  /* tolen */
510                 g_warning(_("Error establishing server TCP connection: %m"));
511                 client_destroy(server);
512                 return;
513                 }
514         g_assert(server->connect_pending);
515         server->connect_pending=0;
516 }
517
518 /* Read from client->gpollfd.fd the data for client->bound->gstring_to_send. */
519 static void handle_client_tcp_read(struct client *client)
520 {
521         g_return_if_fail(client!=NULL);
522         g_return_if_fail(client->bound!=NULL);
523         g_return_if_fail(!client->connect_pending);
524         g_return_if_fail(master_tcp!=NULL);
525
526         for (;;) {
527 ssize_t gotlen;
528 size_t read_max;
529 char buf[GSTRING_TO_SEND_MAX];
530
531                 read_max=sizeof(buf)-client->bound->gstring_to_send->len;
532                 g_assert(read_max>=0);
533                 if (read_max<=0)        /* In fact it initially should not happen, there would be no: G_IO_IN */
534                         break;
535                 gotlen=read(client->gpollfd.fd,buf,read_max);
536                 if (gotlen==-1) {
537                         if (errno==EAGAIN)
538                                 break;
539                         g_warning(_("Error reading data from %s"),SOCKADDR_IN_TO_STRING(&client->sockaddr_in_from));
540                         client_destroy(client);
541                         return;
542                         }
543                 if (gotlen==0) {
544                         /* Successful close; leave the bound peer's 'gstring_to_send' to be written there. */
545                         if (client->server_only && client->bound->gstring_to_send->len)
546                                 client_split(client);
547                         client_destroy(client);
548                         return;
549                         }
550                 g_assert(gotlen>0);
551                 g_assert((size_t)gotlen<=read_max);
552                 g_string_append_len(client->bound->gstring_to_send,buf,gotlen);
553                 }
554 }
555
556 /* Write to client->gpollfd.fd the data from client->gstring_to_send. */
557 static void handle_client_tcp_write(struct client *client)
558 {
559         g_return_if_fail(client!=NULL);
560         g_return_if_fail(!client->connect_pending);
561         g_return_if_fail(master_tcp!=NULL);
562
563         for (;;) {
564 ssize_t gotlen;
565
566                 if (client->gstring_to_send->len<=0)    /* In fact it initially should not happen, there would be no: G_IO_OUT */
567                         break;
568                 gotlen=write(client->gpollfd.fd,client->gstring_to_send->str,client->gstring_to_send->len);
569                 if (gotlen==-1) {
570                         if (errno==EAGAIN)
571                                 break;
572                         g_warning(_("Error writing data to %s"),SOCKADDR_IN_TO_STRING(&client->sockaddr_in_from));
573                         client_destroy(client);
574                         return;
575                         }
576                 if (gotlen<=0)
577                         break;
578                 g_assert((size_t)gotlen<=client->gstring_to_send->len);
579                 g_string_erase(client->gstring_to_send,0,gotlen);
580                 }
581
582         /* Nothing left to do for such client. */
583         if (!client->gstring_to_send->len && !client->bound)
584                 client_destroy(client);
585 }
586
587 static gboolean sock_source_callback(gpointer data /* unused */)
588 {
589 GList *clientl;
590
591         /* FIXME: Quadratic 'done' marking to not to stick on stale entry! */
592
593         for (clientl=sock_client_list;clientl;clientl=clientl->next) {
594 struct client *client=clientl->data;
595
596                 client->done=0;
597                 }
598 retry_in:
599         for (clientl=sock_client_list;clientl;clientl=clientl->next) {
600 struct client *client=clientl->data;
601
602                 if (client->done)
603                         continue;
604                 client->done=1;
605                 if (client->gpollfd.revents&G_IO_IN) {
606                         /**/ if (client==master_udp)
607                                 handle_master_udp(client);
608                         else if (client==master_tcp)
609                                 handle_master_tcp(client);
610                         else if (client==probe)
611                                 handle_probe(client);
612                         else if (client->connect_pending)
613                                 g_assert_not_reached();
614                         else if (client->bound)
615                                 handle_client_tcp_read(client);
616                         else
617                                 handle_client_udp(client);
618                         }
619                 goto retry_in;
620                 }
621
622         for (clientl=sock_client_list;clientl;clientl=clientl->next) {
623 struct client *client=clientl->data;
624
625                 client->done=0;
626                 }
627 retry_out:
628         for (clientl=sock_client_list;clientl;clientl=clientl->next) {
629 struct client *client=clientl->data;
630
631                 if (client->done)
632                         continue;
633                 client->done=1;
634                 if (client->gpollfd.revents&G_IO_OUT) {
635                         /**/ if (client==master_udp)
636                                 g_assert_not_reached();
637                         else if (client==master_tcp)
638                                 g_assert_not_reached();
639                         else if (client==probe)
640                                 g_assert_not_reached();
641                         else if (client->connect_pending)
642                                 handle_client_tcp_connect(client);
643                         else if (client->gstring_to_send)
644                                 handle_client_tcp_write(client);
645                         else
646                                 g_assert_not_reached();
647                         }
648                 goto retry_out;
649                 }
650
651         return TRUE; /* the source should be kept active */
652 }
653
654 static gboolean sock_source_prepare(GSource *source,gint *timeout)
655 {
656 GList *clientl;
657
658         *timeout=-1;
659
660         for (clientl=sock_client_list;clientl;clientl=clientl->next) {
661 struct client *client=clientl->data;
662
663                 client->gpollfd.events=G_IO_IN;
664                 if (!client->bound && client->gstring_to_send)
665                         client->gpollfd.events&=~G_IO_IN;
666                 if (client->bound && client->bound->gstring_to_send->len>=GSTRING_TO_SEND_MAX)
667                         client->gpollfd.events&=~G_IO_IN;
668                 if (client->connect_pending)
669                         client->gpollfd.events&=~G_IO_IN;
670                 if (client->bound && client->bound->connect_pending)
671                         client->gpollfd.events&=~G_IO_IN;
672                 if (client->connect_pending)
673                         client->gpollfd.events|=G_IO_OUT;
674                 if (client->gstring_to_send && client->gstring_to_send->len>0)
675                         client->gpollfd.events|=G_IO_OUT;
676                 g_assert(!(client->gpollfd.events&~SOCK_SOURCE_CHECK_REVENTS));
677                 }
678         return FALSE;
679 }
680
681 static gboolean sock_source_check(GSource *source)
682 {
683 GList *clientl;
684
685         for (clientl=sock_client_list;clientl;clientl=clientl->next) {
686 struct client *client=clientl->data;
687
688                 if (client->gpollfd.revents&SOCK_SOURCE_CHECK_REVENTS)
689                         return TRUE;
690                 }
691         return FALSE;
692 }
693
694 static gboolean sock_source_dispatch(GSource *source,GSourceFunc callback,gpointer user_data)
695 {
696         g_assert(callback!=NULL);
697         return (*callback)(user_data);
698 }
699
700 static GSourceFuncs sock_source_watch_funcs={
701                 sock_source_prepare,
702                 sock_source_check,
703                 sock_source_dispatch,
704                 NULL, /* finalize */
705                 };
706
707 static void sock_gsource_destroy(void)
708 {
709         while (sock_client_list)
710                 client_destroy(sock_client_list->data);
711
712         g_assert(master_udp==NULL);
713         g_assert(master_tcp==NULL);
714         g_assert(probe==NULL);
715
716         if (sock_gsource) {
717                 g_source_destroy(sock_gsource);
718                 sock_gsource=NULL;
719                 }
720
721         write_daemon_running((pid_t)-1);        /* unlink; errors ignored */
722 }
723
724 static gboolean sock_gsource_new(void)
725 {
726         if (sock_gsource)
727                 return TRUE;
728
729         g_assert(sock_client_list==NULL);
730
731         /* attach sock_source_callback() to watch for any abnormalities
732          * on our open pipe 'parentheart_fds' and terminate the child if parent dies.
733          */
734         if (!(sock_gsource=g_source_new(&sock_source_watch_funcs,sizeof(GSource)))) {
735                 g_warning("g_source_new(): %m");
736                 return FALSE;
737                 }
738         g_source_set_callback(
739                         sock_gsource,  /* source */
740                         sock_source_callback,  /* func */
741                         NULL, /* data */
742                         NULL);  /* notify */
743         if (!g_source_attach(   /* returns 'guint' id */
744                         sock_gsource,  /* source */
745                         NULL)) {        /* context; NULL means 'default context' */
746                 g_warning("g_source_attach(gsource,NULL): %m");
747                 sock_gsource_destroy();
748                 return FALSE;
749                 }
750         return TRUE;
751 }
752
753 static struct client *client_new_from_sock(int sock)
754 {
755 struct client *client;
756 static unsigned long oneul=1;
757
758         g_return_val_if_fail(sock>=0,NULL);
759
760         if (!sock_gsource_new())
761                 return FALSE;
762
763         if (ioctl(sock,FIONBIO,&oneul)) {       /* non-blocking mode */
764                 g_warning("ioctl(sock,FIONBIO,&1): %m");
765                 close(sock);    /* errors ignored */
766                 return NULL;
767                 }
768
769         udpgate_new(client);
770         client->gpollfd.fd=sock;
771         client->gpollfd.events=0;       /* Initialized later. */
772         client->gpollfd.revents=0;      /* Probably does not need to be initialized. */
773         client->timeout_id=0;
774         client->bound=NULL;
775         client->connect_pending=0;
776         client->server_only=0;
777         client->gstring_to_send=0;
778         sock_client_list=g_list_prepend(sock_client_list,client);
779         g_source_add_poll(sock_gsource,&client->gpollfd);
780
781         if (optarg_verbose)
782                 g_message(_("Client fd %d created"),client->gpollfd.fd);
783
784         return client;
785 }
786
787 static struct client *client_new(enum client_new_type type)
788 {
789 int sock;
790
791         switch (type) {
792                 case CLIENT_NEW_TYPE_UDP:
793                         if (-1==(sock=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP))) {
794                                 g_warning("socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP): %m");
795                                 return NULL;
796                                 }
797                         break;
798                 case CLIENT_NEW_TYPE_TCP:
799                         if (-1==(sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))) {
800                                 g_warning("socket(PF_INET,SOCK_STREAM,IPPROTO_TCP): %m");
801                                 return NULL;
802                                 }
803                         break;
804                 default: g_assert_not_reached();
805                 }
806
807         return client_new_from_sock(sock);
808 }
809
810 static void client_destroy(struct client *client)
811 {
812 struct client *bound;
813
814         g_return_if_fail(client!=NULL);
815
816         if (!sock_gsource_new())
817                 return;
818
819         if (optarg_verbose)
820                 g_message(_("Client fd %d timeout id %d destroy enter"),client->gpollfd.fd,client->timeout_id);
821
822         if (client==master_udp) {
823                 master_udp=NULL;
824                 g_assert(client->timeout_id==0);
825                 }
826         else if (client==master_tcp) {
827                 master_tcp=NULL;
828                 g_assert(client->timeout_id==0);
829                 }
830         else {
831                 if (client==probe)
832                         probe=NULL;
833                 client_timeout_remove(client);
834                 }
835
836         g_source_remove_poll(sock_gsource,&client->gpollfd);
837         sock_client_list=g_list_remove(sock_client_list,client);
838         close(client->gpollfd.fd);      /* errors ignored */
839
840         if (client->gstring_to_send)
841                 g_string_free(client->gstring_to_send,TRUE);
842
843         if (optarg_verbose)
844                 g_message(_("Client fd %d timeout id %d destroy finish"),client->gpollfd.fd,client->timeout_id);
845
846         bound=client->bound;
847         g_free(client);
848
849         if (bound) {
850                 g_assert(bound!=client);
851                 g_assert(bound->bound==client);
852                 client->bound=NULL;
853                 bound->bound=NULL;
854                 client_destroy(bound);
855                 }
856 }
857
858 static gboolean probe_send(struct client *probe,gint port_local)
859 {
860 struct sockaddr_in sockaddr_in_probe;
861 GHashTable *probe_hash;
862 gpointer packet;
863 size_t packet_length;
864
865         g_return_val_if_fail(probe!=NULL,FALSE);
866
867         probe_unique=g_random_int();
868
869         probe_hash=g_hash_table_new(
870                         g_direct_hash,  /* hash_func */
871                         g_direct_equal);        /* key_equal_func */
872         g_hash_table_insert(probe_hash,GUINT_TO_POINTER(PACKET_ELEM_TYPE_CLIENT_PORT) ,GUINT_TO_POINTER(port_local));
873         g_hash_table_insert(probe_hash,GUINT_TO_POINTER(PACKET_ELEM_TYPE_DATA_GUINT32),GUINT_TO_POINTER(probe_unique));
874         packet=packet_assembly(&packet_length,probe_hash);
875         g_hash_table_destroy(probe_hash);
876         if (!packet)
877                 return FALSE;
878
879         UDPGATE_MEMZERO(&sockaddr_in_probe);
880         sockaddr_in_probe.sin_family=AF_INET;
881         sockaddr_in_probe.sin_port=htons(PROBE_PORT);
882         sockaddr_in_probe.sin_addr.s_addr=htonl(PROBE_INADDR);
883         /* FIXME: errors checking */
884         sendto(
885                         probe->gpollfd.fd,      /* s */
886                         packet, /* msg */
887                         packet_length,  /* len */
888                         0,      /* flags */
889                         (struct sockaddr *)&sockaddr_in_probe,  /* to */
890                         sizeof(sockaddr_in_probe));     /* tolen */
891
892         return TRUE;
893 }
894
895 static gboolean master_udp_start(gint port,const struct sockaddr_in *sockaddr_in_pointer)
896 {
897         g_return_val_if_fail(master_udp==NULL,FALSE);
898
899         if (!(master_udp=client_new(CLIENT_NEW_TYPE_UDP)))
900                 return FALSE;
901         if (bind(master_udp->gpollfd.fd,(struct sockaddr *)sockaddr_in_pointer,sizeof(*sockaddr_in_pointer))) {
902                 g_warning("bind(sock_udp,{AF_INET,INADDR_ANY:%d}): %m",(int)port);
903                 return FALSE;
904                 }
905         return TRUE;
906 }
907
908 static gboolean master_tcp_start(gint port,const struct sockaddr_in *sockaddr_in_pointer)
909 {
910 static int onei=1;
911
912         g_return_val_if_fail(master_tcp==NULL,FALSE);
913
914         if (!(master_tcp=client_new(CLIENT_NEW_TYPE_TCP)))
915                 return FALSE;
916         if (setsockopt(master_tcp->gpollfd.fd,SOL_SOCKET,SO_REUSEADDR,&onei,sizeof(onei))) {
917                 g_warning("setsockopt(sock_tcp,SOL_SOCKET,SO_REUSEADDR,1): %m");
918                 return FALSE;
919                 }
920         if (bind(master_tcp->gpollfd.fd,(struct sockaddr *)sockaddr_in_pointer,sizeof(*sockaddr_in_pointer))) {
921                 g_warning("bind(sock_tcp,{AF_INET,INADDR_ANY:%d}): %m",(int)port);
922                 return FALSE;
923                 }
924         if (listen(master_tcp->gpollfd.fd,TCP_BACKLOG)) {
925                 g_warning("listen(sock_tcp,%d): %m",TCP_BACKLOG);
926                 return FALSE;
927                 }
928         return TRUE;
929 }
930
931 static gboolean master_start(gint port)
932 {
933 struct sockaddr_in sockaddr_in;
934 uint16_t port_use;
935
936         g_return_val_if_fail(port>=0,FALSE);
937         g_return_val_if_fail(master_udp==NULL,FALSE);
938         g_return_val_if_fail(master_tcp==NULL,FALSE);
939
940         port_use=port;
941         if (port < 0 || port_use != port) {
942                 g_warning(_("Port value %d is not valid for IPv4!"),(int)port);
943                 return FALSE;
944                 }
945         UDPGATE_MEMZERO(&sockaddr_in);
946         sockaddr_in.sin_family=AF_INET;
947         sockaddr_in.sin_port=htons(port_use);
948         sockaddr_in.sin_addr.s_addr=htonl(INADDR_ANY);
949
950         if (!master_udp_start(port,&sockaddr_in))
951                 return FALSE;
952         if (!master_tcp_start(port,&sockaddr_in)) {
953                 client_destroy(master_udp);
954                 return FALSE;
955                 }
956         return TRUE;
957 }
958
959 static gboolean probe_start(gint port)
960 {
961         g_return_val_if_fail(port>=0,FALSE);
962         g_return_val_if_fail(probe==NULL,FALSE);
963
964         /* Setup 'probe': */
965         if (!(probe=client_new(CLIENT_NEW_TYPE_UDP)))
966                 return FALSE;
967         port_local=port;
968         if (!probe_send(probe,port)) {
969                 client_destroy(probe);
970                 return FALSE;
971                 }
972         probe_timeout_sec_now=PROBE_TIMEOUT_SEC_BASE;
973         client_touch(probe,probe_timeout_sec_now);      /* timeout */
974         return TRUE;
975 }
976
977 gboolean network_start(gint port)
978 {
979 pid_t daemon_pid;
980
981         g_return_val_if_fail(port>=0,FALSE);
982
983         UDPGATE_MEMZERO(&sockaddr_in_server);
984         sockaddr_in_server.sin_family=AF_INET;
985         sockaddr_in_server.sin_port=htons(SERVER_PORT);
986         sockaddr_in_server.sin_addr.s_addr=htonl(SERVER_INADDR);
987
988         if ((pid_t)-1!=(daemon_pid=is_daemon_running())) {
989                 g_warning(_("Cannot start network daemon: Daemon is already running on PID %d"),(int)daemon_pid);
990                 return FALSE;
991                 }
992         if (!master_start(port)) {
993                 sock_gsource_destroy();
994                 return FALSE;
995                 }
996         if (!probe_start(port)) {
997                 sock_gsource_destroy();
998                 return FALSE;
999                 }
1000         write_daemon_running(getpid()); /* errors ignored */
1001         if (network_notify_hostip)
1002                 (*network_notify_hostip)(0);
1003         return TRUE;
1004 }
1005
1006 gboolean optarg_port_set_string(const gchar *port_string)
1007 {
1008 char *endp;
1009 long port_long;
1010
1011         g_return_val_if_fail(port_string!=NULL,FALSE);
1012
1013         port_long=strtol(port_string,&endp,0);
1014         if (endp && *endp) {
1015                 g_warning(_("Invalid port specification, offending string: %s"),endp);
1016                 return FALSE;
1017                 }
1018         if (port_long<1 || port_long>=G_MAXINT || (endp && *endp)) {
1019                 g_warning(_("Invalid port integer number specification (%ld)"),port_long);
1020                 return FALSE;
1021                 }
1022         optarg_port=port_long;
1023         return TRUE;
1024 }
1025
1026 gboolean network_stop(void)
1027 {
1028 pid_t daemon_pid;
1029 int errno_save;
1030
1031         if ((pid_t)-1==(daemon_pid=is_daemon_running())) {
1032                 g_warning(_("Cannot stop network daemon: Daemon is not running"));
1033                 return FALSE;
1034                 }
1035         if (daemon_pid==getpid()) {
1036                 sock_gsource_destroy();
1037                 goto ok;
1038                 }
1039         errno=0;
1040         kill(daemon_pid,SIGKILL);
1041         errno_save=errno;
1042         write_daemon_running((pid_t)-1);        /* unlink; errors ignored */
1043         if (errno_save)  {
1044                 g_warning(udpgate_printf_alloca(_("Unable to stop the daemon at PID %d: %s"),
1045                                 (int)daemon_pid,strerror(errno_save)));
1046                 return FALSE;
1047                 }
1048 ok:
1049         if (network_notify_hostip)
1050                 (*network_notify_hostip)(0);
1051         return TRUE;
1052 }
1053
1054 static GMainLoop *gmainloop;
1055 static void network_detach_network_notify_hostip(guint32 hostip_guint32)
1056 {
1057         if (!hostip_guint32)
1058                 g_main_loop_quit(gmainloop);
1059 }
1060
1061 gboolean network_detach(void)
1062 {
1063 pid_t daemon_pid,forked_pid;
1064
1065         if ((pid_t)-1==(daemon_pid=is_daemon_running()))
1066                 return TRUE;
1067         if (getpid()!=daemon_pid)
1068                 return TRUE;
1069         if (!optarg_no_fork) {
1070                 if ((pid_t)-1==(forked_pid=fork())) {
1071                         g_warning("fork(2): %m");
1072                         return FALSE;
1073                         }
1074                 if (forked_pid) {
1075                         /* parent */
1076                         return TRUE;
1077                         }
1078                 write_daemon_running(getpid()); /* errors ignored */
1079                 optarg_verbose=0;
1080                 close(STDIN_FILENO);
1081                 close(STDOUT_FILENO);
1082                 close(STDERR_FILENO);
1083                 setpgrp();
1084                 setsid();
1085                 }
1086
1087         network_notify_hostip=network_detach_network_notify_hostip;
1088         gmainloop=g_main_loop_new(
1089                         NULL,   /* context */
1090                         TRUE);  /* is_running; ignored */
1091         g_main_loop_run(gmainloop);     /* loop */
1092         /* Unable to contact the server, aborting. */
1093         return FALSE;
1094 }