Cleaned up format of source code.

This commit is contained in:
skarg
2007-05-30 23:28:12 +00:00
parent 57af6b6551
commit ba810c0aed
+180 -114
View File
@@ -43,15 +43,15 @@
BACnet Broadcast Management Device, BACnet Broadcast Management Device,
Broadcast Distribution Table, and Broadcast Distribution Table, and
Foreign Device Registration */ Foreign Device Registration */
typedef struct
{
/* true if valid entry - false if not */ /* true if valid entry - false if not */
bool valid; bool valid;
/* true if valid entry - false if not */
/* BACnet/IP address */ /* BACnet/IP address */
struct in_addr dest_address; struct in_addr dest_address;
/* BACnet/IP port number - not always 47808=BAC0h */
uint16_t dest_port; uint16_t dest_port;
struct in_addr dest_address;
/* Broadcast Distribution Mask - stored in host byte order */ /* Broadcast Distribution Mask - stored in host byte order */
struct in_addr broadcast_mask; struct in_addr broadcast_mask;
} BBMD_TABLE_ENTRY; } BBMD_TABLE_ENTRY;
@@ -68,136 +68,174 @@ seconds remaining before the BBMD will purge the registrant's FDT
entry if no re-registration occurs. This value will be initialized entry if no re-registration occurs. This value will be initialized
to the 2-octet Time-to-Live value supplied at the time of to the 2-octet Time-to-Live value supplied at the time of
registration.*/ registration.*/
seconds remaining before the BBMD will purge the registrant's FDT typedef struct
{
bool valid; bool valid;
to the 2-octet Time-to-Live value supplied at the time of
/* BACnet/IP address */ /* BACnet/IP address */
struct in_addr dest_address; struct in_addr dest_address;
/* BACnet/IP port number - not always 47808=BAC0h */
uint16_t dest_port; uint16_t dest_port;
/* seconds for valid entry lifetime */ /* seconds for valid entry lifetime */
uint16_t time_to_live; uint16_t time_to_live;
/* our counter */
time_t seconds_remaining; /* includes 30 second grace period */ time_t seconds_remaining; /* includes 30 second grace period */
} FD_TABLE_ENTRY; } FD_TABLE_ENTRY;
#define MAX_FD_ENTRIES 128 #define MAX_FD_ENTRIES 128
static FD_TABLE_ENTRY FD_Table[MAX_FD_ENTRIES]; static FD_TABLE_ENTRY FD_Table[MAX_FD_ENTRIES];
void bvlc_maintenance_timer(unsigned seconds) void bvlc_maintenance_timer(unsigned seconds)
{ {
unsigned i = 0; unsigned i = 0;
time_t seconds_remaining; /* includes 30 second grace period */
} FD_TABLE_ENTRY;
#define MAX_FD_ENTRIES 128
static FD_TABLE_ENTRY FD_Table[MAX_FD_ENTRIES];
void bvlc_maintenance_timer(unsigned seconds) for (i = 0; i < MAX_FD_ENTRIES; i++) {
if (FD_Table[i].valid) {
if (FD_Table[i].seconds_remaining) {
if (FD_Table[i].seconds_remaining < seconds) {
FD_Table[i].seconds_remaining = 0;
} else {
FD_Table[i].seconds_remaining -= seconds; FD_Table[i].seconds_remaining -= seconds;
}
unsigned i = 0; if (FD_Table[i].seconds_remaining == 0) {
FD_Table[i].valid = false; FD_Table[i].valid = false;
} }
} }
} }
} }
} }
{
int bvlc_encode_bip_address(
uint8_t * pdu, /* buffer to store encoding */
struct in_addr *address, /* in host format */
uint16_t port) uint16_t port)
{ {
int len = 0; int len = 0;
if (pdu) { if (pdu) {
len = encode_unsigned32(&pdu[0], address->s_addr); len = encode_unsigned32(&pdu[0], address->s_addr);
len += encode_unsigned16(&pdu[len], port); len += encode_unsigned16(&pdu[len], port);
} }
return len; return len;
} }
else
int bvlc_decode_bip_address(
uint8_t * pdu, /* buffer to extract encoded address */
struct in_addr * address, /* in host format */
uint16_t * port) uint16_t * port)
{ {
int len = 0;
if (pdu) {
(void) decode_unsigned32(&pdu[0], &(address.s_addr));
(void) decode_unsigned16(&pdu[4], &port);
len = 6;
}
return len;
} }
/* used for both read and write entries */ /* used for both read and write entries */
int bvlc_encode_address_entry(uint8_t * pdu, int bvlc_encode_address_entry(uint8_t * pdu,
struct in_addr *address,
uint16_t port,
struct in_addr *mask)
{ {
int len = 0; int len = 0;
if (pdu) { if (pdu) {
len = bvlc_encode_bip_address(pdu, address, port); len = bvlc_encode_bip_address(pdu, address, port);
len += encode_unsigned32(&pdu[len], mask->s_addr); len += encode_unsigned32(&pdu[len], mask->s_addr);
} }
return len; return len;
} }
}
int bvlc_encode_bvlc_result(
uint8_t * pdu,
BACNET_BVLC_RESULT result_code) BACNET_BVLC_RESULT result_code)
{ {
if (pdu) { if (pdu) {
pdu[0] = BVLL_TYPE_BACNET_IP; pdu[0] = BVLL_TYPE_BACNET_IP;
pdu[1] = BVLC_RESULT; pdu[1] = BVLC_RESULT;
uint8_t * pdu,
/* The 2-octet BVLC Length field is the length, in octets, /* The 2-octet BVLC Length field is the length, in octets,
of the entire BVLL message, including the two octets of the of the entire BVLL message, including the two octets of the
length field itself, most significant octet first. */ length field itself, most significant octet first. */
encode_unsigned16(&pdu[2], 6); encode_unsigned16(&pdu[2], 6);
encode_unsigned16(&pdu[4], result_code); encode_unsigned16(&pdu[4], result_code);
} }
return 6; return 6;
} }
int bvlc_encode_write_bdt_init(
uint8_t * pdu,
unsigned entries)
{ {
int len = 0; int len = 0;
if (pdu) { if (pdu) {
pdu[0] = BVLL_TYPE_BACNET_IP; pdu[0] = BVLL_TYPE_BACNET_IP;
pdu[1] = BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE; pdu[1] = BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE;
/* The 2-octet BVLC Length field is the length, in octets, /* The 2-octet BVLC Length field is the length, in octets,
of the entire BVLL message, including the two octets of the of the entire BVLL message, including the two octets of the
length field itself, most significant octet first. */ length field itself, most significant octet first. */
encode_unsigned16(&pdu[2], 4 + entries * 10); encode_unsigned16(&pdu[2], 4 + entries * 10);
len = 4; len = 4;
} }
return len; return len;
} }
struct in_addr *address, /* in host format */
int bvlc_encode_read_bdt(
uint8_t * pdu)
{ {
int len = 0; int len = 0;
if (pdu) { if (pdu) {
pdu[0] = BVLL_TYPE_BACNET_IP; pdu[0] = BVLL_TYPE_BACNET_IP;
pdu[1] = BVLC_READ_BROADCAST_DISTRIBUTION_TABLE; pdu[1] = BVLC_READ_BROADCAST_DISTRIBUTION_TABLE;
/* The 2-octet BVLC Length field is the length, in octets, /* The 2-octet BVLC Length field is the length, in octets,
of the entire BVLL message, including the two octets of the of the entire BVLL message, including the two octets of the
length field itself, most significant octet first. */ length field itself, most significant octet first. */
encode_unsigned16(&pdu[2], 4); encode_unsigned16(&pdu[2], 4);
len = 4; len = 4;
} }
return len; return len;
} }
int bvlc_encode_read_bdt_ack_init(
uint8_t * pdu,
unsigned entries)
{ {
int len = 0; int len = 0;
if (pdu) { if (pdu) {
pdu[0] = BVLL_TYPE_BACNET_IP; pdu[0] = BVLL_TYPE_BACNET_IP;
pdu[1] = BVLC_READ_BROADCAST_DISTRIBUTION_TABLE_ACK; pdu[1] = BVLC_READ_BROADCAST_DISTRIBUTION_TABLE_ACK;
len += encode_unsigned32(&pdu[len], mask->s_addr);
/* The 2-octet BVLC Length field is the length, in octets, /* The 2-octet BVLC Length field is the length, in octets,
of the entire BVLL message, including the two octets of the of the entire BVLL message, including the two octets of the
length field itself, most significant octet first. */ length field itself, most significant octet first. */
encode_unsigned16(&pdu[2], 4 + entries * 10); encode_unsigned16(&pdu[2], 4 + entries * 10);
len = 4; len = 4;
} }
return len; return len;
} }
int bvlc_encode_forwarded_npdu(uint8_t * pdu, int bvlc_encode_forwarded_npdu(uint8_t * pdu,
int bvlc_encode_bvlc_result(uint8_t * pdu, BACNET_ADDRESS * src,
uint8_t * npdu,
unsigned npdu_length)
{ {
int len = 0; int len = 0;
unsigned i; /* for loop counter */ unsigned i; /* for loop counter */
if (pdu) { if (pdu) {
pdu[0] = BVLL_TYPE_BACNET_IP; pdu[0] = BVLL_TYPE_BACNET_IP;
pdu[1] = BVLC_FORWARDED_NPDU; pdu[1] = BVLC_FORWARDED_NPDU;
pdu[0] = BVLL_TYPE_BACNET_IP;
/* The 2-octet BVLC Length field is the length, in octets, /* The 2-octet BVLC Length field is the length, in octets,
of the entire BVLL message, including the two octets of the of the entire BVLL message, including the two octets of the
length field itself, most significant octet first. */ length field itself, most significant octet first. */
@@ -212,16 +250,19 @@ int bvlc_encode_address_entry(uint8_t * pdu,
len++; len++;
} }
} }
return len; return len;
} }
int bvlc_encode_register_foreign_device(uint8_t * pdu, int bvlc_encode_register_foreign_device(uint8_t * pdu,
uint16_t time_to_live_seconds) uint16_t time_to_live_seconds)
{ {
int len = 0; int len = 0;
if (pdu) { if (pdu) {
pdu[0] = BVLL_TYPE_BACNET_IP; pdu[0] = BVLL_TYPE_BACNET_IP;
pdu[1] = BVLC_REGISTER_FOREIGN_DEVICE; pdu[1] = BVLC_REGISTER_FOREIGN_DEVICE;
int len = 0;
/* The 2-octet BVLC Length field is the length, in octets, /* The 2-octet BVLC Length field is the length, in octets,
of the entire BVLL message, including the two octets of the of the entire BVLL message, including the two octets of the
length field itself, most significant octet first. */ length field itself, most significant octet first. */
@@ -229,67 +270,79 @@ int bvlc_encode_address_entry(uint8_t * pdu,
encode_unsigned16(&pdu[2], time_to_live_seconds); encode_unsigned16(&pdu[2], time_to_live_seconds);
len = 6; len = 6;
} }
return len; return len;
} }
of the entire BVLL message, including the two octets of the
int bvlc_encode_read_fdt(
uint8_t * pdu)
{ {
int len = 0; int len = 0;
if (pdu) { if (pdu) {
pdu[0] = BVLL_TYPE_BACNET_IP; pdu[0] = BVLL_TYPE_BACNET_IP;
pdu[1] = BVLC_READ_FOREIGN_DEVICE_TABLE; pdu[1] = BVLC_READ_FOREIGN_DEVICE_TABLE;
}
/* The 2-octet BVLC Length field is the length, in octets, /* The 2-octet BVLC Length field is the length, in octets,
of the entire BVLL message, including the two octets of the of the entire BVLL message, including the two octets of the
length field itself, most significant octet first. */ length field itself, most significant octet first. */
encode_unsigned16(&pdu[2], 4); encode_unsigned16(&pdu[2], 4);
len = 4; len = 4;
} }
return len; return len;
} }
uint8_t * pdu)
int bvlc_encode_read_fdt_ack_init(
uint8_t * pdu,
unsigned entries)
{ {
int len = 0; int len = 0;
if (pdu) { if (pdu) {
pdu[0] = BVLL_TYPE_BACNET_IP; pdu[0] = BVLL_TYPE_BACNET_IP;
pdu[1] = BVLC_READ_FOREIGN_DEVICE_TABLE_ACK; pdu[1] = BVLC_READ_FOREIGN_DEVICE_TABLE_ACK;
if (pdu) {
/* The 2-octet BVLC Length field is the length, in octets, /* The 2-octet BVLC Length field is the length, in octets,
of the entire BVLL message, including the two octets of the of the entire BVLL message, including the two octets of the
length field itself, most significant octet first. */ length field itself, most significant octet first. */
encode_unsigned16(&pdu[2], 4 + entries * 10); encode_unsigned16(&pdu[2], 4 + entries * 10);
len = 4; len = 4;
} }
return len; return len;
} }
encode_unsigned16(&pdu[2], 4);
int bvlc_encode_delete_fdt_entry(uint8_t * pdu,
struct in_addr *address,
uint16_t port) uint16_t port)
{ {
int len = 0; int len = 0;
if (pdu) { if (pdu) {
pdu[0] = BVLL_TYPE_BACNET_IP; pdu[0] = BVLL_TYPE_BACNET_IP;
pdu[1] = BVLC_READ_FOREIGN_DEVICE_TABLE; pdu[1] = BVLC_READ_FOREIGN_DEVICE_TABLE;
return len;
/* The 2-octet BVLC Length field is the length, in octets, /* The 2-octet BVLC Length field is the length, in octets,
of the entire BVLL message, including the two octets of the of the entire BVLL message, including the two octets of the
length field itself, most significant octet first. */ length field itself, most significant octet first. */
encode_unsigned16(&pdu[2], 10); encode_unsigned16(&pdu[2], 10);
int bvlc_encode_read_bdt_ack_init(
/* FDT Entry */ /* FDT Entry */
encode_unsigned32(&pdu[0], address->s_addr); encode_unsigned32(&pdu[0], address->s_addr);
encode_unsigned16(&pdu[4], port); encode_unsigned16(&pdu[4], port);
len = 10; len = 10;
} }
return len; return len;
} }
int bvlc_encode_distribute_broadcast_to_network(uint8_t * pdu, int bvlc_encode_distribute_broadcast_to_network(uint8_t * pdu,
uint8_t * npdu,
unsigned npdu_length)
{ {
int len = 0; /* return value */ int len = 0; /* return value */
unsigned i; /* for loop counter */ unsigned i; /* for loop counter */
if (pdu) { if (pdu) {
pdu[0] = BVLL_TYPE_BACNET_IP; pdu[0] = BVLL_TYPE_BACNET_IP;
pdu[1] = BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK; pdu[1] = BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK;
length field itself, most significant octet first. */
/* The 2-octet BVLC Length field is the length, in octets, /* The 2-octet BVLC Length field is the length, in octets,
of the entire BVLL message, including the two octets of the of the entire BVLL message, including the two octets of the
length field itself, most significant octet first. */ length field itself, most significant octet first. */
@@ -299,17 +352,20 @@ int bvlc_encode_address_entry(uint8_t * pdu,
len++; len++;
} }
} }
return len; return len;
} }
int bvlc_encode_original_unicast_npdu(uint8_t * pdu,
uint8_t * npdu,
unsigned npdu_length) unsigned npdu_length)
{ {
int len = 0; /* return value */ int len = 0; /* return value */
unsigned i = 0; /* loop counter */ unsigned i = 0; /* loop counter */
if (pdu) { if (pdu) {
pdu[0] = BVLL_TYPE_BACNET_IP; pdu[0] = BVLL_TYPE_BACNET_IP;
pdu[1] = BVLC_ORIGINAL_UNICAST_NPDU; pdu[1] = BVLC_ORIGINAL_UNICAST_NPDU;
/* The 2-octet BVLC Length field is the length, in octets, /* The 2-octet BVLC Length field is the length, in octets,
of the entire BVLL message, including the two octets of the of the entire BVLL message, including the two octets of the
length field itself, most significant octet first. */ length field itself, most significant octet first. */
@@ -319,17 +375,21 @@ int bvlc_encode_address_entry(uint8_t * pdu,
len++; len++;
} }
} }
return len; return len;
} }
length field itself, most significant octet first. */
int bvlc_encode_original_broadcast_npdu(uint8_t * pdu,
uint8_t * npdu,
unsigned npdu_length) unsigned npdu_length)
{ {
int len = 0; /* return value */ int len = 0; /* return value */
unsigned i = 0; /* loop counter */ unsigned i = 0; /* loop counter */
if (pdu) { if (pdu) {
pdu[0] = BVLL_TYPE_BACNET_IP; pdu[0] = BVLL_TYPE_BACNET_IP;
pdu[1] = BVLC_ORIGINAL_BROADCAST_NPDU; pdu[1] = BVLC_ORIGINAL_BROADCAST_NPDU;
/* The 2-octet BVLC Length field is the length, in octets, /* The 2-octet BVLC Length field is the length, in octets,
of the entire BVLL message, including the two octets of the of the entire BVLL message, including the two octets of the
length field itself, most significant octet first. */ length field itself, most significant octet first. */
@@ -339,98 +399,110 @@ int bvlc_encode_address_entry(uint8_t * pdu,
len++; len++;
} }
} }
return len; return len;
} }
}
/* copy the source internet address to the BACnet address */ /* copy the source internet address to the BACnet address */
/* FIXME: IPv6? */ /* FIXME: IPv6? */
/* FIXME: is sockaddr_in host or network order? */ /* FIXME: is sockaddr_in host or network order? */
void bvlc_internet_to_bacnet_address(
BACNET_ADDRESS * src, /* returns the BACnet source address */
struct sockaddr_in *sin) struct sockaddr_in *sin)
{ /* source internet address */ { /* source internet address */
int len = 0; int len = 0;
int bvlc_encode_register_foreign_device(uint8_t * pdu,
if (src && sin) {
len = encode_unsigned32(&src->mac[0], sin->sin_addr.s_addr); len = encode_unsigned32(&src->mac[0], sin->sin_addr.s_addr);
len += encode_unsigned16(&src->mac[4], sin->sin_port); len += encode_unsigned16(&src->mac[4], sin->sin_port);
src->mac_len = len; src->mac_len = len;
src->net = 0; src->net = 0;
src->len = 0; src->len = 0;
} }
return; return;
} }
/* copy the source internet address to the BACnet address */ /* copy the source internet address to the BACnet address */
/* FIXME: IPv6? */ /* FIXME: IPv6? */
/* FIXME: is sockaddr_in host or network order? */ /* FIXME: is sockaddr_in host or network order? */
of the entire BVLL message, including the two octets of the void bvlc_bacnet_to_internet_address(
length field itself, most significant octet first. */ struct sockaddr_in *sin, /* source internet address */
encode_unsigned16(&pdu[2], 6); BACNET_ADDRESS * src) /* returns the BACnet source address */
{
int len = 0; int len = 0;
encode_unsigned16(&pdu[2], time_to_live_seconds);
if (src && sin) {
len = 6; if (src->mac_len == 6) {
len = decode_unsigned32(&src->mac[0], &sin->sin_addr.s_addr); len = decode_unsigned32(&src->mac[0], &sin->sin_addr.s_addr);
len += decode_unsigned16(&src->mac[4], &sin->sin_port); len += decode_unsigned16(&src->mac[4], &sin->sin_port);
} }
} }
return; return;
} }
void bvlc_bdt_forward_npdu(
struct sockaddr_in *sin, /* the source address */
uint8_t * npdu, /* the NPDU */ uint8_t * npdu, /* the NPDU */
uint16_t npdu_length) uint16_t npdu_length)
{ /* length of the NPDU */ { /* length of the NPDU */
{ uint8_t mtu[MAX_MPDU] = {0};
int mtu_len = 0; int mtu_len = 0;
int bytes_sent = 0; int bytes_sent = 0;
unsigned i = 0; /* loop counter */ unsigned i = 0; /* loop counter */
struct sockaddr_in bip_dest; struct sockaddr_in bip_dest;
/* assumes that the driver has already been initialized */ /* assumes that the driver has already been initialized */
if (bip_socket() < 0) {
return; return;
}
/* The 2-octet BVLC Length field is the length, in octets, mtu_len = bvlc_encode_forwarded_npdu(
of the entire BVLL message, including the two octets of the &mtu[0],
sin,
npdu,
npdu_length);
/* load destination IP address */ /* load destination IP address */
bip_dest.sin_family = AF_INET; bip_dest.sin_family = AF_INET;
/* loop through the BDT and send one to each entry, except us */ /* loop through the BDT and send one to each entry, except us */
for (i = 0; i < MAX_BBMD_ENTRIES; i++) {
} if (BBMD_Table[i].valid) {
return len;
/* The B/IP address to which the Forwarded-NPDU message is /* The B/IP address to which the Forwarded-NPDU message is
sent is formed by inverting the broadcast distribution sent is formed by inverting the broadcast distribution
mask in the BDT entry and logically ORing it with the mask in the BDT entry and logically ORing it with the
BBMD address of the same entry. */ BBMD address of the same entry. */
bip_dest.sin_addr.s_addr = bip_dest.sin_addr.s_addr =
uint8_t * pdu, htonl(((~BBMD_Table[i].broadcast_mask.s_addr) |
unsigned entries) BBMD_Table[i].dest_address.s_addr));
bip_dest.sin_port = htons(BBMD_Table[i].dest_port); bip_dest.sin_port = htons(BBMD_Table[i].dest_port);
/* Send the packet */ /* Send the packet */
bytes_sent = bytes_sent =
sendto(bip_socket(), (char *) mtu, mtu_len, 0, sendto(bip_socket(), (char *) mtu, mtu_len, 0,
if (pdu) { (struct sockaddr *) bip_dest,
sizeof(struct sockaddr));
} }
}
return bytes_sent; return bytes_sent;
} }
pdu[1] = BVLC_READ_FOREIGN_DEVICE_TABLE_ACK;
void bvlc_fdt_forward_npdu(
struct sockaddr_in *sin, /* the source address */
uint8_t * npdu, /* returns the NPDU */ uint8_t * npdu, /* returns the NPDU */
/* The 2-octet BVLC Length field is the length, in octets, uint16_t max_npdu) /* amount of space available in the NPDU */
of the entire BVLL message, including the two octets of the {
/* FIXME: add the code */
}
uint16_t bvlc_handler(
BACNET_ADDRESS * src, /* returns the source address */
uint8_t * npdu, /* returns the NPDU */ uint8_t * npdu, /* returns the NPDU */
uint16_t max_npdu, /* amount of space available in the NPDU */ uint16_t max_npdu, /* amount of space available in the NPDU */
unsigned timeout) /* number of milliseconds to wait for a packet */
int received_bytes; int received_bytes;
{
} uint8_t buf[MAX_MPDU] = {0}; /* data */
uint16_t pdu_len = 0; /* return value */ uint16_t pdu_len = 0; /* return value */
fd_set read_fds; fd_set read_fds;
int max; int max;
@@ -440,8 +512,9 @@ void bvlc_bacnet_to_internet_address( struct sockaddr_in *sin, /* source intern
int function_type = 0; int function_type = 0;
/* Make sure the socket is open */ /* Make sure the socket is open */
if (BIP_Socket < 0) {
return 0; return 0;
}
/* we could just use a non-blocking socket, but that consumes all /* we could just use a non-blocking socket, but that consumes all
the CPU time. We can use a timeout; it is only supported as the CPU time. We can use a timeout; it is only supported as
@@ -457,41 +530,37 @@ void bvlc_bacnet_to_internet_address( struct sockaddr_in *sin, /* source intern
FD_ZERO(&read_fds); FD_ZERO(&read_fds);
FD_SET((unsigned int) BIP_Socket, &read_fds); FD_SET((unsigned int) BIP_Socket, &read_fds);
max = BIP_Socket; max = BIP_Socket;
/* see if there is a packet for us */ /* see if there is a packet for us */
encode_unsigned32(&pdu[0], address->s_addr); if (select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0) {
received_bytes = recvfrom(
encode_unsigned16(&pdu[4], port); BIP_Socket,
(char *) &buf[0],
MAX_MPDU, 0,
(struct sockaddr *) &sin, &sin_len); (struct sockaddr *) &sin, &sin_len);
len = 10; } else {
return 0; return 0;
}
/* See if there is a problem */ /* See if there is a problem */
if (received_bytes < 0) { if (received_bytes < 0) {
return 0; return 0;
} }
/* no problem, just no bytes */ /* no problem, just no bytes */
int bvlc_encode_distribute_broadcast_to_network(uint8_t * pdu, if (received_bytes == 0) {
return 0; return 0;
uint8_t * npdu, }
/* the signature of a BACnet/IP packet */ /* the signature of a BACnet/IP packet */
{ if (buf[0] != BVLL_TYPE_BACNET_IP) {
return 0; return 0;
}
function_type = buf[1]; function_type = buf[1];
/* decode the length of the PDU - length is inclusive of BVLC */ /* decode the length of the PDU - length is inclusive of BVLC */
(void) decode_unsigned16(&buf[2], &npdu_len); (void) decode_unsigned16(&buf[2], &npdu_len);
/* subtract off the BVLC header */ /* subtract off the BVLC header */
npdu_len -= 4; npdu_len -= 4;
pdu[0] = BVLL_TYPE_BACNET_IP; switch (function_type) {
case BVLC_RESULT: case BVLC_RESULT:
break; break;
case BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE: case BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE:
of the entire BVLL message, including the two octets of the
/* Upon receipt of a BVLL Write-Broadcast-Distribution-Table /* Upon receipt of a BVLL Write-Broadcast-Distribution-Table
message, a BBMD shall attempt to create or replace its BDT, message, a BBMD shall attempt to create or replace its BDT,
depending on whether or not a BDT has previously existed. depending on whether or not a BDT has previously existed.
@@ -506,7 +575,6 @@ void bvlc_bacnet_to_internet_address( struct sockaddr_in *sin, /* source intern
case BVLC_READ_BROADCAST_DISTRIBUTION_TABLE_ACK: case BVLC_READ_BROADCAST_DISTRIBUTION_TABLE_ACK:
break; break;
case BVLC_FORWARDED_NPDU: case BVLC_FORWARDED_NPDU:
return len;
/* Upon receipt of a BVLL Forwarded-NPDU message, a BBMD shall /* Upon receipt of a BVLL Forwarded-NPDU message, a BBMD shall
process it according to whether it was received from a peer process it according to whether it was received from a peer
BBMD as the result of a directed broadcast or a unicast BBMD as the result of a directed broadcast or a unicast
@@ -541,26 +609,22 @@ void bvlc_bacnet_to_internet_address( struct sockaddr_in *sin, /* source intern
bvlc_fdt_forward_npdu(&sin, &buf[4], npdu_len); bvlc_fdt_forward_npdu(&sin, &buf[4], npdu_len);
break; break;
case BVLC_ORIGINAL_UNICAST_NPDU: case BVLC_ORIGINAL_UNICAST_NPDU:
}
/* ignore messages from me */ /* ignore messages from me */
if (sin.sin_addr.s_addr == BIP_Address.s_addr) {
npdu_len = 0; npdu_len = 0;
} else {
}
bvlc_internet_to_bacnet_address(src, &sin); bvlc_internet_to_bacnet_address(src, &sin);
if (npdu_len < max_npdu) {
/* copy the buffer into the PDU */ /* copy the buffer into the PDU */
uint8_t * npdu,
memmove(&npdu[0], &buf[4], npdu_len); memmove(&npdu[0], &buf[4], npdu_len);
unsigned npdu_length) } else {
/* ignore packets that are too large */ /* ignore packets that are too large */
/* clients should check my max-apdu first */ /* clients should check my max-apdu first */
int len = 0; /* return value */
npdu_len = 0; npdu_len = 0;
} }
}
break; break;
case BVLC_ORIGINAL_BROADCAST_NPDU: case BVLC_ORIGINAL_BROADCAST_NPDU:
if (pdu) {
/* Upon receipt of a BVLL Original-Broadcast-NPDU message, /* Upon receipt of a BVLL Original-Broadcast-NPDU message,
a BBMD shall construct a BVLL Forwarded-NPDU message and a BBMD shall construct a BVLL Forwarded-NPDU message and
send it to each IP subnet in its BDT with the exception send it to each IP subnet in its BDT with the exception
@@ -575,16 +639,14 @@ void bvlc_bacnet_to_internet_address( struct sockaddr_in *sin, /* source intern
shall be sent directly to each foreign device currently in shall be sent directly to each foreign device currently in
the BBMD's FDT also using the BVLL Forwarded-NPDU message. */ the BBMD's FDT also using the BVLL Forwarded-NPDU message. */
bvlc_internet_to_bacnet_address(src, &sin); bvlc_internet_to_bacnet_address(src, &sin);
len++; if (npdu_len < max_npdu) {
/* copy the buffer into the PDU */ /* copy the buffer into the PDU */
}
memmove(&npdu[0], &buf[4], npdu_len); memmove(&npdu[0], &buf[4], npdu_len);
} } else {
/* ignore packets that are too large */ /* ignore packets that are too large */
/* clients should check my max-apdu first */ /* clients should check my max-apdu first */
return len;
npdu_len = 0; npdu_len = 0;
} }
/* if BDT or FDT entries exist, Forward the NPDU */ /* if BDT or FDT entries exist, Forward the NPDU */
bvlc_bdt_forward_npdu(&sin, &buf[4], npdu_len); bvlc_bdt_forward_npdu(&sin, &buf[4], npdu_len);
bvlc_fdt_forward_npdu(&sin, &buf[4], npdu_len); bvlc_fdt_forward_npdu(&sin, &buf[4], npdu_len);
@@ -592,6 +654,7 @@ void bvlc_bacnet_to_internet_address( struct sockaddr_in *sin, /* source intern
default: default:
break; break;
} }
return npdu_len; return npdu_len;
} }
@@ -599,24 +662,27 @@ void bvlc_bacnet_to_internet_address( struct sockaddr_in *sin, /* source intern
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include "ctest.h" #include "ctest.h"
void testBVLC(Test * pTest)
{
(void) pTest; (void) pTest;
} }
#ifdef TEST_BBMD #ifdef TEST_BBMD
int main(void)
{
Test * pTest; Test * pTest;
bool rc; bool rc;
src->mac_len = len;
pTest = ct_create("BACnet Virtual Link Control", NULL);
/* individual tests */ /* individual tests */
rc = ct_addTestFunction(pTest, testBVLC); rc = ct_addTestFunction(pTest, testBVLC);
assert(rc); assert(rc);
/* configure output */ /* configure output */
ct_setStream(pTest, stdout); ct_setStream(pTest, stdout);
ct_run(pTest); ct_run(pTest);
(void) ct_report(pTest); (void) ct_report(pTest);
ct_destroy(pTest); ct_destroy(pTest);
return 0; return 0;
} }