adding BACnet/IP to the Linux port
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
#Makefile to build BACnet Application
|
#Makefile to build BACnet Application for the Linux Port
|
||||||
CC = gcc
|
CC = gcc
|
||||||
BASEDIR = .
|
BASEDIR = .
|
||||||
#CFLAGS = -Wall -I.
|
#CFLAGS = -Wall -I.
|
||||||
@@ -7,9 +7,11 @@ BASEDIR = .
|
|||||||
# Note: you can strip out symbols using the strip command
|
# Note: you can strip out symbols using the strip command
|
||||||
# to get an idea of how big the compile really is.
|
# to get an idea of how big the compile really is.
|
||||||
CFLAGS = -Wall -I. -g -DBACDL_ETHERNET=1
|
CFLAGS = -Wall -I. -g -DBACDL_ETHERNET=1
|
||||||
|
#CFLAGS = -Wall -I. -Iports/linux -g -DBACDL_BIP=1
|
||||||
|
|
||||||
SRCS = ports/linux/main.c \
|
SRCS = ports/linux/main.c \
|
||||||
ports/linux/ethernet.c \
|
ports/linux/ethernet.c \
|
||||||
|
ports/linux/bip.c \
|
||||||
handlers.c \
|
handlers.c \
|
||||||
bacdcode.c \
|
bacdcode.c \
|
||||||
bigend.c \
|
bigend.c \
|
||||||
|
|||||||
+1
-1
@@ -68,6 +68,6 @@ uint16_t bip_receive(
|
|||||||
void bip_set_address(uint8_t octet1, uint8_t octet2,
|
void bip_set_address(uint8_t octet1, uint8_t octet2,
|
||||||
uint8_t octet3, uint8_t octet4);
|
uint8_t octet3, uint8_t octet4);
|
||||||
void bip_set_port(uint16_t port);
|
void bip_set_port(uint16_t port);
|
||||||
|
void bip_set_interface_name(char *ifname);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+37
-22
@@ -25,6 +25,8 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "bacdef.h"
|
#include "bacdef.h"
|
||||||
#include "bacdcode.h"
|
#include "bacdcode.h"
|
||||||
@@ -65,7 +67,6 @@
|
|||||||
#define bacdl_receive bip_receive
|
#define bacdl_receive bip_receive
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// flag to send an I-Am
|
// flag to send an I-Am
|
||||||
bool I_Am_Request = true;
|
bool I_Am_Request = true;
|
||||||
|
|
||||||
@@ -81,6 +82,7 @@ void UnrecognizedServiceHandler(
|
|||||||
{
|
{
|
||||||
BACNET_ADDRESS src;
|
BACNET_ADDRESS src;
|
||||||
int pdu_len = 0;
|
int pdu_len = 0;
|
||||||
|
int bytes_sent = 0;
|
||||||
|
|
||||||
(void)service_request;
|
(void)service_request;
|
||||||
(void)service_len;
|
(void)service_len;
|
||||||
@@ -100,11 +102,14 @@ void UnrecognizedServiceHandler(
|
|||||||
service_data->invoke_id,
|
service_data->invoke_id,
|
||||||
REJECT_REASON_UNRECOGNIZED_SERVICE);
|
REJECT_REASON_UNRECOGNIZED_SERVICE);
|
||||||
|
|
||||||
(void)bacdl_send_pdu(
|
bytes_sent = bacdl_send_pdu(
|
||||||
dest, // destination address
|
dest, // destination address
|
||||||
&Tx_Buf[0],
|
&Tx_Buf[0],
|
||||||
pdu_len); // number of bytes of data
|
pdu_len); // number of bytes of data
|
||||||
fprintf(stderr,"Sent Reject!\n");
|
if (bytes_sent > 0)
|
||||||
|
fprintf(stderr,"Sent Reject!\n");
|
||||||
|
else
|
||||||
|
fprintf(stderr,"Failed to Send Reject (%s)!\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: if we handle multiple ports, then a port neutral version
|
// FIXME: if we handle multiple ports, then a port neutral version
|
||||||
@@ -113,6 +118,7 @@ void Send_IAm(void)
|
|||||||
{
|
{
|
||||||
int pdu_len = 0;
|
int pdu_len = 0;
|
||||||
BACNET_ADDRESS dest;
|
BACNET_ADDRESS dest;
|
||||||
|
int bytes_sent = 0;
|
||||||
|
|
||||||
// I-Am is a global broadcast
|
// I-Am is a global broadcast
|
||||||
bacdl_get_broadcast_address(&dest);
|
bacdl_get_broadcast_address(&dest);
|
||||||
@@ -133,11 +139,14 @@ void Send_IAm(void)
|
|||||||
SEGMENTATION_NONE,
|
SEGMENTATION_NONE,
|
||||||
Device_Vendor_Identifier());
|
Device_Vendor_Identifier());
|
||||||
|
|
||||||
(void)bacdl_send_pdu(
|
bytes_sent = bacdl_send_pdu(
|
||||||
&dest, // destination address
|
&dest, // destination address
|
||||||
&Tx_Buf[0],
|
&Tx_Buf[0],
|
||||||
pdu_len); // number of bytes of data
|
pdu_len); // number of bytes of data
|
||||||
fprintf(stderr,"Sent I-Am Request!\n");
|
if (bytes_sent > 0)
|
||||||
|
fprintf(stderr,"Sent I-Am Request!\n");
|
||||||
|
else
|
||||||
|
fprintf(stderr,"Failed to Send I-Am Request (%s)!\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WhoIsHandler(
|
void WhoIsHandler(
|
||||||
@@ -211,6 +220,7 @@ void ReadPropertyHandler(
|
|||||||
int32_t array_index;
|
int32_t array_index;
|
||||||
BACNET_ADDRESS my_address;
|
BACNET_ADDRESS my_address;
|
||||||
bool send = false;
|
bool send = false;
|
||||||
|
int bytes_sent = 0;
|
||||||
|
|
||||||
len = rp_decode_service_request(
|
len = rp_decode_service_request(
|
||||||
service_request,
|
service_request,
|
||||||
@@ -244,7 +254,7 @@ void ReadPropertyHandler(
|
|||||||
&Tx_Buf[pdu_len],
|
&Tx_Buf[pdu_len],
|
||||||
service_data->invoke_id,
|
service_data->invoke_id,
|
||||||
ABORT_REASON_OTHER);
|
ABORT_REASON_OTHER);
|
||||||
fprintf(stderr,"Sent Abort!\n");
|
fprintf(stderr,"Sending Abort!\n");
|
||||||
send = true;
|
send = true;
|
||||||
}
|
}
|
||||||
else if (service_data->segmented_message)
|
else if (service_data->segmented_message)
|
||||||
@@ -253,7 +263,7 @@ void ReadPropertyHandler(
|
|||||||
&Tx_Buf[pdu_len],
|
&Tx_Buf[pdu_len],
|
||||||
service_data->invoke_id,
|
service_data->invoke_id,
|
||||||
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED);
|
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED);
|
||||||
fprintf(stderr,"Sent Abort!\n");
|
fprintf(stderr,"Sending Abort!\n");
|
||||||
send = true;
|
send = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -283,7 +293,7 @@ void ReadPropertyHandler(
|
|||||||
&Tx_Buf[pdu_len],
|
&Tx_Buf[pdu_len],
|
||||||
service_data->invoke_id,
|
service_data->invoke_id,
|
||||||
&rp_data);
|
&rp_data);
|
||||||
fprintf(stderr,"Sent Read Property Ack!\n");
|
fprintf(stderr,"Sending Read Property Ack!\n");
|
||||||
send = true;
|
send = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -294,7 +304,7 @@ void ReadPropertyHandler(
|
|||||||
SERVICE_CONFIRMED_READ_PROPERTY,
|
SERVICE_CONFIRMED_READ_PROPERTY,
|
||||||
ERROR_CLASS_PROPERTY,
|
ERROR_CLASS_PROPERTY,
|
||||||
ERROR_CODE_UNKNOWN_PROPERTY);
|
ERROR_CODE_UNKNOWN_PROPERTY);
|
||||||
fprintf(stderr,"Sent Unknown Property Error!\n");
|
fprintf(stderr,"Sending Unknown Property Error!\n");
|
||||||
send = true;
|
send = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -306,7 +316,7 @@ void ReadPropertyHandler(
|
|||||||
SERVICE_CONFIRMED_READ_PROPERTY,
|
SERVICE_CONFIRMED_READ_PROPERTY,
|
||||||
ERROR_CLASS_OBJECT,
|
ERROR_CLASS_OBJECT,
|
||||||
ERROR_CODE_UNKNOWN_OBJECT);
|
ERROR_CODE_UNKNOWN_OBJECT);
|
||||||
fprintf(stderr,"Sent Unknown Object Error!\n");
|
fprintf(stderr,"Sending Unknown Object Error!\n");
|
||||||
send = true;
|
send = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -332,7 +342,7 @@ void ReadPropertyHandler(
|
|||||||
&Tx_Buf[pdu_len],
|
&Tx_Buf[pdu_len],
|
||||||
service_data->invoke_id,
|
service_data->invoke_id,
|
||||||
&rp_data);
|
&rp_data);
|
||||||
fprintf(stderr,"Sent Read Property Ack!\n");
|
fprintf(stderr,"Sending Read Property Ack!\n");
|
||||||
send = true;
|
send = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -343,7 +353,7 @@ void ReadPropertyHandler(
|
|||||||
SERVICE_CONFIRMED_READ_PROPERTY,
|
SERVICE_CONFIRMED_READ_PROPERTY,
|
||||||
ERROR_CLASS_PROPERTY,
|
ERROR_CLASS_PROPERTY,
|
||||||
ERROR_CODE_UNKNOWN_PROPERTY);
|
ERROR_CODE_UNKNOWN_PROPERTY);
|
||||||
fprintf(stderr,"Sent Unknown Property Error!\n");
|
fprintf(stderr,"Sending Unknown Property Error!\n");
|
||||||
send = true;
|
send = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -355,7 +365,7 @@ void ReadPropertyHandler(
|
|||||||
SERVICE_CONFIRMED_READ_PROPERTY,
|
SERVICE_CONFIRMED_READ_PROPERTY,
|
||||||
ERROR_CLASS_OBJECT,
|
ERROR_CLASS_OBJECT,
|
||||||
ERROR_CODE_UNKNOWN_OBJECT);
|
ERROR_CODE_UNKNOWN_OBJECT);
|
||||||
fprintf(stderr,"Sent Unknown Object Error!\n");
|
fprintf(stderr,"Sending Unknown Object Error!\n");
|
||||||
send = true;
|
send = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -366,17 +376,19 @@ void ReadPropertyHandler(
|
|||||||
SERVICE_CONFIRMED_READ_PROPERTY,
|
SERVICE_CONFIRMED_READ_PROPERTY,
|
||||||
ERROR_CLASS_OBJECT,
|
ERROR_CLASS_OBJECT,
|
||||||
ERROR_CODE_UNKNOWN_OBJECT);
|
ERROR_CODE_UNKNOWN_OBJECT);
|
||||||
fprintf(stderr,"Sent Unknown Object Error!\n");
|
fprintf(stderr,"Sending Unknown Object Error!\n");
|
||||||
send = true;
|
send = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (send)
|
if (send)
|
||||||
{
|
{
|
||||||
(void)bacdl_send_pdu(
|
bytes_sent = bacdl_send_pdu(
|
||||||
src, // destination address
|
src, // destination address
|
||||||
&Tx_Buf[0],
|
&Tx_Buf[0],
|
||||||
pdu_len); // number of bytes of data
|
pdu_len); // number of bytes of data
|
||||||
|
if (bytes_sent <= 0)
|
||||||
|
fprintf(stderr,"Failed to send PDU (%s)!\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -395,6 +407,7 @@ void WritePropertyHandler(
|
|||||||
bool send = false;
|
bool send = false;
|
||||||
BACNET_ERROR_CLASS error_class;
|
BACNET_ERROR_CLASS error_class;
|
||||||
BACNET_ERROR_CODE error_code;
|
BACNET_ERROR_CODE error_code;
|
||||||
|
int bytes_sent = 0;
|
||||||
|
|
||||||
// decode the service request only
|
// decode the service request only
|
||||||
len = wp_decode_service_request(
|
len = wp_decode_service_request(
|
||||||
@@ -426,7 +439,7 @@ void WritePropertyHandler(
|
|||||||
&Tx_Buf[pdu_len],
|
&Tx_Buf[pdu_len],
|
||||||
service_data->invoke_id,
|
service_data->invoke_id,
|
||||||
ABORT_REASON_OTHER);
|
ABORT_REASON_OTHER);
|
||||||
fprintf(stderr,"Sent Abort!\n");
|
fprintf(stderr,"Sending Abort!\n");
|
||||||
send = true;
|
send = true;
|
||||||
}
|
}
|
||||||
else if (service_data->segmented_message)
|
else if (service_data->segmented_message)
|
||||||
@@ -435,7 +448,7 @@ void WritePropertyHandler(
|
|||||||
&Tx_Buf[pdu_len],
|
&Tx_Buf[pdu_len],
|
||||||
service_data->invoke_id,
|
service_data->invoke_id,
|
||||||
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED);
|
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED);
|
||||||
fprintf(stderr,"Sent Abort!\n");
|
fprintf(stderr,"Sending Abort!\n");
|
||||||
send = true;
|
send = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -449,7 +462,7 @@ void WritePropertyHandler(
|
|||||||
&Tx_Buf[pdu_len],
|
&Tx_Buf[pdu_len],
|
||||||
service_data->invoke_id,
|
service_data->invoke_id,
|
||||||
SERVICE_CONFIRMED_WRITE_PROPERTY);
|
SERVICE_CONFIRMED_WRITE_PROPERTY);
|
||||||
fprintf(stderr,"Sent Write Property Simple Ack!\n");
|
fprintf(stderr,"Sending Write Property Simple Ack!\n");
|
||||||
send = true;
|
send = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -460,7 +473,7 @@ void WritePropertyHandler(
|
|||||||
SERVICE_CONFIRMED_WRITE_PROPERTY,
|
SERVICE_CONFIRMED_WRITE_PROPERTY,
|
||||||
error_class,
|
error_class,
|
||||||
error_code);
|
error_code);
|
||||||
fprintf(stderr,"Sent Write Property Error!\n");
|
fprintf(stderr,"Sending Write Property Error!\n");
|
||||||
send = true;
|
send = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -471,7 +484,7 @@ void WritePropertyHandler(
|
|||||||
SERVICE_CONFIRMED_WRITE_PROPERTY,
|
SERVICE_CONFIRMED_WRITE_PROPERTY,
|
||||||
ERROR_CLASS_PROPERTY,
|
ERROR_CLASS_PROPERTY,
|
||||||
ERROR_CODE_WRITE_ACCESS_DENIED);
|
ERROR_CODE_WRITE_ACCESS_DENIED);
|
||||||
fprintf(stderr,"Sent Write Access Error!\n");
|
fprintf(stderr,"Sending Write Access Error!\n");
|
||||||
send = true;
|
send = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -481,17 +494,19 @@ void WritePropertyHandler(
|
|||||||
SERVICE_CONFIRMED_WRITE_PROPERTY,
|
SERVICE_CONFIRMED_WRITE_PROPERTY,
|
||||||
ERROR_CLASS_OBJECT,
|
ERROR_CLASS_OBJECT,
|
||||||
ERROR_CODE_UNKNOWN_OBJECT);
|
ERROR_CODE_UNKNOWN_OBJECT);
|
||||||
fprintf(stderr,"Sent Unknown Object Error!\n");
|
fprintf(stderr,"Sending Unknown Object Error!\n");
|
||||||
send = true;
|
send = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (send)
|
if (send)
|
||||||
{
|
{
|
||||||
(void)bacdl_send_pdu(
|
bytes_sent = bacdl_send_pdu(
|
||||||
src, // destination address
|
src, // destination address
|
||||||
&Tx_Buf[0],
|
&Tx_Buf[0],
|
||||||
pdu_len); // number of bytes of data
|
pdu_len); // number of bytes of data
|
||||||
|
if (bytes_sent <= 0)
|
||||||
|
fprintf(stderr,"Failed to send PDU (%s)!\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -34,17 +34,17 @@
|
|||||||
|
|
||||||
#include <stdint.h> // for standard integer types uint8_t etc.
|
#include <stdint.h> // for standard integer types uint8_t etc.
|
||||||
#include <stdbool.h> // for the standard bool type.
|
#include <stdbool.h> // for the standard bool type.
|
||||||
#include <socket.h>
|
|
||||||
#include "bacdcode.h"
|
#include "bacdcode.h"
|
||||||
#include "bip.h"
|
#include "bip.h"
|
||||||
|
#include "net.h"
|
||||||
|
|
||||||
static int BIP_Receive_Socket = -1;
|
static int BIP_Receive_Socket = -1;
|
||||||
/* port to use - stored in network byte order */
|
/* port to use - stored in network byte order */
|
||||||
static uint16_t BIP_Port = 0;
|
static uint16_t BIP_Port = 0;
|
||||||
/* IP Address - stored in network byte order */
|
/* IP Address - stored in network byte order */
|
||||||
static struct in_addr BIP_Address = {{{-1}}};
|
static struct in_addr BIP_Address;
|
||||||
/* Broadcast Address */
|
/* Broadcast Address */
|
||||||
static struct in_addr BIP_Broadcast_Address = {{{-1}}};
|
static struct in_addr BIP_Broadcast_Address;
|
||||||
|
|
||||||
bool bip_valid(void)
|
bool bip_valid(void)
|
||||||
{
|
{
|
||||||
@@ -54,7 +54,7 @@ bool bip_valid(void)
|
|||||||
void bip_cleanup(void)
|
void bip_cleanup(void)
|
||||||
{
|
{
|
||||||
if (bip_valid())
|
if (bip_valid())
|
||||||
closesocket(BIP_Receive_Socket);
|
close(BIP_Receive_Socket);
|
||||||
BIP_Receive_Socket = -1;
|
BIP_Receive_Socket = -1;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -76,7 +76,11 @@ static void set_network_address(struct in_addr *net_address,
|
|||||||
net_address->s_addr = htonl(long_data.value);
|
net_address->s_addr = htonl(long_data.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bip_set_address(uint8_t octet1, uint8_t octet2, uint8_t octet3, uint8_t octet4)
|
void bip_set_address(
|
||||||
|
uint8_t octet1,
|
||||||
|
uint8_t octet2,
|
||||||
|
uint8_t octet3,
|
||||||
|
uint8_t octet4)
|
||||||
{
|
{
|
||||||
set_network_address(&BIP_Address, octet1, octet2, octet3, octet4);
|
set_network_address(&BIP_Address, octet1, octet2, octet3, octet4);
|
||||||
}
|
}
|
||||||
@@ -89,8 +93,8 @@ void bip_set_port(uint16_t port)
|
|||||||
bool bip_init(void)
|
bool bip_init(void)
|
||||||
{
|
{
|
||||||
int rv = 0; // return from socket lib calls
|
int rv = 0; // return from socket lib calls
|
||||||
struct sockaddr_in sin = {-1};
|
struct sockaddr_in sin;
|
||||||
|
|
||||||
/* network global broadcast address */
|
/* network global broadcast address */
|
||||||
set_network_address(&BIP_Broadcast_Address,255,255,255,255);
|
set_network_address(&BIP_Broadcast_Address,255,255,255,255);
|
||||||
/* configure standard BACnet/IP port */
|
/* configure standard BACnet/IP port */
|
||||||
@@ -110,7 +114,7 @@ bool bip_init(void)
|
|||||||
(const struct sockaddr*)&sin, sizeof(struct sockaddr));
|
(const struct sockaddr*)&sin, sizeof(struct sockaddr));
|
||||||
if (rv < 0)
|
if (rv < 0)
|
||||||
{
|
{
|
||||||
closesocket(BIP_Receive_Socket);
|
close(BIP_Receive_Socket);
|
||||||
BIP_Receive_Socket = -1;
|
BIP_Receive_Socket = -1;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -119,18 +123,16 @@ bool bip_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* function to send a packet out the 802.2 socket */
|
/* function to send a packet out the 802.2 socket */
|
||||||
/* returns 0 on success, non-zero on failure */
|
/* returns number of bytes sent on success, negative on failure */
|
||||||
static int bip_send(
|
static int bip_send(
|
||||||
struct sockaddr_in *bip_dest,
|
struct sockaddr_in *bip_dest,
|
||||||
uint8_t *pdu, // any data to be sent - may be null
|
uint8_t *pdu, // any data to be sent - may be null
|
||||||
unsigned pdu_len) // number of bytes of data
|
unsigned pdu_len) // number of bytes of data
|
||||||
{
|
{
|
||||||
int status = -1; /* initially fail status */
|
int status = -1; /* initially fail status */
|
||||||
int bytes = 0;
|
|
||||||
int bip_send_socket = -1;
|
int bip_send_socket = -1;
|
||||||
uint8_t mtu[MAX_MPDU] = { 0 };
|
uint8_t mtu[MAX_MPDU] = { 0 };
|
||||||
int mtu_len = 0;
|
int mtu_len = 0;
|
||||||
int i = 0;
|
|
||||||
int rv = 0; /* return value from socket calls */
|
int rv = 0; /* return value from socket calls */
|
||||||
|
|
||||||
// assumes that the driver has already been initialized
|
// assumes that the driver has already been initialized
|
||||||
@@ -138,15 +140,15 @@ static int bip_send(
|
|||||||
// FIXME: can we use the same socket as receive bip?
|
// FIXME: can we use the same socket as receive bip?
|
||||||
bip_send_socket = socket(AF_INET, SOCK_DGRAM, 0);
|
bip_send_socket = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
if (bip_send_socket < 0)
|
if (bip_send_socket < 0)
|
||||||
return status;
|
return bip_send_socket;
|
||||||
|
|
||||||
/* UDP is connection based */
|
/* UDP is connection based */
|
||||||
rv = connect(bip_send_socket,
|
status = connect(bip_send_socket,
|
||||||
(const struct sockaddr*)bip_dest,
|
(const struct sockaddr*)bip_dest,
|
||||||
sizeof(struct sockaddr));
|
sizeof(struct sockaddr));
|
||||||
if (bip_send_socket < 0)
|
if (status < 0)
|
||||||
{
|
{
|
||||||
closesocket(bip_send_socket);
|
close(bip_send_socket);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,13 +163,11 @@ static int bip_send(
|
|||||||
mtu_len += pdu_len;
|
mtu_len += pdu_len;
|
||||||
|
|
||||||
/* Send the packet */
|
/* Send the packet */
|
||||||
rv = sendto(bip_send_socket, (char *)mtu, mtu_len, 0,
|
status = sendto(bip_send_socket, (char *)mtu, mtu_len, 0,
|
||||||
(struct sockaddr *)bip_dest,
|
(struct sockaddr *)bip_dest,
|
||||||
sizeof(struct sockaddr));
|
sizeof(struct sockaddr));
|
||||||
if (rv >= 0)
|
|
||||||
status = 0;
|
|
||||||
|
|
||||||
closesocket(bip_send_socket);
|
close(bip_send_socket);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -179,10 +179,7 @@ int bip_send_pdu(
|
|||||||
uint8_t *pdu, // any data to be sent - may be null
|
uint8_t *pdu, // any data to be sent - may be null
|
||||||
unsigned pdu_len) // number of bytes of data
|
unsigned pdu_len) // number of bytes of data
|
||||||
{
|
{
|
||||||
int i = 0; // counter
|
|
||||||
struct sockaddr_in bip_dest;
|
struct sockaddr_in bip_dest;
|
||||||
uint32_t network_address = 0;
|
|
||||||
uint16_t network_port = 0;
|
|
||||||
|
|
||||||
/* load destination IP address */
|
/* load destination IP address */
|
||||||
bip_dest.sin_family = AF_INET;
|
bip_dest.sin_family = AF_INET;
|
||||||
|
|||||||
@@ -35,74 +35,7 @@
|
|||||||
#include <stdint.h> // for standard integer types uint8_t etc.
|
#include <stdint.h> // for standard integer types uint8_t etc.
|
||||||
#include <stdbool.h> // for the standard bool type.
|
#include <stdbool.h> // for the standard bool type.
|
||||||
|
|
||||||
/* common unix sockets headers needed */
|
#include "net.h"
|
||||||
#include <sys/types.h> /* basic system data types */
|
|
||||||
#include <sys/time.h> /* timeval{} for select() */
|
|
||||||
#include <time.h> /* timespec{} for pselect() */
|
|
||||||
#include <netinet/in.h> /* sockaddr_in{} and other Internet defns */
|
|
||||||
#include <arpa/inet.h> /* inet(3) functions */
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h> /* for nonblocking */
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/stat.h> /* for S_xxx file mode constants */
|
|
||||||
#include <sys/uio.h> /* for iovec{} and readv/writev */
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <sys/un.h> /* for Unix domain sockets */
|
|
||||||
|
|
||||||
#ifdef HAVE_SYS_SELECT_H
|
|
||||||
# include <sys/select.h> /* for convenience */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_POLL_H
|
|
||||||
# include <poll.h> /* for convenience */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_STRINGS_H
|
|
||||||
# include <strings.h> /* for convenience */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Three headers are normally needed for socket/file ioctl's:
|
|
||||||
* <sys/ioctl.h>, <sys/filio.h>, and <sys/sockio.h>.
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_SYS_IOCTL_H
|
|
||||||
# include <sys/ioctl.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_FILIO_H
|
|
||||||
# include <sys/filio.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_SOCKIO_H
|
|
||||||
# include <sys/sockio.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_PTHREAD_H
|
|
||||||
# include <pthread.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define ENUMS
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <net/route.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <features.h> /* for the glibc version number */
|
|
||||||
#if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1
|
|
||||||
#include <netpacket/packet.h>
|
|
||||||
#include <net/ethernet.h> /* the L2 protocols */
|
|
||||||
#else
|
|
||||||
#include <asm/types.h>
|
|
||||||
#include <linux/if_packet.h>
|
|
||||||
#include <linux/if_ether.h> /* The L2 protocols */
|
|
||||||
#endif
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
|
|
||||||
#include "bacdef.h"
|
#include "bacdef.h"
|
||||||
#include "ethernet.h"
|
#include "ethernet.h"
|
||||||
#include "bacdcode.h"
|
#include "bacdcode.h"
|
||||||
@@ -248,14 +181,13 @@ bool ethernet_init(char *interface_name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* function to send a packet out the 802.2 socket */
|
/* function to send a packet out the 802.2 socket */
|
||||||
/* returns 0 on success, non-zero on failure */
|
/* returns bytes sent success, negative on failure */
|
||||||
int ethernet_send(
|
int ethernet_send(
|
||||||
BACNET_ADDRESS *dest, // destination address
|
BACNET_ADDRESS *dest, // destination address
|
||||||
BACNET_ADDRESS *src, // source address
|
BACNET_ADDRESS *src, // source address
|
||||||
uint8_t *pdu, // any data to be sent - may be null
|
uint8_t *pdu, // any data to be sent - may be null
|
||||||
unsigned pdu_len) // number of bytes of data
|
unsigned pdu_len) // number of bytes of data
|
||||||
{
|
{
|
||||||
int status = -1;
|
|
||||||
int bytes = 0;
|
int bytes = 0;
|
||||||
uint8_t mtu[MAX_MPDU] = { 0 };
|
uint8_t mtu[MAX_MPDU] = { 0 };
|
||||||
int mtu_len = 0;
|
int mtu_len = 0;
|
||||||
@@ -265,7 +197,7 @@ int ethernet_send(
|
|||||||
if (eth802_sockfd < 0)
|
if (eth802_sockfd < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "ethernet: 802.2 socket is invalid!\n");
|
fprintf(stderr, "ethernet: 802.2 socket is invalid!\n");
|
||||||
return status;
|
return -1;
|
||||||
}
|
}
|
||||||
/* load destination ethernet MAC address */
|
/* load destination ethernet MAC address */
|
||||||
if (dest->mac_len == 6)
|
if (dest->mac_len == 6)
|
||||||
@@ -279,7 +211,7 @@ int ethernet_send(
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr, "ethernet: invalid destination MAC address!\n");
|
fprintf(stderr, "ethernet: invalid destination MAC address!\n");
|
||||||
return status;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* load source ethernet MAC address */
|
/* load source ethernet MAC address */
|
||||||
@@ -294,12 +226,12 @@ int ethernet_send(
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr, "ethernet: invalid source MAC address!\n");
|
fprintf(stderr, "ethernet: invalid source MAC address!\n");
|
||||||
return status;
|
return -3;
|
||||||
}
|
}
|
||||||
if ((14 + 3 + pdu_len) > MAX_MPDU)
|
if ((14 + 3 + pdu_len) > MAX_MPDU)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "ethernet: PDU is too big to send!\n");
|
fprintf(stderr, "ethernet: PDU is too big to send!\n");
|
||||||
return status;
|
return -4;
|
||||||
}
|
}
|
||||||
/* packet length */
|
/* packet length */
|
||||||
mtu_len += encode_unsigned16(&mtu[12],
|
mtu_len += encode_unsigned16(&mtu[12],
|
||||||
@@ -316,20 +248,15 @@ int ethernet_send(
|
|||||||
sendto(eth802_sockfd, &mtu, mtu_len, 0,
|
sendto(eth802_sockfd, &mtu, mtu_len, 0,
|
||||||
(struct sockaddr *) ð_addr, sizeof(struct sockaddr));
|
(struct sockaddr *) ð_addr, sizeof(struct sockaddr));
|
||||||
/* did it get sent? */
|
/* did it get sent? */
|
||||||
if (bytes < 0) {
|
if (bytes < 0)
|
||||||
fprintf(stderr,"ethernet: Error sending packet: %s\n",
|
fprintf(stderr,"ethernet: Error sending packet: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// got this far - must be good!
|
return bytes;
|
||||||
status = 0;
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* function to send a packet out the 802.2 socket */
|
/* function to send a packet out the 802.2 socket */
|
||||||
/* returns zero on success, non-zero on failure */
|
/* returns number of bytes sent on success, negative on failure */
|
||||||
int ethernet_send_pdu(
|
int ethernet_send_pdu(
|
||||||
BACNET_ADDRESS *dest, // destination address
|
BACNET_ADDRESS *dest, // destination address
|
||||||
uint8_t *pdu, // any data to be sent - may be null
|
uint8_t *pdu, // any data to be sent - may be null
|
||||||
|
|||||||
+111
-10
@@ -26,26 +26,93 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <signal.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "bacdef.h"
|
#include "bacdef.h"
|
||||||
|
#include "handlers.h"
|
||||||
#include "bacdcode.h"
|
#include "bacdcode.h"
|
||||||
#include "npdu.h"
|
#include "npdu.h"
|
||||||
#include "apdu.h"
|
#include "apdu.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "ai.h"
|
#ifdef BACDL_ETHERNET
|
||||||
#include "rp.h"
|
#include "ethernet.h"
|
||||||
#include "wp.h"
|
#endif
|
||||||
#include "iam.h"
|
#ifdef BACDL_BIP
|
||||||
#include "whois.h"
|
#include "bip.h"
|
||||||
#include "reject.h"
|
#endif
|
||||||
#include "abort.h"
|
#include "net.h"
|
||||||
#include "bacerror.h"
|
|
||||||
#include "ethernet.h"
|
|
||||||
#include "handlers.h"
|
|
||||||
|
|
||||||
// buffers used for receiving
|
// buffers used for receiving
|
||||||
static uint8_t Rx_Buf[MAX_MPDU] = {0};
|
static uint8_t Rx_Buf[MAX_MPDU] = {0};
|
||||||
|
|
||||||
|
static int get_local_ifr_ioctl(char *ifname, struct ifreq *ifr, int request)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int rv; // return value
|
||||||
|
|
||||||
|
strncpy(ifr->ifr_name, ifname, sizeof(ifr->ifr_name));
|
||||||
|
fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||||
|
if (fd < 0)
|
||||||
|
rv = fd;
|
||||||
|
else
|
||||||
|
rv = ioctl(fd, request, ifr);
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_local_address_ioctl(
|
||||||
|
char *ifname,
|
||||||
|
struct in_addr *addr,
|
||||||
|
int request)
|
||||||
|
{
|
||||||
|
struct ifreq ifr = { {{0}} };
|
||||||
|
struct sockaddr_in *tcpip_address;
|
||||||
|
int rv; // return value
|
||||||
|
|
||||||
|
rv = get_local_ifr_ioctl(ifname,&ifr,request);
|
||||||
|
if (rv >= 0) {
|
||||||
|
tcpip_address = (struct sockaddr_in *) &ifr.ifr_addr;
|
||||||
|
memcpy(addr, &tcpip_address->sin_addr, sizeof(struct in_addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void decode_network_address(struct in_addr *net_address,
|
||||||
|
uint8_t *octet1, uint8_t *octet2, uint8_t *octet3, uint8_t *octet4)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
uint8_t byte[4];
|
||||||
|
uint32_t value;
|
||||||
|
} long_data = {{0}};
|
||||||
|
|
||||||
|
long_data.value = net_address->s_addr;
|
||||||
|
|
||||||
|
*octet1 = long_data.byte[0];
|
||||||
|
*octet2 = long_data.byte[1];
|
||||||
|
*octet3 = long_data.byte[2];
|
||||||
|
*octet4 = long_data.byte[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Init_Network(char *ifname)
|
||||||
|
{
|
||||||
|
struct in_addr local_address;
|
||||||
|
uint8_t octet1;
|
||||||
|
uint8_t octet2;
|
||||||
|
uint8_t octet3;
|
||||||
|
uint8_t octet4;
|
||||||
|
|
||||||
|
/* setup local address */
|
||||||
|
get_local_address_ioctl(ifname, &local_address, SIOCGIFADDR);
|
||||||
|
decode_network_address(&local_address, &octet1, &octet2, &octet3, &octet4);
|
||||||
|
#ifdef BACDL_BIP
|
||||||
|
bip_set_address(octet1, octet2, octet3, octet4);
|
||||||
|
#endif
|
||||||
|
fprintf(stderr,"IP Address: %d.%d.%d.%d\n",
|
||||||
|
(int)octet1, (int)octet2, (int)octet3, (int)octet4);
|
||||||
|
}
|
||||||
|
|
||||||
static void Init_Device_Parameters(void)
|
static void Init_Device_Parameters(void)
|
||||||
{
|
{
|
||||||
// configure my initial values
|
// configure my initial values
|
||||||
@@ -83,17 +150,42 @@ static void Init_Service_Handlers(void)
|
|||||||
WritePropertyHandler);
|
WritePropertyHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sig_handler(int signo)
|
||||||
|
{
|
||||||
|
#ifdef BACDL_ETHERNET
|
||||||
|
ethernet_cleanup();
|
||||||
|
#endif
|
||||||
|
#ifdef BACDL_BIP
|
||||||
|
bip_cleanup();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
BACNET_ADDRESS src = {0}; // address where message came from
|
BACNET_ADDRESS src = {0}; // address where message came from
|
||||||
uint16_t pdu_len = 0;
|
uint16_t pdu_len = 0;
|
||||||
unsigned timeout = 100; // milliseconds
|
unsigned timeout = 100; // milliseconds
|
||||||
|
|
||||||
|
// Linux specials
|
||||||
|
signal(SIGINT, sig_handler);
|
||||||
|
signal(SIGHUP, sig_handler);
|
||||||
|
signal(SIGTERM, sig_handler);
|
||||||
|
// setup this BACnet Server
|
||||||
Init_Device_Parameters();
|
Init_Device_Parameters();
|
||||||
Init_Service_Handlers();
|
Init_Service_Handlers();
|
||||||
|
#ifdef BACDL_ETHERNET
|
||||||
// init the physical layer
|
// init the physical layer
|
||||||
if (!ethernet_init("eth0"))
|
if (!ethernet_init("eth0"))
|
||||||
return 1;
|
return 1;
|
||||||
|
#endif
|
||||||
|
#ifdef BACDL_BIP
|
||||||
|
Init_Network("eth0");
|
||||||
|
if (!bip_init())
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// loop forever
|
// loop forever
|
||||||
for (;;)
|
for (;;)
|
||||||
@@ -101,11 +193,20 @@ int main(int argc, char *argv[])
|
|||||||
// input
|
// input
|
||||||
|
|
||||||
// returns 0 bytes on timeout
|
// returns 0 bytes on timeout
|
||||||
|
#ifdef BACDL_ETHERNET
|
||||||
pdu_len = ethernet_receive(
|
pdu_len = ethernet_receive(
|
||||||
&src,
|
&src,
|
||||||
&Rx_Buf[0],
|
&Rx_Buf[0],
|
||||||
MAX_MPDU,
|
MAX_MPDU,
|
||||||
timeout);
|
timeout);
|
||||||
|
#endif
|
||||||
|
#ifdef BACDL_BIP
|
||||||
|
pdu_len = bip_receive(
|
||||||
|
&src,
|
||||||
|
&Rx_Buf[0],
|
||||||
|
MAX_MPDU,
|
||||||
|
timeout);
|
||||||
|
#endif
|
||||||
|
|
||||||
// process
|
// process
|
||||||
if (pdu_len)
|
if (pdu_len)
|
||||||
|
|||||||
Reference in New Issue
Block a user