]> arthur.barton.de Git - netatalk.git/blob - libatalk/util/server_ipc.c
afpd set the logger default to log_info and move some log msgs to log_debug
[netatalk.git] / libatalk / util / server_ipc.c
1 /*
2  * $Id: server_ipc.c,v 1.4 2010-01-21 14:14:49 didg Exp $
3  *
4  * All rights reserved. See COPYRIGHT.
5  *
6  *
7  * ipc between parent and children.
8  */
9
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif 
13
14 #include <sys/types.h>
15 #ifdef HAVE_UNISTD_H
16 #include <unistd.h>
17 #endif 
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21
22 #include <atalk/server_child.h>
23 #include <atalk/server_ipc.h>
24 #include <atalk/logger.h>
25
26 typedef struct ipc_header {
27         u_int16_t command;
28         pid_t     child_pid;
29         uid_t     uid;
30         u_int32_t len;
31         char      *msg;
32 } ipc_header;
33
34 static int pipe_fd[2];
35    
36 void *server_ipc_create(void)
37 {
38     if (pipe(pipe_fd)) {
39         return NULL;
40     }
41     return &pipe_fd;
42 }
43
44 /* ----------------- */
45 int server_ipc_child(void *obj _U_)
46 {
47     /* close input */
48     close(pipe_fd[0]);
49     return pipe_fd[1];
50 }
51
52 /* ----------------- */
53 int server_ipc_parent(void *obj _U_)
54 {
55     return pipe_fd[0];
56 }
57
58 /* ----------------- */
59 static int ipc_kill_token (struct ipc_header *ipc, server_child *children)
60 {
61     pid_t pid;
62
63     if (ipc->len != sizeof(pid_t)) {
64         return -1;
65     }
66     /* assume signals SA_RESTART set */
67     memcpy (&pid, ipc->msg, sizeof(pid_t));
68
69     LOG(log_info, logtype_default, "child %d user %d disconnected", pid, ipc->uid);
70     server_child_kill_one(children, CHILD_DSIFORK, pid, ipc->uid);
71     return 0;
72 }
73
74 /* ----------------- */
75 static int ipc_get_session (struct ipc_header *ipc, server_child *children)
76 {
77     u_int32_t boottime;
78     u_int32_t idlen;
79     char     *clientid, *p;
80
81
82     if (ipc->len < (sizeof(idlen) + sizeof(boottime)) ) {
83         return -1;
84     }
85     p = ipc->msg;
86     memcpy (&idlen, p, sizeof(idlen));
87     idlen = ntohl (idlen);
88     p += sizeof(idlen); 
89
90     memcpy (&boottime, p, sizeof(boottime));
91     p += sizeof(boottime);
92     
93     if (ipc->len < idlen + sizeof(idlen) + sizeof(boottime)) {
94         return -1;
95     }
96     if (NULL == (clientid = (char*) malloc(idlen)) ) {
97         return -1;
98     }
99     memcpy (clientid, p, idlen);
100   
101     server_child_kill_one_by_id (children, CHILD_DSIFORK, ipc->child_pid, ipc->uid, idlen, clientid, boottime);
102     /* FIXME byte to ascii if we want to log clientid */
103     LOG (log_debug, logtype_afpd, "ipc_get_session: len: %u, idlen %d, time %x", ipc->len, idlen, boottime); 
104     return 0;
105 }
106
107 #define IPC_HEADERLEN 14
108 #define IPC_MAXMSGSIZE 90
109
110 /* ----------------- 
111  * Ipc format
112  * command
113  * pid
114  * uid
115  * 
116 */
117 int server_ipc_read(server_child *children)
118 {
119     int       ret = 0;
120     struct ipc_header ipc;
121     char      buf[IPC_MAXMSGSIZE], *p;
122
123     if ((ret = read(pipe_fd[0], buf, IPC_HEADERLEN)) != IPC_HEADERLEN) {
124         LOG (log_info, logtype_afpd, "Reading IPC header failed (%u of %u  bytes read)", ret, IPC_HEADERLEN);
125         return -1;
126     } 
127
128     p = buf;
129
130     memcpy(&ipc.command, p, sizeof(ipc.command));
131     p += sizeof(ipc.command);
132
133     memcpy(&ipc.child_pid, p, sizeof(ipc.child_pid));
134     p += sizeof(ipc.child_pid);
135
136     memcpy(&ipc.uid, p, sizeof(ipc.uid));
137     p += sizeof(ipc.uid);
138
139     memcpy(&ipc.len, p, sizeof(ipc.len));
140
141     /* This should never happen */
142     if (ipc.len > (IPC_MAXMSGSIZE - IPC_HEADERLEN))
143     {
144         LOG (log_info, logtype_afpd, "IPC message exceeds allowed size (%u)", ipc.len);
145         return -1;
146     }
147
148     memset (buf, 0, IPC_MAXMSGSIZE);
149     if ( ipc.len != 0) {
150             if ((ret = read(pipe_fd[0], buf, ipc.len)) != (int) ipc.len) {
151                 LOG (log_info, logtype_afpd, "Reading IPC message failed (%u of %u  bytes read)", ret, ipc.len);
152                 return -1;
153         }        
154     }
155     ipc.msg = buf;
156     
157     LOG (log_debug, logtype_afpd, "ipc_read: command: %u, pid: %u, len: %u", ipc.command, ipc.child_pid, ipc.len); 
158
159     switch (ipc.command)
160     {
161         case IPC_KILLTOKEN:
162                 return (ipc_kill_token(&ipc, children));
163                 break;
164         case IPC_GETSESSION:
165                 return (ipc_get_session(&ipc, children));
166                 break;
167         default:
168                 LOG (log_info, logtype_afpd, "ipc_read: unknown command: %d", ipc.command);
169                 return -1;
170     }
171
172 }
173
174 /* ----------------- */
175 int server_ipc_write( u_int16_t command, int len, void *msg)
176 {
177    char block[IPC_MAXMSGSIZE], *p;
178    pid_t pid;
179    uid_t uid;
180    p = block;
181
182    memset ( p, 0 , IPC_MAXMSGSIZE);
183    if (len + IPC_HEADERLEN > IPC_MAXMSGSIZE)
184        return -1;
185
186    memcpy(p, &command, sizeof(command));
187    p   += sizeof(command);
188
189    pid = getpid();
190    memcpy(p, &pid, sizeof(pid_t));
191    p += sizeof(pid_t);
192    
193    /* FIXME 
194     * using uid is wrong. It will not disconnect if the new connection
195     * is with a different user. 
196     * But we really don't want a remote kill command.
197    */
198    uid = geteuid();
199    memcpy(p, &uid, sizeof(uid_t));
200    p += sizeof(uid_t);
201
202    memcpy(p, &len, 4);
203    p += 4;
204
205    memcpy(p, msg, len);
206
207    LOG (log_debug, logtype_afpd, "ipc_write: command: %u, pid: %u, msglen: %u", command, pid, len); 
208    return write(pipe_fd[1], block, len+IPC_HEADERLEN );
209 }
210