#include <atalk/compat.h>
#include <atalk/util.h>
#include <atalk/uuid.h>
+#include <atalk/paths.h>
+#include <atalk/server_ipc.h>
#include "globals.h"
#include "switch.h"
u_int32_t err, cmd;
u_int8_t function;
struct sigaction action;
+ struct pollfd pollfds[1];
AFPobj = obj;
obj->exit = afp_dsi_die;
obj->attention = (int (*)(void *, AFPUserBytes)) dsi_attention;
dsi->tickle = 0;
+ pollfds[0].fd = obj->ipc_fd;
+ pollfds[0].events = POLLOUT;
+
memset(&action, 0, sizeof(action));
/* install SIGHUP */
* or a primary reconnect succeeds */
}
+ static int saved_ipcfd = -1;
+ if (saved_ipcfd == -1)
+ saved_ipcfd = obj->ipc_fd;
+ if (poll(pollfds, 1, 0) == 1) {
+ if (pollfds[0].revents & (POLLHUP | POLLERR)) {
+ if (saved_ipcfd == obj->ipc_fd && getppid() == 1) {
+ close(obj->ipc_fd);
+ sleep(30); /* give it enough time to start */
+ if ((obj->ipc_fd = ipc_client_uds(_PATH_AFP_IPC)) == -1) {
+ LOG(log_error, logtype_afpd, "afp_over_dsi: cant reconnect to master");
+ afp_dsi_die(EXITERR_SYS);
+ }
+ }
+ }
+ }
+
+
if (!(dsi->flags & DSI_EXTSLEEP) && (dsi->flags & DSI_SLEEPING)) {
LOG(log_debug, logtype_afpd, "afp_over_dsi: got data, ending normal sleep");
dsi->flags &= ~DSI_SLEEPING;
if (ibuflen < idlen || idlen > (90-10)) {
return AFPERR_PARAM;
}
- ipc_child_write(obj->ipc_fd, IPC_GETSESSION, idlen+8, p);
+ if (!obj->sinfo.clientid) {
+ obj->sinfo.clientid = malloc(idlen + 8);
+ memcpy(obj->sinfo.clientid, p, idlen + 8);
+ }
+ if (ipc_child_write(&obj->ipc_fd, IPC_GETSESSION, idlen+8, p) == -1) {
+
+ }
tklen = obj->sinfo.sessiontoken_len;
token = obj->sinfo.sessiontoken;
}
setitimer(ITIMER_REAL, &none, NULL);
/* check for old session, possibly transfering session from here to there */
- if (ipc_child_write(obj->ipc_fd, IPC_DISCOLDSESSION, tklen, &token) == -1)
+ if (ipc_child_write(&obj->ipc_fd, IPC_DISCOLDSESSION, tklen, &token) == -1)
goto exit;
/* write uint16_t DSI request ID */
if (writet(obj->ipc_fd, &dsi->header.dsi_requestID, 2, 0, 2) != 2) {
#define IPC_GETSESSION 1
extern int ipc_server_uds(const char *name);
+extern int ipc_client_uds(const char *name);
extern int ipc_server_read(server_child *children, int fd);
-extern int ipc_child_write(int fd, uint16_t command, int len, void *token);
+extern ssize_t ipc_child_write(int *fd, uint16_t command, int len, void *token);
#endif /* IPC_GETSESSION_LOGIN */
size_t cryptedkey_len;
void *sessiontoken; /* session token sent to the client on FPGetSessionToken*/
size_t sessiontoken_len;
+ void *clientid; /* whole buffer cotaining eg idlen, id and boottime */
+ size_t clientid_len;
};
/* register and unregister uams with these functions */
#include <atalk/logger.h>
#include <atalk/util.h>
#include <atalk/errchk.h>
+#include <atalk/paths.h>
#define IPC_HEADERLEN 14
#define IPC_MAXMSGSIZE 90
***********************************************************************************/
/*!
- * Listen on UNIX domain socket "name" for IPD from old sesssion
+ * Listen on UNIX domain socket "name" for IPC from old sesssion
*
* @args name (r) file name to use for UNIX domain socket
* @returns socket fd, -1 on error
EC_CLEANUP:
if (ret != 0) {
-
return -1;
}
LOG(log_note, logtype_afpd, "ipc_server_uds: fd: %d", fd);
return fd;
}
+/*!
+ * Connect to UNIX domain socket "name" for IPC with new afpd master
+ *
+ * 1. Connect
+ * 2. send pid, which establishes a child structure for us in the master
+ *
+ * @args name (r) file name to use for UNIX domain socket
+ * @returns socket fd, -1 on error
+ */
+int ipc_client_uds(const char *name)
+{
+ EC_INIT;
+ struct sockaddr_un address;
+ socklen_t address_length;
+ int fd = -1;
+ pid_t pid = getpid();
+
+ EC_NEG1_LOG( fd = socket(PF_UNIX, SOCK_STREAM, 0) );
+ EC_ZERO_LOG( setnonblock(fd, 1) );
+ address.sun_family = AF_UNIX;
+ address_length = sizeof(address.sun_family) + sprintf(address.sun_path, name);
+
+ EC_ZERO_LOG( connect(fd, (struct sockaddr *)&address, address_length) ); /* 1 */
+
+ if (writet(fd, &pid, sizeof(pid_t), 0, 1) != sizeof(pid_t)) {
+ LOG(log_error, logtype_afpd, "ipc_client_uds: writet: %s", strerror(errno));
+ EC_FAIL;
+ }
+
+EC_CLEANUP:
+ if (ret != 0) {
+ return -1;
+ }
+ LOG(log_note, logtype_afpd, "ipc_client_uds: fd: %d", fd);
+ return fd;
+}
+
/* -----------------
* Ipc format
* command
}
/* ----------------- */
-int ipc_child_write(int fd, uint16_t command, int len, void *msg)
+ssize_t ipc_child_write(int *fd, uint16_t command, int len, void *msg)
{
+ static int fd_saved = -1;
char block[IPC_MAXMSGSIZE], *p;
pid_t pid;
uid_t uid;
+ ssize_t ret;
+
p = block;
+ if (fd_saved == -1)
+ fd_saved = *fd;
+
memset ( p, 0 , IPC_MAXMSGSIZE);
if (len + IPC_HEADERLEN > IPC_MAXMSGSIZE)
return -1;
LOG(log_debug, logtype_afpd, "ipc_child_write(%s)", ipc_cmd_str[command]);
- return write(fd, block, len+IPC_HEADERLEN );
+ if ((ret = writet(*fd, block, len+IPC_HEADERLEN, 0, 1)) == -1) {
+ if (*fd == fd_saved && getppid() == 1) {
+ /* still using original socketpair IPC fd, master was possibly restarted, try reestablish connection across uds */
+ if ((*fd = ipc_client_uds(_PATH_AFP_IPC)) == -1)
+ return -1;
+ /* now try again */
+ ret = writet(*fd, block, len+IPC_HEADERLEN, 0, 1);
+ }
+ }
+
+ return ret;
}