From 08faf9d912491956b34b48565659e92b67a80575 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Tue, 7 Mar 2000 01:55:45 +0000 Subject: [PATCH] * socket stuff --- citadel/citmail.c | 130 +++++------------------------------------ citadel/dynloader.c | 10 +++- citadel/dynloader.h | 1 + citadel/ipc_c_tcp.c | 68 ++++++++++++--------- citadel/serv_pop3.c | 1 + citadel/serv_smtp.c | 10 +++- citadel/server.h | 1 + citadel/sysdep.c | 97 +++++++++++++++--------------- citadel/sysdep_decls.h | 1 + 9 files changed, 125 insertions(+), 194 deletions(-) diff --git a/citadel/citmail.c b/citadel/citmail.c index 83c54ea66..5a41f2d5a 100644 --- a/citadel/citmail.c +++ b/citadel/citmail.c @@ -17,8 +17,6 @@ #include #include #include -#include -#include #include #include #include @@ -32,10 +30,6 @@ #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); diff --git a/citadel/dynloader.c b/citadel/dynloader.c index be6d6353a..eb521eadd 100644 --- a/citadel/dynloader.c +++ b/citadel/dynloader.c @@ -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; diff --git a/citadel/dynloader.h b/citadel/dynloader.h index 088f4d2fb..1a43066be 100644 --- a/citadel/dynloader.h +++ b/citadel/dynloader.h @@ -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) ) ; diff --git a/citadel/ipc_c_tcp.c b/citadel/ipc_c_tcp.c index 4be220227..befb21afc 100644 --- a/citadel/ipc_c_tcp.c +++ b/citadel/ipc_c_tcp.c @@ -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"); diff --git a/citadel/serv_pop3.c b/citadel/serv_pop3.c index 808f10fac..3112c3ea1 100644 --- a/citadel/serv_pop3.c +++ b/citadel/serv_pop3.c @@ -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); diff --git a/citadel/serv_smtp.c b/citadel/serv_smtp.c index 3174d8932..cda7c3d71 100644 --- a/citadel/serv_smtp.c +++ b/citadel/serv_smtp.c @@ -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$"; diff --git a/citadel/server.h b/citadel/server.h index 10a6f853b..9f69f19bf 100644 --- a/citadel/server.h +++ b/citadel/server.h @@ -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; diff --git a/citadel/sysdep.c b/citadel/sysdep.c index 59de2f8b5..1952c1bb2 100644 --- a/citadel/sysdep.c +++ b/citadel/sysdep.c @@ -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); diff --git a/citadel/sysdep_decls.h b/citadel/sysdep_decls.h index 4cfdb2297..13d5c931f 100644 --- a/citadel/sysdep_decls.h +++ b/citadel/sysdep_decls.h @@ -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); -- 2.39.2