Arthur de Jong

Open Source / Free Software developer

summaryrefslogtreecommitdiffstats
path: root/server/nslcd-server.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/nslcd-server.c')
-rw-r--r--server/nslcd-server.c191
1 files changed, 191 insertions, 0 deletions
diff --git a/server/nslcd-server.c b/server/nslcd-server.c
new file mode 100644
index 0000000..7f3c10d
--- /dev/null
+++ b/server/nslcd-server.c
@@ -0,0 +1,191 @@
+/*
+ nslcd-server.c - server socket routines
+
+ Copyright (C) 2006 West Consulting
+ Copyright (C) 2006 Arthur de Jong
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ MA 02110-1301 USA
+*/
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "nslcd-server.h"
+#include "log.h"
+
+
+/* returns a socket ready to answer requests from the client,
+ return <0 on error */
+int nslcd_server_open(void)
+{
+ int sock;
+ /*int flag;*/
+ struct sockaddr_un addr;
+
+ /* create a socket */
+ if ( (sock=socket(PF_UNIX,SOCK_STREAM,0))<0 )
+ {
+ log_log(LOG_ERR,"cannot create socket: %s",strerror(errno));
+ exit(1);
+ }
+
+ /* create socket address structure */
+ memset(&addr,0,sizeof(struct sockaddr_un));
+ addr.sun_family=AF_UNIX;
+ strcpy(addr.sun_path,NSLCD_SOCKET);
+
+ /* unlink to socket */
+ if (unlink(NSLCD_SOCKET)<0)
+ {
+ log_log(LOG_DEBUG,"unlink() of "NSLCD_SOCKET" failed (ignored): %s",
+ strerror(errno));
+ }
+
+ /* bind to the socket */
+ if (bind(sock,(struct sockaddr *)&addr,sizeof(struct sockaddr_un))<0)
+ {
+ log_log(LOG_ERR,"bind() to "NSLCD_SOCKET" failed: %s",
+ strerror(errno));
+ if (close(sock))
+ log_log(LOG_WARNING,"problem closing socket: %s",strerror(errno));
+ exit(1);
+ }
+
+#ifdef NONBLOCKING
+ /* we are going to block for now and implement threading later on */
+ /* do not block on accept() */
+ if ((flag=fcntl(sock,F_GETFL,0))<0)
+ {
+ log_log(LOG_ERR,"fctnl(F_GETFL) failed: %s",strerror(errno));
+ if (close(sock))
+ log_log(LOG_WARNING,"problem closing socket: %s",strerror(errno));
+ exit(1);
+ }
+ if (fcntl(sock,F_SETFL,flag|O_NONBLOCK)<0)
+ {
+ log_log(LOG_ERR,"fctnl(F_SETFL,O_NONBLOCK) failed: %s",strerror(errno));
+ if (close(sock))
+ log_log(LOG_WARNING,"problem closing socket: %s",strerror(errno));
+ exit(1);
+ }
+#endif /* NONBLOCKING */
+
+ /* close the file descriptor on exit */
+ if (fcntl(sock,F_SETFD,FD_CLOEXEC)<0)
+ {
+ log_log(LOG_ERR,"fctnl(F_SETFL,O_NONBLOCK) failed: %s",strerror(errno));
+ if (close(sock))
+ log_log(LOG_WARNING,"problem closing socket: %s",strerror(errno));
+ exit(1);
+ }
+
+#ifdef DONT_FOR_NOW
+ /* Set permissions for the socket. */
+ chmod (_PATH_NSCDSOCKET, DEFFILEMODE);
+#endif /* DONT_FOR_NOW */
+
+ /* start listening for connections */
+ if (listen(sock,SOMAXCONN)<0)
+ {
+ log_log(LOG_ERR,"listen() failed: %s",strerror(errno));
+ if (close(sock))
+ log_log(LOG_WARNING,"problem closing socket: %s",strerror(errno));
+ exit(1);
+ }
+
+ /* we're done */
+ return sock;
+}
+
+/* redifine the ERROR_OUT mechanism */
+#undef ERROR_OUT_READERROR
+#define ERROR_OUT_READERROR(fp) \
+ fclose(fp); \
+ log_log(LOG_DEBUG,"error reading from stream: %s",strerror(errno)); \
+ return;
+
+/* read a request message, returns <0 in case of errors,
+ this function closes the socket */
+void nslcd_server_handlerequest(int sock)
+{
+ int32_t tmpint32;
+ FILE *fp;
+ /* create a stream object */
+ if ((fp=fdopen(sock,"w+"))==NULL)
+ {
+ close(sock);
+ return;
+ }
+ /* read the protocol version */
+ READ_TYPE(fp,tmpint32,int32_t);
+ if (tmpint32 != NSLCD_VERSION)
+ {
+ fclose(fp);
+ log_log(LOG_DEBUG,"wrong nslcd version id (%d)",(int)tmpint32);
+ return;
+ }
+ /* read the request type */
+ READ_TYPE(fp,tmpint32,int32_t);
+ /* handle request */
+ switch (tmpint32)
+ {
+ case NSLCD_ACTION_ALIAS_BYNAME: nslcd_alias_byname(fp); break;
+ case NSLCD_ACTION_ALIAS_ALL: nslcd_alias_all(fp); break;
+ case NSLCD_ACTION_ETHER_BYNAME: nslcd_ether_byname(fp); break;
+ case NSLCD_ACTION_ETHER_BYETHER: nslcd_ether_byether(fp); break;
+ case NSLCD_ACTION_ETHER_ALL: nslcd_ether_all(fp); break;
+ case NSLCD_ACTION_GROUP_BYNAME: nslcd_group_byname(fp); break;
+ case NSLCD_ACTION_GROUP_BYGID: nslcd_group_bygid(fp); break;
+ case NSLCD_ACTION_GROUP_BYMEMBER: nslcd_group_bymember(fp); break;
+ case NSLCD_ACTION_GROUP_ALL: nslcd_group_all(fp); break;
+ case NSLCD_ACTION_HOST_BYNAME: nslcd_host_byname(fp); break;
+ case NSLCD_ACTION_HOST_BYADDR: nslcd_host_byaddr(fp); break;
+ case NSLCD_ACTION_HOST_ALL: nslcd_host_all(fp); break;
+ case NSLCD_ACTION_NETGROUP_BYNAME: nslcd_netgroup_byname(fp); break;
+ case NSLCD_ACTION_NETWORK_BYNAME: nslcd_network_byname(fp); break;
+ case NSLCD_ACTION_NETWORK_BYADDR: nslcd_network_byaddr(fp); break;
+ case NSLCD_ACTION_NETWORK_ALL: nslcd_network_all(fp); break;
+ case NSLCD_ACTION_PASSWD_BYNAME: nslcd_passwd_byname(fp); break;
+ case NSLCD_ACTION_PASSWD_BYUID: nslcd_passwd_byuid(fp); break;
+ case NSLCD_ACTION_PASSWD_ALL: nslcd_passwd_all(fp); break;
+ case NSLCD_ACTION_PROTOCOL_BYNAME: nslcd_protocol_byname(fp); break;
+ case NSLCD_ACTION_PROTOCOL_BYNUMBER:nslcd_protocol_bynumber(fp); break;
+ case NSLCD_ACTION_PROTOCOL_ALL: nslcd_protocol_all(fp); break;
+ case NSLCD_ACTION_RPC_BYNAME: nslcd_rpc_byname(fp); break;
+ case NSLCD_ACTION_RPC_BYNUMBER: nslcd_rpc_bynumber(fp); break;
+ case NSLCD_ACTION_RPC_ALL: nslcd_rpc_all(fp); break;
+ case NSLCD_ACTION_SERVICE_BYNAME: nslcd_service_byname(fp); break;
+ case NSLCD_ACTION_SERVICE_BYNUMBER: nslcd_service_bynumber(fp); break;
+ case NSLCD_ACTION_SERVICE_ALL: nslcd_service_all(fp); break;
+ case NSLCD_ACTION_SHADOW_BYNAME: nslcd_shadow_byname(fp); break;
+ case NSLCD_ACTION_SHADOW_ALL: nslcd_shadow_all(fp); break;
+ default:
+ log_log(LOG_WARNING,"invalid request id: %d",(int)tmpint32);
+ break;
+ }
+ /* we're done with the request */
+ fclose(fp);
+ return;
+}