2 * All rights reserved. See COPYRIGHT.
18 #include <atalk/server_child.h>
19 #include <atalk/server_ipc.h>
20 #include <atalk/logger.h>
22 typedef struct ipc_header {
30 static int pipe_fd[2];
32 void *server_ipc_create(void)
40 /* ----------------- */
41 int server_ipc_child(void *obj _U_)
48 /* ----------------- */
49 int server_ipc_parent(void *obj _U_)
54 /* ----------------- */
55 static int ipc_kill_token (struct ipc_header *ipc, server_child *children)
59 if (ipc->len != sizeof(pid_t)) {
62 /* assume signals SA_RESTART set */
63 memcpy (&pid, ipc->msg, sizeof(pid_t));
65 LOG(log_info, logtype_default, "child %d user %d disconnected", pid, ipc->uid);
66 server_child_kill_one(children, CHILD_DSIFORK, pid, ipc->uid);
70 /* ----------------- */
71 static int ipc_get_session (struct ipc_header *ipc, server_child *children)
78 if (ipc->len < (sizeof(idlen) + sizeof(boottime)) ) {
82 memcpy (&idlen, p, sizeof(idlen));
83 idlen = ntohl (idlen);
86 memcpy (&boottime, p, sizeof(boottime));
87 p += sizeof(boottime);
89 if (ipc->len < idlen + sizeof(idlen) + sizeof(boottime)) {
92 if (NULL == (clientid = (char*) malloc(idlen)) ) {
95 memcpy (clientid, p, idlen);
97 server_child_kill_one_by_id (children, CHILD_DSIFORK, ipc->child_pid, ipc->uid, idlen, clientid, boottime);
98 /* FIXME byte to ascii if we want to log clientid */
99 LOG (log_debug, logtype_afpd, "ipc_get_session: len: %u, idlen %d, time %x", ipc->len, idlen, boottime);
103 #define IPC_HEADERLEN 14
104 #define IPC_MAXMSGSIZE 90
113 int server_ipc_read(server_child *children)
116 struct ipc_header ipc;
117 char buf[IPC_MAXMSGSIZE], *p;
119 if ((ret = read(pipe_fd[0], buf, IPC_HEADERLEN)) != IPC_HEADERLEN) {
120 LOG (log_info, logtype_afpd, "Reading IPC header failed (%u of %u bytes read)", ret, IPC_HEADERLEN);
126 memcpy(&ipc.command, p, sizeof(ipc.command));
127 p += sizeof(ipc.command);
129 memcpy(&ipc.child_pid, p, sizeof(ipc.child_pid));
130 p += sizeof(ipc.child_pid);
132 memcpy(&ipc.uid, p, sizeof(ipc.uid));
133 p += sizeof(ipc.uid);
135 memcpy(&ipc.len, p, sizeof(ipc.len));
137 /* This should never happen */
138 if (ipc.len > (IPC_MAXMSGSIZE - IPC_HEADERLEN))
140 LOG (log_info, logtype_afpd, "IPC message exceeds allowed size (%u)", ipc.len);
144 memset (buf, 0, IPC_MAXMSGSIZE);
146 if ((ret = read(pipe_fd[0], buf, ipc.len)) != (int) ipc.len) {
147 LOG (log_info, logtype_afpd, "Reading IPC message failed (%u of %u bytes read)", ret, ipc.len);
153 LOG (log_debug, logtype_afpd, "ipc_read: command: %u, pid: %u, len: %u", ipc.command, ipc.child_pid, ipc.len);
158 return (ipc_kill_token(&ipc, children));
161 return (ipc_get_session(&ipc, children));
164 LOG (log_info, logtype_afpd, "ipc_read: unknown command: %d", ipc.command);
170 /* ----------------- */
171 int server_ipc_write( u_int16_t command, int len, void *msg)
173 char block[IPC_MAXMSGSIZE], *p;
178 memset ( p, 0 , IPC_MAXMSGSIZE);
179 if (len + IPC_HEADERLEN > IPC_MAXMSGSIZE)
182 memcpy(p, &command, sizeof(command));
183 p += sizeof(command);
186 memcpy(p, &pid, sizeof(pid_t));
190 * using uid is wrong. It will not disconnect if the new connection
191 * is with a different user.
192 * But we really don't want a remote kill command.
195 memcpy(p, &uid, sizeof(uid_t));
203 LOG (log_debug, logtype_afpd, "ipc_write: command: %u, pid: %u, msglen: %u", command, pid, len);
204 return write(pipe_fd[1], block, len+IPC_HEADERLEN );