]> arthur.barton.de Git - netatalk.git/blob - libatalk/util/server_ipc.c
AFP 3.x add sleep timeout, add disconnect old session. Björn Fernhomberg and me
[netatalk.git] / libatalk / util / server_ipc.c
1 /*
2  * $Id: server_ipc.c,v 1.1 2003-05-16 15:29:28 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         u_int32_t len;
30         char      *msg;
31 } ipc_header;
32
33 static int pipe_fd[2];
34    
35 void *server_ipc_create(void)
36 {
37     if (pipe(pipe_fd)) {
38         return NULL;
39     }
40     return &pipe_fd;
41 }
42
43 /* ----------------- */
44 int server_ipc_child(void *obj)
45 {
46     /* close input */
47     close(pipe_fd[0]);
48     return pipe_fd[1];
49 }
50
51 /* ----------------- */
52 int server_ipc_parent(void *obj)
53 {
54     return pipe_fd[0];
55 }
56
57 /* ----------------- */
58 int ipc_kill_token (struct ipc_header *ipc, server_child *children)
59 {
60     pid_t pid;
61
62     if (ipc->len != sizeof(pid_t)) {
63         return -1;
64     }
65     /* assume signals SA_RESTART set */
66     memcpy (&pid, ipc->msg, sizeof(pid_t));
67
68     LOG(log_info, logtype_default, "child %d disconnected", pid); 
69     server_child_kill_one(children, CHILD_DSIFORK, pid);
70     return 0;
71 }
72
73 /* ----------------- */
74 int ipc_get_session (struct ipc_header *ipc, server_child *children)
75 {
76     u_int32_t boottime;
77     u_int32_t idlen;
78     char     *clientid, *p;
79
80
81     if (ipc->len < (sizeof(idlen) + sizeof(boottime)) ) {
82         return -1;
83     }
84     p = ipc->msg;
85     memcpy (&idlen, p, sizeof(idlen));
86     idlen = ntohl (idlen);
87     p += sizeof(idlen); 
88
89     memcpy (&boottime, p, sizeof(boottime));
90     p += sizeof(boottime);
91     
92     if (ipc->len < idlen + sizeof(idlen) + sizeof(boottime)) {
93         return -1;
94     }
95     if (NULL == (clientid = (char*) malloc(idlen)) ) {
96         return -1;
97     }
98     memcpy (clientid, p, idlen);
99   
100     server_child_kill_one_by_id (children, CHILD_DSIFORK, ipc->child_pid, idlen, clientid, boottime);
101     /* FIXME byte to ascii if we want to log clientid */
102     LOG (log_info, logtype_afpd, "ipc_get_session: len: %u, idlen %d, time %x", ipc->len, idlen, boottime); 
103     return 0;
104 }
105
106 #define IPC_HEADERLEN 10
107 #define IPC_MAXMSGSIZE 90
108
109 /* ----------------- */
110 int server_ipc_read(server_child *children)
111 {
112     int       ret = 0;
113     struct ipc_header ipc;
114     char      buf[IPC_MAXMSGSIZE], *p;
115
116     if ((ret = read(pipe_fd[0], buf, IPC_HEADERLEN)) != IPC_HEADERLEN) {
117         LOG (log_info, logtype_afpd, "Reading IPC header failed (%u of %u  bytes read)", ret, IPC_HEADERLEN);
118         return -1;
119     } 
120
121     p = buf;
122     memcpy(&ipc.command, p, sizeof(ipc.command));
123     p += sizeof(ipc.command);
124     memcpy(&ipc.child_pid, p, sizeof(ipc.child_pid));
125     p += sizeof(ipc.child_pid);
126     memcpy(&ipc.len, p, sizeof(ipc.len));
127
128     /* This should never happen */
129     if (ipc.len > (IPC_MAXMSGSIZE - IPC_HEADERLEN))
130     {
131         LOG (log_info, logtype_afpd, "IPC message exceeds allowed size (%u)", ipc.len);
132         return -1;
133     }
134
135     memset (buf, 0, IPC_MAXMSGSIZE);
136     if ( ipc.len != 0) {
137             if ((ret = read(pipe_fd[0], buf, ipc.len)) != ipc.len) {
138                 LOG (log_info, logtype_afpd, "Reading IPC message failed (%u of %u  bytes read)", ret, ipc.len);
139                 return -1;
140         }        
141     }
142     ipc.msg = buf;
143     
144     LOG (log_info, logtype_afpd, "ipc_read: command: %u, pid: %u, len: %u", ipc.command, ipc.child_pid, ipc.len); 
145
146     switch (ipc.command)
147     {
148         case IPC_KILLTOKEN:
149                 return (ipc_kill_token(&ipc, children));
150                 break;
151         case IPC_GETSESSION:
152                 return (ipc_get_session(&ipc, children));
153                 break;
154         default:
155                 LOG (log_info, logtype_afpd, "ipc_read: unknown command: %d", ipc.command);
156                 return -1;
157     }
158
159 }
160
161 /* ----------------- */
162 int server_ipc_write( u_int16_t command, int len, void *msg)
163 {
164    char block[IPC_MAXMSGSIZE], *p;
165    pid_t pid;
166    p = block;
167
168    memset ( p, 0 , IPC_MAXMSGSIZE);
169    if (len + IPC_HEADERLEN > IPC_MAXMSGSIZE)
170        return -1;
171
172    memcpy(p, &command, sizeof(command));
173    p   += sizeof(command);
174
175    pid = getpid();
176    memcpy(p, &pid, sizeof(pid_t));
177    p += sizeof(pid_t);
178
179    memcpy(p, &len, 4);
180    p += 4;
181
182    memcpy(p, msg, len);
183
184    LOG (log_info, logtype_afpd, "ipc_write: command: %u, pid: %u, msglen: %u", command, pid, len); 
185    return write(pipe_fd[1], block, len+IPC_HEADERLEN );
186 }
187