//
// Copyright (C) 1999,2000 Yokogawa Electric Corporation and
//                         YDC Corporation.
// All rights reserved.
// 
// Redistribution and use of this software in source and binary
// forms, with or without modification, are permitted provided that
// the following conditions and disclaimer are agreed and accepted
// by the user:
// 
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materials provided with
//    the distribution.
// 
// 3. Neither the names of the copyrighters, the name of the project
//    which is related to this software (hereinafter referred to as
//    "project") nor the names of the contributors may be used to
//    endorse or promote products derived from this software without
//    specific prior written permission.
// 
// 4. No merchantable use may be permitted without prior written
//    notification to the copyrighters.
// 
// 5. The copyrighters, the project and the contributors may prohibit
//    the use of this software at any time.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHTERS, THE PROJECT AND
// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING
// BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.  IN NO EVENT SHALL THE
// COPYRIGHTERS, THE PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// $Name:  $
//
// $Id: RTU_common.def,v 1.1.1.1 2000/09/28 00:16:01 sekiya Exp $
//
#ifndef IPSEC_RTU_COMMON_DEF
#define IPSEC_RTU_COMMON_DEF

#include "./ipsecaddr.def"
#if (IPSEC_IPVERSION == 4)

#define vX(x)   v4(x)
#define FEM_icmpX_echo_request          FEM_icmp4_echo_request
#define FEM_icmpX_echo_reply            FEM_icmp4_echo_reply
#define FEM_icmpX_echo_request_exth     FEM_icmp4_echo_request_exth
#define FEM_icmpX_echo_reply_exth       FEM_icmp4_echo_reply_exth
#define FEM_hdr_ipvX_exth		FEM_hdr_ipv4_exth
#define _HDR_IPVX_NAME                  _HDR_IPV4_NAME
#define _ICMPVX_NAME                    _ICMPV4_NAME
#define _PACKET_IPVX_NAME               _PACKET_IPV4_NAME

#ifndef IPSEC_ECHO_DATA
#define IPSEC_ECHO_DATA echo_data24
#endif

#else /* default V6 */

#define vX(x)   v6(x)
#define FEM_icmpX_echo_request          FEM_icmp6_echo_request
#define FEM_icmpX_echo_reply            FEM_icmp6_echo_reply
#define FEM_icmpX_echo_request_exth     FEM_icmp6_echo_request_exth
#define FEM_icmpX_echo_reply_exth       FEM_icmp6_echo_reply_exth
#define FEM_hdr_ipvX_exth		FEM_hdr_ipv6_exth
#define _HDR_IPVX_NAME                  _HDR_IPV6_NAME
#define _ICMPVX_NAME                    _ICMPV6_NAME
#define _PACKET_IPVX_NAME               _PACKET_IPV6_NAME

#ifndef IPSEC_ECHO_DATA
#define IPSEC_ECHO_DATA echo_data8
#endif

#endif

//======================================================================
// NS-NA at TN-Router-Net0 <-> NUT-Net0
//

_HETHER_define(hether_router2nut,
	ether(IPSEC_ROUTER_NET0_MAC_ADDR),
	nutether()
)

_HETHER_define(hether_nut2router,
	nutether(),
	ether(IPSEC_ROUTER_NET0_MAC_ADDR)
)

//
// NS/NA or ARP Request/Reply
//

#if (IPSEC_IPVERSION == 4)
FEM_hdr_arp(
        ns_to_router,
        _HETHER_nut2broadcast,
        {
                Operation=1;
                SenderHAddr=nutether();
                SenderPAddr=v4(IPSEC_NUT_NET0_ADDR);
                TargetHAddr=any; // not only 00:00:00:00:00:00
                                 // but also ff:ff:ff:ff:ff:ff (same as ether_src)
                                 // is allowed
                TargetPAddr=v4(IPSEC_ROUTER_NET0_ADDR);
        }
)

FEM_hdr_arp(
        na_from_router,
        hether_router2nut,
        {
                Operation=2;
                SenderHAddr=ether(IPSEC_ROUTER_NET0_MAC_ADDR);
                SenderPAddr=v4(IPSEC_ROUTER_NET0_ADDR);
                TargetHAddr=nutether();
                TargetPAddr=v4(IPSEC_NUT_NET0_ADDR);
        }
)

#else
_HETHER_define(hether_nut2routersolnode,
	nutether(),
	oneof(_ETHER_SOLNODE_MCAST(v6(IPSEC_ROUTER_NET0_ADDR)),
	      ether(IPSEC_ROUTER_NET0_MAC_ADDR) )
)

FEM_icmp6_ns(
	ns_to_router,
	hether_nut2routersolnode,
	{
		_SRC(oneof(v6(IPSEC_NUT_NET0_ADDR), nutv6()));
		_DST(oneof(v6(IPSEC_ROUTER_NET0_ADDR), _IPV6_SOLNODE_MCAST(v6(IPSEC_ROUTER_NET0_ADDR) )));
		HopLimit = 255;
	},
	{
		TargetAddress = v6(IPSEC_ROUTER_NET0_ADDR);
		option = _SLLOPT_nut;
	}
)

_TLLOPT_define(tllopt_router, ether(IPSEC_ROUTER_NET0_MAC_ADDR))

FEM_icmp6_na(
	na_from_router,
	hether_router2nut,
	{
		_SRC(v6(IPSEC_ROUTER_NET0_ADDR));
		_DST(v6(IPSEC_NUT_NET0_ADDR));
		HopLimit = 255;
	},
	{
		RFlag = 1;
		SFlag = 1;
		OFlag = 1;
		TargetAddress = v6(IPSEC_ROUTER_NET0_ADDR);
		option = tllopt_router;
	}
)
#endif

//======================================================================
// NS-NA at TN-Host1-Net1 <-> NUT-Net1
//

_HETHER_define(hether_host12nut,
	ether(IPSEC_HOST1_NET1_MAC_ADDR),
	nutether()
)

_HETHER_define(hether_nut2host1,
	nutether(),
	ether(IPSEC_HOST1_NET1_MAC_ADDR)
)

#if (IPSEC_IPVERSION == 4)
FEM_hdr_arp(
	ns_to_host1_net1,
        _HETHER_nut2broadcast,
        {
                Operation=1;
                SenderHAddr=nutether();
                SenderPAddr=v4(IPSEC_NUT_NET1_ADDR);
                TargetHAddr=ether("00:00:00:00:00:00");
                TargetPAddr=v4(IPSEC_HOST1_NET1_ADDR);
        }
)

FEM_hdr_arp(
	na_from_host1_net1,
        hether_router2nut,
        {
                Operation=2;
                SenderHAddr=ether(IPSEC_HOST1_NET1_MAC_ADDR);
                SenderPAddr=v4(IPSEC_HOST1_NET1_ADDR);
                TargetHAddr=nutether();
                TargetPAddr=v4(IPSEC_NUT_NET1_ADDR);
        }
)
#else

//
// NS
//

_HETHER_define(hether_nut2host1solnode,
	nutether(),
	oneof(_ETHER_SOLNODE_MCAST(v6(IPSEC_HOST1_NET1_ADDR)),
              ether(IPSEC_HOST1_NET1_MAC_ADDR) )
)

FEM_icmp6_ns(
	ns_to_host1_net1,
	hether_nut2host1solnode,
	{
		_SRC(oneof(v6(IPSEC_NUT_NET1_ADDR), nutv6()));
		_DST(oneof(v6(IPSEC_HOST1_NET1_ADDR), _IPV6_SOLNODE_MCAST(v6(IPSEC_HOST1_NET1_ADDR))));
		HopLimit = 255;
	},
	{
		TargetAddress = v6(IPSEC_HOST1_NET1_ADDR);
		option = _SLLOPT_nut;
	}
)

//
// Neighbor Advertisement
//

_TLLOPT_define(tllopt_host1, ether(IPSEC_HOST1_NET1_MAC_ADDR))

FEM_icmp6_na(
	na_from_host1_net1,
	hether_host12nut,
	{
		_SRC(v6(IPSEC_HOST1_NET1_ADDR));
		_DST(v6(IPSEC_NUT_NET1_ADDR));
		HopLimit = 255;
	},
	{
		RFlag = 0;
		SFlag = 1;
		OFlag = 1;
		TargetAddress = v6(IPSEC_HOST1_NET1_ADDR);
		option = tllopt_host1;
	}
)
#endif

//======================================================================
//
// Echo Request from Router
//

FEM_icmpX_echo_request(
	echo_request_from_router,
	hether_router2nut,
	{
		_SRC(vX(IPSEC_ROUTER_NET0_ADDR));
		_DST(vX(IPSEC_NUT_NET0_ADDR));
	},
	{
		payload = IPSEC_ECHO_DATA;
	}
)

//======================================================================
//
// Echo Reply to Router
//

FEM_icmpX_echo_reply(
	echo_reply_to_router,
	hether_nut2router,
	{
		_SRC(vX(IPSEC_NUT_NET0_ADDR));
		_DST(vX(IPSEC_ROUTER_NET0_ADDR));
	},
	{
		payload = IPSEC_ECHO_DATA;
	}
)

//======================================================================
//
// Echo Request from SG1 (Net2)
//

FEM_icmpX_echo_request(
	echo_request_from_sg1_net2,
	hether_router2nut,
	{
		_SRC(vX(IPSEC_SG1_NET2_ADDR));
		_DST(vX(IPSEC_NUT_NET0_ADDR));
	},
	{
		payload = IPSEC_ECHO_DATA;
	}
)

//======================================================================
//
// Echo Reply to SG1 (Net2)
//

FEM_icmpX_echo_reply(
	echo_reply_to_sg1_net2,
	hether_nut2router,
	{
		_SRC(vX(IPSEC_NUT_NET0_ADDR));
		_DST(vX(IPSEC_SG1_NET2_ADDR));
	},
	{
		payload = IPSEC_ECHO_DATA;
	}
)

//======================================================================
//
// Echo Request from Host1 (Net1)
//

FEM_icmpX_echo_request(
	echo_request_from_host1_net1,
	hether_host12nut,
	{
		_SRC(vX(IPSEC_HOST1_NET1_ADDR));
		_DST(vX(IPSEC_NUT_NET1_ADDR));
	},
	{
		payload = IPSEC_ECHO_DATA;
	}
)

//======================================================================
//
// Echo Reply to Host1 (Net1)
//

FEM_icmpX_echo_reply(
	echo_reply_to_host1_net1,
	hether_nut2host1,
	{
		_SRC(vX(IPSEC_NUT_NET1_ADDR));
		_DST(vX(IPSEC_HOST1_NET1_ADDR));
	},
	{
		payload = IPSEC_ECHO_DATA;
	}
)

//======================================================================
//
// Echo Request from Host1 (Net4) to Host1 (Net1) on Net0/Net1
//

FEM_icmpX_echo_request(
	echo_request_from_host1_net4_to_host1_net1_on_net0,
	hether_router2nut,
	{
		_SRC(vX(IPSEC_HOST1_NET4_ADDR));
		_DST(vX(IPSEC_HOST1_NET1_ADDR));
	},
	{
		payload = IPSEC_ECHO_DATA;
	}
)

FEM_icmpX_echo_request(
	echo_request_from_host1_net4_to_host1_net1_on_net1,
	hether_nut2host1,
	{
		_SRC(vX(IPSEC_HOST1_NET4_ADDR));
		_DST(vX(IPSEC_HOST1_NET1_ADDR));
	},
	{
		payload = IPSEC_ECHO_DATA;
	}
)

//======================================================================
//
// Echo Reply from Host1 (Net4) to Host1 (Net1) on Net0/Net1
//

FEM_icmpX_echo_reply(
	echo_reply_from_host1_net1_to_host1_net4_on_net1,
	hether_host12nut,
	{
		_SRC(vX(IPSEC_HOST1_NET1_ADDR));
		_DST(vX(IPSEC_HOST1_NET4_ADDR));
	},
	{
		payload = IPSEC_ECHO_DATA;
	}
)

FEM_icmpX_echo_reply(
	echo_reply_from_host1_net1_to_host1_net4_on_net0,
	hether_nut2router,
	{
		_SRC(vX(IPSEC_HOST1_NET1_ADDR));
		_DST(vX(IPSEC_HOST1_NET4_ADDR));
	},
	{
		payload = IPSEC_ECHO_DATA;
	}
)

//======================================================================
//
// Payload Data
//

Payload echo_data8 {
	data = { 0x45, 0x63, 0x68, 0x6f, 0x44, 0x61, 0x74, 0x61};
}

Payload echo_data24 {
	data = { 0x45, 0x63, 0x68, 0x6f, 0x44, 0x61, 0x74, 0x61};
	data = { 0x45, 0x63, 0x68, 0x6f, 0x44, 0x61, 0x74, 0x61};
	data = { 0x45, 0x63, 0x68, 0x6f, 0x44, 0x61, 0x74, 0x61};
}


//======================================================================
//
// Echo Data 1 ("Data 1")
//

Payload echo_data_1 {
#if (IPSEC_IPVERSION == 4)
	data = { 0x45, 0x63, 0x68, 0x6f, 0x44, 0x61, 0x74, 0x61};
	data = { 0x45, 0x63, 0x68, 0x6f, 0x44, 0x61, 0x74, 0x61, 0x20, 0x31 };
#else
	data = { 0x44, 0x61, 0x74, 0x61, 0x20, 0x31 };
#endif
}

//======================================================================
//
// Echo Data 2 ("Data 2")
//

Payload echo_data_2 {
#if (IPSEC_IPVERSION == 4)
	data = { 0x45, 0x63, 0x68, 0x6f, 0x44, 0x61, 0x74, 0x61};
	data = { 0x45, 0x63, 0x68, 0x6f, 0x44, 0x61, 0x74, 0x61, 0x20, 0x32 };
#else
	data = { 0x44, 0x61, 0x74, 0x61, 0x20, 0x32 };
#endif
}

#endif
