added clang format C and H files.

This commit is contained in:
Steve Karg
2019-10-24 16:23:10 -05:00
parent da91a11454
commit 710173d6e0
205 changed files with 19377 additions and 25754 deletions
+140 -167
View File
@@ -1,31 +1,31 @@
/**
* @file
* @author Andriy Sukhynyuk, Vasyl Tkhir, Andriy Ivasiv
* @date 2012
* @brief Datalink IP module
*
* @section LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
* @file
* @author Andriy Sukhynyuk, Vasyl Tkhir, Andriy Ivasiv
* @date 2012
* @brief Datalink IP module
*
* @section LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -33,26 +33,23 @@
#include "bacint.h"
#ifdef TEST_PACKET
uint8_t test_packet[] = { 0x81, 0x0a, 0x00, 0x16, /* BVLC header */
0x01, 0x24, 0x00, 0x01, 0x01, 0x0b, 0xff, /* NPDU */
0x00, 0x03, 0x01, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x19, 0x55
}; /* APDU */
uint8_t test_packet[] = {0x81, 0x0a, 0x00, 0x16, /* BVLC header */
0x01, 0x24, 0x00, 0x01, 0x01, 0x0b, 0xff, /* NPDU */
0x00, 0x03, 0x01, 0x0c, 0x0c, 0x00, 0x00,
0x00, 0x02, 0x19, 0x55}; /* APDU */
#endif
extern int get_local_address_ioctl(
char *ifname,
struct in_addr *addr,
int request);
extern int get_local_address_ioctl(char *ifname, struct in_addr *addr,
int request);
void *dl_ip_thread(
void *pArgs)
void *dl_ip_thread(void *pArgs)
{
MSGBOX_ID msgboxid;
BACMSG msg_storage, *bacmsg = NULL;
MSG_DATA *msg_data;
ROUTER_PORT *port = (ROUTER_PORT *) pArgs;
IP_DATA ip_data; /* port specific parameters */
BACNET_ADDRESS address = { 0 };
ROUTER_PORT *port = (ROUTER_PORT *)pArgs;
IP_DATA ip_data; /* port specific parameters */
BACNET_ADDRESS address = {0};
int status;
uint8_t shutdown = 0;
@@ -64,7 +61,7 @@ void *dl_ip_thread(
/* allocate buffer */
ip_data.max_buff = MAX_BIP_MPDU;
ip_data.buff = (uint8_t *) malloc(ip_data.max_buff);
ip_data.buff = (uint8_t *)malloc(ip_data.max_buff);
if (ip_data.buff == NULL) {
port->state = INIT_FAILED;
@@ -82,38 +79,37 @@ void *dl_ip_thread(
port->state = RUNNING;
while (!shutdown) {
/* check for incoming messages */
bacmsg = recv_from_msgbox(port->port_id, &msg_storage);
if (bacmsg) {
switch (bacmsg->type) {
case DATA:{
msg_data = (MSG_DATA *) bacmsg->data;
memmove(&address.net, &msg_data->dest.net, 2);
memmove(&address.mac_len, &msg_data->dest.len, 1);
memmove(&address.mac[0], &msg_data->dest.adr[0],
case DATA: {
msg_data = (MSG_DATA *)bacmsg->data;
memmove(&address.net, &msg_data->dest.net, 2);
memmove(&address.mac_len, &msg_data->dest.len, 1);
memmove(&address.mac[0], &msg_data->dest.adr[0],
MAX_MAC_LEN);
dl_ip_send(&ip_data, &address, msg_data->pdu,
msg_data->pdu_len);
dl_ip_send(&ip_data, &address, msg_data->pdu,
msg_data->pdu_len);
check_data(msg_data);
check_data(msg_data);
break;
}
case SERVICE:{
switch (bacmsg->subtype) {
case SHUTDOWN:
del_msgbox(port->port_id);
shutdown = 1;
break;
default:
break;
}
break;
break;
}
case SERVICE: {
switch (bacmsg->subtype) {
case SHUTDOWN:
del_msgbox(port->port_id);
shutdown = 1;
break;
default:
break;
}
break;
}
default:
break;
@@ -140,28 +136,24 @@ void *dl_ip_thread(
return NULL;
}
bool dl_ip_init(
ROUTER_PORT * port,
IP_DATA * ip_data)
bool dl_ip_init(ROUTER_PORT *port, IP_DATA *ip_data)
{
struct sockaddr_in sin;
int socket_opt = 0;
int status = 0; /* for error checking */
int status = 0; /* for error checking */
/* setup port for later use */
ip_data->port = htons(port->params.bip_params.port);
/* get local address */
status =
get_local_address_ioctl(port->iface, &ip_data->local_addr,
SIOCGIFADDR);
get_local_address_ioctl(port->iface, &ip_data->local_addr, SIOCGIFADDR);
if (status < 0) {
return false;
}
/* get broadcast address */
status =
get_local_address_ioctl(port->iface, &ip_data->broadcast_addr,
SIOCGIFBRDADDR);
status = get_local_address_ioctl(port->iface, &ip_data->broadcast_addr,
SIOCGIFBRDADDR);
if (status < 0) {
return false;
}
@@ -173,17 +165,15 @@ bool dl_ip_init(
/* setup socket options */
socket_opt = 1;
status =
setsockopt(ip_data->socket, SOL_SOCKET, SO_REUSEADDR, &socket_opt,
sizeof(socket_opt));
status = setsockopt(ip_data->socket, SOL_SOCKET, SO_REUSEADDR, &socket_opt,
sizeof(socket_opt));
if (status < 0) {
close(ip_data->socket);
return false;
}
status =
setsockopt(ip_data->socket, SOL_SOCKET, SO_BROADCAST, &socket_opt,
sizeof(socket_opt));
status = setsockopt(ip_data->socket, SOL_SOCKET, SO_BROADCAST, &socket_opt,
sizeof(socket_opt));
if (status < 0) {
close(ip_data->socket);
return false;
@@ -196,9 +186,8 @@ bool dl_ip_init(
memset(&sin.sin_zero, '\0', sizeof(sin.sin_zero));
status =
bind(ip_data->socket, (const struct sockaddr *) &sin,
sizeof(struct sockaddr));
status = bind(ip_data->socket, (const struct sockaddr *)&sin,
sizeof(struct sockaddr));
if (status < 0) {
close(ip_data->socket);
return false;
@@ -212,20 +201,17 @@ bool dl_ip_init(
PRINT(INFO, "Interface: %s\n", port->iface);
PRINT(INFO, "IP Address: %s\n", inet_ntoa(ip_data->local_addr));
PRINT(INFO, "IP Broadcast Address: %s\n",
inet_ntoa(ip_data->broadcast_addr));
inet_ntoa(ip_data->broadcast_addr));
PRINT(INFO, "UDP Port: 0x%04X [%hu]\n", (port->params.bip_params.port),
(port->params.bip_params.port));
(port->params.bip_params.port));
return true;
}
int dl_ip_send(
IP_DATA * data,
BACNET_ADDRESS * dest,
uint8_t * pdu,
unsigned pdu_len)
int dl_ip_send(IP_DATA *data, BACNET_ADDRESS *dest, uint8_t *pdu,
unsigned pdu_len)
{
struct sockaddr_in bip_dest = { 0 };
struct sockaddr_in bip_dest = {0};
int buff_len = 0;
int bytes_sent = 0;
@@ -249,33 +235,28 @@ int dl_ip_send(
}
buff_len = 2;
buff_len +=
encode_unsigned16(&data->buff[buff_len],
(uint16_t) (pdu_len + 4 /*inclusive */ ));
buff_len += encode_unsigned16(&data->buff[buff_len],
(uint16_t)(pdu_len + 4 /*inclusive */));
memcpy(&data->buff[buff_len], pdu, pdu_len);
buff_len += pdu_len;
/* send the packet */
bytes_sent =
sendto(data->socket, (char *) data->buff, buff_len, 0,
(struct sockaddr *) &bip_dest, sizeof(struct sockaddr));
bytes_sent = sendto(data->socket, (char *)data->buff, buff_len, 0,
(struct sockaddr *)&bip_dest, sizeof(struct sockaddr));
PRINT(DEBUG, "send to %s\n", inet_ntoa(bip_dest.sin_addr));
return bytes_sent;
}
int dl_ip_recv(
IP_DATA * data,
MSG_DATA ** msg_data,
BACNET_ADDRESS * src,
unsigned timeout)
int dl_ip_recv(IP_DATA *data, MSG_DATA **msg_data, BACNET_ADDRESS *src,
unsigned timeout)
{
int received_bytes = 0;
uint16_t buff_len = 0; /* return value */
uint16_t buff_len = 0; /* return value */
fd_set read_fds;
struct timeval select_timeout;
struct sockaddr_in sin = { 0 };
struct sockaddr_in sin = {0};
socklen_t sin_len = sizeof(sin);
/* make sure the socket is open */
@@ -304,8 +285,8 @@ int dl_ip_recv(
/* see if there is a packet for us */
if (ret > 0)
received_bytes =
recvfrom(data->socket, (char *) &data->buff[0], data->max_buff, 0,
(struct sockaddr *) &sin, &sin_len);
recvfrom(data->socket, (char *)&data->buff[0], data->max_buff, 0,
(struct sockaddr *)&sin, &sin_len);
else
return 0;
#endif
@@ -322,76 +303,69 @@ int dl_ip_recv(
switch (data->buff[1]) {
case BVLC_ORIGINAL_UNICAST_NPDU:
case BVLC_ORIGINAL_BROADCAST_NPDU:{
if ((sin.sin_addr.s_addr == data->local_addr.s_addr) &&
(sin.sin_port == data->port)) {
case BVLC_ORIGINAL_BROADCAST_NPDU: {
if ((sin.sin_addr.s_addr == data->local_addr.s_addr) &&
(sin.sin_port == data->port)) {
buff_len = 0;
PRINT(DEBUG, "BIP: src is me. Discarded!\n");
} else {
src->mac_len = 6;
memcpy(&src->mac[0], &sin.sin_addr.s_addr, 4);
memcpy(&src->mac[4], &sin.sin_port, 2);
(void)decode_unsigned16(&data->buff[2], &buff_len);
/* subtract off the BVLC header */
buff_len -= 4;
if (buff_len < data->max_buff) {
/* allocate data message stucture */
(*msg_data) = (MSG_DATA *)malloc(sizeof(MSG_DATA));
(*msg_data)->pdu_len = buff_len;
(*msg_data)->pdu = (uint8_t *)malloc((*msg_data)->pdu_len);
/* fill up data message structure */
memmove(&(*msg_data)->pdu[0], &data->buff[4],
(*msg_data)->pdu_len);
memmove(&(*msg_data)->src, src, sizeof(BACNET_ADDRESS));
}
/* ignore packets that are too large */
else {
buff_len = 0;
PRINT(DEBUG, "BIP: src is me. Discarded!\n");
PRINT(ERROR, "BIP: PDU too large. Discarded!.\n");
}
}
} break;
} else {
src->mac_len = 6;
memcpy(&src->mac[0], &sin.sin_addr.s_addr, 4);
memcpy(&src->mac[4], &sin.sin_port, 2);
case BVLC_FORWARDED_NPDU: {
memcpy(&sin.sin_addr.s_addr, &data->buff[4], 4);
memcpy(&sin.sin_port, &data->buff[8], 2);
if ((sin.sin_addr.s_addr == data->local_addr.s_addr) &&
(sin.sin_port == data->port)) {
buff_len = 0;
} else {
src->mac_len = 6;
memcpy(&src->mac[0], &sin.sin_addr.s_addr, 4);
memcpy(&src->mac[4], &sin.sin_port, 2);
(void) decode_unsigned16(&data->buff[2], &buff_len);
/* subtract off the BVLC header */
buff_len -= 4;
if (buff_len < data->max_buff) {
/* allocate data message stucture */
(*msg_data) = (MSG_DATA *) malloc(sizeof(MSG_DATA));
(*msg_data)->pdu_len = buff_len;
(*msg_data)->pdu =
(uint8_t *) malloc((*msg_data)->pdu_len);
/* fill up data message structure */
memmove(&(*msg_data)->pdu[0], &data->buff[4],
(void)decode_unsigned16(&data->buff[2], &buff_len);
/* subtract off the BVLC header */
buff_len -= 10;
if (buff_len < data->max_buff) {
/* allocate data message stucture */
(*msg_data) = (MSG_DATA *)malloc(sizeof(MSG_DATA));
(*msg_data)->pdu_len = buff_len;
(*msg_data)->pdu = (uint8_t *)malloc((*msg_data)->pdu_len);
/* fill up data message structure */
memmove(&(*msg_data)->pdu[0], &data->buff[4 + 6],
(*msg_data)->pdu_len);
memmove(&(*msg_data)->src, src,
sizeof(BACNET_ADDRESS));
}
memmove(&(*msg_data)->src, src, sizeof(BACNET_ADDRESS));
} else {
/* ignore packets that are too large */
else {
buff_len = 0;
PRINT(ERROR, "BIP: PDU too large. Discarded!.\n");
}
}
}
break;
case BVLC_FORWARDED_NPDU:{
memcpy(&sin.sin_addr.s_addr, &data->buff[4], 4);
memcpy(&sin.sin_port, &data->buff[8], 2);
if ((sin.sin_addr.s_addr == data->local_addr.s_addr) &&
(sin.sin_port == data->port)) {
buff_len = 0;
} else {
src->mac_len = 6;
memcpy(&src->mac[0], &sin.sin_addr.s_addr, 4);
memcpy(&src->mac[4], &sin.sin_port, 2);
(void) decode_unsigned16(&data->buff[2], &buff_len);
/* subtract off the BVLC header */
buff_len -= 10;
if (buff_len < data->max_buff) {
/* allocate data message stucture */
(*msg_data) = (MSG_DATA *) malloc(sizeof(MSG_DATA));
(*msg_data)->pdu_len = buff_len;
(*msg_data)->pdu =
(uint8_t *) malloc((*msg_data)->pdu_len);
/* fill up data message structure */
memmove(&(*msg_data)->pdu[0], &data->buff[4 + 6],
(*msg_data)->pdu_len);
memmove(&(*msg_data)->src, src,
sizeof(BACNET_ADDRESS));
} else {
/* ignore packets that are too large */
buff_len = 0;
}
}
}
break;
} break;
default:
PRINT(ERROR, "BIP: BVLC discarded!\n");
@@ -401,8 +375,7 @@ int dl_ip_recv(
return buff_len;
}
void dl_ip_cleanup(
IP_DATA * ip_data)
void dl_ip_cleanup(IP_DATA *ip_data)
{
/* free buffer */
if (ip_data->buff)
+186 -232
View File
@@ -1,47 +1,47 @@
/**
* @file
* @author Andriy Sukhynyuk, Vasyl Tkhir, Andriy Ivasiv
* @date 2012
* @brief BACnet/IP to MS/TP Router example application.
* The Router connects two or more BACnet/IP and BACnet MS/TP networks.
* Number of netwoks is limited only by available hardware communication
* devices (or ports for Ethernet).
*
* @section LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
* @file
* @author Andriy Sukhynyuk, Vasyl Tkhir, Andriy Ivasiv
* @date 2012
* @brief BACnet/IP to MS/TP Router example application.
* The Router connects two or more BACnet/IP and BACnet MS/TP networks.
* Number of netwoks is limited only by available hardware communication
* devices (or ports for Ethernet).
*
* @section LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h> /* for time */
#include <time.h> /* for time */
#include <errno.h>
#include <assert.h>
#include <fcntl.h>
#include <libconfig.h> /* read config files */
#include <unistd.h> /* for getopt */
#include <termios.h> /* used in kbhit() */
#include <libconfig.h> /* read config files */
#include <unistd.h> /* for getopt */
#include <termios.h> /* used in kbhit() */
#include <getopt.h>
#include <sys/ioctl.h>
#include <net/if.h>
@@ -55,49 +55,33 @@
#define KEY_ESC 27
ROUTER_PORT *head = NULL; /* pointer to list of router ports */
ROUTER_PORT *head = NULL; /* pointer to list of router ports */
int port_count;
void print_help(
);
void print_help();
bool read_config(
char *filepath);
bool read_config(char *filepath);
bool parse_cmd(
int argc,
char *argv[]);
bool parse_cmd(int argc, char *argv[]);
void init_port_threads(
ROUTER_PORT * port_list);
void init_port_threads(ROUTER_PORT *port_list);
bool init_router(
);
bool init_router();
void cleanup(
);
void cleanup();
void print_msg(
BACMSG * msg);
void print_msg(BACMSG *msg);
uint16_t process_msg(
BACMSG * msg,
MSG_DATA * data,
uint8_t ** buff);
uint16_t process_msg(BACMSG *msg, MSG_DATA *data, uint8_t **buff);
uint16_t get_next_free_dnet(
);
uint16_t get_next_free_dnet();
int kbhit(
);
int kbhit();
inline bool is_network_msg(
BACMSG * msg);
inline bool is_network_msg(BACMSG *msg);
int main(
int argc,
char *argv[])
int main(int argc, char *argv[])
{
printf("I am router\n");
@@ -119,9 +103,8 @@ int main(
return -1;
}
send_network_message(NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK, msg_data,
&buff, NULL);
&buff, NULL);
while (true) {
if (kbhit()) {
@@ -135,83 +118,78 @@ int main(
bacmsg = recv_from_msgbox(head->main_id, &msg_storage);
if (bacmsg) {
switch (bacmsg->type) {
case DATA:
{
MSGBOX_ID msg_src = bacmsg->origin;
case DATA: {
MSGBOX_ID msg_src = bacmsg->origin;
/* allocate message structure */
msg_data = malloc(sizeof(MSG_DATA));
if (!msg_data) {
PRINT(ERROR, "Error: Could not allocate memory\n");
/* allocate message structure */
msg_data = malloc(sizeof(MSG_DATA));
if (!msg_data) {
PRINT(ERROR, "Error: Could not allocate memory\n");
break;
}
print_msg(bacmsg);
if (is_network_msg(bacmsg)) {
buff_len =
process_network_message(bacmsg, msg_data, &buff);
if (buff_len == 0) {
free_data(bacmsg->data);
break;
}
} else {
buff_len = process_msg(bacmsg, msg_data, &buff);
}
/* if buff_len */
/* >0 - form new message and send */
/* =-1 - try to find next router */
/* other value - discard message */
if (buff_len > 0) {
/* form new message */
msg_data->pdu = buff;
msg_data->pdu_len = buff_len;
msg_storage.origin = head->main_id;
msg_storage.type = DATA;
msg_storage.data = msg_data;
print_msg(bacmsg);
if (is_network_msg(bacmsg)) {
buff_len =
process_network_message(bacmsg, msg_data,
&buff);
if (buff_len == 0) {
free_data(bacmsg->data);
break;
}
msg_data->ref_count = 1;
send_to_msgbox(msg_src, &msg_storage);
} else if (msg_data->dest.net !=
BACNET_BROADCAST_NETWORK) {
msg_data->ref_count = 1;
port =
find_dnet(msg_data->dest.net, &msg_data->dest);
send_to_msgbox(port->port_id, &msg_storage);
} else {
buff_len = process_msg(bacmsg, msg_data, &buff);
}
/* if buff_len */
/* >0 - form new message and send */
/* =-1 - try to find next router */
/* other value - discard message */
if (buff_len > 0) {
/* form new message */
msg_data->pdu = buff;
msg_data->pdu_len = buff_len;
msg_storage.origin = head->main_id;
msg_storage.type = DATA;
msg_storage.data = msg_data;
print_msg(bacmsg);
if (is_network_msg(bacmsg)) {
msg_data->ref_count = 1;
send_to_msgbox(msg_src, &msg_storage);
} else if (msg_data->dest.net !=
BACNET_BROADCAST_NETWORK) {
msg_data->ref_count = 1;
port =
find_dnet(msg_data->dest.net,
&msg_data->dest);
send_to_msgbox(port->port_id, &msg_storage);
} else {
port = head;
msg_data->ref_count = port_count - 1;
while (port != NULL) {
if (port->port_id == msg_src ||
port->state == FINISHED) {
port = port->next;
continue;
}
send_to_msgbox(port->port_id,
&msg_storage);
port = head;
msg_data->ref_count = port_count - 1;
while (port != NULL) {
if (port->port_id == msg_src ||
port->state == FINISHED) {
port = port->next;
continue;
}
send_to_msgbox(port->port_id, &msg_storage);
port = port->next;
}
} else if (buff_len == -1) {
uint16_t net = msg_data->dest.net; /* NET to find */
PRINT(INFO, "Searching NET...\n");
send_network_message
(NETWORK_MESSAGE_WHO_IS_ROUTER_TO_NETWORK,
msg_data, &buff, &net);
} else {
/* if invalid message send Reject-Message-To-Network */
PRINT(ERROR, "Error: Invalid message\n");
free_data(msg_data);
}
} else if (buff_len == -1) {
uint16_t net = msg_data->dest.net; /* NET to find */
PRINT(INFO, "Searching NET...\n");
send_network_message(
NETWORK_MESSAGE_WHO_IS_ROUTER_TO_NETWORK, msg_data,
&buff, &net);
} else {
/* if invalid message send Reject-Message-To-Network */
PRINT(ERROR, "Error: Invalid message\n");
free_data(msg_data);
}
break;
} break;
case SERVICE:
default:
break;
@@ -220,27 +198,29 @@ int main(
}
return 0;
}
void print_help(
)
void print_help()
{
printf("Usage: router <init_method> [init_parameters]\n" "\ninit_method:\n"
"-c, --config <filepath>\n\tinitialize router with a configuration file (.cfg) located at <filepath>\n"
"-D, --device <dev_type> <iface> [params]\n\tinitialize a <dev_type> device using an <iface> interface specified with\n\t[params]\n"
printf(
"Usage: router <init_method> [init_parameters]\n"
"\ninit_method:\n"
"-c, --config <filepath>\n\tinitialize router with a configuration "
"file (.cfg) located at <filepath>\n"
"-D, --device <dev_type> <iface> [params]\n\tinitialize a <dev_type> "
"device using an <iface> interface specified with\n\t[params]\n"
"\ninit_parameters:\n"
"-n, --network <net>\n\tspecify device network number\n"
"-P, --port <port>\n\tspecify udp port for BIP device\n"
"-m, --mac <mac_address> [max_master] [max_frames]\n\tspecify MSTP port parameters\n"
"-m, --mac <mac_address> [max_master] [max_frames]\n\tspecify MSTP "
"port parameters\n"
"-b, --baud <baud>\n\tspecify MSTP port baud rate\n"
"-p, --parity <None|Even|Odd>\n\tspecify MSTP port parity\n"
"-d, --databits <5|6|7|8>\n\tspecify MSTP port databits\n"
"-s, --stopbits <1|2>\n\tspecify MSTP port stopbits\n");
}
bool read_config(
char *filepath)
bool read_config(char *filepath)
{
config_t cfg;
config_setting_t *setting;
@@ -252,7 +232,7 @@ bool read_config(
/* open configuration file */
if (!config_read_file(&cfg, filepath)) {
PRINT(ERROR, "Config file error: %d - %s\n", config_error_line(&cfg),
config_error_text(&cfg));
config_error_text(&cfg));
config_destroy(&cfg);
return false;
}
@@ -273,13 +253,13 @@ bool read_config(
/* create new list node to store port information */
if (head == NULL) {
head = (ROUTER_PORT *) malloc(sizeof(ROUTER_PORT));
head = (ROUTER_PORT *)malloc(sizeof(ROUTER_PORT));
head->next = NULL;
current = head;
} else {
ROUTER_PORT *tmp = current;
current = current->next;
current = (ROUTER_PORT *) malloc(sizeof(ROUTER_PORT));
current = (ROUTER_PORT *)malloc(sizeof(ROUTER_PORT));
current->next = NULL;
tmp->next = current;
}
@@ -293,7 +273,7 @@ bool read_config(
result = config_setting_lookup_string(port, "device", &iface);
if (result) {
current->iface =
(char *) malloc((strlen(iface) + 1) * sizeof(char));
(char *)malloc((strlen(iface) + 1) * sizeof(char));
strcpy(current->iface, iface);
/* check if interface is valid */
@@ -301,13 +281,13 @@ bool read_config(
if (fd) {
struct ifreq ifr;
strncpy(ifr.ifr_name, current->iface,
sizeof(ifr.ifr_name) - 1);
sizeof(ifr.ifr_name) - 1);
result = ioctl(fd, SIOCGIFADDR, &ifr);
if (result != -1) {
close(fd);
} else {
PRINT(ERROR,
"Error: Invalid interface for BIP device\n");
"Error: Invalid interface for BIP device\n");
return false;
}
}
@@ -315,15 +295,14 @@ bool read_config(
current->iface = "eth0";
}
result =
config_setting_lookup_int(port, "port", (int *) &param);
result = config_setting_lookup_int(port, "port", (int *)&param);
if (result) {
current->params.bip_params.port = param;
} else {
current->params.bip_params.port = 0xBAC0;
}
result =
config_setting_lookup_int(port, "network", (int *) &param);
config_setting_lookup_int(port, "network", (int *)&param);
if (result) {
current->route_info.net = param;
} else {
@@ -336,7 +315,7 @@ bool read_config(
result = config_setting_lookup_string(port, "device", &iface);
if (result) {
current->iface =
(char *) malloc((strlen(iface) + 1) * sizeof(char));
(char *)malloc((strlen(iface) + 1) * sizeof(char));
strcpy(current->iface, iface);
/* check if interface is valid */
@@ -345,14 +324,13 @@ bool read_config(
close(fd);
} else {
PRINT(ERROR,
"Error: Invalid interface for MSTP device\n");
"Error: Invalid interface for MSTP device\n");
return false;
}
} else {
current->iface = "/dev/ttyS0";
}
result =
config_setting_lookup_int(port, "mac", (int *) &param);
result = config_setting_lookup_int(port, "mac", (int *)&param);
if (result) {
current->route_info.mac[0] = param;
current->route_info.mac_len = 1;
@@ -360,24 +338,21 @@ bool read_config(
current->route_info.mac[0] = 127;
current->route_info.mac_len = 1;
}
result =
config_setting_lookup_int(port, "max_master",
(int *) &param);
result = config_setting_lookup_int(port, "max_master",
(int *)&param);
if (result) {
current->params.mstp_params.max_master = param;
} else {
current->params.mstp_params.max_master = 127;
}
result =
config_setting_lookup_int(port, "max_frames",
(int *) &param);
result = config_setting_lookup_int(port, "max_frames",
(int *)&param);
if (result) {
current->params.mstp_params.max_frames = param;
} else {
current->params.mstp_params.max_frames = 1;
}
result =
config_setting_lookup_int(port, "baud", (int *) &param);
result = config_setting_lookup_int(port, "baud", (int *)&param);
if (result) {
current->params.mstp_params.baudrate = param;
} else {
@@ -401,23 +376,21 @@ bool read_config(
current->params.mstp_params.parity = PARITY_NONE;
}
result =
config_setting_lookup_int(port, "databits",
(int *) &param);
config_setting_lookup_int(port, "databits", (int *)&param);
if (result && param >= 5 && param <= 8) {
current->params.mstp_params.databits = param;
} else {
current->params.mstp_params.databits = 8;
}
result =
config_setting_lookup_int(port, "stopbits",
(int *) &param);
config_setting_lookup_int(port, "stopbits", (int *)&param);
if (result && param >= 1 && param <= 2) {
current->params.mstp_params.stopbits = param;
} else {
current->params.mstp_params.stopbits = 1;
}
result =
config_setting_lookup_int(port, "network", (int *) &param);
config_setting_lookup_int(port, "network", (int *)&param);
if (result) {
current->route_info.net = param;
} else {
@@ -439,9 +412,7 @@ bool read_config(
return true;
}
bool parse_cmd(
int argc,
char *argv[])
bool parse_cmd(int argc, char *argv[])
{
const char *optString = "hc:D:";
const char *bipString = "p:n:D:";
@@ -463,11 +434,10 @@ bool parse_cmd(
int opt, dev_opt, index, result, fd;
ROUTER_PORT *current = head;
if (argc < 2)
{
if (argc < 2) {
print_help();
return false;
}
return false;
}
/* begin checking cmd parameters */
opt = getopt_long(argc, argv, optString, Options, &index);
@@ -485,13 +455,13 @@ bool parse_cmd(
/* create new list node to store port information */
if (head == NULL) {
head = (ROUTER_PORT *) malloc(sizeof(ROUTER_PORT));
head = (ROUTER_PORT *)malloc(sizeof(ROUTER_PORT));
head->next = NULL;
current = head;
} else {
ROUTER_PORT *tmp = current;
current = current->next;
current = (ROUTER_PORT *) malloc(sizeof(ROUTER_PORT));
current = (ROUTER_PORT *)malloc(sizeof(ROUTER_PORT));
current->next = NULL;
tmp->next = current;
}
@@ -507,7 +477,7 @@ bool parse_cmd(
}
/* setup default parameters */
current->params.bip_params.port = 0xBAC0; /* 47808 */
current->params.bip_params.port = 0xBAC0; /* 47808 */
current->route_info.net = get_next_free_dnet();
/* check if interface is valid */
@@ -515,13 +485,13 @@ bool parse_cmd(
if (fd) {
struct ifreq ifr;
strncpy(ifr.ifr_name, current->iface,
sizeof(ifr.ifr_name) - 1);
sizeof(ifr.ifr_name) - 1);
result = ioctl(fd, SIOCGIFADDR, &ifr);
if (result != -1) {
close(fd);
} else {
PRINT(ERROR,
"Error: Invalid interface for BIP device \n");
"Error: Invalid interface for BIP device \n");
return false;
}
}
@@ -534,24 +504,23 @@ bool parse_cmd(
result = atoi(optarg);
if (result) {
current->params.bip_params.port =
(uint16_t) result;
(uint16_t)result;
} else {
current->params.bip_params.port = 0xBAC0; /* 47808 */
current->params.bip_params.port =
0xBAC0; /* 47808 */
}
break;
case 'n':
result = atoi(optarg);
if (result) {
current->route_info.net =
(uint16_t) result;
current->route_info.net = (uint16_t)result;
} else {
current->route_info.net = port_count;
}
break;
}
dev_opt =
getopt_long(argc, argv, bipString, Options,
&index);
getopt_long(argc, argv, bipString, Options, &index);
}
opt = dev_opt;
} else if (strcmp(optarg, "mstp") == 0) {
@@ -569,7 +538,7 @@ bool parse_cmd(
close(fd);
} else {
PRINT(ERROR,
"Error: Invalid interface for MSTP device\n");
"Error: Invalid interface for MSTP device\n");
return false;
}
@@ -592,22 +561,19 @@ bool parse_cmd(
result = atoi(optarg);
if (result) {
current->route_info.mac[0] =
(uint8_t) result;
(uint8_t)result;
}
if (argv[optind][0] != '-') {
current->params.mstp_params.max_master =
(uint8_t) atoi(argv[optind]);
if (current->params.mstp_params.
max_master <
(uint8_t)atoi(argv[optind]);
if (current->params.mstp_params.max_master <
current->route_info.mac[0])
current->params.mstp_params.
max_master =
current->params.mstp_params.max_master =
current->route_info.mac[0];
if (argv[optind + 1][0] != '-') {
current->params.mstp_params.
max_frames =
(uint8_t) atoi(argv[optind + 1]);
current->params.mstp_params.max_frames =
(uint8_t)atoi(argv[optind + 1]);
}
}
break;
@@ -615,7 +581,7 @@ bool parse_cmd(
result = atoi(optarg);
if (result) {
current->params.mstp_params.baudrate =
(uint32_t) result;
(uint32_t)result;
}
break;
case 'p':
@@ -638,27 +604,25 @@ bool parse_cmd(
result = atoi(optarg);
if (result >= 5 && result <= 8) {
current->params.mstp_params.databits =
(uint8_t) result;
(uint8_t)result;
}
break;
case 's':
result = atoi(optarg);
if (result >= 1 && result <= 2) {
current->params.mstp_params.stopbits =
(uint8_t) result;
(uint8_t)result;
}
break;
case 'n':
result = atoi(optarg);
if (result) {
current->route_info.net =
(uint16_t) result;
current->route_info.net = (uint16_t)result;
}
break;
}
dev_opt =
getopt_long(argc, argv, mstpString, Options,
&index);
dev_opt = getopt_long(argc, argv, mstpString, Options,
&index);
}
opt = dev_opt;
} else {
@@ -671,8 +635,7 @@ bool parse_cmd(
return true;
}
void init_port_threads(
ROUTER_PORT * port_list)
void init_port_threads(ROUTER_PORT *port_list)
{
ROUTER_PORT *port = port_list;
pthread_t *thread;
@@ -688,17 +651,16 @@ void init_port_threads(
}
port->state = INIT;
thread = (pthread_t *) malloc(sizeof(pthread_t));
thread = (pthread_t *)malloc(sizeof(pthread_t));
pthread_create(thread, NULL, port->func, port);
pthread_detach(*thread); /* for proper thread termination */
pthread_detach(*thread); /* for proper thread termination */
port = port->next;
}
}
bool init_router(
)
bool init_router()
{
MSGBOX_ID msgboxid;
ROUTER_PORT *port;
@@ -735,8 +697,7 @@ bool init_router(
return true;
}
void cleanup(
)
void cleanup()
{
ROUTER_PORT *port;
BACMSG msg;
@@ -748,7 +709,7 @@ void cleanup(
msg.type = SERVICE;
msg.subtype = SHUTDOWN;
del_msgbox(head->main_id); /* close routers message box */
del_msgbox(head->main_id); /* close routers message box */
/* send shutdown message to all router ports */
port = head;
@@ -772,12 +733,11 @@ void cleanup(
pthread_mutex_destroy(&msg_lock);
}
void print_msg(
BACMSG * msg)
void print_msg(BACMSG *msg)
{
if (msg->type == DATA) {
int i;
MSG_DATA *data = (MSG_DATA *) msg->data;
MSG_DATA *data = (MSG_DATA *)msg->data;
if (data->pdu_len) {
PRINT(DEBUG, "Message PDU: ");
@@ -788,12 +748,8 @@ void print_msg(
}
}
uint16_t process_msg(
BACMSG * msg,
MSG_DATA * data,
uint8_t ** buff)
uint16_t process_msg(BACMSG *msg, MSG_DATA *data, uint8_t **buff)
{
BACNET_ADDRESS addr;
BACNET_NPDU_DATA npdu_data;
ROUTER_PORT *srcport;
@@ -816,12 +772,14 @@ uint16_t process_msg(
if (srcport && destport) {
data->src.net = srcport->route_info.net;
/* if received from another router save real source address (not other router source address) */
/* if received from another router save real source address (not other
* router source address) */
if (addr.net > 0 && addr.net < BACNET_BROADCAST_NETWORK &&
data->src.net != addr.net)
memmove(&data->src, &addr, sizeof(BACNET_ADDRESS));
/* encode both source and destination for broadcast and router-to-router communication */
/* encode both source and destination for broadcast and router-to-router
* communication */
if (data->dest.net == BACNET_BROADCAST_NETWORK ||
destport->route_info.net != data->dest.net) {
npdu_len =
@@ -832,9 +790,10 @@ uint16_t process_msg(
buff_len = npdu_len + data->pdu_len - apdu_offset;
*buff = (uint8_t *) malloc(buff_len);
*buff = (uint8_t *)malloc(buff_len);
memmove(*buff, npdu, npdu_len); /* copy newly formed NPDU */
memmove(*buff + npdu_len, &data->pdu[apdu_offset], apdu_len); /* copy APDU */
memmove(*buff + npdu_len, &data->pdu[apdu_offset],
apdu_len); /* copy APDU */
} else {
/* request net search */
@@ -842,13 +801,12 @@ uint16_t process_msg(
}
/* delete received message */
free_data((MSG_DATA *) msg->data);
free_data((MSG_DATA *)msg->data);
return buff_len;
}
int kbhit(
)
int kbhit()
{
static const int STDIN = 0;
static bool initialized = false;
@@ -868,22 +826,18 @@ int kbhit(
return bytesWaiting;
}
bool is_network_msg(
BACMSG * msg)
bool is_network_msg(BACMSG *msg)
{
uint8_t control_byte; /* NPDU control byte */
MSG_DATA *data = (MSG_DATA *) msg->data;
uint8_t control_byte; /* NPDU control byte */
MSG_DATA *data = (MSG_DATA *)msg->data;
control_byte = data->pdu[1];
return control_byte & 0x80; /* check 7th bit */
}
uint16_t get_next_free_dnet(
)
uint16_t get_next_free_dnet()
{
ROUTER_PORT *port = head;
uint16_t i = 1;
while (port) {
+36 -48
View File
@@ -1,31 +1,31 @@
/**
* @file
* @author Andriy Sukhynyuk, Vasyl Tkhir, Andriy Ivasiv
* @date 2012
* @brief Message queue module
*
* @section LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
* @file
* @author Andriy Sukhynyuk, Vasyl Tkhir, Andriy Ivasiv
* @date 2012
* @brief Message queue module
*
* @section LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
@@ -35,8 +35,7 @@
pthread_mutex_t msg_lock = PTHREAD_MUTEX_INITIALIZER;
MSGBOX_ID create_msgbox(
)
MSGBOX_ID create_msgbox()
{
MSGBOX_ID msgboxid;
@@ -48,28 +47,23 @@ MSGBOX_ID create_msgbox(
return msgboxid;
}
bool send_to_msgbox(
MSGBOX_ID dest,
BACMSG * msg)
bool send_to_msgbox(MSGBOX_ID dest, BACMSG *msg)
{
int err;
err = msgsnd(dest, msg, sizeof(BACMSG)-sizeof(MSGTYPE), 0);
err = msgsnd(dest, msg, sizeof(BACMSG) - sizeof(MSGTYPE), 0);
if (err) {
return false;
}
return true;
}
BACMSG *recv_from_msgbox(
MSGBOX_ID src,
BACMSG * msg)
BACMSG *recv_from_msgbox(MSGBOX_ID src, BACMSG *msg)
{
int recv_bytes;
recv_bytes = msgrcv(src, msg, sizeof(BACMSG)-sizeof(MSGTYPE), 0, IPC_NOWAIT);
recv_bytes =
msgrcv(src, msg, sizeof(BACMSG) - sizeof(MSGTYPE), 0, IPC_NOWAIT);
if (recv_bytes > 0) {
return msg;
} else {
@@ -77,20 +71,16 @@ BACMSG *recv_from_msgbox(
}
}
void del_msgbox(
MSGBOX_ID msgboxid)
void del_msgbox(MSGBOX_ID msgboxid)
{
if (msgboxid == INVALID_MSGBOX_ID)
return;
else
msgctl(msgboxid, IPC_RMID, NULL);
}
void free_data(
MSG_DATA * data)
void free_data(MSG_DATA *data)
{
if (data->pdu) {
free(data->pdu);
data->pdu = NULL;
@@ -101,10 +91,8 @@ void free_data(
}
}
void check_data(
MSG_DATA * data)
void check_data(MSG_DATA *data)
{
/* lock and decrement messages reference count */
pthread_mutex_lock(&msg_lock);
if (--data->ref_count == 0) {
+45 -49
View File
@@ -1,31 +1,31 @@
/**
* @file
* @author Andriy Sukhynyuk, Vasyl Tkhir, Andriy Ivasiv
* @date 2012
* @brief Datalink for MS/TP module
*
* @section LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
* @file
* @author Andriy Sukhynyuk, Vasyl Tkhir, Andriy Ivasiv
* @date 2012
* @brief Datalink for MS/TP module
*
* @section LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -36,18 +36,16 @@
#define MSTP_THREAD_PRINT_ENABLED
#ifdef MSTP_THREAD_PRINT_ENABLED
#define mstp_thread_debug(...) fprintf(stderr, __VA_ARGS__)
#define mstp_thread_debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define mstp_thread_debug(...)
#define mstp_thread_debug(...)
#endif
void *dl_mstp_thread(
void *pArgs)
void *dl_mstp_thread(void *pArgs)
{
ROUTER_PORT *port = (ROUTER_PORT *) pArgs;
struct mstp_port_struct_t mstp_port = { (MSTP_RECEIVE_STATE) 0 };
volatile SHARED_MSTP_DATA shared_port_data = { 0 };
ROUTER_PORT *port = (ROUTER_PORT *)pArgs;
struct mstp_port_struct_t mstp_port = {(MSTP_RECEIVE_STATE)0};
volatile SHARED_MSTP_DATA shared_port_data = {0};
uint16_t pdu_len;
uint8_t shutdown = 0;
@@ -87,11 +85,10 @@ void *dl_mstp_thread(
if (port->params.mstp_params.stopbits == 2)
shared_port_data.RS485MOD |= CSTOPB;
mstp_port.UserData = (void *) &shared_port_data;
mstp_port.UserData = (void *)&shared_port_data;
dlmstp_set_baud_rate(&mstp_port, port->params.mstp_params.baudrate);
dlmstp_set_mac_address(&mstp_port, port->route_info.mac[0]);
dlmstp_set_max_info_frames(&mstp_port,
port->params.mstp_params.max_frames);
dlmstp_set_max_info_frames(&mstp_port, port->params.mstp_params.max_frames);
dlmstp_set_max_master(&mstp_port, port->params.mstp_params.max_master);
if (!dlmstp_init(&mstp_port, port->iface))
printf("MSTP %s init failed. Stop.\n", port->iface);
@@ -114,7 +111,7 @@ void *dl_mstp_thread(
if (bacmsg) {
switch (bacmsg->type) {
case DATA:
msg_data = (MSG_DATA *) bacmsg->data;
msg_data = (MSG_DATA *)bacmsg->data;
if (msg_data->dest.net == BACNET_BROADCAST_NETWORK) {
dlmstp_get_broadcast_address(&(msg_data->dest));
@@ -124,11 +121,10 @@ void *dl_mstp_thread(
}
dlmstp_send_pdu(&mstp_port, &(msg_data->dest),
msg_data->pdu, msg_data->pdu_len);
msg_data->pdu, msg_data->pdu_len);
check_data(msg_data);
break;
case SERVICE:
switch (bacmsg->subtype) {
@@ -147,20 +143,21 @@ void *dl_mstp_thread(
pdu_len = dlmstp_receive(&mstp_port, NULL, NULL, 0, 5);
if (pdu_len > 0) {
msg_data = (MSG_DATA *) malloc(sizeof(MSG_DATA));
memmove(&(msg_data->src),
(const void *) &(shared_port_data.Receive_Packet.address),
msg_data = (MSG_DATA *)malloc(sizeof(MSG_DATA));
memmove(
&(msg_data->src),
(const void *)&(shared_port_data.Receive_Packet.address),
sizeof(shared_port_data.Receive_Packet.address));
msg_data->src.adr[0] = msg_data->src.mac[0];
msg_data->src.len = 1;
msg_data->pdu = (uint8_t *) malloc(pdu_len);
msg_data->pdu = (uint8_t *)malloc(pdu_len);
memmove(msg_data->pdu,
(const void *) &(shared_port_data.Receive_Packet.pdu),
pdu_len);
(const void *)&(shared_port_data.Receive_Packet.pdu),
pdu_len);
msg_data->pdu_len = pdu_len;
msg_storage.type = DATA;
msg_storage.subtype = (MSGSUBTYPE) 0;
msg_storage.subtype = (MSGSUBTYPE)0;
msg_storage.origin = port->port_id;
msg_storage.data = msg_data;
@@ -175,5 +172,4 @@ void *dl_mstp_thread(
port->state = FINISHED;
return NULL;
}
+111 -128
View File
@@ -1,43 +1,39 @@
/**
* @file
* @author Andriy Sukhynyuk, Vasyl Tkhir, Andriy Ivasiv
* @date 2012
* @brief Network layer for BACnet routing
*
* @section LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
* @file
* @author Andriy Sukhynyuk, Vasyl Tkhir, Andriy Ivasiv
* @date 2012
* @brief Network layer for BACnet routing
*
* @section LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "network_layer.h"
#include "bacint.h"
uint16_t process_network_message(
BACMSG * msg,
MSG_DATA * data,
uint8_t ** buff)
uint16_t process_network_message(BACMSG *msg, MSG_DATA *data, uint8_t **buff)
{
BACNET_NPDU_DATA npdu_data;
ROUTER_PORT *srcport;
ROUTER_PORT *destport;
@@ -56,7 +52,6 @@ uint16_t process_network_message(
data->src.net = srcport->route_info.net;
switch (npdu_data.network_message_type) {
case NETWORK_MESSAGE_WHO_IS_ROUTER_TO_NETWORK:
PRINT(INFO, "Recieved Who-Is-Router-To-Network message\n");
if (apdu_len) {
@@ -67,83 +62,83 @@ uint16_t process_network_message(
return -2;
}
destport = find_dnet(net, NULL); /* see if NET can be reached */
destport = find_dnet(net, NULL); /* see if NET can be reached */
if (destport) {
/* if TRUE send reply */
PRINT(INFO, "Sending I-Am-Router-To-Network message\n");
buff_len =
create_network_message
(NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK, data, buff,
buff_len = create_network_message(
NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK, data, buff,
&net);
} else {
data->dest.net = net; /* NET to look for */
return -1; /* else initiate NET search procedure */
data->dest.net = net; /* NET to look for */
return -1; /* else initiate NET search procedure */
}
} else {
/* if NET is omitted (message sent with -1) */
PRINT(INFO, "Sending I-Am-Router-To-Network message\n");
buff_len =
create_network_message
(NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK, data, buff, NULL);
buff_len = create_network_message(
NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK, data, buff, NULL);
}
break;
case NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK:
{
PRINT(INFO, "Recieved I-Am-Router-To-Network message\n");
int net_count = apdu_len / 2;
int i;
for (i = 0; i < net_count; i++) {
decode_unsigned16(&data->pdu[apdu_offset + 2 * i], &net); /* decode received NET values */
add_dnet(&srcport->route_info, net, data->src); /* and update routing table */
}
break;
case NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK: {
PRINT(INFO, "Recieved I-Am-Router-To-Network message\n");
int net_count = apdu_len / 2;
int i;
for (i = 0; i < net_count; i++) {
decode_unsigned16(&data->pdu[apdu_offset + 2 * i],
&net); /* decode received NET values */
add_dnet(&srcport->route_info, net,
data->src); /* and update routing table */
}
case NETWORK_MESSAGE_REJECT_MESSAGE_TO_NETWORK:
{
/* first octet of the message contains rejection reason */
/* next two octets contain NET (can be decoded for additional info on error) */
error_code = data->pdu[apdu_offset];
switch (error_code) {
case 0:
PRINT(ERROR, "Error!\n");
break;
case 1:
PRINT(ERROR, "Error: Network unreachable\n");
break;
case 2:
PRINT(ERROR, "Error: Network is busy\n");
break;
case 3:
PRINT(ERROR, "Error: Unknown network message type\n");
break;
case 4:
PRINT(ERROR, "Error: Message too long\n");
break;
}
break;
break;
}
case NETWORK_MESSAGE_REJECT_MESSAGE_TO_NETWORK: {
/* first octet of the message contains rejection reason */
/* next two octets contain NET (can be decoded for additional info
* on error) */
error_code = data->pdu[apdu_offset];
switch (error_code) {
case 0:
PRINT(ERROR, "Error!\n");
break;
case 1:
PRINT(ERROR, "Error: Network unreachable\n");
break;
case 2:
PRINT(ERROR, "Error: Network is busy\n");
break;
case 3:
PRINT(ERROR, "Error: Unknown network message type\n");
break;
case 4:
PRINT(ERROR, "Error: Message too long\n");
break;
}
break;
}
case NETWORK_MESSAGE_INIT_RT_TABLE:
PRINT(INFO, "Recieved Initialize-Routing-Table message\n");
if (data->pdu[apdu_offset] > 0) {
int net_count = data->pdu[apdu_offset];
while (net_count--) {
int i = 1;
decode_unsigned16(&data->pdu[apdu_offset + i], &net); /* decode received NET values */
add_dnet(&srcport->route_info, net, data->src); /* and update routing table */
if (data->pdu[apdu_offset + i + 3] > 0) /* find next NET value */
decode_unsigned16(&data->pdu[apdu_offset + i],
&net); /* decode received NET values */
add_dnet(&srcport->route_info, net,
data->src); /* and update routing table */
if (data->pdu[apdu_offset + i + 3] >
0) /* find next NET value */
i = data->pdu[apdu_offset + i + 3] + 4;
else
i = i + 4;
}
buff_len =
create_network_message(NETWORK_MESSAGE_INIT_RT_TABLE_ACK,
data, buff, NULL);
buff_len = create_network_message(
NETWORK_MESSAGE_INIT_RT_TABLE_ACK, data, buff, NULL);
} else
buff_len =
create_network_message(NETWORK_MESSAGE_INIT_RT_TABLE_ACK,
data, buff, &buff);
buff_len = create_network_message(
NETWORK_MESSAGE_INIT_RT_TABLE_ACK, data, buff, &buff);
break;
case NETWORK_MESSAGE_INIT_RT_TABLE_ACK:
@@ -152,9 +147,12 @@ uint16_t process_network_message(
int net_count = data->pdu[apdu_offset];
while (net_count--) {
int i = 1;
decode_unsigned16(&data->pdu[apdu_offset + i], &net); /* decode received NET values */
add_dnet(&srcport->route_info, net, data->src); /* and update routing table */
if (data->pdu[apdu_offset + i + 3] > 0) /* find next NET value */
decode_unsigned16(&data->pdu[apdu_offset + i],
&net); /* decode received NET values */
add_dnet(&srcport->route_info, net,
data->src); /* and update routing table */
if (data->pdu[apdu_offset + i + 3] >
0) /* find next NET value */
i = data->pdu[apdu_offset + i + 3] + 4;
else
i = i + 4;
@@ -182,12 +180,10 @@ uint16_t process_network_message(
/* security messages */
break;
case NETWORK_MESSAGE_WHAT_IS_NETWORK_NUMBER:
buff_len =
create_network_message(NETWORK_MESSAGE_NETWORK_NUMBER_IS,
data, buff, &buff);
buff_len = create_network_message(NETWORK_MESSAGE_NETWORK_NUMBER_IS,
data, buff, &buff);
break;
default:
PRINT(ERROR, "Error: Message unsupported\n");
break;
@@ -197,12 +193,9 @@ uint16_t process_network_message(
}
uint16_t create_network_message(
BACNET_NETWORK_MESSAGE_TYPE network_message_type,
MSG_DATA * data,
uint8_t ** buff,
void *val)
BACNET_NETWORK_MESSAGE_TYPE network_message_type, MSG_DATA *data,
uint8_t **buff, void *val)
{
int16_t buff_len;
bool data_expecting_reply = false;
BACNET_NPDU_DATA npdu_data;
@@ -211,17 +204,16 @@ uint16_t create_network_message(
data_expecting_reply = true;
init_npdu(&npdu_data, network_message_type, data_expecting_reply);
*buff = (uint8_t *) malloc(128); /* resolve different length */
*buff = (uint8_t *)malloc(128); /* resolve different length */
/* manual destination setup for Init-RT-Table-Ack message */
data->dest.net = BACNET_BROADCAST_NETWORK;
buff_len = npdu_encode_pdu(*buff, &data->dest, NULL, &npdu_data);
switch (network_message_type) {
case NETWORK_MESSAGE_WHO_IS_ROUTER_TO_NETWORK:
if (val != NULL) {
uint8_t *valptr = (uint8_t *) val;
uint8_t *valptr = (uint8_t *)val;
uint16_t val16 = (valptr[0]) + (valptr[1] << 8);
buff_len += encode_unsigned16(*buff + buff_len, val16);
}
@@ -229,7 +221,7 @@ uint16_t create_network_message(
case NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK:
if (val != NULL) {
uint8_t *valptr = (uint8_t *) val;
uint8_t *valptr = (uint8_t *)val;
uint16_t val16 = (valptr[0]) + (valptr[1] << 8);
buff_len += encode_unsigned16(*buff + buff_len, val16);
} else {
@@ -237,9 +229,8 @@ uint16_t create_network_message(
DNET *dnet;
while (port != NULL) {
if (port->route_info.net != data->src.net) {
buff_len +=
encode_unsigned16(*buff + buff_len,
port->route_info.net);
buff_len += encode_unsigned16(*buff + buff_len,
port->route_info.net);
dnet = port->route_info.dnets;
while (dnet != NULL) {
buff_len +=
@@ -260,33 +251,31 @@ uint16_t create_network_message(
}
break;
case NETWORK_MESSAGE_REJECT_MESSAGE_TO_NETWORK:
{
uint8_t *valptr = (uint8_t *) val;
uint16_t val16 = (valptr[0]) + (valptr[1] << 8);
buff_len += encode_unsigned16(*buff + buff_len, val16);
break;
}
case NETWORK_MESSAGE_REJECT_MESSAGE_TO_NETWORK: {
uint8_t *valptr = (uint8_t *)val;
uint16_t val16 = (valptr[0]) + (valptr[1] << 8);
buff_len += encode_unsigned16(*buff + buff_len, val16);
break;
}
case NETWORK_MESSAGE_INIT_RT_TABLE:
case NETWORK_MESSAGE_INIT_RT_TABLE_ACK:
if ((uint8_t *) val) {
(*buff)[buff_len++] = (uint8_t) port_count;
if ((uint8_t *)val) {
(*buff)[buff_len++] = (uint8_t)port_count;
if (port_count > 0) {
ROUTER_PORT *port = head;
uint8_t portID = 1;
while (port != NULL) {
buff_len +=
encode_unsigned16(*buff + buff_len,
port->route_info.net);
buff_len += encode_unsigned16(*buff + buff_len,
port->route_info.net);
(*buff)[buff_len++] = portID++;
(*buff)[buff_len++] = 0;
port = port->next;
}
}
} else
(*buff)[buff_len++] = (uint8_t) 0;
(*buff)[buff_len++] = (uint8_t)0;
break;
case NETWORK_MESSAGE_INVALID:
@@ -317,19 +306,15 @@ uint16_t create_network_message(
return buff_len;
}
void send_network_message(
BACNET_NETWORK_MESSAGE_TYPE network_message_type,
MSG_DATA * data,
uint8_t ** buff,
void *val)
void send_network_message(BACNET_NETWORK_MESSAGE_TYPE network_message_type,
MSG_DATA *data, uint8_t **buff, void *val)
{
BACMSG msg;
ROUTER_PORT *port = head;
int16_t buff_len;
if (!data) {
data = (MSG_DATA *) malloc(sizeof(MSG_DATA));
data = (MSG_DATA *)malloc(sizeof(MSG_DATA));
data->dest.net = BACNET_BROADCAST_NETWORK;
data->dest.len = 0;
}
@@ -354,12 +339,10 @@ void send_network_message(
}
}
void init_npdu(
BACNET_NPDU_DATA * npdu_data,
BACNET_NETWORK_MESSAGE_TYPE network_message_type,
bool data_expecting_reply)
void init_npdu(BACNET_NPDU_DATA *npdu_data,
BACNET_NETWORK_MESSAGE_TYPE network_message_type,
bool data_expecting_reply)
{
if (npdu_data) {
npdu_data->data_expecting_reply = data_expecting_reply;
npdu_data->protocol_version = BACNET_PROTOCOL_VERSION;
+34 -47
View File
@@ -1,40 +1,38 @@
/**
* @file
* @author Andriy Sukhynyuk, Vasyl Tkhir, Andriy Ivasiv
* @date 2012
* @brief Network port storage and handling
*
* @section LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
* @file
* @author Andriy Sukhynyuk, Vasyl Tkhir, Andriy Ivasiv
* @date 2012
* @brief Network port storage and handling
*
* @section LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "portthread.h"
ROUTER_PORT *find_snet(
MSGBOX_ID id)
ROUTER_PORT *find_snet(MSGBOX_ID id)
{
ROUTER_PORT *port = head;
while (port != NULL) {
@@ -46,11 +44,8 @@ ROUTER_PORT *find_snet(
return NULL;
}
ROUTER_PORT *find_dnet(
uint16_t net,
BACNET_ADDRESS * addr)
ROUTER_PORT *find_dnet(uint16_t net, BACNET_ADDRESS *addr)
{
ROUTER_PORT *port = head;
DNET *dnet;
@@ -59,7 +54,6 @@ ROUTER_PORT *find_dnet(
return port;
while (port != NULL) {
/* check if DNET is directly connected to the router */
if (net == port->route_info.net)
return port;
@@ -84,32 +78,27 @@ ROUTER_PORT *find_dnet(
return NULL;
}
void add_dnet(
RT_ENTRY * route_info,
uint16_t net,
BACNET_ADDRESS addr)
void add_dnet(RT_ENTRY *route_info, uint16_t net, BACNET_ADDRESS addr)
{
DNET *dnet = route_info->dnets;
DNET *tmp;
if (dnet == NULL) {
route_info->dnets = (DNET *) malloc(sizeof(DNET));
route_info->dnets = (DNET *)malloc(sizeof(DNET));
memmove(&route_info->dnets->mac_len, &addr.len, 1);
memmove(&route_info->dnets->mac[0], &addr.adr[0], MAX_MAC_LEN);
route_info->dnets->net = net;
route_info->dnets->state = true;
route_info->dnets->next = NULL;
} else {
while (dnet != NULL) {
if (dnet->net == net) /* make sure NETs are not repeated */
if (dnet->net == net) /* make sure NETs are not repeated */
return;
tmp = dnet;
dnet = dnet->next;
}
dnet = (DNET *) malloc(sizeof(DNET));
dnet = (DNET *)malloc(sizeof(DNET));
memmove(&dnet->mac_len, &addr.len, 1);
memmove(&dnet->mac[0], &addr.adr[0], MAX_MAC_LEN);
dnet->net = net;
@@ -119,10 +108,8 @@ void add_dnet(
}
}
void cleanup_dnets(
DNET * dnets)
void cleanup_dnets(DNET *dnets)
{
DNET *dnet = dnets;
while (dnet != NULL) {
dnet = dnet->next;