//
// $Copyright_v6PC$
//
// $Copyright$
//
// $TAHI: ct/nd/hostRecvRaRLifetimeN.def,v 1.9 2004/04/02 02:28:22 akisada Exp $

#include "nd.def"

//----------------------------------------------------------------------
_HETHER_define(hether_y2nut, ether(A0N_MAC_ADDR), nutether())
_HETHER_define(hether_z2nut, ether(A1N_MAC_ADDR), nutether())

_HETHER_define(hether_y2allnodes, ether(A0N_MAC_ADDR),
        v62ethermulti(v6(_ALLNODES_MCAST_ADDR)))
_HETHER_define(hether_z2allnodes, ether(A1N_MAC_ADDR),
        v62ethermulti(v6(_ALLNODES_MCAST_ADDR)))

_HETHER_define(hether_nut2wsolnode, nutether(),
        _ETHER_SOLNODE_MCAST(v6ether(A9N_MAC_ADDR)))
_HETHER_define(hether_nut2ysolnode, nutether(),
        _ETHER_SOLNODE_MCAST(v6ether(A0N_MAC_ADDR)))
_HETHER_define(hether_nut2zsolnode, nutether(),
        _ETHER_SOLNODE_MCAST(v6ether(A1N_MAC_ADDR)))

_HETHER_define(hether_w2nut, ether(A2N_MAC_ADDR), nutether())
_HETHER_define(hether_nut2y, nutether(), ether(A0N_MAC_ADDR))
_HETHER_define(hether_nut2z, nutether(), ether(A1N_MAC_ADDR))

_SLLOPT_define(sllopt_y, ether(A0N_MAC_ADDR))
_SLLOPT_define(sllopt_z, ether(A1N_MAC_ADDR))
_TLLOPT_define(tllopt_y, ether(A0N_MAC_ADDR))
_TLLOPT_define(tllopt_z, ether(A1N_MAC_ADDR))

//----------------------------------------------------------------------
// multicast RA
//      TN(link-local) ==> all-node
//      M=0, O=0
//      lifetime=600 or 5 sec
//	ReachableTime=0 msec (not specified)
//	RetransTimer=0 msec (not specified)
//      w/ SLLA
//      w/ prefix
//              l=1, a=1
//              ValidLifetime=2592000
//		PreferredLifetime=604800;
//----------------------------------------------------------------------
FEM_icmp6_ra(ra_tn2allnode_sll, _HETHER_tn2allnodes,
        {
         _SRC(tnv6());
         _DST(v6(_ALLNODES_MCAST_ADDR));
         HopLimit=255;
        },
        {
         CurHopLimit=0;
         MFlag=0;
         OFlag=0;
         LifeTime=600;
         ReachableTime=0;
         RetransTimer=0;
         option=_SLLOPT_tn;
         option=prefixopt_tn;
        }
)

//----------------------------------------------------------------------
FEM_icmp6_ra(ra_tn2allnode_sll_clear, _HETHER_tn2allnodes,
        {
         _SRC(tnv6());
         _DST(v6(_ALLNODES_MCAST_ADDR));
         HopLimit=255;
        },
        {
         CurHopLimit=0;
         MFlag=0;
         OFlag=0;
         LifeTime=5;
         ReachableTime=0;
         RetransTimer=0;
         option=_SLLOPT_tn;
        }
)

//----------------------------------------------------------------------
Opt_ICMPv6_Prefix prefixopt_tn {
//      Type=3;
//      Length=4;
//      PrefixLength=_GLOBAL0_UCAST_PRFXLEN;
        LFlag=1;
        AFlag=1;        
//      Reserved1=ZERO; 
        ValidLifetime=2592000;
        PreferredLifetime=604800;
//      Reserved2=ZERO; 
        Prefix=v6(_GLOBAL0_UCAST_PRFX);
}

//----------------------------------------------------------------------
// multicast RA
//      Y(link-local) ==> all-node
//      M=0, O=0
//      lifetime=600 or 5 sec
//	ReachableTime=0 msec (not specified)
//	RetransTimer=0 msec (not specified)
//      w/ SLLA
//      w/ prefix
//              l=1, a=1
//              ValidLifetime=2592000
//		PreferredLifetime=604800;
//----------------------------------------------------------------------
FEM_icmp6_ra(ra_y2allnode_sll, hether_y2allnodes,
        {
         _SRC(v6ether(A0N_MAC_ADDR));
	 _DST(v6(_ALLNODES_MCAST_ADDR));
         HopLimit=255;
        },
        {
         CurHopLimit=0;
         MFlag=0;
         OFlag=0;
         LifeTime=600;
         ReachableTime=0;
         RetransTimer=0;
         option=sllopt_y;
         option=prefixopt_y;
        }
)

//----------------------------------------------------------------------
FEM_icmp6_ra(ra_y2allnode_sll_clear, hether_y2allnodes,
        {
         _SRC(v6ether(A0N_MAC_ADDR));
	 _DST(v6(_ALLNODES_MCAST_ADDR));
         HopLimit=255;
        },
        {
         CurHopLimit=0;
         MFlag=0;
         OFlag=0;
         LifeTime=5;
         ReachableTime=0;
         RetransTimer=0;
         option=sllopt_y;
        }
)

//----------------------------------------------------------------------
Opt_ICMPv6_Prefix prefixopt_y {
//      Type=3;
//      Length=4;
//      PrefixLength=_GLOBAL0_UCAST_PRFXLEN;
        LFlag=1;
        AFlag=1;        
//      Reserved1=ZERO; 
        ValidLifetime=2592000;
        PreferredLifetime=604800;
//      Reserved2=ZERO; 
        Prefix=v6(_GLOBAL0_UCAST_PRFX);
}

//----------------------------------------------------------------------
// multicast RA
//      Z(link-local) ==> all-node
//      M=0, O=0
//      lifetime=600 or 5 sec
//	ReachableTime=0 msec (not specified)
//	RetransTimer=0 msec (not specified)
//      w/ SLLA
//      w/ prefix
//              l=1, a=1
//              ValidLifetime=2592000
//		PreferredLifetime=604800;
//----------------------------------------------------------------------
FEM_icmp6_ra(ra_z2allnode_sll, hether_z2allnodes,
        {
         _SRC(v6ether(A1N_MAC_ADDR));
         _DST(v6(_ALLNODES_MCAST_ADDR));
         HopLimit=255;
        },
        {
         CurHopLimit=0;
         MFlag=0;
         OFlag=0;
         LifeTime=600;
         ReachableTime=0;
         RetransTimer=0;
         option=sllopt_z;
         option=prefixopt_z;
        }
)

//----------------------------------------------------------------------
FEM_icmp6_ra(ra_z2allnode_sll_clear, hether_z2allnodes,
        {
         _SRC(v6ether(A1N_MAC_ADDR));
         _DST(v6(_ALLNODES_MCAST_ADDR));
         HopLimit=255;
        },
        {
         CurHopLimit=0;
         MFlag=0;
         OFlag=0;
         LifeTime=5;
         ReachableTime=0;
         RetransTimer=0;
         option=sllopt_z;
        }
)

//----------------------------------------------------------------------
Opt_ICMPv6_Prefix prefixopt_z {
//      Type=3;
//      Length=4;
//      PrefixLength=_GLOBAL0_UCAST_PRFXLEN;
        LFlag=1;
        AFlag=1;        
//      Reserved1=ZERO; 
        ValidLifetime=2592000;
        PreferredLifetime=604800;
//      Reserved2=ZERO; 
        Prefix=v6(_GLOBAL0_UCAST_PRFX);
}

//----------------------------------------------------------------------
// multicast RA
//      TN(link-local) ==> all-node
//      M=0, O=0
//      lifetime=0 sec
//	ReachableTime=0 msec (not specified)
//	RetransTimer=0 msec (not specified)
//      w/o SLLA
//      w/o
//----------------------------------------------------------------------
FEM_icmp6_ra(ra_tn2allnode_clrrtr, _HETHER_tn2allnodes,
        {
         _SRC(tnv6());
         _DST(v6(_ALLNODES_MCAST_ADDR));
         HopLimit=255;
        },
        {
         CurHopLimit=0;
         MFlag=0;
         OFlag=0;
         LifeTime=0;
         ReachableTime=0;
         RetransTimer=0;
        }
)

//----------------------------------------------------------------------
FEM_icmp6_ra(ra_y2allnode_clrrtr, hether_y2allnodes,
        {
         _SRC(v6ether(A0N_MAC_ADDR));
	 _DST(v6(_ALLNODES_MCAST_ADDR));
         HopLimit=255;
        },
        {
         CurHopLimit=0;
         MFlag=0;
         OFlag=0;
         LifeTime=0;
         ReachableTime=0;
         RetransTimer=0;
        }
)

//----------------------------------------------------------------------
FEM_icmp6_ra(ra_z2allnode_clrrtr, hether_z2allnodes,
        {
         _SRC(v6ether(A1N_MAC_ADDR));
         _DST(v6(_ALLNODES_MCAST_ADDR));
         HopLimit=255;
        },
        {
         CurHopLimit=0;
         MFlag=0;
         OFlag=0;
         LifeTime=0;
         ReachableTime=0;
         RetransTimer=0;
        }
)

//----------------------------------------------------------------------
// multicast NS for DAD
//      unspecified ==> solnode[NUT's link-local]
//      target=NUT(global)
//      w/o SLLA
//----------------------------------------------------------------------
FEM_icmp6_ns(dad_ns, _HETHER_src2dstsolnode,
        {
         _SRC(v6(_UNSPEC_ADDR));
         _DST(_IPV6_SOLNODE_MCAST(nutv6()));
         HopLimit=255;
        },
        {
         TargetAddress=nut2v6(_GLOBAL0_UCAST_PRFX, _GLOBAL0_UCAST_PRFXLEN);
        }
)

//----------------------------------------------------------------------
// unicast NA
//	TN(link-local) ==> NUT(link-local)
//	R=1, S=1, O=1
//	w/ TLLA
//----------------------------------------------------------------------
FEM_icmp6_na(unicast_na_tn2nut_RSO_tll, _HETHER_tn2nut,
        {
         _SRC(tnv6());
         _DST(nutv6());
         HopLimit=255;
        },
        {
         RFlag=1;
         SFlag=1;
         OFlag=1;
         TargetAddress=tnv6();
         option=_TLLOPT_tn;
        }
)

//----------------------------------------------------------------------
// unicast NA
//	Y(link-local) ==> NUT(link-local)
//	R=1, S=1, O=1
//	w/ TLLA
//----------------------------------------------------------------------
FEM_icmp6_na(unicast_na_y2nut_RSO_tll, hether_y2nut,
        {
         _SRC(v6ether(A0N_MAC_ADDR));
         _DST(nutv6());
         HopLimit=255;
        },
        {
         RFlag=1;
         SFlag=1;
         OFlag=1;
         TargetAddress=v6ether(A0N_MAC_ADDR);
         option=tllopt_y;
        }
)

//----------------------------------------------------------------------
// unicast NA
//	Z(link-local) ==> NUT(link-local)
//	R=1, S=1, O=1
//	w/ TLLA
//----------------------------------------------------------------------
FEM_icmp6_na(unicast_na_z2nut_RSO_tll, hether_z2nut,
        {
         _SRC(v6ether(A1N_MAC_ADDR));
         _DST(nutv6());
         HopLimit=255;
        },
        {
         RFlag=1;
         SFlag=1;
         OFlag=1;
         TargetAddress=v6ether(A1N_MAC_ADDR);
         option=tllopt_z;
        }
)

//----------------------------------------------------------------------
// echo-request
//      X(off-link global, but max:W) ==> NUT(global)
//----------------------------------------------------------------------
FEM_icmp6_echo_request(echo_request_x2nut_via_w, hether_w2nut,
        {
         _SRC(v6merge(_GLOBAL9_UCAST_PRFX, _GLOBAL9_UCAST_PRFXLEN,
                        v6ether(A9N_MAC_ADDR)));
         _DST(nut2v6(_GLOBAL0_UCAST_PRFX, _GLOBAL0_UCAST_PRFXLEN));
        },
        {
         payload=echo_data;
        }
)

//----------------------------------------------------------------------
// echo-request
//      X(off-link global, but max:TN) ==> NUT(global)
//----------------------------------------------------------------------
FEM_icmp6_echo_request(echo_request_x2nut_via_tn, _HETHER_tn2nut,
        {
         _SRC(v6merge(_GLOBAL9_UCAST_PRFX, _GLOBAL9_UCAST_PRFXLEN,
                        v6ether(A9N_MAC_ADDR)));
         _DST(nut2v6(_GLOBAL0_UCAST_PRFX, _GLOBAL0_UCAST_PRFXLEN));
        },
        {
         payload=echo_data;
        }
)

//----------------------------------------------------------------------
// echo-reply
//      NUT(global) ==> X(off-link global, bug max:TN)
//----------------------------------------------------------------------
FEM_icmp6_echo_reply(echo_reply_nut2x_via_tn, _HETHER_nut2tn,
        {
         _SRC(nut2v6(_GLOBAL0_UCAST_PRFX, _GLOBAL0_UCAST_PRFXLEN));
         _DST(v6merge(_GLOBAL9_UCAST_PRFX, _GLOBAL9_UCAST_PRFXLEN,
                        v6ether(A9N_MAC_ADDR)));
        },
        {
         payload=echo_data;
        }
)

//----------------------------------------------------------------------
// echo-reply
//      NUT(global) ==> X(off-link global, bug max:Y)
//----------------------------------------------------------------------
FEM_icmp6_echo_reply(echo_reply_nut2x_via_y, hether_nut2y,
        {
         _SRC(nut2v6(_GLOBAL0_UCAST_PRFX, _GLOBAL0_UCAST_PRFXLEN));
         _DST(v6merge(_GLOBAL9_UCAST_PRFX, _GLOBAL9_UCAST_PRFXLEN,
                        v6ether(A9N_MAC_ADDR)));
        },
        {
         payload=echo_data;
        }
)

//----------------------------------------------------------------------
// echo-reply
//      NUT(global) ==> X(off-link global, bug max:Z)
//----------------------------------------------------------------------
FEM_icmp6_echo_reply(echo_reply_nut2x_via_z, hether_nut2z,
        {
         _SRC(nut2v6(_GLOBAL0_UCAST_PRFX, _GLOBAL0_UCAST_PRFXLEN));
         _DST(v6merge(_GLOBAL9_UCAST_PRFX, _GLOBAL9_UCAST_PRFXLEN,
                        v6ether(A9N_MAC_ADDR)));
        },
        {
         payload=echo_data;
        }
)

//----------------------------------------------------------------------
Payload echo_data {
        data=repeat(0xaa,0x10);
}

//----------------------------------------------------------------------
// multicast NS
//      NUT(global) ==> W(solicited-node[global])
//      target=W(global)
//      w/ SLLA
//----------------------------------------------------------------------
FEM_icmp6_ns(multicast_ns_nut2wsolnode, hether_nut2wsolnode,
        {
	 _SRC(oneof(NUT_GLOBAL, nutv6()));
         _DST(_IPV6_SOLNODE_MCAST(v6ether(A9N_MAC_ADDR)));
         HopLimit=255;
        },
        {
         TargetAddress=v6merge(_GLOBAL9_UCAST_PRFX, _GLOBAL9_UCAST_PRFXLEN,
                                v6ether(A9N_MAC_ADDR));
         option=_SLLOPT_nut;
        }
)


//----------------------------------------------------------------------
// update NUT's neighbor cache entries for router TN, Y and Z
//----------------------------------------------------------------------

// echo-request
//	TN ==> NUT
//----------------------------------------------------------------------
FEM_icmp6_echo_request(
	echoreq_tn2nut,
	_HETHER_tn2nut,
        {
		_SRC(tnv6());
		_DST(nutv6());
        },
        {
		payload = echo_data;
        }
)

// echo-request
//	Y ==> NUT
//----------------------------------------------------------------------
FEM_icmp6_echo_request(
	echoreq_y2nut,
	hether_y2nut,
        {
		_SRC(v6ether(A0N_MAC_ADDR));
		_DST(nutv6());
        },
        {
		payload = echo_data;
        }
)

// echo-request
//	Z ==> NUT
//----------------------------------------------------------------------
FEM_icmp6_echo_request(
	echoreq_z2nut,
	hether_z2nut,
        {
		_SRC(v6ether(A1N_MAC_ADDR));
		_DST(nutv6());
        },
        {
		payload = echo_data;
        }
)

// echo-reply
//	NUT ==> TN
//----------------------------------------------------------------------
FEM_icmp6_echo_reply(
	echorep_nut2tn,
	_HETHER_nut2tn,
        {
		_SRC(nutv6());
		_DST(tnv6());
        },
        {
		payload = echo_data;
        }
)

// echo-reply
//	Y ==> NUT
//----------------------------------------------------------------------
FEM_icmp6_echo_reply(
	echorep_nut2y,
	hether_nut2y,
        {
		_SRC(nutv6());
		_DST(v6ether(A0N_MAC_ADDR));
        },
        {
		payload = echo_data;
        }
)

// echo-reply
//	Z ==> NUT
//----------------------------------------------------------------------
FEM_icmp6_echo_reply(
	echorep_nut2z,
	hether_nut2z,
        {
		_SRC(nutv6());
		_DST(v6ether(A1N_MAC_ADDR));
        },
        {
		payload = echo_data;
        }
)

_HETHER_define(HETHER_nut2tn_oneof, nutether(), oneof(tnether(), _ETHER_SOLNODE_MCAST(tnv6())))
_HETHER_define(HETHER_nut2y_oneof, nutether(), oneof(ether(A0N_MAC_ADDR), _ETHER_SOLNODE_MCAST(v6ether(A0N_MAC_ADDR))))
_HETHER_define(HETHER_nut2z_oneof, nutether(), oneof(ether(A1N_MAC_ADDR), _ETHER_SOLNODE_MCAST(v6ether(A1N_MAC_ADDR))))

// neighbor solicitation
//	NUT => TN (w/o sll option)
//----------------------------------------------------------------------
FEM_icmp6_ns(
	ns_nut2tn,
	HETHER_nut2tn_oneof,
	{
		_SRC(oneof(NUT_GLOBAL, nutv6()));
		_DST(oneof(_IPV6_SOLNODE_MCAST(tnv6()), tnv6()));
		HopLimit = 255;
	},
	{
		TargetAddress = tnv6();
	}
)

// neighbor solicitation
//	NUT => TN (w/ sll option)
//----------------------------------------------------------------------
FEM_icmp6_ns(
	ns_nut2tn_sll,
	HETHER_nut2tn_oneof,
	{
		_SRC(oneof(NUT_GLOBAL, nutv6()));
		_DST(oneof(_IPV6_SOLNODE_MCAST(tnv6()), tnv6()));
		HopLimit = 255;
	},
	{
		TargetAddress = tnv6();
		option = _SLLOPT_nut;
	}
)

// neighbor solicitation
//	NUT => Y (w/o sll option)
//----------------------------------------------------------------------
FEM_icmp6_ns(
	ns_nut2y,
	HETHER_nut2y_oneof,
	{
		_SRC(oneof(NUT_GLOBAL, nutv6()));
		_DST(oneof(_IPV6_SOLNODE_MCAST(v6ether(A0N_MAC_ADDR)),
		     v6ether(A0N_MAC_ADDR)));
		HopLimit = 255;
	},
	{
		TargetAddress = v6ether(A0N_MAC_ADDR);
	}
)

// neighbor solicitation
//	NUT => Y (w/ sll option)
//----------------------------------------------------------------------
FEM_icmp6_ns(
	ns_nut2y_sll,
	HETHER_nut2y_oneof,
	{
		_SRC(oneof(NUT_GLOBAL, nutv6()));
		_DST(oneof(_IPV6_SOLNODE_MCAST(v6ether(A0N_MAC_ADDR)),
		     v6ether(A0N_MAC_ADDR)));
		HopLimit = 255;
	},
	{
		TargetAddress = v6ether(A0N_MAC_ADDR);
		option = _SLLOPT_nut;
	}
)

// neighbor solicitation
//	NUT => Z (w/o sll option)
//----------------------------------------------------------------------
FEM_icmp6_ns(
	ns_nut2z,
	HETHER_nut2z_oneof,
	{
		_SRC(oneof(NUT_GLOBAL, nutv6()));
		_DST(oneof(_IPV6_SOLNODE_MCAST(v6ether(A1N_MAC_ADDR)),
		     v6ether(A1N_MAC_ADDR)));
		HopLimit = 255;
	},
	{
		TargetAddress = v6ether(A1N_MAC_ADDR);
	}
)

// neighbor solicitation
//	NUT => Z (w/ sll option)
//----------------------------------------------------------------------
FEM_icmp6_ns(
	ns_nut2z_sll,
	HETHER_nut2z_oneof,
	{
		_SRC(oneof(NUT_GLOBAL, nutv6()));
		_DST(oneof(_IPV6_SOLNODE_MCAST(v6ether(A1N_MAC_ADDR)),
		     v6ether(A1N_MAC_ADDR)));
		HopLimit = 255;
	},
	{
		TargetAddress = v6ether(A1N_MAC_ADDR);
		option = _SLLOPT_nut;
	}
)


//----------------------------------------------------------------------
