diff options
Diffstat (limited to 'jni/iodine/src/read.c')
-rw-r--r-- | jni/iodine/src/read.c | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/jni/iodine/src/read.c b/jni/iodine/src/read.c new file mode 100644 index 0000000..ff40382 --- /dev/null +++ b/jni/iodine/src/read.c @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <string.h> +#include <stdint.h> +#include <stdlib.h> + +static int +readname_loop(char *packet, int packetlen, char **src, char *dst, size_t length, size_t loop) +{ + char *dummy; + char *s; + char *d; + int len; + int offset; + char c; + + if (loop <= 0) + return 0; + + len = 0; + s = *src; + d = dst; + while(*s && len < length - 2) { + c = *s++; + + /* is this a compressed label? */ + if((c & 0xc0) == 0xc0) { + offset = (((s[-1] & 0x3f) << 8) | (s[0] & 0xff)); + if (offset > packetlen) { + if (len == 0) { + /* Bad jump first in packet */ + return 0; + } else { + /* Bad jump after some data */ + break; + } + } + dummy = packet + offset; + len += readname_loop(packet, packetlen, &dummy, d, length - len, loop - 1); + goto end; + } + + while(c && len < length - 1) { + *d++ = *s++; + len++; + + c--; + } + + if (len >= length - 1) { + break; /* We used up all space */ + } + + if (*s != 0) { + *d++ = '.'; + len++; + } + } + dst[len++] = '\0'; + +end: + (*src) = s+1; + return len; +} + +int +readname(char *packet, int packetlen, char **src, char *dst, size_t length) +{ + return readname_loop(packet, packetlen, src, dst, length, 10); +} + +int +readshort(char *packet, char **src, short *dst) +{ + unsigned char *p; + + p = (unsigned char *) *src; + *dst = (p[0] << 8) | p[1]; + + (*src) += sizeof(short); + return sizeof(short); +} + +int +readlong(char *packet, char **src, uint32_t *dst) +{ + /* A long as described in dns protocol is always 32 bits */ + unsigned char *p; + + p = (unsigned char *) *src; + + *dst = ((uint32_t)p[0] << 24) + | ((uint32_t)p[1] << 16) + | ((uint32_t)p[2] << 8) + | ((uint32_t)p[3]); + + (*src) += sizeof(uint32_t); + return sizeof(uint32_t); +} + +int +readdata(char *packet, char **src, char *dst, size_t len) +{ + if (len < 0) + return 0; + + memcpy(dst, *src, len); + + (*src) += len; + + return len; +} + +int +readtxtbin(char *packet, char **src, size_t srcremain, char *dst, size_t dstremain) +{ + unsigned char *uc; + int tocopy; + int dstused = 0; + + while (srcremain > 0) + { + uc = (unsigned char*) (*src); + tocopy = *uc; + (*src)++; + srcremain--; + + if (tocopy > srcremain) + return 0; /* illegal, better have nothing */ + if (tocopy > dstremain) + return 0; /* doesn't fit, better have nothing */ + + memcpy(dst, *src, tocopy); + dst += tocopy; + (*src) += tocopy; + srcremain -= tocopy; + dstremain -= tocopy; + dstused += tocopy; + } + return dstused; +} + +int +putname(char **buf, size_t buflen, const char *host) +{ + char *word; + int left; + char *h; + char *p; + + h = strdup(host); + left = buflen; + p = *buf; + + word = strtok(h, "."); + while(word) { + if (strlen(word) > 63 || strlen(word) > left) { + free(h); + return -1; + } + + left -= (strlen(word) + 1); + *p++ = (char)strlen(word); + memcpy(p, word, strlen(word)); + p += strlen(word); + + word = strtok(NULL, "."); + } + + *p++ = 0; + + free(h); + + *buf = p; + return buflen - left; +} + +int +putbyte(char **dst, unsigned char value) +{ + **dst = value; + (*dst)++; + + return sizeof(char); +} + +int +putshort(char **dst, unsigned short value) +{ + unsigned char *p; + + p = (unsigned char *) *dst; + + *p++ = (value >> 8); + *p++ = value; + + (*dst) = (char *) p; + return sizeof(short); +} + +int +putlong(char **dst, uint32_t value) +{ + /* A long as described in dns protocol is always 32 bits */ + unsigned char *p; + + p = (unsigned char *) *dst; + + *p++ = (value >> 24); + *p++ = (value >> 16); + *p++ = (value >> 8); + *p++ = (value); + + (*dst) = (char *) p; + return sizeof(uint32_t); +} + +int +putdata(char **dst, char *data, size_t len) +{ + if (len < 0) + return 0; + + memcpy(*dst, data, len); + + (*dst) += len; + return len; +} + +int +puttxtbin(char **buf, size_t bufremain, char *from, size_t fromremain) +{ + unsigned char uc; + unsigned char *ucp = &uc; + char *cp = (char *) ucp; + int tocopy; + int bufused = 0; + + while (fromremain > 0) + { + tocopy = fromremain; + if (tocopy > 252) + tocopy = 252; /* allow off-by-1s in caches etc */ + if (tocopy + 1 > bufremain) + return -1; /* doesn't fit, better have nothing */ + + uc = tocopy; + **buf = *cp; + (*buf)++; + bufremain--; + bufused++; + + memcpy(*buf, from, tocopy); + (*buf) += tocopy; + from += tocopy; + bufremain -= tocopy; + fromremain -= tocopy; + bufused += tocopy; + } + return bufused; +} |