diff options
Diffstat (limited to 'src/server/ipc.c')
-rw-r--r-- | src/server/ipc.c | 240 |
1 files changed, 145 insertions, 95 deletions
diff --git a/src/server/ipc.c b/src/server/ipc.c index 38066c8..ebc907b 100644 --- a/src/server/ipc.c +++ b/src/server/ipc.c @@ -25,6 +25,7 @@ #include <sys/stat.h> #include <grp.h> #include <stdlib.h> +#include <sys/ioctl.h> #include <unistd.h> #include <pthread.h> #include <netinet/in.h> @@ -34,6 +35,7 @@ #include <libxml/parser.h> #include <libxml/xpath.h> +#include "xmlutil.h" #include "ipc.h" #include "../config.h" @@ -41,14 +43,24 @@ #include "utils.h" #include "memlog.h" +#define IPC_PORT (PORT+1) + static int server_sock = -1; static volatile int keep_running = 1; static char *payload = NULL; +#define char_repeat_br(_c, _times) do { \ + int _makro_i_ = (_times); \ + while (--_makro_i_ >= 0) putchar(_c); \ + putchar('\n'); \ +} while (0) + static int ipc_receive(int client_sock); static int get_highest_fd(GSList *sockets); static int send_reply(int client_sock, void *data_in, int len); static int recv_data(int client_sock, void *buffer_out, int len); +static int is_password_correct(xmlDocPtr doc); +static int get_terminal_width(); static int get_highest_fd(GSList *sockets) { @@ -67,7 +79,11 @@ static int get_highest_fd(GSList *sockets) void *dnbd3_ipc_mainloop() { - payload = malloc(MAX_PAYLOAD); + + // Check version and initialize + LIBXML_TEST_VERSION + + payload = malloc(MAX_IPC_PAYLOAD); if (payload == NULL) { memlogf("[CRITICAL] Couldn't allocate IPC payload buffer. IPC disabled."); @@ -173,8 +189,6 @@ void *dnbd3_ipc_mainloop() flags = 0; fcntl(server_sock, F_SETFL, flags | O_NONBLOCK); - xmlInitParser(); - while (keep_running) { readset = exceptset = all_sockets; @@ -358,7 +372,7 @@ static int ipc_receive(int client_sock) int ret, locked; int return_value = 0; - xmlDocPtr doc = NULL; + xmlDocPtr docReply = NULL, docRequest = NULL; xmlNodePtr root_node, images_node, clients_node, tmp_node, log_parent_node, log_node; xmlChar *xmlbuff; int buffersize; @@ -374,7 +388,7 @@ static int ipc_receive(int client_sock) if (header.size != 0) { // Message has payload, receive it - if (header.size > MAX_PAYLOAD) + if (header.size > MAX_IPC_PAYLOAD) { memlogf("[WARNING] IPC command with payload of %u bytes ignored.", (unsigned int)header.size); return 0; @@ -396,13 +410,13 @@ static int ipc_receive(int client_sock) case IPC_INFO: locked = 0; xmlbuff = NULL; - doc = xmlNewDoc(BAD_CAST "1.0"); - if (doc == NULL) + docReply = xmlNewDoc(BAD_CAST "1.0"); + if (docReply == NULL) goto get_info_reply_cleanup; - root_node = xmlNewNode(NULL, BAD_CAST "info"); + root_node = xmlNewNode(NULL, BAD_CAST "data"); if (root_node == NULL) goto get_info_reply_cleanup; - xmlDocSetRootElement(doc, root_node); + xmlDocSetRootElement(docReply, root_node); // Images images_node = xmlNewNode(NULL, BAD_CAST "images"); @@ -420,7 +434,7 @@ static int ipc_receive(int client_sock) tmp_node = xmlNewNode(NULL, BAD_CAST "image"); if (tmp_node == NULL) goto get_info_reply_cleanup; - xmlNewProp(tmp_node, BAD_CAST "name", BAD_CAST image->name); + xmlNewProp(tmp_node, BAD_CAST "name", BAD_CAST image->config_group); xmlNewProp(tmp_node, BAD_CAST "atime", BAD_CAST time_buff); xmlNewProp(tmp_node, BAD_CAST "rid", BAD_CAST rid); xmlNewProp(tmp_node, BAD_CAST "file", BAD_CAST image->file); @@ -458,13 +472,13 @@ static int ipc_receive(int client_sock) char *log = fetchlog(0); if (log == NULL) log = "LOG IS NULL"; - log_node = xmlNewCDataBlock(doc, BAD_CAST log, strlen(log)); + log_node = xmlNewCDataBlock(docReply, BAD_CAST log, strlen(log)); if (log_node == NULL) goto get_info_reply_cleanup; xmlAddChild(log_parent_node, log_node); // Dump and send - xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1); + xmlDocDumpFormatMemory(docReply, &xmlbuff, &buffersize, 1); header.size = htonl(buffersize); header.error = htonl(0); @@ -477,7 +491,6 @@ get_info_reply_cleanup: return_value = send_reply(client_sock, xmlbuff, buffersize); // Cleanup xmlFree(xmlbuff); - xmlFreeDoc(doc); free(log); break; @@ -490,55 +503,50 @@ get_info_reply_cleanup: return_value = send_reply(client_sock, &header, sizeof(header)); break; } - doc = xmlReadMemory(payload, header.size, "noname.xml", NULL, 0); + docRequest = xmlReadMemory(payload, header.size, "noname.xml", NULL, 0); - if (doc) + if (docRequest) { - xmlXPathContextPtr xpathCtx = NULL; - xmlXPathObjectPtr xpathObj = NULL; - xmlNodeSetPtr nodes = NULL; + if (!is_password_correct(docRequest)) + { + header.error = htonl(ERROR_WRONG_PASSWORD); + header.size = htonl(0); + return_value = send_reply(client_sock, &header, sizeof(header)); + break; + } + xmlNodePtr cur = NULL; + int count = 0; - xpathCtx = xmlXPathNewContext(doc); - if (xpathCtx == NULL) - goto add_del_cleanup; - xpathObj = xmlXPathEvalExpression(BAD_CAST "/info/images/image", xpathCtx); - if (xpathObj == NULL) - goto add_del_cleanup; - nodes = xpathObj->nodesetval; - if (nodes == NULL || nodes->nodeNr < 1) - goto add_del_cleanup; - cur = nodes->nodeTab[0]; - if (cur->type == XML_ELEMENT_NODE) + FOR_EACH_NODE(docRequest, "/data/images/image", cur) { - dnbd3_image_t image; - memset(&image, 0, sizeof(dnbd3_image_t)); - image.name = (char *)xmlGetNoNsProp(cur, BAD_CAST "name"); - char *rid_str = (char *)xmlGetNoNsProp(cur, BAD_CAST "rid"); - image.file = (char *)xmlGetNoNsProp(cur, BAD_CAST "file"); - image.cache_file = (char *)xmlGetNoNsProp(cur, BAD_CAST "cache"); - if (image.name && rid_str && image.file && image.cache_file) + if (cur->type == XML_ELEMENT_NODE) { - image.rid = atoi(rid_str); - if (cmd == IPC_ADDIMG) - header.error = htonl(dnbd3_add_image(&image)); + ++count; + dnbd3_image_t image; + memset(&image, 0, sizeof(dnbd3_image_t)); + image.config_group = (char *)xmlGetNoNsProp(cur, BAD_CAST "name"); + char *rid_str = (char *)xmlGetNoNsProp(cur, BAD_CAST "rid"); + image.file = (char *)xmlGetNoNsProp(cur, BAD_CAST "file"); + image.cache_file = (char *)xmlGetNoNsProp(cur, BAD_CAST "cache"); + if (image.config_group && rid_str && image.file && image.cache_file) + { + image.rid = atoi(rid_str); + if (cmd == IPC_ADDIMG) + header.error = htonl(dnbd3_add_image(&image)); + else + header.error = htonl(dnbd3_del_image(&image)); + } else - header.error = htonl(dnbd3_del_image(&image)); + header.error = htonl(ERROR_MISSING_ARGUMENT); + xmlFree(image.config_group); + xmlFree(rid_str); + xmlFree(image.file); + xmlFree(image.cache_file); } - else - header.error = htonl(ERROR_MISSING_ARGUMENT); - xmlFree(image.name); - xmlFree(rid_str); - xmlFree(image.file); - xmlFree(image.cache_file); - } - else + } END_FOR_EACH; + if (count == 0) header.error = htonl(ERROR_MISSING_ARGUMENT); - -add_del_cleanup: - xmlXPathFreeObject(xpathObj); - xmlXPathFreeContext(xpathCtx); - xmlFreeDoc(doc); } else header.error = htonl(ERROR_INVALID_XML); @@ -555,6 +563,10 @@ add_del_cleanup: break; } + + xmlFreeDoc(docReply); + xmlFreeDoc(docRequest); + return return_value; } @@ -562,6 +574,9 @@ void dnbd3_ipc_send(int cmd) { int client_sock, size; + // Check version and initialize + LIBXML_TEST_VERSION + #ifdef IPC_TCP struct sockaddr_in server; struct timeval client_timeout; @@ -629,72 +644,76 @@ void dnbd3_ipc_send(int cmd) if (doc) { - int n, i; - - xmlXPathContextPtr xpathCtx; - xmlXPathObjectPtr xpathObj; - xmlChar *xpathExpr; - xmlNodeSetPtr nodes; + int count; + int term_width = get_terminal_width(); xmlNodePtr cur; // Print log - xpathExpr = BAD_CAST "/info/log"; - xpathCtx = xmlXPathNewContext(doc); - xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx); - if (xpathObj->nodesetval && xpathObj->nodesetval->nodeTab && xpathObj->nodesetval->nodeTab[0]) + xmlChar *log = getTextFromPath(doc, "/data/log"); + if (log) { - printf("--- Last log lines ----\n%s\n\n", xmlNodeGetContent(xpathObj->nodesetval->nodeTab[0])); + printf("--- Last log lines ----\n%s\n\n", log); } - xmlXPathFreeObject(xpathObj); - xmlXPathFreeContext(xpathCtx); + + int watime = 0, wname = 0, wrid = 5; + FOR_EACH_NODE(doc, "/data/images/image", cur) + { + if (cur->type == XML_ELEMENT_NODE) + { + xmlChar *atime = xmlGetNoNsProp(cur, BAD_CAST "atime"); + xmlChar *vid = xmlGetNoNsProp(cur, BAD_CAST "name"); + xmlChar *rid = xmlGetNoNsProp(cur, BAD_CAST "rid"); + watime = MAX(watime, xmlStrlen(atime)); + wname = MAX(wname, xmlStrlen(vid)); + wrid = MAX(wrid, xmlStrlen(rid)); + // Too lazy to free vars, client will exit anyways + } + } END_FOR_EACH; + + char format[100]; + snprintf(format, 100, + "%%-%ds %%-%ds %%%ds %%s\n", watime, wname, wrid); // Print images - xpathExpr = BAD_CAST "/info/images/image"; - xpathCtx = xmlXPathNewContext(doc); - xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx); - printf("Exported images (atime, name, rid, file):\n"); - printf("========================================\n"); - nodes = xpathObj->nodesetval; - n = (nodes) ? nodes->nodeNr : 0; - for (i = 0; i < n; ++i) + printf("Exported images\n"); + printf(format, "atime", "name", "rid", "file"); + char_repeat_br('=', term_width); + count = 0; + FOR_EACH_NODE(doc, "/data/images/image", cur) { - if (nodes->nodeTab[i]->type == XML_ELEMENT_NODE) + if (cur->type == XML_ELEMENT_NODE) { - cur = nodes->nodeTab[i]; + ++count; xmlChar *atime = xmlGetNoNsProp(cur, BAD_CAST "atime"); xmlChar *vid = xmlGetNoNsProp(cur, BAD_CAST "name"); xmlChar *rid = xmlGetNoNsProp(cur, BAD_CAST "rid"); xmlChar *file = xmlGetNoNsProp(cur, BAD_CAST "file"); - printf("%s\t%s\t%s\t%s\n", atime, vid, rid, file); + printf(format, atime, vid, rid, file); + // Too lazy to free vars, client will exit anyways } - } - printf("\nNumber images: %d\n\n", n); - xmlXPathFreeObject(xpathObj); - xmlXPathFreeContext(xpathCtx); + } END_FOR_EACH; + char_repeat_br('=', term_width); + printf("\nNumber of images: %d\n\n", count); // Print clients - xpathExpr = BAD_CAST "/info/clients/client"; - xpathCtx = xmlXPathNewContext(doc); - xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx); printf("Connected clients (ip, file):\n"); - printf("=============================\n"); - nodes = xpathObj->nodesetval; - n = (nodes) ? nodes->nodeNr : 0; - for (i = 0; i < n; ++i) + char_repeat_br('=', term_width); + count = 0; + FOR_EACH_NODE(doc, "/data/clients/client", cur) { - if (nodes->nodeTab[i]->type == XML_ELEMENT_NODE) + if (cur->type == XML_ELEMENT_NODE) { - cur = nodes->nodeTab[i]; + ++count; xmlChar *ip = xmlGetNoNsProp(cur, BAD_CAST "ip"); xmlChar *file = xmlGetNoNsProp(cur, BAD_CAST "file"); - printf("%s\t%s\n", ip, file); + printf("%-40s %s\n", ip, file); + // Too lazy to free vars, client will exit anyways } - } - printf("\nNumber clients: %d\n\n", n); + } END_FOR_EACH; + char_repeat_br('=', term_width); + printf("\nNumber clients: %d\n\n", count); // Cleanup - xmlXPathFreeObject(xpathObj); - xmlXPathFreeContext(xpathCtx); xmlFreeDoc(doc); xmlCleanupParser(); @@ -710,3 +729,34 @@ void dnbd3_ipc_send(int cmd) close(client_sock); } + +/** + * Check if the correct server password is present in xpath /data/password + * return !=0 if correct, 0 otherwise + */ +static int is_password_correct(xmlDocPtr doc) +{ + if (_ipc_password == NULL) + { + memlogf("[WARNING] IPC access granted as no password is set!"); + return 1; + } + xmlChar *pass = getTextFromPath(doc, "/data/password"); + if (pass == NULL) + return 0; + if (strcmp((char*)pass, _ipc_password) == 0) + { + xmlFree(pass); + return 1; + } + xmlFree(pass); + return 0; +} + +static int get_terminal_width() +{ + struct winsize w; + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) < 0) + return 80; + return w.ws_col; +} |