summaryrefslogtreecommitdiffstats
path: root/qarsh_packet.c
diff options
context:
space:
mode:
authorNathan Straz <nstraz@redhat.com>2013-08-01 04:21:38 -0400
committerNathan Straz <nstraz@redhat.com>2013-09-11 17:33:58 -0400
commitbbf62ffff81089ae1ef74d4e1927710af982799b (patch)
treeca6e3194aa46db2e69fd9db21a0aaed634d6559c /qarsh_packet.c
parentbbceec6030f8501ce129a93980c0f2e045cce562 (diff)
downloadqarsh-bbf62ffff81089ae1ef74d4e1927710af982799b.tar.gz
qarsh-bbf62ffff81089ae1ef74d4e1927710af982799b.tar.xz
qarsh-bbf62ffff81089ae1ef74d4e1927710af982799b.zip
Convert packet parsing
Diffstat (limited to 'qarsh_packet.c')
-rw-r--r--qarsh_packet.c314
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
*