* socket stuff
authorArt Cancro <ajc@citadel.org>
Tue, 7 Mar 2000 01:55:45 +0000 (01:55 +0000)
committerArt Cancro <ajc@citadel.org>
Tue, 7 Mar 2000 01:55:45 +0000 (01:55 +0000)
citadel/citmail.c
citadel/dynloader.c
citadel/dynloader.h
citadel/ipc_c_tcp.c
citadel/serv_pop3.c
citadel/serv_smtp.c
citadel/server.h
citadel/sysdep.c
citadel/sysdep_decls.h

index 83c54ea664dbb8eea1d3fe472d2369e9070cd32b..5a41f2d5a35340d46022943fff0784d8c5eeb702 100644 (file)
@@ -17,8 +17,6 @@
 #include <signal.h>
 #include <sys/types.h>
 #include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
 #include <sys/un.h>
 #include <netdb.h>
 #include <string.h>
 #include "snprintf.h"
 #endif
 
-#ifndef INADDR_NONE
-#define INADDR_NONE 0xffffffff
-#endif
-
 int serv_sock;
 
 
@@ -46,135 +40,37 @@ void strip_trailing_nonprint(char *buf)
 }
 
 
-
-
-
-
 void timeout(int signum)
 {
        exit(signum);
 }
 
 
-int connectsock(char *host, char *service, char *protocol)
+int uds_connectsock(char *sockpath)
 {
-       struct hostent *phe;
-       struct servent *pse;
-       struct protoent *ppe;
-       struct sockaddr_in sin;
-       int s, type;
+       int s;
        struct sockaddr_un sun;
 
-       if ( (!strcmp(protocol, "unix")) || (atoi(service)<0) ) {
-               memset(&sun, 0, sizeof(sun));
-               sun.sun_family = AF_UNIX;
-               sprintf(sun.sun_path, USOCKPATH, 0-atoi(service) );
-
-               s = socket(AF_UNIX, SOCK_STREAM, 0);
-               if (s < 0) {
-                       fprintf(stderr, "Can't create socket: %s\n",
-                               strerror(errno));
-                       exit(3);
-               }
-
-               if (connect(s, (struct sockaddr *) &sun, sizeof(sun)) < 0) {
-                       fprintf(stderr, "can't connect: %s\n",
-                               strerror(errno));
-                       exit(3);
-               }
-
-               return s;
-       }
-
-
-       /* otherwise it's a network connection */
+       memset(&sun, 0, sizeof(sun));
+       sun.sun_family = AF_UNIX;
+       strncpy(sun.sun_path, sockpath, sizeof sun.sun_path);
 
-       memset(&sin, 0, sizeof(sin));
-       sin.sin_family = AF_INET;
-
-       pse = getservbyname(service, protocol);
-       if (pse) {
-               sin.sin_port = pse->s_port;
-       } else if ((sin.sin_port = htons((u_short) atoi(service))) == 0) {
-               fprintf(stderr, "Can't get %s service entry: %s\n",
-                       service, strerror(errno));
-               exit(3);
-       }
-       phe = gethostbyname(host);
-       if (phe) {
-               memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
-       } else if ((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) {
-               fprintf(stderr, "Can't get %s host entry: %s\n",
-                       host, strerror(errno));
-               exit(3);
-       }
-       if ((ppe = getprotobyname(protocol)) == 0) {
-               fprintf(stderr, "Can't get %s protocol entry: %s\n",
-                       protocol, strerror(errno));
-               exit(3);
-       }
-       if (!strcmp(protocol, "udp")) {
-               type = SOCK_DGRAM;
-       } else {
-               type = SOCK_STREAM;
-       }
-
-       s = socket(PF_INET, type, ppe->p_proto);
+       s = socket(AF_UNIX, SOCK_STREAM, 0);
        if (s < 0) {
-               fprintf(stderr, "Can't create socket: %s\n", strerror(errno));
+               fprintf(stderr, "Can't create socket: %s\n",
+                       strerror(errno));
                exit(3);
        }
-       signal(SIGALRM, timeout);
-       alarm(30);
 
-       if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
-               fprintf(stderr, "can't connect to %s.%s: %s\n",
-                       host, service, strerror(errno));
+       if (connect(s, (struct sockaddr *) &sun, sizeof(sun)) < 0) {
+               fprintf(stderr, "can't connect: %s\n",
+                       strerror(errno));
                exit(3);
        }
-       alarm(0);
-       signal(SIGALRM, SIG_IGN);
 
-       return (s);
+       return s;
 }
 
-/*
- * convert service and host entries into a six-byte numeric in the format
- * expected by a SOCKS v4 server
- */
-void numericize(char *buf, char *host, char *service, char *protocol)
-{
-       struct hostent *phe;
-       struct servent *pse;
-       struct sockaddr_in sin;
-
-       memset(&sin, 0, sizeof(sin));
-       sin.sin_family = AF_INET;
-
-       pse = getservbyname(service, protocol);
-       if (pse) {
-               sin.sin_port = pse->s_port;
-       } else if ((sin.sin_port = htons((u_short) atoi(service))) == 0) {
-               fprintf(stderr, "Can't get %s service entry: %s\n",
-                       service, strerror(errno));
-               exit(3);
-       }
-       buf[1] = (((sin.sin_port) & 0xFF00) >> 8);
-       buf[0] = ((sin.sin_port) & 0x00FF);
-
-       phe = gethostbyname(host);
-       if (phe) {
-               memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
-       } else if ((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) {
-               fprintf(stderr, "Can't get %s host entry: %s\n",
-                       host, strerror(errno));
-               exit(3);
-       }
-       buf[5] = ((sin.sin_addr.s_addr) & 0xFF000000) >> 24;
-       buf[4] = ((sin.sin_addr.s_addr) & 0x00FF0000) >> 16;
-       buf[3] = ((sin.sin_addr.s_addr) & 0x0000FF00) >> 8;
-       buf[2] = ((sin.sin_addr.s_addr) & 0x000000FF);
-}
 
 /*
  * input binary data from socket
@@ -281,7 +177,7 @@ int main(int argc, char **argv) {
        strip_trailing_nonprint(fromline);
 
        sprintf(buf, "%d", SMTP_PORT);
-       serv_sock = connectsock("localhost", buf, "tcp");
+       serv_sock = uds_connectsock("smtp.socket");
        serv_gets(buf);
        fprintf(stderr, "%s\n", buf);
        if (buf[0]!='2') cleanup(1);
index be6d6353a1e0fe1c1602fcbff392481884f1518b..eb521eadd0bd3bdc4e92d94259139eca84ccf4dc 100644 (file)
@@ -230,6 +230,7 @@ void CtdlRegisterXmsgHook(int (*fcn_ptr) (char *, char *, char *), int order)
 }
 
 void CtdlRegisterServiceHook(int tcp_port,
+                       char *sockpath,
                        void (*h_greeting_function) (void),
                        void (*h_command_function) (void) )
 {
@@ -239,9 +240,16 @@ void CtdlRegisterServiceHook(int tcp_port,
            mallok(sizeof(struct ServiceFunctionHook));
        newfcn->next = ServiceHookTable;
        newfcn->tcp_port = tcp_port;
+       newfcn->sockpath = sockpath;
        newfcn->h_greeting_function = h_greeting_function;
        newfcn->h_command_function = h_command_function;
-       newfcn->msock = ig_tcp_server(tcp_port, config.c_maxsessions);
+
+       if (sockpath != NULL) {
+               newfcn->msock = ig_uds_server(sockpath, config.c_maxsessions);
+       }
+       else {
+               newfcn->msock = ig_tcp_server(tcp_port, config.c_maxsessions);
+       }
 
        if (newfcn->msock >= 0) {
                ServiceHookTable = newfcn;
index 088f4d2fb2ba416b03d402f9444c4eec4c6f69f5..1a43066be1a3575186dcd5b2fe792c4d0880d497 100644 (file)
@@ -22,6 +22,7 @@ int PerformMessageHooks(struct CtdlMessage *, int EventType);
 void CtdlRegisterCleanupHook(void (*fcn_ptr)(void));
 void CtdlRegisterProtoHook(void (*handler)(char *), char *cmd, char *desc);
 void CtdlRegisterServiceHook(int tcp_port,
+                       char *sockpath,
                         void (*h_greeting_function) (void),
                         void (*h_command_function) (void) ) ;
 
index 4be2202271da441e27ae7c4ab2365a6035cb18d7..befb21afc47ca085baefd5562c7ce59acd894d43 100644 (file)
@@ -7,8 +7,10 @@
  *
  */
 
-#define DEFAULT_HOST   "127.0.0.1"
-#define DEFAULT_PORT   "citadel"
+#define        UDS                     "citadel unix domain socket type of thing"
+
+#define DEFAULT_HOST           UDS
+#define DEFAULT_PORT           "citadel"
 
 
 #include "sysdep.h"
@@ -73,34 +75,8 @@ int connectsock(char *host, char *service, char *protocol)
        struct servent *pse;
        struct protoent *ppe;
        struct sockaddr_in sin;
-       struct sockaddr_un sun;
        int s, type;
 
-
-       if ( (!strcmp(protocol, "unix")) || (atoi(service)<0) ) {
-               memset(&sun, 0, sizeof(sun));
-               sun.sun_family = AF_UNIX;
-               sprintf(sun.sun_path, USOCKPATH, 0-atoi(service) );
-
-               s = socket(AF_UNIX, SOCK_STREAM, 0);
-               if (s < 0) {
-                       fprintf(stderr, "Can't create socket: %s\n",
-                               strerror(errno));
-                       logoff(3);
-               }
-
-               if (connect(s, (struct sockaddr *) &sun, sizeof(sun)) < 0) {
-                       fprintf(stderr, "can't connect: %s\n",
-                               strerror(errno));
-                       logoff(3);
-               }
-
-               return s;
-       }
-
-
-       /* otherwise it's a network connection */
-
        memset(&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;
 
@@ -150,6 +126,31 @@ int connectsock(char *host, char *service, char *protocol)
        return (s);
 }
 
+int uds_connectsock(char *sockpath)
+{
+       struct sockaddr_un sun;
+       int s;
+
+       memset(&sun, 0, sizeof(sun));
+       sun.sun_family = AF_UNIX;
+       strncpy(sun.sun_path, sockpath, sizeof sun.sun_path);
+
+       s = socket(AF_UNIX, SOCK_STREAM, 0);
+       if (s < 0) {
+               fprintf(stderr, "Can't create socket: %s\n",
+                       strerror(errno));
+               logoff(3);
+       }
+
+       if (connect(s, (struct sockaddr *) &sun, sizeof(sun)) < 0) {
+               fprintf(stderr, "can't connect: %s\n",
+                       strerror(errno));
+               logoff(3);
+       }
+
+       return s;
+}
+
 /*
  * convert service and host entries into a six-byte numeric in the format
  * expected by a SOCKS v4 server
@@ -278,6 +279,7 @@ void attach_to_server(int argc, char **argv)
        char socks4[256];
        char buf[256];
        struct passwd *p;
+       char sockpath[256];
 
        strcpy(cithost, DEFAULT_HOST);  /* default host */
        strcpy(citport, DEFAULT_PORT);  /* default port */
@@ -307,9 +309,17 @@ void attach_to_server(int argc, char **argv)
 
        server_is_local = 0;
        if ((!strcmp(cithost, "localhost"))
-           || (!strcmp(cithost, "127.0.0.1")))
+           || (!strcmp(cithost, "127.0.0.1"))
+           || (!strcmp(cithost, "uds")))
                server_is_local = 1;
 
+       /* If we're using a unix domain socket we can do a bunch of stuff */
+       if (!strcmp(cithost, UDS)) {
+               sprintf(sockpath, "%s/citadel.socket", BBSDIR);
+               serv_sock = uds_connectsock(sockpath);
+               return;
+       }
+
        /* if not using a SOCKS proxy server, make the connection directly */
        if (strlen(socks4) == 0) {
                serv_sock = connectsock(cithost, citport, "tcp");
index 808f10fac50df3b37e5ae2cd8b7cb0667155c35d..3112c3ea1a899d6f6025c60472d2f9c2f7f00db5 100644 (file)
@@ -539,6 +539,7 @@ char *Dynamic_Module_Init(void)
 {
        SYM_POP3 = CtdlGetDynamicSymbol();
        CtdlRegisterServiceHook(POP3_PORT,
+                               NULL,
                                pop3_greeting,
                                pop3_command_loop);
        CtdlRegisterSessionHook(pop3_cleanup_function, EVT_STOP);
index 3174d89329ea3dcf164c490d8fa54fec702fc04b..cda7c3d711a401aaac578881b9b1d7dcdcf5d8d9 100644 (file)
@@ -1425,9 +1425,17 @@ char *Dynamic_Module_Init(void)
 {
        SYM_SMTP = CtdlGetDynamicSymbol();
        SYM_SMTP_RECP = CtdlGetDynamicSymbol();
-       CtdlRegisterServiceHook(SMTP_PORT,
+
+       CtdlRegisterServiceHook(SMTP_PORT,              /* On the net... */
+                               NULL,
                                smtp_greeting,
                                smtp_command_loop);
+
+       CtdlRegisterServiceHook(0,                      /* ...and locally */
+                               "smtp.socket",
+                               smtp_greeting,
+                               smtp_command_loop);
+
        create_room(SMTP_SPOOLOUT_ROOM, 3, "", 0);
        CtdlRegisterSessionHook(smtp_do_queue, EVT_TIMER);
        return "$Id$";
index 10a6f853bd1f8f0064236f54ef22d567338d8b0c..9f69f19bf05c9d378f32636245a7c79074fdbc9f 100644 (file)
@@ -329,6 +329,7 @@ enum {
 struct ServiceFunctionHook {
        struct ServiceFunctionHook *next;
        int tcp_port;
+       char *sockpath;
        void (*h_greeting_function) (void) ;
        void (*h_command_function) (void) ;
        int msock;
index 59de2f8b5ab682cd8b091a26539ab1c3dfb76933..1952c1bb2c4a723d9d304fd0afb09eca7b6ba7ad 100644 (file)
@@ -261,64 +261,70 @@ void end_critical_section(int which_one)
  * This is a generic function to set up a master socket for listening on
  * a TCP port.  The server shuts down if the bind fails.
  *
- * If a negative number is specified, a Unix domain socket is created.
  */
 int ig_tcp_server(int port_number, int queue_len)
 {
        struct sockaddr_in sin;
-       struct sockaddr_un addr;
        int s, i;
-       int is_unix = 0;
 
-       if (port_number < 0) {
-               is_unix = 1;
-       }
+       memset(&sin, 0, sizeof(sin));
+       sin.sin_family = AF_INET;
+       sin.sin_addr.s_addr = INADDR_ANY;
+       sin.sin_port = htons((u_short)port_number);
 
-       if (is_unix) {
-               memset(&addr, 0, sizeof(addr));
-               addr.sun_family = AF_UNIX;
-               sprintf(addr.sun_path, USOCKPATH, 0-port_number);
-       }
-       else {
-               memset(&sin, 0, sizeof(sin));
-               sin.sin_family = AF_INET;
-               sin.sin_addr.s_addr = INADDR_ANY;
-               sin.sin_port = htons((u_short)port_number);
+       s = socket(PF_INET, SOCK_STREAM,
+               (getprotobyname("tcp")->p_proto));
+
+       if (s < 0) {
+               lprintf(1, "citserver: Can't create a socket: %s\n",
+                       strerror(errno));
+               return(-1);
        }
 
-       if (is_unix) {
-               s = socket(AF_UNIX, SOCK_STREAM, 0);
+       i = 1;
+       setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
+
+       if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+               lprintf(1, "citserver: Can't bind: %s\n",
+                       strerror(errno));
+               return(-1);
        }
-       else {
-               s = socket(PF_INET, SOCK_STREAM,
-                       (getprotobyname("tcp")->p_proto));
+
+       if (listen(s, queue_len) < 0) {
+               lprintf(1, "citserver: Can't listen: %s\n", strerror(errno));
+               return(-1);
        }
 
+       return(s);
+}
+
+
+
+/*
+ * Create a Unix domain socket and listen on it
+ */
+int ig_uds_server(char *sockpath, int queue_len)
+{
+       struct sockaddr_un addr;
+       int s;
+
+       unlink(sockpath);
+
+       memset(&addr, 0, sizeof(addr));
+       addr.sun_family = AF_UNIX;
+       safestrncpy(addr.sun_path, sockpath, sizeof addr.sun_path);
+
+       s = socket(AF_UNIX, SOCK_STREAM, 0);
        if (s < 0) {
                lprintf(1, "citserver: Can't create a socket: %s\n",
                        strerror(errno));
                return(-1);
        }
 
-       /* Set the SO_REUSEADDR socket option, because it makes sense. */
-       if (!is_unix) {
-               i = 1;
-               setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
-       }
-
-       if (is_unix) {
-               if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
-                       lprintf(1, "citserver: Can't bind: %s\n",
-                               strerror(errno));
-                       return(-1);
-               }
-       }
-       else {
-               if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
-                       lprintf(1, "citserver: Can't bind: %s\n",
-                               strerror(errno));
-                       return(-1);
-               }
+       if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+               lprintf(1, "citserver: Can't bind: %s\n",
+                       strerror(errno));
+               return(-1);
        }
 
        if (listen(s, queue_len) < 0) {
@@ -531,7 +537,6 @@ int client_gets(char *buf)
  */
 void sysdep_master_cleanup(void) {
        struct ServiceFunctionHook *serviceptr;
-       char sockpath[256];
 
        /*
         * close all protocol master sockets
@@ -543,10 +548,8 @@ void sysdep_master_cleanup(void) {
                close(serviceptr->msock);
 
                /* If it's a Unix domain socket, remove the file. */
-               if (serviceptr->tcp_port < 0) {
-                       sprintf(sockpath, USOCKPATH, 0-(serviceptr->tcp_port));
-                       lprintf(9, "Removing <%s>\n", sockpath);
-                       unlink(sockpath);
+               if (serviceptr->sockpath != NULL) {
+                       unlink(serviceptr->sockpath);
                }
        }
 }
@@ -867,9 +870,11 @@ int main(int argc, char **argv)
         * Bind the server to our favorite ports.
         */
        CtdlRegisterServiceHook(config.c_port_number,           /* TCP */
+                               NULL,
                                citproto_begin_session,
                                do_command_loop);
-       CtdlRegisterServiceHook(0-config.c_port_number,         /* Unix */
+       CtdlRegisterServiceHook(0,                              /* TCP */
+                               "citadel.socket",
                                citproto_begin_session,
                                do_command_loop);
 
index 4cfdb22973dd8df85c8269170b7dec12f14dfbd3..13d5c931fd240472b716ae1635f3ad9513f8d9fe 100644 (file)
@@ -4,6 +4,7 @@ void init_sysdep (void);
 void begin_critical_section (int which_one);
 void end_critical_section (int which_one);
 int ig_tcp_server (int port_number, int queue_len);
+int ig_uds_server(char *sockpath, int queue_len);
 struct CitContext *MyContext (void);
 struct CitContext *CreateNewContext (void);
 void InitMyContext (struct CitContext *con);