diff options
author | Nathan Straz <nstraz@redhat.com> | 2013-08-01 04:21:38 -0400 |
---|---|---|
committer | Nathan Straz <nstraz@redhat.com> | 2013-09-11 17:33:58 -0400 |
commit | bbf62ffff81089ae1ef74d4e1927710af982799b (patch) | |
tree | ca6e3194aa46db2e69fd9db21a0aaed634d6559c /qarsh_packet.c | |
parent | bbceec6030f8501ce129a93980c0f2e045cce562 (diff) | |
download | qarsh-bbf62ffff81089ae1ef74d4e1927710af982799b.tar.gz qarsh-bbf62ffff81089ae1ef74d4e1927710af982799b.tar.xz qarsh-bbf62ffff81089ae1ef74d4e1927710af982799b.zip |
Convert packet parsing
Diffstat (limited to 'qarsh_packet.c')
-rw-r--r-- | qarsh_packet.c | 314 |
1 files changed, 118 insertions, 196 deletions
diff --git a/qarsh_packet.c b/qarsh_packet.c index fea4435..dfd6e72 100644 --- a/qarsh_packet.c +++ b/qarsh_packet.c @@ -30,6 +30,7 @@ #include <string.h> #include <assert.h> #include <sys/wait.h> +#include <stdint.h> #include <endian.h> #include <libxml/parser.h> @@ -38,18 +39,16 @@ #include "qarsh_packet.h" /* Prototypes */ -static char *get_xpath_string(xmlXPathContextPtr ctxt, const char *xpath_query); - -int parse_qp_hello(xmlXPathContextPtr ctxt, struct qa_packet *qp); -int parse_qp_returncode(xmlXPathContextPtr ctxt, struct qa_packet *qp); -int parse_qp_ack(xmlXPathContextPtr ctxt, struct qa_packet *qp); -int parse_qp_runcmd(xmlXPathContextPtr ctxt, struct qa_packet *qp); -int parse_qp_cmdexit(xmlXPathContextPtr ctxt, struct qa_packet *qp); -int parse_qp_setuser(xmlXPathContextPtr ctxt, struct qa_packet *qp); -int parse_qp_kill(xmlXPathContextPtr ctxt, struct qa_packet *qp); -int parse_qp_recvfile(xmlXPathContextPtr ctxt, struct qa_packet *qp); -int parse_qp_sendfile(xmlXPathContextPtr ctxt, struct qa_packet *qp); -int parse_qp_rstat(xmlXPathContextPtr ctxt, struct qa_packet *qp); +void parse_qp_hello(char *buf, int *buflen, struct qa_packet *qp); +void parse_qp_returncode(char *buf, int *buflen, struct qa_packet *qp); +void parse_qp_ack(char *buf, int *buflen, struct qa_packet *qp); +void parse_qp_runcmd(char *buf, int *buflen, struct qa_packet *qp); +void parse_qp_cmdexit(char *buf, int *buflen, struct qa_packet *qp); +void parse_qp_setuser(char *buf, int *buflen, struct qa_packet *qp); +void parse_qp_kill(char *buf, int *buflen, struct qa_packet *qp); +void parse_qp_recvfile(char *buf, int *buflen, struct qa_packet *qp); +void parse_qp_sendfile(char *buf, int *buflen, struct qa_packet *qp); +void parse_qp_rstat(char *buf, int *buflen, struct qa_packet *qp); char *store_qp_hello(char *buf, struct qa_packet *qp); char *store_qp_returncode(char *buf, struct qa_packet *qp); @@ -83,7 +82,7 @@ void dump_qp_rstat(struct qa_packet *qp); struct packet_internals { char *pi_name; - int (*pi_parse)(xmlXPathContextPtr ctxt, struct qa_packet *qp); + void (*pi_parse)(char *buf, int *buflen, struct qa_packet *qp); char *(*pi_store)(char *buf, struct qa_packet *qp); void (*pi_free)(struct qa_packet *qp); void (*pi_dump)(struct qa_packet *qp); @@ -191,237 +190,160 @@ qp_packet_type(enum qa_packet_type t) /* * Packet parsing functions */ -int -parse_qp_hello(xmlXPathContextPtr ctxt, struct qa_packet *qp) + +char * +fetch_int(char *buf, int *buflen, int *out) { - qp->qp_hello.qp_greeting = get_xpath_string(ctxt, - "param[@name='greeting']"); - return 0; + int i; + if (*buflen < sizeof i) { + printf("Not enough data to unpack a uint32_t, %d\n", *buflen); + return buf; + } + memcpy(&i, buf, sizeof i); + *out = be32toh(i); + *buflen -= sizeof i; + return buf + sizeof i; } -int -parse_qp_returncode(xmlXPathContextPtr ctxt, struct qa_packet *qp) +char * +fetch_string(char *buf, int *buflen, char **out) { - char *s; - s = get_xpath_string(ctxt, "param[@name='rc']"); - qp->qp_returncode.qp_rc = atoi(s); - free(s); - s = get_xpath_string(ctxt, "param[@name='errno']"); - qp->qp_returncode.qp_errno = atoi(s); - free(s); - qp->qp_returncode.qp_strerror = get_xpath_string(ctxt, - "param[@name='strerror']"); - return 0; -} + int slen; + if (*buflen < sizeof slen) { + printf("Not enough data to unpack string length, %d\n", *buflen); + *out = NULL; + return buf; + } + buf = fetch_int(buf, buflen, &slen); + if (slen > *buflen) { + printf("String is more than available data, %d > %d\n", slen, *buflen); + *out = NULL; + return buf; + } + *out = malloc(slen+1); + memcpy(*out, buf, slen); + (*out)[slen] = '\0'; -int -parse_qp_runcmd(xmlXPathContextPtr ctxt, struct qa_packet *qp) -{ - char *s; - qp->qp_runcmd.qp_cmdline = get_xpath_string(ctxt, - "param[@name='cmdline']"); - s = get_xpath_string(ctxt, "param[@name='stdin']"); - qp->qp_runcmd.qp_stdin_port = atoi(s); - free(s); - s = get_xpath_string(ctxt, "param[@name='stdout']"); - qp->qp_runcmd.qp_stdout_port = atoi(s); - free(s); - s = get_xpath_string(ctxt, "param[@name='stderr']"); - qp->qp_runcmd.qp_stderr_port = atoi(s); - free(s); - return 0; + *buflen -= slen; + return buf+slen; } -int -parse_qp_ack(xmlXPathContextPtr ctxt, struct qa_packet *qp) +char * +fetch_off_t(char *buf, int *buflen, off_t *out) { - char *s; - s = get_xpath_string(ctxt, "param[@name='type']"); - qp->qp_ack.qp_ack_type = parse_packet_type(s); - free(s); - s = get_xpath_string(ctxt, "param[@name='seq']"); - qp->qp_ack.qp_ack_seq = atoi(s); - free(s); - return 0; + off_t i; + if (*buflen < sizeof i) { + printf("Not enough data to unpack a off_t, %d\n", *buflen); + return buf; + } + memcpy(&i, buf, sizeof i); + *out = be64toh(i); + *buflen -= sizeof i; + return buf + sizeof i; } -int -parse_qp_cmdexit(xmlXPathContextPtr ctxt, struct qa_packet *qp) +void +parse_qp_hello(char *buf, int *buflen, struct qa_packet *qp) { - char *s; - - s = get_xpath_string(ctxt, "param[@name='status']"); - qp->qp_cmdexit.qp_status = atoi(s); - free(s); - return 0; + fetch_string(buf, buflen, &(qp->qp_hello.qp_greeting)); } -int -parse_qp_setuser(xmlXPathContextPtr ctxt, struct qa_packet *qp) +void +parse_qp_returncode(char *buf, int *buflen, struct qa_packet *qp) { - qp->qp_setuser.qp_user = get_xpath_string(ctxt, "param[@name='user']"); - qp->qp_setuser.qp_group = get_xpath_string(ctxt, "param[@name='group']"); - return 0; + buf = fetch_int(buf, buflen, &(qp->qp_returncode.qp_rc)); + buf = fetch_int(buf, buflen, &(qp->qp_returncode.qp_errno)); + buf = fetch_string(buf, buflen, &(qp->qp_returncode.qp_strerror)); } - -int -parse_qp_kill(xmlXPathContextPtr ctxt, struct qa_packet *qp) -{ - char *s; - s = get_xpath_string(ctxt, "param[@name='signal']"); - qp->qp_kill.qp_sig = atoi(s); - free(s); - return 0; +void +parse_qp_runcmd(char *buf, int *buflen, struct qa_packet *qp) +{ + buf = fetch_string(buf, buflen, &(qp->qp_runcmd.qp_cmdline)); + buf = fetch_int(buf, buflen, &(qp->qp_runcmd.qp_stdin_port)); + buf = fetch_int(buf, buflen, &(qp->qp_runcmd.qp_stdout_port)); + buf = fetch_int(buf, buflen, &(qp->qp_runcmd.qp_stderr_port)); } -int -parse_qp_recvfile(xmlXPathContextPtr ctxt, struct qa_packet *qp) +void +parse_qp_ack(char *buf, int *buflen, struct qa_packet *qp) { - char *s; - - qp->qp_recvfile.qp_path = get_xpath_string(ctxt, "param[@name='path']"); - - s = get_xpath_string(ctxt, "param[@name='if_port']"); - qp->qp_recvfile.qp_if_port = atoi(s); - free(s); - - s = get_xpath_string(ctxt, "param[@name='count']"); - qp->qp_recvfile.qp_count = atoll(s); - free(s); - - s = get_xpath_string(ctxt, "param[@name='mode']"); - qp->qp_recvfile.qp_mode = atoi(s); - free(s); - - return 0; + buf = fetch_int(buf, buflen, &(qp->qp_ack.qp_ack_type)); + buf = fetch_int(buf, buflen, &(qp->qp_ack.qp_ack_seq)); } -int -parse_qp_sendfile(xmlXPathContextPtr ctxt, struct qa_packet *qp) +void +parse_qp_cmdexit(char *buf, int *buflen, struct qa_packet *qp) { - char *s; - - qp->qp_sendfile.qp_path = get_xpath_string(ctxt, "param[@name='path']"); - s = get_xpath_string(ctxt, "param[@name='of_port']"); - qp->qp_sendfile.qp_of_port = atoi(s); - free(s); - return 0; + buf = fetch_int(buf, buflen, &(qp->qp_cmdexit.qp_pid)); + buf = fetch_int(buf, buflen, &(qp->qp_cmdexit.qp_status)); } -int -parse_qp_rstat(xmlXPathContextPtr ctxt, struct qa_packet *qp) +void +parse_qp_setuser(char *buf, int *buflen, struct qa_packet *qp) { - char *s; - - qp->qp_rstat.qp_path = get_xpath_string(ctxt, "param[@name='path']"); - - s = get_xpath_string(ctxt, "param[@name='st_mode']"); - qp->qp_rstat.qp_st_mode = atoi(s); - free(s); + buf = fetch_string(buf, buflen, &(qp->qp_setuser.qp_user)); + if (*buflen) + buf = fetch_string(buf, buflen, &(qp->qp_setuser.qp_group)); +} + +void +parse_qp_kill(char *buf, int *buflen, struct qa_packet *qp) +{ + fetch_int(buf, buflen, &(qp->qp_kill.qp_sig)); +} - s = get_xpath_string(ctxt, "param[@name='st_uid']"); - qp->qp_rstat.qp_st_uid = atoi(s); - free(s); +void +parse_qp_recvfile(char *buf, int *buflen, struct qa_packet *qp) +{ + buf = fetch_string(buf, buflen, &(qp->qp_recvfile.qp_path)); + buf = fetch_int(buf, buflen, &(qp->qp_recvfile.qp_if_port)); + buf = fetch_off_t(buf, buflen, &(qp->qp_recvfile.qp_count)); + buf = fetch_int(buf, buflen, &(qp->qp_recvfile.qp_mode)); +} - s = get_xpath_string(ctxt, "param[@name='st_gid']"); - qp->qp_rstat.qp_st_gid = atoi(s); - free(s); +void +parse_qp_sendfile(char *buf, int *buflen, struct qa_packet *qp) +{ + buf = fetch_string(buf, buflen, &(qp->qp_sendfile.qp_path)); + buf = fetch_int(buf, buflen, &(qp->qp_sendfile.qp_of_port)); +} - s = get_xpath_string(ctxt, "param[@name='st_size']"); - qp->qp_rstat.qp_st_size = atol(s); - free(s); +void +parse_qp_rstat(char *buf, int *buflen, struct qa_packet *qp) +{ - return 0; + buf = fetch_string(buf, buflen, &(qp->qp_rstat.qp_path)); + buf = fetch_int(buf, buflen, &(qp->qp_rstat.qp_st_mode)); + buf = fetch_int(buf, buflen, &(qp->qp_rstat.qp_st_uid)); + buf = fetch_int(buf, buflen, &(qp->qp_rstat.qp_st_gid)); + buf = fetch_off_t(buf, buflen, &(qp->qp_rstat.qp_st_size)); } struct qa_packet * -parse_packet(xmlXPathContextPtr ctxt) +parse_packet(char *buf, int buflen) { struct qa_packet *qp = NULL; - char *s; qp = malloc(sizeof *qp); assert(qp); memset(qp, 0, sizeof *qp); - s = get_xpath_string(ctxt, "@type"); - qp->qp_type = parse_packet_type(s); - free(s); - s = get_xpath_string(ctxt, "@seq"); - qp->qp_seq = atoi(s); - free(s); - + buf = fetch_int(buf, &buflen, &(qp->qp_seq)); + buf = fetch_int(buf, &buflen, &(qp->qp_type)); + if (qa_pi[qp->qp_type].pi_parse) - qa_pi[qp->qp_type].pi_parse(ctxt, qp); + qa_pi[qp->qp_type].pi_parse(buf, &buflen, qp); else { - printf("Packet type %s not implemented yet\n", s); + printf("Packet type %d not implemented yet\n", qp->qp_type); free(qp); qp = NULL; } + if (buflen) { printf("%d remaining bytes of data in packet\n", buflen); } return qp; } -struct qa_packet * -parse_packets(char *buf, int n) -{ - xmlDocPtr doc; - xmlXPathContextPtr context; - xmlXPathObjectPtr obj = NULL; - struct qa_packet *qp = NULL; - - doc = xmlParseMemory(buf, n); - - /* If we can't parse the packet, we don't care about it */ - if (doc == NULL) return NULL; - - context = xmlXPathNewContext(doc); - obj = xmlXPathEvalExpression((xmlChar *)"//packet", context); - if (obj == NULL) { - printf("didn't find anything\n"); - goto free_context; - } - if (obj->type != XPATH_NODESET || obj->nodesetval->nodeNr == 0) { - printf("didn't find anything\n"); - goto free_obj; - } - if (obj->nodesetval->nodeNr > 1) { - printf("One packet at a time please!\n"); - } - context->node = xmlXPathNodeSetItem(obj->nodesetval, 0); - qp = parse_packet(context); - -free_obj: - xmlXPathFreeObject(obj); -free_context: - xmlXPathFreeContext(context); - xmlFreeDoc(doc); - return qp; -} - - -static char * -get_xpath_string(xmlXPathContextPtr ctxt, const char *xpath_query) -{ - xmlXPathObjectPtr obj = NULL; - char querystr[512]; - char *ret; - - snprintf(querystr, 512, "string(%s)", xpath_query); - obj = xmlXPathEvalExpression((xmlChar *)querystr, ctxt); - - if (obj == NULL) return NULL; - if (obj->type != XPATH_STRING) { - xmlXPathFreeObject(obj); - return NULL; - } - - ret = strdup((char *)obj->stringval); - xmlXPathFreeObject(obj); - return ret; -} - /* * Packet serialization functions * |