mirror of
https://github.com/nmap/nmap.git
synced 2025-12-31 03:49:01 +00:00
459 lines
8.5 KiB
C
459 lines
8.5 KiB
C
/*
|
|
* blob.c
|
|
*
|
|
* Copyright (c) 2002 Dug Song <dugsong@monkey.org>
|
|
*
|
|
* $Id: blob.c 615 2006-01-08 16:06:49Z dugsong $
|
|
*/
|
|
|
|
#ifdef _WIN32
|
|
#include "dnet_winconfig.h"
|
|
#else
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <ctype.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "dnet.h"
|
|
|
|
static void *(*bl_malloc)(size_t) = malloc;
|
|
static void *(*bl_realloc)(void *, size_t) = realloc;
|
|
static void (*bl_free)(void *) = free;
|
|
static int bl_size = BUFSIZ;
|
|
|
|
static int fmt_D(int, int, blob_t *, va_list *);
|
|
static int fmt_H(int, int, blob_t *, va_list *);
|
|
static int fmt_b(int, int, blob_t *, va_list *);
|
|
static int fmt_c(int, int, blob_t *, va_list *);
|
|
static int fmt_d(int, int, blob_t *, va_list *);
|
|
static int fmt_h(int, int, blob_t *, va_list *);
|
|
static int fmt_s(int, int, blob_t *, va_list *);
|
|
|
|
static void print_hexl(blob_t *);
|
|
|
|
static blob_fmt_cb blob_ascii_fmt[] = {
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, fmt_D, NULL, NULL, NULL,
|
|
fmt_H, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, fmt_b, fmt_c, fmt_d, NULL, NULL, NULL,
|
|
fmt_h, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, fmt_s, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
|
};
|
|
|
|
struct blob_printer {
|
|
char *name;
|
|
void (*print)(blob_t *);
|
|
} blob_printers[] = {
|
|
{ "hexl", print_hexl },
|
|
{ NULL, NULL },
|
|
};
|
|
|
|
blob_t *
|
|
blob_new(void)
|
|
{
|
|
blob_t *b;
|
|
|
|
if ((b = bl_malloc(sizeof(*b))) != NULL) {
|
|
b->off = b->end = 0;
|
|
b->size = bl_size;
|
|
if ((b->base = bl_malloc(b->size)) == NULL) {
|
|
bl_free(b);
|
|
b = NULL;
|
|
}
|
|
}
|
|
return (b);
|
|
}
|
|
|
|
static int
|
|
blob_reserve(blob_t *b, int len)
|
|
{
|
|
void *p;
|
|
int nsize;
|
|
|
|
if (b->size < b->end + len) {
|
|
if (b->size == 0)
|
|
return (-1);
|
|
|
|
if ((nsize = b->end + len) > bl_size)
|
|
nsize = ((nsize / bl_size) + 1) * bl_size;
|
|
|
|
if ((p = bl_realloc(b->base, nsize)) == NULL)
|
|
return (-1);
|
|
|
|
b->base = p;
|
|
b->size = nsize;
|
|
}
|
|
b->end += len;
|
|
|
|
return (0);
|
|
}
|
|
|
|
int
|
|
blob_read(blob_t *b, void *buf, int len)
|
|
{
|
|
if (b->end - b->off < len)
|
|
len = b->end - b->off;
|
|
|
|
memcpy(buf, b->base + b->off, len);
|
|
b->off += len;
|
|
|
|
return (len);
|
|
}
|
|
|
|
int
|
|
blob_write(blob_t *b, const void *buf, int len)
|
|
{
|
|
if (b->off + len <= b->end ||
|
|
blob_reserve(b, b->off + len - b->end) == 0) {
|
|
memcpy(b->base + b->off, (u_char *)buf, len);
|
|
b->off += len;
|
|
return (len);
|
|
}
|
|
return (-1);
|
|
}
|
|
|
|
int
|
|
blob_insert(blob_t *b, const void *buf, int len)
|
|
{
|
|
if (blob_reserve(b, len) == 0 && b->size) {
|
|
if (b->end - b->off > 0)
|
|
memmove( b->base + b->off + len, b->base + b->off, b->end - b->off);
|
|
memcpy(b->base + b->off, buf, len);
|
|
b->off += len;
|
|
return (len);
|
|
}
|
|
return (-1);
|
|
}
|
|
|
|
int
|
|
blob_delete(blob_t *b, void *buf, int len)
|
|
{
|
|
if (b->off + len <= b->end && b->size) {
|
|
if (buf != NULL)
|
|
memcpy(buf, b->base + b->off, len);
|
|
memmove(b->base + b->off, b->base + b->off + len, b->end - (b->off + len));
|
|
b->end -= len;
|
|
return (len);
|
|
}
|
|
return (-1);
|
|
}
|
|
|
|
static int
|
|
blob_fmt(blob_t *b, int pack, const char *fmt, va_list *ap)
|
|
{
|
|
blob_fmt_cb fmt_cb;
|
|
char *p;
|
|
int len;
|
|
|
|
for (p = (char *)fmt; *p != '\0'; p++) {
|
|
if (*p == '%') {
|
|
p++;
|
|
if (isdigit((int) (unsigned char) *p)) {
|
|
len = strtol(p, &p, 10);
|
|
} else if (*p == '*') {
|
|
len = va_arg(*ap, int);
|
|
p++;
|
|
} else
|
|
len = 0;
|
|
|
|
if ((fmt_cb = blob_ascii_fmt[(int)*p]) == NULL)
|
|
return (-1);
|
|
|
|
if ((*fmt_cb)(pack, len, b, ap) < 0)
|
|
return (-1);
|
|
} else {
|
|
if (pack) {
|
|
if (b->off + 1 < b->end ||
|
|
blob_reserve(b, b->off + 1 - b->end) == 0)
|
|
b->base[b->off++] = *p;
|
|
else
|
|
return (-1);
|
|
} else {
|
|
if (b->base[b->off++] != *p)
|
|
return (-1);
|
|
}
|
|
}
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
int
|
|
blob_pack(blob_t *b, const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
return (blob_fmt(b, 1, fmt, &ap));
|
|
}
|
|
|
|
int
|
|
blob_unpack(blob_t *b, const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
return (blob_fmt(b, 0, fmt, &ap));
|
|
}
|
|
|
|
int
|
|
blob_seek(blob_t *b, int off, int whence)
|
|
{
|
|
if (whence == SEEK_CUR)
|
|
off += b->off;
|
|
else if (whence == SEEK_END)
|
|
off += b->end;
|
|
|
|
if (off < 0 || off > b->end)
|
|
return (-1);
|
|
|
|
return ((b->off = off));
|
|
}
|
|
|
|
int
|
|
blob_index(blob_t *b, const void *buf, int len)
|
|
{
|
|
int i;
|
|
|
|
for (i = b->off; i <= b->end - len; i++) {
|
|
if (memcmp(b->base + i, buf, len) == 0)
|
|
return (i);
|
|
}
|
|
return (-1);
|
|
}
|
|
|
|
int
|
|
blob_rindex(blob_t *b, const void *buf, int len)
|
|
{
|
|
int i;
|
|
|
|
for (i = b->end - len; i >= 0; i--) {
|
|
if (memcmp(b->base + i, buf, len) == 0)
|
|
return (i);
|
|
}
|
|
return (-1);
|
|
}
|
|
|
|
int
|
|
blob_print(blob_t *b, char *style, int len)
|
|
{
|
|
struct blob_printer *bp;
|
|
|
|
for (bp = blob_printers; bp->name != NULL; bp++) {
|
|
if (strcmp(bp->name, style) == 0)
|
|
bp->print(b);
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
int
|
|
blob_sprint(blob_t *b, char *style, int len, char *dst, int size)
|
|
{
|
|
return (0);
|
|
}
|
|
|
|
blob_t *
|
|
blob_free(blob_t *b)
|
|
{
|
|
if (b->size)
|
|
bl_free(b->base);
|
|
bl_free(b);
|
|
return (NULL);
|
|
}
|
|
|
|
int
|
|
blob_register_alloc(size_t size, void *(bmalloc)(size_t),
|
|
void (*bfree)(void *), void *(*brealloc)(void *, size_t))
|
|
{
|
|
bl_size = size;
|
|
if (bmalloc != NULL)
|
|
bl_malloc = bmalloc;
|
|
if (bfree != NULL)
|
|
bl_free = bfree;
|
|
if (brealloc != NULL)
|
|
bl_realloc = brealloc;
|
|
return (0);
|
|
}
|
|
|
|
int
|
|
blob_register_pack(char c, blob_fmt_cb fmt_cb)
|
|
{
|
|
if (blob_ascii_fmt[(int)c] == NULL) {
|
|
blob_ascii_fmt[(int)c] = fmt_cb;
|
|
return (0);
|
|
}
|
|
return (-1);
|
|
}
|
|
|
|
static int
|
|
fmt_D(int pack, int len, blob_t *b, va_list *ap)
|
|
{
|
|
if (len) return (-1);
|
|
|
|
if (pack) {
|
|
uint32_t n = va_arg(*ap, uint32_t);
|
|
n = htonl(n);
|
|
if (blob_write(b, &n, sizeof(n)) < 0)
|
|
return (-1);
|
|
} else {
|
|
uint32_t *n = va_arg(*ap, uint32_t *);
|
|
if (blob_read(b, n, sizeof(*n)) != sizeof(*n))
|
|
return (-1);
|
|
*n = ntohl(*n);
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
static int
|
|
fmt_H(int pack, int len, blob_t *b, va_list *ap)
|
|
{
|
|
if (len) return (-1);
|
|
|
|
if (pack) {
|
|
uint16_t n = va_arg(*ap, int);
|
|
n = htons(n);
|
|
if (blob_write(b, &n, sizeof(n)) < 0)
|
|
return (-1);
|
|
} else {
|
|
uint16_t *n = va_arg(*ap, uint16_t *);
|
|
if (blob_read(b, n, sizeof(*n)) != sizeof(*n))
|
|
return (-1);
|
|
*n = ntohs(*n);
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
static int
|
|
fmt_b(int pack, int len, blob_t *b, va_list *ap)
|
|
{
|
|
void *p = va_arg(*ap, void *);
|
|
|
|
if (len <= 0) return (-1);
|
|
|
|
if (pack)
|
|
return (blob_write(b, p, len));
|
|
else
|
|
return (blob_read(b, p, len));
|
|
}
|
|
|
|
static int
|
|
fmt_c(int pack, int len, blob_t *b, va_list *ap)
|
|
{
|
|
if (len) return (-1);
|
|
|
|
if (pack) {
|
|
uint8_t n = va_arg(*ap, int);
|
|
return (blob_write(b, &n, sizeof(n)));
|
|
} else {
|
|
uint8_t *n = va_arg(*ap, uint8_t *);
|
|
return (blob_read(b, n, sizeof(*n)));
|
|
}
|
|
}
|
|
|
|
static int
|
|
fmt_d(int pack, int len, blob_t *b, va_list *ap)
|
|
{
|
|
if (len) return (-1);
|
|
|
|
if (pack) {
|
|
uint32_t n = va_arg(*ap, uint32_t);
|
|
return (blob_write(b, &n, sizeof(n)));
|
|
} else {
|
|
uint32_t *n = va_arg(*ap, uint32_t *);
|
|
return (blob_read(b, n, sizeof(*n)));
|
|
}
|
|
}
|
|
|
|
static int
|
|
fmt_h(int pack, int len, blob_t *b, va_list *ap)
|
|
{
|
|
if (len) return (-1);
|
|
|
|
if (pack) {
|
|
uint16_t n = va_arg(*ap, int);
|
|
return (blob_write(b, &n, sizeof(n)));
|
|
} else {
|
|
uint16_t *n = va_arg(*ap, uint16_t *);
|
|
return (blob_read(b, n, sizeof(*n)));
|
|
}
|
|
}
|
|
|
|
static int
|
|
fmt_s(int pack, int len, blob_t *b, va_list *ap)
|
|
{
|
|
char *p = va_arg(*ap, char *);
|
|
char c = '\0';
|
|
int i, end;
|
|
|
|
if (pack) {
|
|
if (len > 0) {
|
|
if ((c = p[len - 1]) != '\0')
|
|
p[len - 1] = '\0';
|
|
} else
|
|
len = strlen(p) + 1;
|
|
|
|
if (blob_write(b, p, len) > 0) {
|
|
if (c != '\0')
|
|
p[len - 1] = c;
|
|
return (len);
|
|
}
|
|
} else {
|
|
if (len <= 0) return (-1);
|
|
|
|
if ((end = b->end - b->off) < len)
|
|
end = len;
|
|
|
|
for (i = 0; i < end; i++) {
|
|
if ((p[i] = b->base[b->off + i]) == '\0') {
|
|
b->off += i + 1;
|
|
return (i);
|
|
}
|
|
}
|
|
}
|
|
return (-1);
|
|
}
|
|
|
|
static void
|
|
print_hexl(blob_t *b)
|
|
{
|
|
u_int i, j, jm, len;
|
|
u_char *p;
|
|
int c;
|
|
|
|
p = b->base + b->off;
|
|
len = b->end - b->off;
|
|
|
|
printf("\n");
|
|
|
|
for (i = 0; i < len; i += 0x10) {
|
|
printf(" %04x: ", (u_int)(i + b->off));
|
|
jm = len - i;
|
|
jm = jm > 16 ? 16 : jm;
|
|
|
|
for (j = 0; j < jm; j++) {
|
|
printf((j % 2) ? "%02x " : "%02x", (u_int)p[i + j]);
|
|
}
|
|
for (; j < 16; j++) {
|
|
printf((j % 2) ? " " : " ");
|
|
}
|
|
printf(" ");
|
|
|
|
for (j = 0; j < jm; j++) {
|
|
c = p[i + j];
|
|
printf("%c", isprint(c) ? c : '.');
|
|
}
|
|
printf("\n");
|
|
}
|
|
}
|