Commit da2390e7 authored by Michael Graff's avatar Michael Graff
Browse files

move ccapi to trunk

git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@109 e5f2f494-b856-4b98-b285-d166d9295462
parent 2891ecb0
# Copyright (C) 2002 Internet Software Consortium.
#
# 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 INTERNET SOFTWARE CONSORTIUM
# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# INTERNET SOFTWARE CONSORTIUM 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.
OBJS=cc.o msgq.o msgbuf.o
TARGETS=msgq ${OBJS}
CFLAGS += ${ISC_CFLAGS} -g
CFLAGS += -Wall -Wstrict-prototypes
CFLAGS += `isc-config.sh --cflags isc`
ISC_LIBS += `isc-config.sh --libs isc`
msgq: ${OBJS}
${CC} -o msgq ${OBJS} ${ISC_LIBS}
clean:
rm -f *.o *~ *.core core msgq
msgq.o: msgq.c msgbuf.h cc.h
msgbuf.o: msgbuf.c msgbuf.h
cc.o: cc.c cc.h
/*
* Copyright (C) 2002 Internet Software Consortium.
*
* 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 INTERNET SOFTWARE CONSORTIUM
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM 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.
*/
/* $Id: cc.c,v 1.6 2002/12/06 21:06:26 lidl Exp $ */
#include <stdlib.h>
#include <string.h>
#include <isc/buffer.h>
#include <isc/util.h>
#include "cc.h"
#define MSG_MAGIC 0x536b616e
int
cc_matchdata(ccsearch_t *c, u_int32_t type, void *data, u_int32_t dlen)
{
if (c->type == type
&& c->dlen == dlen
&& memcmp(c->data, data, dlen) == 0)
return 1;
return 0;
}
ccsearch_t *
cc_findtag(ccsearch_t *cc, char *tag, u_int32_t tlen)
{
ccsearch_t *c;
c = cc;
while (c->tag != NULL) {
if (c->tlen == tlen
&& memcmp(c->tag, tag, tlen) == 0)
return c;
c++;
}
return NULL;
}
int
cc_search(logfunc_t lf, void *lfarg, ccsearch_t *cc,
void *msg, unsigned int msglen)
{
isc_buffer_t b;
u_int32_t magic;
ccsearch_t *c;
u_int32_t item_type, item_code, item_lencode;
u_int32_t item_len, tag_len;
char *tag_name, *item_ptr;
int total, n;
n = 0;
c = cc;
while (c->tag != NULL) {
c->type = ITEM_UNDEFINED;
c->dlen = 0;
c->data = 0;
c++;
n++;
}
if (n == 0)
return 0;
total = n;
isc_buffer_init(&b, msg, msglen);
isc_buffer_add(&b, msglen);
if (isc_buffer_remaininglength(&b) < 4)
return -1;
magic = isc_buffer_getuint32(&b);
if (magic != MSG_MAGIC) {
if (lf != NULL)
lf(lfarg, "BAD PACKET: MAGIC == %x", magic);
return -1;
}
/*
* Walk the buffer, remembering when we find important tags.
* We'll set pointers and remember the lengths of:
* to from type group instance
*
* We assume all of these are at the top level (it's our protocol,
* so this is pretty safe) and we only decode the bits we need.
* This is by no means a general purpose decoder.
*/
while (n != 0 && isc_buffer_remaininglength(&b) > 0) {
if (isc_buffer_remaininglength(&b) < 1) {
if (lf != NULL)
lf(lfarg, "PKTFMT tag len");
return -1;
}
tag_len = isc_buffer_getuint8(&b);
if (isc_buffer_remaininglength(&b) < tag_len) {
if (lf != NULL)
lf(lfarg, "PKTFMT tag (len %d)");
return -1;
}
tag_name = isc_buffer_current(&b);
isc_buffer_forward(&b, tag_len);
if (isc_buffer_remaininglength(&b) < 1) {
if (lf != NULL)
lf(lfarg, "PKTFMT len/type");
return -1;
}
item_type = isc_buffer_getuint8(&b);
item_code = item_type & ITEM_MASK;
item_lencode = item_type & LENGTH_MASK;
/*
* Crack out the message length.
*/
item_len = 0;
item_ptr = NULL;
if (item_code != ITEM_NULL) {
switch (item_lencode) {
case LENGTH_8:
if (isc_buffer_remaininglength(&b) < 1) {
if (lf != NULL)
lf(lfarg, "PKTFMT (len8)");
return -1;
}
item_len = isc_buffer_getuint8(&b);
break;
case LENGTH_16:
if (isc_buffer_remaininglength(&b) < 2) {
if (lf != NULL)
lf(lfarg, "PKTFMT (len16)");
return -1;
}
item_len = isc_buffer_getuint16(&b);
break;
case LENGTH_32:
if (isc_buffer_remaininglength(&b) < 4) {
if (lf != NULL)
lf(lfarg, "PKTFMT (len32)");
return -1;
}
item_len = isc_buffer_getuint32(&b);
break;
default:
if (lf != NULL)
lf(lfarg, "PKTFMT (len code 0x%02x)",
item_lencode);
return -1;
}
if (isc_buffer_remaininglength(&b) < item_len) {
if (lf != NULL)
lf(lfarg, "PKTFMT (item length %d, remaining %d)",
item_len,
isc_buffer_remaininglength(&b));
return -1;
}
item_ptr = isc_buffer_current(&b);
isc_buffer_forward(&b, item_len);
}
c = cc;
while (c->tag != NULL) {
if (c->tlen == tag_len
&& memcmp(c->tag, tag_name, tag_len) == 0) {
if (c->type != ITEM_UNDEFINED)
break;
c->type = item_code;
c->data = item_ptr;
c->dlen = item_len;
n--;
break;
}
c++;
}
}
return (total - n);
}
void
ccmsg_init(ccmsg_t *msg, void *buf, unsigned int buflen)
{
isc_buffer_init(&msg->b, buf, buflen);
isc_buffer_putuint32(&msg->b, MSG_MAGIC);
}
void
ccmsg_add(ccmsg_t *msg, u_int32_t type, char *tag, u_int32_t tlen,
char *data, u_int32_t dlen)
{
isc_buffer_putuint8(&msg->b, tlen);
isc_buffer_putmem(&msg->b, tag, tlen);
if (dlen < 0x000000ff) {
type |= LENGTH_8;
isc_buffer_putuint8(&msg->b, type);
isc_buffer_putuint8(&msg->b, dlen);
isc_buffer_putmem(&msg->b, data, dlen);
} else if (dlen < 0x0000ffff) {
type |= LENGTH_16;
isc_buffer_putuint8(&msg->b, type);
isc_buffer_putuint16(&msg->b, dlen);
isc_buffer_putmem(&msg->b, data, dlen);
} else {
type |= LENGTH_32;
isc_buffer_putuint8(&msg->b, type);
isc_buffer_putuint32(&msg->b, dlen);
isc_buffer_putmem(&msg->b, data, dlen);
}
}
u_int32_t
ccmsg_render(ccmsg_t *msg)
{
return isc_buffer_usedlength(&msg->b);
}
/*
* Copyright (C) 2002 Internet Software Consortium.
*
* 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 INTERNET SOFTWARE CONSORTIUM
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM 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.
*/
/* $Id: cc.h,v 1.5 2002/12/06 21:06:27 lidl Exp $ */
#ifndef MSGQ_CC_H
#define MSGQ_CC_H
#include <isc/buffer.h>
#include <isc/types.h>
/*
* Item types and data lengths.
*/
#define ITEM_UNDEFINED 0x00
#define ITEM_DATA 0x01
#define ITEM_HASH 0x02
#define ITEM_LIST 0x03
#define ITEM_NULL 0x04
#define ITEM_MASK 0x0f
#define LENGTH_32 0x00
#define LENGTH_16 0x10
#define LENGTH_8 0x20
#define LENGTH_MASK 0x30
typedef struct {
/* Set by caller */
char *tag; /* the target of our search */
u_int8_t tlen; /* length of tag name */
/* Set by function */
u_int8_t type; /* the item type found */
u_int32_t dlen; /* the length of the item */
void *data; /* a pointer to the data for this item */
} ccsearch_t;
typedef struct {
isc_buffer_t b;
} ccmsg_t;
typedef int (*logfunc_t)(void *, const char *, ...);
/*
* Given a NULL-terminated array of ccsearch_t, searches the message
* and fills it in. If logging is needed, it will use the logging function
* to log, or now logging if NULL.
*/
int cc_search(logfunc_t, void *, ccsearch_t *, void *, unsigned int);
/*
* Returns 1 if the type, dlen, and data matches.
*/
int cc_matchdata(ccsearch_t *, u_int32_t, void *, u_int32_t);
/*
* Find the tag in the ccsearch structure, or return NULL if not found.
*/
ccsearch_t *cc_findtag(ccsearch_t *, char *, u_int32_t);
/*
* Initialize a ccmsg_t using the buffer provided.
*/
void ccmsg_init(ccmsg_t *, void *, unsigned int);
/*
* Add a data item to the buffer.
*/
void ccmsg_add(ccmsg_t *, u_int32_t, char *, u_int32_t, char *, u_int32_t);
/*
* "render" the message. This really just returns its length.
*/
u_int32_t ccmsg_render(ccmsg_t *);
#endif /* MSGQ_CC_H */
/*
* Copyright (C) 2002 Internet Software Consortium.
*
* 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 INTERNET SOFTWARE CONSORTIUM
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM 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.
*/
/* $Id: msgbuf.c,v 1.2 2002/12/06 21:06:27 lidl Exp $ */
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <isc/mem.h>
#include <isc/util.h>
#include "msgbuf.h"
msgbuf_t *
msgbuf_create(isc_mem_t *mctx, unsigned int length)
{
msgbuf_t *mb;
unsigned int len;
len = sizeof(msgbuf_t);
len += length;
mb = isc_mem_get(mctx, len);
RUNTIME_CHECK(mb != NULL);
mb->ref = 1;
mb->r.base = (unsigned char *)(mb + 1);
mb->r.length = length;
return (mb);
}
void
msgbuf_detach(isc_mem_t *mctx, msgbuf_t **mbp)
{
msgbuf_t *mb = *mbp;
unsigned int len;
*mbp = NULL;
INSIST(mb->ref > 0);
mb->ref--;
if (mb->ref == 0) {
len = sizeof(msgbuf_t);
len += mb->r.length;
isc_mem_put(mctx, mb, len);
}
}
msgbuf_t *
msgbuf_attach(msgbuf_t *mb)
{
INSIST(mb->ref > 0);
mb->ref++;
return (mb);
}
/*
* Copyright (C) 2002 Internet Software Consortium.
*
* 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 INTERNET SOFTWARE CONSORTIUM
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM 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.
*/
/* $Id: msgbuf.h,v 1.2 2002/12/06 21:06:27 lidl Exp $ */
#ifndef MSGQ_MSGBUF_H
#define MSGQ_MSGBUF_H
#include <isc/region.h>
typedef struct _msgbuf msgbuf_t;
/*
* A buffer.
*/
struct _msgbuf {
int ref;
isc_region_t r;
};
msgbuf_t *msgbuf_create(isc_mem_t *mctx, unsigned int);
void msgbuf_detach(isc_mem_t *mctx, msgbuf_t **);
msgbuf_t *msgbuf_attach(msgbuf_t *);
#endif /* MSGQ_MSGBUF_H */
This diff is collapsed.
# Copyright (C) 2009 Internet Systems Consortium.
#
# 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 INTERNET SYSTEMS CONSORTIUM
# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# INTERNET SYSTEMS CONSORTIUM 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.
import sys
import struct
class DecodeError(Exception): pass
PROTOCOL_VERSION = 0x536b616e
_ITEM_DATA = 0x01
_ITEM_HASH = 0x02
_ITEM_LIST = 0x03
_ITEM_NULL = 0x04
_ITEM_MASK = 0x0f
_ITEM_LENGTH_32 = 0x00
_ITEM_LENGTH_16 = 0x10
_ITEM_LENGTH_8 = 0x20
_ITEM_LENGTH_MASK = 0x30
def to_wire(items):
"""Encode a dict into wire format.
>>> wire_format = Message.to_wire({"a": "b"})
"""
ret = []
ret.append(struct.pack(">I", PROTOCOL_VERSION))
ret.append(_encode_hash(items))
return (''.join(ret))
def _encode_tag(tag):
"""Encode a single UTF-8 tag.
... wire_partial = Message._encode_tag('this')
"""
return(struct.pack(">B", len(str(tag))) + str(tag))
def _encode_length_and_type(data, datatype):
"""Helper method to handle the length encoding in one place."""
if data == None:
return(struct.pack(">B", _ITEM_NULL))
length = len(data)
if length < 0x0000100:
return(struct.pack(">B B", datatype | _ITEM_LENGTH_8, length)
+ data)
elif length < 0x00010000:
return(struct.pack(">B H", datatype | _ITEM_LENGTH_16, length)
+ data)
else:
return(struct.pack(">B I", datatype, length) + data)
def _pack_string(item):
"""Pack a string (data) and its type/length prefix."""
return (_encode_length_and_type(item, _ITEM_DATA))
def _pack_array(item):
"""Pack a list (array) and its type/length prefix."""
return (_encode_length_and_type(_encode_array(item),
_ITEM_LIST))
def _pack_hash(item):
"""Pack a dict (hash) and its type/length prefix."""
data = _encode_hash(item)
return (_encode_length_and_type(data, _ITEM_HASH))
def _encode_string(item):
"""Encode a string. More or less identity."""
return (item)
def _pack_nil():
"""Encode a nil (NULL, None) item."""
return _encode_length_and_type(None, None)
def _encode_item(item):
"""Encode each item depending on its type"""
if item == None:
return (_pack_nil())
elif type(item) == dict:
return (_pack_hash(item))
elif type(item) == list:
return (_pack_array(item))
else:
return (_pack_string(str(item)))
def _encode_array(item):
"""Encode an array, where each value is encoded recursively"""
ret = []
for i in item:
ret.append(_encode_item(i))
return (''.join(ret))
def _encode_hash(item):
"""Encode a hash, where each value is encoded recursively"""
ret = []
for key, value in item.items():
ret.append(_encode_tag(key))
ret.append(_encode_item(value))
return (''.join(ret))
#
# decode methods
#
def from_wire(data):
if len(data) < 5:
raise DecodeError("Data is too short to decode")
wire_version, data = data[0:4], data[4:]
wire_version = struct.unpack(">I", wire_version)[0]
if wire_version != PROTOCOL_VERSION:
raise DecodeError("Incorrect protocol version")
return _decode_hash(data)
def _decode_tag(data):
if len(data) < 1:
raise DecodeError("Data underrun while decoding")
length = struct.unpack(">B", data[0])[0]
if len(data) - 1 < length:
raise DecodeError("Data underrun while decoding")
return [data[1:length + 1], data[length + 1:]]
def _decode_item(data):
if len(data) < 1:
raise DecodeError("Data underrun while decoding")
type_and_length_format = struct.unpack(">B", data[0])[0]
item_type = type_and_length_format & _ITEM_MASK
length_format = type_and_length_format & _ITEM_LENGTH_MASK
if item_type == _ITEM_NULL: