Files
bacnet_stack/ports/uip/bip.c
T
2026-04-24 06:40:32 -05:00

231 lines
6.0 KiB
C

/**************************************************************************
*
* Copyright (C) 2005 Steve Karg
*
* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0
*
*********************************************************************/
#include <stdint.h> /* for standard integer types uint8_t etc. */
#include <stdbool.h> /* for the standard bool type. */
#include "bacnet/bacdcode.h"
#include "bacnet/datalink/bip.h"
#include "eth.h"
#include "bacport.h" /* custom per port */
static int BIP_Socket = -1;
/* port to use - stored in host byte order */
static uint16_t BIP_Port = 0xBAC0U;
/* broadcast destination port to use */
static uint16_t BIP_Broadcast_Port;
/* IP Address - stored in host byte order */
static struct in_addr BIP_Address;
/* Broadcast Address - stored in host byte order */
static struct in_addr BIP_Broadcast_Address;
void bip_set_socket(int sock_fd)
{
BIP_Socket = sock_fd;
}
int bip_socket(void)
{
return BIP_Socket;
}
bool bip_valid(void)
{
return (BIP_Socket != -1);
}
void bip_cleanup(void)
{
/* if (bip_valid()) */
/* close(BIP_Socket); */
BIP_Socket = -1;
BIP_Broadcast_Port = 0;
return;
}
/* set using network byte order */
void bip_set_addr(uint32_t net_address)
{
/* BIP_Address.s_addr = ntohl(net_address); */
BIP_Address.s_addr = net_address;
}
/* returns host byte order */
uint32_t bip_get_addr(void)
{
return BIP_Address.s_addr;
}
/* set using network byte order */
void bip_set_broadcast_addr(uint32_t net_address)
{
/* BIP_Broadcast_Address.s_addr = ntohl(net_address); */
BIP_Broadcast_Address.s_addr = net_address;
}
/* returns host byte order */
uint32_t bip_get_broadcast_addr(void)
{
return BIP_Broadcast_Address.s_addr;
}
/* set using host byte order */
void bip_set_port(uint16_t port)
{
BIP_Port = port;
}
/* set using host byte order */
void bip_set_broadcast_port(uint16_t port)
{
BIP_Broadcast_Port = port;
}
/* returns host byte order */
uint16_t bip_get_port(void)
{
return BIP_Port;
}
/* returns host byte order */
uint16_t bip_get_broadcast_port(void)
{
if (BIP_Broadcast_Port) {
return BIP_Broadcast_Port;
}
return BIP_Port;
}
/* function to send a packet out the BACnet/IP socket (Annex J) */
/* returns number of bytes sent on success, negative number on failure */
int bip_send_pdu(BACNET_ADDRESS *dest, /* destination address */
BACNET_NPDU_DATA *npdu_data, /* network information */
uint8_t *pdu, /* any data to be sent - may be null */
unsigned pdu_len)
{ /* number of bytes of data */
struct sockaddr_in bip_dest;
uint8_t mtu[4];
int mtu_len = 0;
int bytes_sent = 0;
UDP_HDR udphdr;
IP_HDR iphdr;
uint8_t mac[6];
(void)npdu_data;
/* assumes that the driver has already been initialized */
/* if (BIP_Socket < 0) */
/* return BIP_Socket; */
mtu[0] = BVLL_TYPE_BACNET_IP;
bip_dest.sin_family = AF_INET;
if (dest->mac_len == 6) {
memcpy(&(bip_dest.sin_addr.s_addr), &dest->mac[0], 4);
decode_unsigned16(&dest->mac[4], &(bip_dest.sin_port));
memset(&(bip_dest.sin_zero), '\0', 8);
mtu[1] = BVLC_ORIGINAL_UNICAST_NPDU;
}
/* broadcast */
else if (dest->mac_len == 0) {
bip_dest.sin_addr.s_addr = BIP_Broadcast_Address.s_addr;
bip_dest.sin_port = htons(bip_get_broadcast_port());
memset(&(bip_dest.sin_zero), '\0', 8);
mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU;
} else
return -1;
mtu_len = 2;
mtu_len += encode_unsigned16(
&mtu[mtu_len], (uint16_t)(pdu_len + 4 /*inclusive */));
mtu_len += pdu_len;
/* IP address should be in network byte order */
ARPIsResolved(bip_dest.sin_addr.s_addr, mac);
iphdr.vhl = 0x45;
iphdr.tos = 0;
iphdr.iplen = htons(mtu_len + sizeof(IP_HDR) + sizeof(UDP_HDR));
++ipid;
iphdr.ipid = htons(ipid);
iphdr.ipoffset[0] = iphdr.ipoffset[1] = 0;
iphdr.ttl = UIP_TTL;
iphdr.proto = UIP_PROTO_UDP;
iphdr.ipchksum = 0;
iphdr.srcipaddr = BIP_Address.s_addr;
iphdr.destipaddr = bip_dest.sin_addr.s_addr;
/* Calculate IP checksum. */
iphdr.ipchksum = ~(ip_getchksum((uint8_t *)&iphdr));
/* Ports are sent in Network byte order. BIP_Port is stored in Host byte
* order */
udphdr.srcport = htons(BIP_Port);
udphdr.destport = bip_dest.sin_port;
udphdr.udplen = htons(mtu_len + sizeof(UDP_HDR));
/* Not using UDP checksums */
udphdr.udpchksum = 0;
EthernetSendHeader(mac, UIP_ETHTYPE_IP);
EthernetSend((uint8_t *)&iphdr, sizeof(IP_HDR));
EthernetSend((uint8_t *)&udphdr, sizeof(UDP_HDR));
EthernetSend(mtu, 4);
EthernetSend(pdu, pdu_len);
EthernetFlush();
uip_stat.ip.sent++;
}
/* receives a BACnet/IP packet */
/* returns the number of octets in the PDU, or zero on failure */
uint16_t bip_receive(BACNET_ADDRESS *src, /* source address */
uint8_t *pdu, /* PDU data */
uint16_t max_pdu, /* amount of space available in the PDU */
unsigned timeout)
{ /* number of milliseconds to wait for a packet */
return 0;
}
void bip_get_my_address(BACNET_ADDRESS *my_address)
{
int i = 0;
my_address->mac_len = 6;
(void)encode_unsigned32(&my_address->mac[0], htonl(BIP_Address.s_addr));
(void)encode_unsigned16(&my_address->mac[4], htons(BIP_Port));
my_address->net = 0; /* local only, no routing */
my_address->len = 0; /* no SLEN */
for (i = 0; i < MAX_MAC_LEN; i++) {
/* no SADR */
my_address->adr[i] = 0;
}
return;
}
void bip_get_broadcast_address(BACNET_ADDRESS *dest)
{ /* destination address */
int i = 0; /* counter */
if (dest) {
dest->mac_len = 6;
(void)encode_unsigned32(
&dest->mac[0], htonl(BIP_Broadcast_Address.s_addr));
(void)encode_unsigned16(
&dest->mac[4], htons(bip_get_broadcast_port()));
dest->net = BACNET_BROADCAST_NETWORK;
dest->len = 0; /* no SLEN */
for (i = 0; i < MAX_MAC_LEN; i++) {
/* no SADR */
dest->adr[i] = 0;
}
}
return;
}