BACnet protocol stack porting Analysis 3: mstpsnap. c

Source: Internet
Author: User
Tags htons

The mstpscap. c file is used to capture packets on the MS/TP protocol from the serial port. The format for testing is: mstsnap [Serial] [baud] [network]

The default parameters are serial port/dev/ttyusb0, baud rate is 38400, and eth0.

# Include <stddef. h>
# Include <stdint. h>
# Include <stdio. h>
# Include <stdlib. h>
# Include <string. h>
# Include <errno. h>
/* OS specific include */
# Include "net. H"
# Include "timer. H"
/* Local primary des */
# Include "bytes. H"
# Include "rs485.h"
# Include "CRC. H"
# Include "MSTP. H"
# Include "dlmstp. H"
# Include "mstptext. H"
# Include "bacint. H"

/** @ File Linux/mstpsnap. c example application testing BACnet MS/TP on Linux .*/

# Ifndef Max
# Define max (A, B) (a)> (B ))? (A): (B ))
# Define min (A, B) (a) <(B ))? (A): (B ))
# Endif

/* Local port data-shared with RS-485 */
Static volatile struct mstp_port_struct_t mstp_port;
/* Buffers needed by MSTP port struct */
Static uint8_t rxbuffer [max_mpdu];
Static uint8_t txbuffer [max_mpdu];
Static uint16_t timer_silence (
Void)
{
Uint32_t delta_time = 0;

Delta_time = timer_milliseconds (timer_silence );
If (delta_time> 0 xFFFF ){
Delta_time = 0 xFFFF;
}

Return (uint16_t) delta_time;
}

Static void timer_silence_reset (
Void)
{
Timer_reset (timer_silence );
}

/* Functions used by the MS/TP state machine to put or get data */
Uint16_t mstp_put_receive (
Volatile struct mstp_port_struct_t * mstp_port)
{
(Void) mstp_port;

Return 0;
}

/* For the MS/TP state machine to use for getting data to send */
/* Return: Amount of PDU data */
Uint16_t mstp_get_send (
Volatile struct mstp_port_struct_t * mstp_port,
Unsigned timeout)
{/* Milliseconds to wait for a packet */
(Void) mstp_port;
(Void) Timeout;
Return 0;
}

Uint16_t mstp_get_reply (
Volatile struct mstp_port_struct_t * mstp_port,
Unsigned timeout)
{/* Milliseconds to wait for a packet */
(Void) mstp_port;
(Void) Timeout;
Return 0;
}

Static int network_init (
Const char * Name,
Int Protocol)
{
/* Check to see if we are being run as root */
If (getuid ()! = 0) {// The function returns the real User ID of a calling program. Generally, this function is called successfully. Getuid = 0 indicates the root user.
Fprintf (stderr, "requires root priveleges. \ n ");
Return-1;
}

Int sockfd = socket (pf_packet, sock_raw, htons (Protocol); // get the original IP package. htons gets the network byte order (large-end mode) and uses the big-end mode for unified transmission.
If (sockfd =-1 ){
Perror ("unable to create socket ");
Return sockfd;
}

Struct ifreq IFR;
// Obtain the IP address and MAC address

Memset (& IFR, 0, sizeof (IFR ));
Strncpy (IFR. ifr_name, name, strlen (name ));

If (IOCTL (sockfd, siocgifindex, & IFR) =-1) {// obtain and print the NIC address
Perror ("unable to get interface Index ");
Return-1;
}

Struct sockaddr_ll sll;
// Local address

Memset (& sll, 0, sizeof (SLL ));
SLL. sll_family = af_packet;
SLL. sll_ifindex = IFR. ifr_ifindex;
SLL. sll_protocol = htons (Protocol );

If (BIND (sockfd, (struct sockaddr *) & sll, sizeof (SLL) =-1) {// bind a socket
Perror ("unable to bind socket ");
Return-1;
}

Return sockfd;
}

Static void snap_received_packet (
Volatile struct mstp_port_struct_t * mstp_port,
Int sockfd)
{
Uint16_t mtu_len = 0;/* Number of ETS ets of packet saved in file */
Unsigned I = 0;/* counter */
Static uint8_t MTU [1500] = {0}; // for physical layer implementation and other reasons, the length of an Ethernet frame is generally less than 1500 bytes.
Uint16_t max_data = 0;

MTU [0] = 0;
MTU [1] = 0;
MTU [2] = 0;
MTU [3] = 0;
MTU [4] = 0;
MTU [5] = mstp_port-> destinationaddress;
MTU [6] = 0;
MTU [7] = 0;
MTU [8] = 0;
MTU [9] = 0;
MTU [10] = 0;
MTU [11] = mstp_port-> sourceaddress;
/* Length-12, 13 */
MTU [14] = 0xaa;/* DSAP for SNAP */
MTU [15] = 0xaa;/* SSAP for SNAP */
MTU [16] = 0x03;/* control field for SNAP */
MTU [17] = 0x00;/* Organization Code: cimetrics */
MTU [18] = 0x10;/* Organization Code: cimetrics */
MTU [19] = 0x90;/* Organization Code: cimetrics */
MTU [20] = 0x00;/* protocol id */
MTU [21] = 0x01;/* protocol id */
MTU [22] = 0x00;/* Delta time */
MTU [23] = 0x00;/* Delta time */
MTU [24] = 0x80;/* unknown byte */
MTU [25] = mstp_port-> frametype;
MTU [26] = mstp_port-> destinationaddress;
MTU [27] = mstp_port-> sourceaddress;
MTU [28] = hi_byte (mstp_port-> datalength );
MTU [29] = lo_byte (mstp_port-> datalength );
MTU [30] = mstp_port-> headercrcactual;
Mtu_len = 31;
If (mstp_port-> datalength) {// store data from the input cache and datacrcactual (first high and then low order)
Max_data = min (mstp_port-> inputbuffersize, mstp_port-> datalength );
For (I = 0; I <max_data; I ++ ){
MTU [31 + I] = mstp_port-> inputbuffer [I];
}
MTU [31 + max_data] = mstp_port-> datacrcactualmsb;
MTU [31 + max_data + 1] = mstp_port-> datacrcactuallsb;
Mtu_len + = (max_data + 2 );
}
/* Ethernet length is data only-not address or length bytes */
Encode_unsigned16 (& MTU [12], mtu_len-14); // encode the integer type
(Void) write (sockfd, & MTU [0], mtu_len );
}

Static void cleanup (
Void)
{
}

# If (! Defined (_ Win32 ))
Static void sig_int (
Int signo)
{
(Void) signo;

Cleanup ();
Exit (0 );
}

Void signal_init (
Void)
{
Signal (SIGINT, sig_int );
Signal (sighup, sig_int );
Signal (sigterm, sig_int );
}
# Endif

/* Simple test to packetize the data and print it */
Int main (INT argc, char * argv []) // The main function is used to run root # mstpsnap/dev/tty/usb0 38400 eth0 on a Linux terminal.
{
Volatile struct mstp_port_struct_t * mstp_port;
Long my_baud = 38400;
Uint32_t packet_count = 0;
Int sockfd =-1;
Char * my_interface = "eth0 ";

/* Mimic our pointer in the state machine */
Mstp_port = & mstp_port;
If (argc> 1) & (strcmp (argv [1], "-- Help") = 0 )){
Printf ("mstsnap [Serial] [baud] [network] \ r \ n"
& Quot; captures MS/TP packets from a serial interface \ r \ n & quot"
"And sends them to a network interface using SNAP \ r \ n"
"Protocol packets (mimics cimetrics U + 4 packet). \ r \ n" "\ r \ n"
"Command line options: \ r \ n" "[Serial]-serial interface. \ r \ n"
"Defaults to/dev/ttyusb0. \ r \ n"
"[Baud]-baud rate. 9600,192 00, 38400,576 00, 115200 \ r \ n"
"Defaults to 38400. \ r \ n" "[network]-network interface. \ r \ n"
"Defaults to eth0. \ r \ n """);
Return 0;
}
/* Initialize our interface */
If (argc> 1 ){
Rs485_set_interface (argv [1]);
}
If (argc> 2 ){
My_baud = strtol (argv [2], null, 0); // convert argv [2] to decimal form
}
If (argc> 3 ){
My_interface = argv [3];
}
Sockfd = network_init (my_interface, eth_p_all );
If (sockfd =-1 ){
Return 1;
} // Set some content parameters in the MS/TP protocol. This part requires familiarity with the MS/TP protocol content. For more information, see <principles and control of smart building BACnet>
Rs485_set_baud_rate (my_baud );
Rs485_initialize ();
Mstp_port.inputbuffer = & rxbuffer [0];
Mstp_port.inputbuffersize = sizeof (rxbuffer );
Mstp_port.outputbuffer = & txbuffer [0];
Mstp_port.outputbuffersize = sizeof (txbuffer );
Mstp_port.this_station = 127;
Mstp_port.nmax_info_frames = 1;
Mstp_port.nmax_master = 127;
Mstp_port.silencetimer = timer_silence;
Mstp_port.silencetimerreset = timer_silence_reset;
Mstp_init (mstp_port );
Fprintf (stdout, "mstpcap: using % s for capture at % ld bps. \ n ",
Rs485_interface (), (long) rs485_get_baud_rate ());
Atexit (cleanup );
# If defined (_ Win32)
Setconsolemode (getstdhandle (std_input_handle), enable_processed_input );
Setconsolectrlhandler (phandler_routine) ctrlchandler, true );
# Else
Signal_init ();
# Endif
/* Run forever */
For (;;){
Rs485_check_uart_data (mstp_port );
Mstp_receive_frame_fsm (mstp_port );
/* Process the data portion of the frame */
If (mstp_port-> receivedvalidframe ){
Mstp_port-> receivedvalidframe = false;
Snap_received_packet (mstp_port, sockfd );
Packet_count ++;
} Else if (mstp_port-> receivedinvalidframe ){
Mstp_port-> receivedinvalidframe = false;
Fprintf (stderr, "receivedinvalidframe \ n ");
Snap_received_packet (mstp_port, sockfd );
Packet_count ++;
}
If (! (Packet_count % 100 )){
Fprintf (stdout, "\ r % Hu packets", packet_count );
}
}

Return 0;
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.