diff options
Diffstat (limited to 'src/server/ipc.c')
-rw-r--r-- | src/server/ipc.c | 240 |
1 files changed, 103 insertions, 137 deletions
diff --git a/src/server/ipc.c b/src/server/ipc.c index 5ee1194..a345794 100644 --- a/src/server/ipc.c +++ b/src/server/ipc.c @@ -60,6 +60,7 @@ static int ipc_receive(int client_sock); static int get_highest_fd(GSList *sockets); static int is_password_correct(xmlDocPtr doc); static int get_terminal_width(); +static int ipc_send_reply(int sock, dnbd3_ipc_t* header, int result_code, xmlDocPtr payload); static int get_highest_fd(GSList *sockets) { @@ -90,7 +91,6 @@ void *dnbd3_ipc_mainloop() return NULL; } -#ifdef IPC_TCP struct sockaddr_in server, client; socklen_t len = sizeof(client); @@ -122,48 +122,6 @@ void *dnbd3_ipc_mainloop() perror("ERROR: IPC listen"); exit(EXIT_FAILURE); } -#else - struct sockaddr_un server, client; - socklen_t len = sizeof(client); - - // Create socket - if ((server_sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) - { - perror("ERROR: IPC socket"); - exit(EXIT_FAILURE); - } - - server.sun_family = AF_UNIX; - strcpy(server.sun_path, UNIX_SOCKET); - unlink(UNIX_SOCKET); - - // Bind to socket - if (bind(server_sock, &server, sizeof(server.sun_family) + strlen(server.sun_path)) < 0) - { - perror("ERROR: IPC bind"); - exit(EXIT_FAILURE); - } - - // Listen on socket - if (listen(server_sock, 5) < 0) - { - perror("ERROR: IPC listen"); - exit(EXIT_FAILURE); - } - - // Set groupID and permissions on ipc socket - struct group *grp; - grp = getgrnam(UNIX_SOCKET_GROUP); - if (grp == NULL) - { - memlogf("WARN: Group '%s' not found.\n", UNIX_SOCKET_GROUP); - } - else - { - chmod(UNIX_SOCKET, 0775); - chown(UNIX_SOCKET, -1, grp->gr_gid); - } -#endif // Run connection-accepting loop @@ -311,12 +269,10 @@ static int ipc_receive(int client_sock) uint32_t cmd; - int ret, locked; + int ret, locked = 0; int return_value = 0; xmlDocPtr docReply = NULL, docRequest = NULL; xmlNodePtr root_node, parent_node, tmp_node, log_parent_node, log_node, server_node; - xmlChar *xmlbuff; - int buffersize; ret = recv(client_sock, &header, sizeof(header), MSG_WAITALL); if (ret != sizeof(header)) @@ -324,7 +280,7 @@ static int ipc_receive(int client_sock) cmd = ntohl(header.cmd); // Leave header.cmd in network byte order for reply header.size = ntohl(header.size); - header.error = htonl(ERROR_UNSPECIFIED_ERROR); // Default value of error, so remember to set it for the reply if call succeeded + int rpc_error = ERROR_UNSPECIFIED_ERROR; // Default value of error, so remember to set it for the reply if call succeeded if (header.size != 0) { @@ -345,28 +301,20 @@ static int ipc_receive(int client_sock) case IPC_EXIT: memlogf("[INFO] Server shutdown by IPC request"); header.size = ntohl(0); - header.error = ntohl(0); return_value = send_data(client_sock, &header, sizeof(header)); dnbd3_cleanup(); break; - case IPC_INFO: - locked = 0; - xmlbuff = NULL; - docReply = xmlNewDoc(BAD_CAST "1.0"); - if (docReply == NULL) - goto get_info_reply_cleanup; - root_node = xmlNewNode(NULL, BAD_CAST "data"); - if (root_node == NULL) - goto get_info_reply_cleanup; - xmlDocSetRootElement(docReply, root_node); + case IPC_IMG_LIST: + if (!createXmlDoc(&docReply, &root_node, "data")) + goto case_end; xmlNewTextChild(root_node, NULL, BAD_CAST "defaultns", BAD_CAST _local_namespace); // Images parent_node = xmlNewNode(NULL, BAD_CAST "images"); if (parent_node == NULL) - goto get_info_reply_cleanup; + goto case_end; xmlAddChild(root_node, parent_node); locked = 1; pthread_spin_lock(&_spinlock); @@ -375,7 +323,7 @@ static int ipc_receive(int client_sock) const dnbd3_image_t *image = iterator->data; tmp_node = xmlNewNode(NULL, BAD_CAST "image"); if (tmp_node == NULL) - goto get_info_reply_cleanup; + goto case_end; xmlNewProp(tmp_node, BAD_CAST "name", BAD_CAST image->config_group); sprintf(strbuffer, "%u", (unsigned int)image->atime); xmlNewProp(tmp_node, BAD_CAST "atime", BAD_CAST strbuffer); @@ -401,10 +349,18 @@ static int ipc_receive(int client_sock) pthread_spin_unlock(&_spinlock); locked = 0; + // Dump and send + rpc_error = 0; + break; + + case IPC_CLIENT_LIST: + if (!createXmlDoc(&docReply, &root_node, "data")) + goto case_end; + // Clients parent_node = xmlNewNode(NULL, BAD_CAST "clients"); if (parent_node == NULL) - goto get_info_reply_cleanup; + goto case_end; xmlAddChild(root_node, parent_node); locked = 1; pthread_spin_lock(&_spinlock); @@ -415,21 +371,31 @@ static int ipc_receive(int client_sock) { tmp_node = xmlNewNode(NULL, BAD_CAST "client"); if (tmp_node == NULL) - goto get_info_reply_cleanup; + goto case_end; *strbuffer = '\0'; host_to_string(&client->host, strbuffer, STRBUFLEN); - xmlNewProp(tmp_node, BAD_CAST "ip", BAD_CAST strbuffer); - xmlNewProp(tmp_node, BAD_CAST "file", BAD_CAST client->image->file); + xmlNewProp(tmp_node, BAD_CAST "address", BAD_CAST strbuffer); + xmlNewProp(tmp_node, BAD_CAST "image", BAD_CAST client->image->config_group); + sprintf(strbuffer, "%d", client->image->rid); + xmlNewProp(tmp_node, BAD_CAST "rid", BAD_CAST strbuffer); xmlAddChild(parent_node, tmp_node); } } pthread_spin_unlock(&_spinlock); locked = 0; + // Dump and send + rpc_error = 0; + break; + + case IPC_TRUSTED_LIST: + if (!createXmlDoc(&docReply, &root_node, "data")) + goto case_end; + // Trusted servers parent_node = xmlNewNode(NULL, BAD_CAST "trusted"); if (parent_node == NULL) - goto get_info_reply_cleanup; + goto case_end; xmlAddChild(root_node, parent_node); locked = 1; pthread_spin_lock(&_spinlock); @@ -440,10 +406,10 @@ static int ipc_receive(int client_sock) { tmp_node = xmlNewNode(NULL, BAD_CAST "server"); if (tmp_node == NULL) - goto get_info_reply_cleanup; + goto case_end; xmlNodePtr namespace_root = xmlNewNode(NULL, BAD_CAST "namespaces"); if (namespace_root == NULL) - goto get_info_reply_cleanup; + goto case_end; host_to_string(&server->host, strbuffer, STRBUFLEN); xmlNewProp(tmp_node, BAD_CAST "address", BAD_CAST strbuffer); if (server->comment) @@ -453,7 +419,7 @@ static int ipc_receive(int client_sock) const dnbd3_namespace_t *ns = iterator2->data; server_node = xmlNewNode(NULL, BAD_CAST "namespace"); if (server_node == NULL) - goto get_info_reply_cleanup; + goto case_end; xmlAddChild(namespace_root, server_node); xmlNewProp(server_node, BAD_CAST "name", BAD_CAST ns->name); if (ns->auto_replicate) @@ -468,44 +434,38 @@ static int ipc_receive(int client_sock) pthread_spin_unlock(&_spinlock); locked = 0; + // Dump and send + rpc_error = 0; + break; + + case IPC_GET_LOG: + if (!createXmlDoc(&docReply, &root_node, "data")) + goto case_end; + // Log log_parent_node = xmlNewChild(root_node, NULL, BAD_CAST "log", NULL); if (log_parent_node == NULL) - goto get_info_reply_cleanup; + goto case_end; char *log = fetchlog(0); if (log == NULL) - log = "LOG IS NULL"; + log = strdup("LOG IS NULL"); log_node = xmlNewCDataBlock(docReply, BAD_CAST log, strlen(log)); + free(log); if (log_node == NULL) - goto get_info_reply_cleanup; + goto case_end; xmlAddChild(log_parent_node, log_node); // Dump and send - xmlDocDumpFormatMemory(docReply, &xmlbuff, &buffersize, 1); - header.size = htonl(buffersize); - header.error = htonl(0); - -get_info_reply_cleanup: - if (locked) - pthread_spin_unlock(&_spinlock); - // Send reply - return_value = send_data(client_sock, &header, sizeof(header)); - if (return_value && xmlbuff) - return_value = send_data(client_sock, xmlbuff, buffersize); - // Cleanup - xmlFree(xmlbuff); - free(log); + rpc_error = 0; break; - case IPC_ADDIMG: - case IPC_DELIMG: + case IPC_ADD_IMG: + case IPC_DEL_IMG: if (docRequest) { if (!is_password_correct(docRequest)) { - header.error = htonl(ERROR_WRONG_PASSWORD); - header.size = htonl(0); - return_value = send_data(client_sock, &header, sizeof(header)); + rpc_error = ERROR_WRONG_PASSWORD; break; } @@ -526,47 +486,42 @@ get_info_reply_cleanup: image.cache_file = (char *)XML_GETPROP(cur, "cache"); if (image.file && !file_exists(image.file)) { - header.error = htonl(ERROR_FILE_NOT_FOUND); + rpc_error = ERROR_FILE_NOT_FOUND; } else if (image.cache_file && !file_writable(image.cache_file)) { - header.error = htonl(ERROR_NOT_WRITABLE); + rpc_error = ERROR_NOT_WRITABLE; } else { if (image.config_group && rid_str) { image.rid = atoi(rid_str); - if (cmd == IPC_ADDIMG) - header.error = htonl(dnbd3_add_image(&image)); + if (cmd == IPC_ADD_IMG) + rpc_error = dnbd3_add_image(&image); else - header.error = htonl(dnbd3_del_image(&image)); + rpc_error = dnbd3_del_image(&image); } else - header.error = htonl(ERROR_MISSING_ARGUMENT); + rpc_error = ERROR_MISSING_ARGUMENT; } FREE_POINTERLIST; } END_FOR_EACH; if (count == 0) - header.error = htonl(ERROR_MISSING_ARGUMENT); + rpc_error = ERROR_MISSING_ARGUMENT; } else - header.error = htonl(ERROR_INVALID_XML); + rpc_error = ERROR_INVALID_XML; - header.size = htonl(0); - printf("Code: %d\n", (int)ntohl(header.error)); - return_value = send_data(client_sock, &header, sizeof(header)); break; - case IPC_ADDNS: - case IPC_DELNS: + case IPC_ADD_NS: + case IPC_DEL_NS: if (docRequest) { if (!is_password_correct(docRequest)) { - header.error = htonl(ERROR_WRONG_PASSWORD); - header.size = htonl(0); - return_value = send_data(client_sock, &header, sizeof(header)); + rpc_error = ERROR_WRONG_PASSWORD; break; } @@ -577,14 +532,14 @@ get_info_reply_cleanup: if (cur->type != XML_ELEMENT_NODE) continue; NEW_POINTERLIST; - char *host = (char *)XML_GETPROP(cur, "server"); + char *host = (char *)XML_GETPROP(cur, "address"); char *ns = (char *)XML_GETPROP(cur, "name"); char *flags = (char *)XML_GETPROP(cur, "flags"); char *comment = (char *)XML_GETPROP(cur, "comment"); pthread_spin_lock(&_spinlock); if (host && ns) { - if (cmd == IPC_ADDNS) + if (cmd == IPC_ADD_NS) { dnbd3_trusted_server_t *server = dnbd3_get_trusted_server(host, TRUE, comment); if (server) @@ -603,20 +558,22 @@ get_info_reply_cleanup: } else - header.error = htonl(ERROR_INVALID_XML); + rpc_error = ERROR_INVALID_XML; - header.size = htonl(0); - return_value = send_data(client_sock, &header, sizeof(header)); break; default: memlogf("[ERROR] Unknown IPC command: %u", (unsigned int)header.cmd); - header.size = htonl(0); - header.error = htonl(ERROR_UNKNOWN_COMMAND); - return_value = send_data(client_sock, &header, sizeof(header)); + rpc_error = htonl(ERROR_UNKNOWN_COMMAND); break; } +case_end: + + if (locked) + pthread_spin_unlock(&_spinlock); + // Send reply + return_value = ipc_send_reply(client_sock, &header, rpc_error, docReply); xmlFreeDoc(docReply); xmlFreeDoc(docRequest); @@ -631,7 +588,6 @@ void dnbd3_ipc_send(int cmd) // Check version and initialize LIBXML_TEST_VERSION -#ifdef IPC_TCP struct sockaddr_in server; struct timeval client_timeout; @@ -658,38 +614,17 @@ void dnbd3_ipc_send(int cmd) perror("ERROR: IPC connect"); exit(EXIT_FAILURE); } -#else - struct sockaddr_un server; - - // Create socket - if ((client_sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) - { - perror("ERROR: IPC socket"); - exit(EXIT_FAILURE); - } - server.sun_family = AF_UNIX; - strcpy(server.sun_path, UNIX_SOCKET); - - // Connect to server - if (connect(client_sock, &server, sizeof(server.sun_family) + strlen(server.sun_path)) < 0) - { - perror("ERROR: IPC connect"); - exit(EXIT_FAILURE); - } -#endif // Send message dnbd3_ipc_t header; header.cmd = htonl(cmd); header.size = 0; - header.error = 0; send(client_sock, (char *)&header, sizeof(header), MSG_WAITALL); recv(client_sock, &header, sizeof(header), MSG_WAITALL); header.cmd = ntohl(header.cmd); header.size = ntohl(header.size); - header.error = ntohl(header.error); - if (cmd == IPC_INFO && header.size > 0) + if (cmd == IPC_IMG_LIST && header.size > 0) { char *buf = malloc(header.size + 1); size = recv(client_sock, buf, header.size, MSG_WAITALL); @@ -853,3 +788,34 @@ static int get_terminal_width() return 80; return w.ws_col; } + +#define RETBUFLEN 8000 +static char returnbuffer[RETBUFLEN]; +static int ipc_send_reply(int sock, dnbd3_ipc_t* header, int result_code, xmlDocPtr payload) +{ + if (result_code == 0 && payload != NULL) + { + // No error + xmlChar *xmlbuff = NULL; + int buffersize; + xmlDocDumpFormatMemory(payload, &xmlbuff, &buffersize, 1); + header->size = htonl(buffersize); + if (!send_data(sock, header, sizeof(*header))) + return FALSE; + if (xmlbuff) + return send_data(sock, xmlbuff, buffersize); + return TRUE; + } + // Error code, build xml struct (lazy shortcut) + int len = snprintf(returnbuffer, RETBUFLEN, "<?xml version=\"1.0\"?>\n" + "<data>\n" + "<result retcode=\"%d\" retstr=\"%s\">\n" + "</data>", result_code, "TODO"); + if (len >= RETBUFLEN) + len = 10; + header->size = htonl(len); + header->cmd = htonl(IPC_ERROR); + if (!send_data(sock, header, sizeof(*header))) + return FALSE; + return send_data(sock, returnbuffer, len); +} |