/* * IvyDaemon, an Ivy gateway for short-lived agents * * Copyright (C) 1999 * Centre d'Études de la Navigation Aérienne * * Main file for the super-daemon * * Author(s): Stephane Chatty * from code by Patrick Amar * * $Id$ * * Please refer to file version.h for the * copyright notice regarding this software * */ /* * Le super-demon wixd. * * Il est normalement lance par inetd, avec la chaussette SOCK_DGRAM * sur le descripteur 0, ou alors, si le symbole FROMBOOT est defini, il est * lance depuis /etc/rc.local. * * Le serveur wixd: * Il envoie un paquet connmsg de type MSG_SERVER contenant le numero * de port sur lequel il a connecte sa chaussette. * * Les clients wix (wx, wxcat, etc ...): * Ils envoient un paquet connmsg de type MSG_CLIENT ou ils demandent * le port. * * L'identification de l'emetteur du paquet est le numero d'utilisateur. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "ivyd.h" const char* const dumpfilename = "/usr/tmp/wixd.db"; const int dumpfilemode = 0644; const char* const servicename = "ivyd"; const char* const port_env_variable = "INIVYD_PORT"; const int default_port = 3006; /* * Definition de la table geree par le super-demon */ typedef struct { short s_port; /* le port sur lequel le client communique avec son serveur */ short s_uid; /* le numero de processus du serveur wixd */ } serverinfo; #define TABSIZ 64 /* 64 connections simultanees, ca devrait aller */ serverinfo si_table [TABSIZ]; /* * GetInfo (name) * * Rend l'information concernant l'utilisateur uid. */ serverinfo* GetInfo (int uid) { register serverinfo *si; register serverinfo *res = 0; for (si = si_table; si - si_table < TABSIZ; ++si) { if (si->s_port == 0) { if (! res) res = si; continue; } if (si->s_uid != uid) continue; res = si; break; } return res; } /* * DumpInfo () * * Dumps to a file the contents of the table */ int DumpInfo () { register serverinfo *si; register int fd = creat (dumpfilename, dumpfilemode); char buf [512]; if (fd == -1) return 0; for (si = si_table; si - si_table < TABSIZ; ++si) { if (! si->s_port) continue; (void) sprintf (buf, "user %5d, port %d\n", si->s_uid, ntohs (si->s_port)); (void) write (fd, buf, strlen (buf)); } (void) close (fd); return 1; } void SigHup (int sig) { DumpInfo (); } void main (int argc, const char **argv) { struct servent *serv; u_short serv_port = 0; struct sockaddr_in from; int fromlen; struct connmsg msg; register serverinfo *si; int boot = 0; int debug = 0; (void) signal (SIGHUP, SigHup); serv = getservbyname (servicename, 0); if (! serv) { char *pp = getenv (port_env_variable); serv_port = htons (pp ? atoi (pp) : default_port); if (serv_port <= 0) exit (0); } else serv_port = serv -> s_port; ++argv; while (argc > 1) { if (strcmp (*argv, "-boot") == 0 || strcmp (*argv, "-b") == 0) boot = 1; else if (strcmp (*argv, "-debug") == 0 || strcmp (*argv, "-d") == 0) debug = 1; else fprintf (stderr, "bad option %s\n", *argv); ++argv; --argc; } if (boot) { if (!debug) { int s; if (fork ()) exit (0); /* on ferme tous les descripteurs */ for (s = getdtablesize (); --s >= 0;) close (s); /* et on se debarrasse du terminal de controle */ if (-1 != open ("/dev/tty", 2)) { (void) ioctl (0, TIOCNOTTY, 0); close (0); } } else close (0); /* * Ouvre la chaussette et l'attache a bon port */ if (-1 == socket (AF_INET, SOCK_DGRAM, 0)) exit (1); memset (&from, 0, sizeof from); from.sin_family = AF_INET; from.sin_port = serv_port; from.sin_addr.s_addr = INADDR_ANY; if (-1 == bind (0, &from, sizeof from)) exit (1); } for (;;) { fromlen = sizeof from; if (recvfrom (0, (char *)&msg, sizeof msg, 0, (struct sockaddr *)&from, &fromlen) <= 0) { if (errno == EINTR) continue; exit (1); } si = GetInfo (msg.msg_uid); switch (msg.msg_type) { case MSG_SERVER: si->s_port = msg.msg_port; si->s_uid = msg.msg_uid; break; case MSG_CLIENT: msg.msg_port = si->s_port; msg.msg_type = MSG_REPLY; (void) sendto (0, (char *)&msg, sizeof msg, 0, (struct sockaddr *)&from, fromlen); break; } } }