s3-rpc_server: Add generic listener callback.
[idra/samba.git] / source3 / rpc_server / rpc_server.c
1 /*
2    Unix SMB/Netbios implementation.
3    Generic infrstructure for RPC Daemons
4    Copyright (C) Simo Sorce 2010
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "rpc_server/rpc_server.h"
22
23 struct named_pipe_listen_state {
24         int fd;
25         char *name;
26 };
27
28 static void named_pipe_listener(struct tevent_context *ev,
29                                 struct tevent_fd *fde,
30                                 uint16_t flags,
31                                 void *private_data);
32
33 bool setup_named_pipe_socket(const char *pipe_name,
34                              struct tevent_context *ev_ctx)
35 {
36         struct named_pipe_listen_state *state;
37         struct tevent_fd *fde;
38         char *np_dir;
39
40         state = talloc(ev_ctx, struct named_pipe_listen_state);
41         if (!state) {
42                 DEBUG(0, ("Out of memory\n"));
43                 return false;
44         }
45         state->name = talloc_strdup(state, pipe_name);
46         if (!state->name) {
47                 DEBUG(0, ("Out of memory\n"));
48                 goto out;
49         }
50         state->fd = -1;
51
52         np_dir = talloc_asprintf(state, "%s/np", lp_ncalrpc_dir());
53         if (!np_dir) {
54                 DEBUG(0, ("Out of memory\n"));
55                 goto out;
56         }
57
58         if (!directory_create_or_exist(np_dir, geteuid(), 0700)) {
59                 DEBUG(0, ("Failed to create pipe directory %s - %s\n",
60                           np_dir, strerror(errno)));
61                 goto out;
62         }
63
64         state->fd = create_pipe_sock(np_dir, pipe_name, 0700);
65         if (state->fd == -1) {
66                 DEBUG(0, ("Failed to create pipe socket! [%s/%s]\n",
67                           np_dir, pipe_name));
68                 goto out;
69         }
70
71         DEBUG(10, ("Openened pipe socket fd %d for %s\n",
72                    state->fd, pipe_name));
73
74         fde = tevent_add_fd(ev_ctx,
75                             state, state->fd, TEVENT_FD_READ,
76                             named_pipe_listener, state);
77         if (!fde) {
78                 DEBUG(0, ("Failed to add event handler!\n"));
79                 goto out;
80         }
81
82         tevent_fd_set_auto_close(fde);
83         return true;
84
85 out:
86         if (state->fd != -1) {
87                 close(state->fd);
88         }
89         TALLOC_FREE(state);
90         return false;
91 }
92
93 static void named_pipe_accept_function(const char *pipe_name, int fd);
94
95 static void named_pipe_listener(struct tevent_context *ev,
96                                 struct tevent_fd *fde,
97                                 uint16_t flags,
98                                 void *private_data)
99 {
100         struct named_pipe_listen_state *state =
101                         talloc_get_type_abort(private_data,
102                                               struct named_pipe_listen_state);
103         struct sockaddr_un sunaddr;
104         socklen_t len;
105         int sd = -1;
106
107         /* TODO: should we have a limit to the number of clients ? */
108
109         len = sizeof(sunaddr);
110
111         while (sd == -1) {
112                 sd = accept(state->fd,
113                             (struct sockaddr *)(void *)&sunaddr, &len);
114                 if (errno != EINTR) break;
115         }
116
117         if (sd == -1) {
118                 DEBUG(6, ("Failed to get a valid socket [%s]\n",
119                           strerror(errno)));
120                 return;
121         }
122
123         DEBUG(6, ("Accepted socket %d\n", sd));
124
125         named_pipe_accept_function(state->name, sd);
126 }
127
128 static void named_pipe_accept_function(const char *pipe_name, int fd)
129 {
130         return;
131 }