From 3d9338fb921dd9b2c2f82ac5353e9874e69156a6 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Mon, 29 Jan 2018 20:42:54 +0100 Subject: ggsn_tests: Add test case to validate packets forwarded vs dropped New dependency is required: titan.ProtocolModules.ICMP It tests that ICMP echo packets can be sent successfully (reply is received or otherwise dest unreachable if routing is not set up correctly during the test). It also tests some cases in which osmo-ggsn is required to drop the packets (eg. unknown src ip unrelated to pdp ctx). It also checks that IPv6 packets are dropped in IPv4 pdp ctx and viceversa It also checks that IPv6 packets are dropped in IPv4 pdp ctx and vice versa. Change-Id: Ib9c6043a6cd3b6622782ec7e7fcd2815101755ba --- ggsn_tests/GGSN_Tests.cfg | 2 + ggsn_tests/GGSN_Tests.ttcn | 262 +++++++++++++++++++++++++++++++++++++++++-- ggsn_tests/gen_links.sh | 4 + ggsn_tests/regen_makefile.sh | 2 +- 4 files changed, 262 insertions(+), 8 deletions(-) (limited to 'ggsn_tests') diff --git a/ggsn_tests/GGSN_Tests.cfg b/ggsn_tests/GGSN_Tests.cfg index d8994df5..bf820573 100644 --- a/ggsn_tests/GGSN_Tests.cfg +++ b/ggsn_tests/GGSN_Tests.cfg @@ -26,9 +26,11 @@ GGSN_Tests.m_ggsn_ip6_dns2 := "2001:4860:4860::8844" GGSN_Tests.TC_pdp4_act_deact GGSN_Tests.TC_pdp4_act_deact_ipcp GGSN_Tests.TC_pdp4_act_deact_pcodns +GGSN_Tests.TC_pdp4_act_deact_gtpu_access GGSN_Tests.TC_pdp6_act_deact GGSN_Tests.TC_pdp6_act_deact_pcodns GGSN_Tests.TC_pdp6_act_deact_icmp6 +GGSN_Tests.TC_pdp6_act_deact_gtpu_access GGSN_Tests.TC_echo_req_resp diff --git a/ggsn_tests/GGSN_Tests.ttcn b/ggsn_tests/GGSN_Tests.ttcn index f7814db7..b802564e 100644 --- a/ggsn_tests/GGSN_Tests.ttcn +++ b/ggsn_tests/GGSN_Tests.ttcn @@ -10,6 +10,7 @@ module GGSN_Tests { import from GTPU_Types all; import from IPCP_Types all; import from IP_Types all; + import from ICMP_Types all; import from ICMPv6_Types all; import from Native_Functions all; @@ -734,6 +735,63 @@ module GGSN_Tests { /* IPv6 neighbor solicitation fe80::2 -> ff02::1:ff00:2 from 02:88:b5:1f:25:59 */ const octetstring c_neigh_solicit:= '6000000000203afffe800000000000000000000000000002ff0200000000000000000001ff00000287009f9600000000fe80000000000000000000000000000201010288b51f2559'O; + /* template for an ICMPv6 echo request */ + template PDU_ICMP ts_ICMPv4_ERQ := { + echo := { + type_field := 8, + code := 0, + checksum := '0000'O, + identifier := '0345'O, + sequence_number := '0001'O, + data := ''O + } + } + + /* template for an ICMPv4 echo reply */ + template PDU_ICMP tr_ICMPv4_ERP(template octetstring data := *) := { + echo_reply := { + type_field := 0, + code := 0, + checksum := ?, + identifier := ?, + sequence_number := ?, + data := data + } + } + + /* template for receiving/matching an ICMPv6 Destination Unreachable */ + template PDU_ICMP tr_ICMPv4_DU := { + destination_unreachable := { + type_field := 1, + code := ?, + checksum := ?, + unused := ?, + original_ip_msg := ? + } + } + + /* template to construct IPv4_packet from input arguments, ready for use in f_IPv4_enc() */ + template IPv4_packet ts_IP4(OCT4 srcaddr, OCT4 dstaddr, LIN1 proto, LIN2_BO_LAST tlen, octetstring payload) := { + header := { + ver := 4, + hlen := 5, + tos := 0, + tlen := tlen, + id := 35902, + res := '0'B, + dfrag := '1'B, + mfrag := '0'B, + foffset := 0, + ttl := 64, + proto := proto, + cksum := 0, + srcaddr := srcaddr, + dstaddr := dstaddr + }, + ext_headers := omit, + payload := payload + } + /* template to generate a 'Prefix Information' ICMPv6 option */ template OptionField ts_ICMP6_OptPrefix(OCT16 prefix, INT1 prefix_len) := { prefixInformation := { @@ -750,6 +808,18 @@ module GGSN_Tests { } } + /* template for an ICMPv6 echo request */ + template PDU_ICMPv6 ts_ICMPv6_ERQ := { + echoRequest := { + typeField := 128, + code := 0, + checksum := '0000'O, + identifier := 0, + sequenceNr := 0, + data := ''O + } + } + /* template for an ICMPv6 router solicitation */ template PDU_ICMPv6 ts_ICMPv6_RS := { routerSolicitation := { @@ -829,6 +899,29 @@ module GGSN_Tests { } } + /* template for receiving/matching an ICMPv6 Destination Unreachable */ + template PDU_ICMPv6 tr_ICMPv6_DU := { + destinationUnreachable := { + typeField := 1, + code := ?, + checksum := ?, + unused := ?, + originalIpMsg := ? + } + } + + /* template for receiving/matching an ICMPv6 echo reply */ + template PDU_ICMPv6 tr_ICMPv6_ERP(template octetstring data := *) := { + echoReply := { + typeField := 129, + code := 0, + checksum := ?, + identifier := ?, + sequenceNr := ?, + data := data + } + } + /* template to construct IPv6_packet from input arguments, ready for use in f_IPv6_enc() */ template IPv6_packet ts_IP6(OCT16 srcaddr, OCT16 dstaddr, LIN1 nexthead, octetstring payload, LIN1 hlim := 255) := { header := { @@ -849,6 +942,21 @@ module GGSN_Tests { return 'FE80000000000000'O & substr(link_id, 8, 8); } + function f_ipv6_global(in OCT16 link_id) return OCT16 { + return substr(link_id, 0, 8) & '1234123412341234'O; + } + + /* Create a new different IPv6 addr from input. Starts mangling at byte prefix. */ + function f_ipv6_mangle(in OCT16 addr, in integer prefix := 0) return OCT16 { + var integer i; + var octetstring res := substr(addr, 0, prefix); + for (i := prefix; i < lengthof(addr); i := i + 1) { + var octetstring a := addr[i] xor4b '11'O; + res := res & a; + } + return res; + } + /* Compute solicited-node multicast address as per RFC4291 2.7.1 */ function f_ipv6_sol_node_mcast(in OCT16 addr) return OCT16 { return 'FF0200000000000000000001FF'O & substr(addr, 13, 3); @@ -889,24 +997,72 @@ module GGSN_Tests { return f_gen_icmpv6_neigh_solicit(link_local, daddr, link_local); } - /* wait for GGSN to send us an ICMPv6 router advertisement */ - function f_wait_rtr_adv(PdpContext ctx) runs on GT_CT { + /* Send an ICMPv4 echo msg through GTP given pdp ctx, and ip src and dst addr */ + function f_gen_icmpv4_echo(OCT4 saddr, OCT4 daddr) return octetstring { + var octetstring tmp := f_enc_PDU_ICMP(valueof(ts_ICMPv4_ERQ)); + var IPv4_packet ip4 := valueof(ts_IP4(saddr, daddr, 1, 50, tmp)); + var octetstring data := f_IPv4_enc(ip4); + var OCT2 cksum := f_IPv4_checksum(data); + data[10] := cksum[0]; + data[11] := cksum[1]; + return data; + } + + /* Send an ICMPv6 echo msg through GTP given pdp ctx, and ip src and dst addr */ + function f_gen_icmpv6_echo(OCT16 saddr, OCT16 daddr) return octetstring { + var octetstring tmp := f_enc_PDU_ICMPv6(valueof(ts_ICMPv6_ERQ), saddr, daddr); + var IPv6_packet ip6 := valueof(ts_IP6(saddr, daddr, 58, tmp)); + var octetstring data := f_IPv6_enc(ip6); + return data; + } + + /* Wait for ICMPv4 from GTP */ + function f_wait_icmp4(PdpContext ctx, template PDU_ICMP expected) runs on GT_CT { + var Gtp1uUnitdata ud; + T_default.start; + alt { + [] GTPU.receive(tr_GTPU_GPDU(g_peer_u, ?)) -> value ud { + var octetstring gpdu := ud.gtpu.gtpu_IEs.g_PDU_IEs.data; + var IPv4_packet ip4 := f_IPv4_dec(gpdu); + if (ip4.header.ver != 4) { + repeat; + } + var PDU_ICMP icmp4 := f_dec_PDU_ICMP(ip4.payload); + if (not match(icmp4, expected)) { + repeat; + } + } + [] GTPU.receive { setverdict(fail); } + [] T_default.timeout { setverdict(fail); } + } + T_default.stop; + } + + /* Wait for ICMPv4 echo reply (or unreachable) from GTP */ + function f_wait_icmp4_echo_reply(PdpContext ctx) runs on GT_CT { + f_wait_icmp4(ctx, (tr_ICMPv4_ERP, tr_ICMPv4_DU)); + } + + /* Wait for ICMPv6 from GTP */ + function f_wait_icmp6(PdpContext ctx, template PDU_ICMPv6 expected) runs on GT_CT { var Gtp1uUnitdata ud; T_default.start; alt { - //'6???????????3aff'O [] GTPU.receive(tr_GTPU_GPDU(g_peer_u, ?)) -> value ud { var octetstring gpdu := ud.gtpu.gtpu_IEs.g_PDU_IEs.data; var IPv6_packet ip6 := f_IPv6_dec(gpdu); - if (ip6.header.ver != 6 or ip6.header.nexthead != 58 or ip6.header.hlim != 255) { + if (ip6.header.ver != 6 or ip6.header.nexthead != 58) { repeat; } var PDU_ICMPv6 icmp6 := f_dec_PDU_ICMPv6(ip6.payload); - if (not match(icmp6, tr_ICMPv6_RA(?, 64))) { + if (not match(icmp6, expected)) { repeat; } - ctx.ip6_prefix := icmp6.routerAdvertisement.options[0].prefixInformation.prefix; - log("RA with /64 prefix ", ctx.ip6_prefix); + /* We are waiting for RA, update ctx */ + if (match(icmp6, tr_ICMPv6_RA(?, 64))) { + ctx.ip6_prefix := icmp6.routerAdvertisement.options[0].prefixInformation.prefix; + log("RA with /64 prefix ", ctx.ip6_prefix); + } } [] GTPU.receive(tr_GTPU_GPDU(?, ?)) { repeat; } [] GTPU.receive { setverdict(fail); } @@ -915,6 +1071,26 @@ module GGSN_Tests { T_default.stop; } + /* wait for GGSN to send us an ICMPv6 router advertisement */ + function f_wait_rtr_adv(PdpContext ctx) runs on GT_CT { + f_wait_icmp6(ctx, tr_ICMPv6_RA(?, 64)); + } + + /* Wait for ICMPv6 echo reply (or unreachable) from GTP */ + function f_wait_icmp6_echo_reply(PdpContext ctx) runs on GT_CT { + f_wait_icmp6(ctx, (tr_ICMPv6_ERP,tr_ICMPv6_DU)); + } + + /* Assert we don't receive a ICMPv4/6 echo reply (or unreachable) from GTP */ + function f_wait_gtpu_fail(PdpContext ctx) runs on GT_CT { + T_default.start; + alt { + [] GTPU.receive { setverdict(fail); } + [] T_default.timeout { } + } + T_default.stop; + } + /* Test IPv6 context activation for dynamic IPv6 EUA without request of IPv6 DNS */ testcase TC_pdp6_act_deact() runs on GT_CT { f_init(); @@ -964,6 +1140,49 @@ module GGSN_Tests { f_pdp_ctx_del(ctx, '1'B); } + /* Test PDP context activation for dynamic IPv6 EUA with IPv6 DNS in PCO and router solicitation/advertisement. + Test we can send ICMPv6 ping over GTPU to DNS server. */ + testcase TC_pdp6_act_deact_gtpu_access() runs on GT_CT { + f_init(); + var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet6, valueof(t_EuaIPv6Dyn))); + ctx.pco_req := valueof(ts_PCO_IPv6_DNS); + f_pdp_ctx_act(ctx); + + f_send_gtpu(ctx, f_icmpv6_rs_for_pdp(ctx)); + f_wait_rtr_adv(ctx); + f_send_gtpu(ctx, f_gen_icmpv6_neigh_solicit_for_pdp(ctx)); + + var OCT16 dns1_addr := f_PCO_extract_proto(ctx.pco_neg, '0003'O); + + /* Check if we can use valid link-local src addr. */ + var OCT16 saddr_ll := f_ipv6_link_local(ctx.eua.endUserAddress.endUserAddressIPv6.ipv6_address); + f_send_gtpu(ctx, f_gen_icmpv6_echo(saddr_ll, dns1_addr)); + f_wait_icmp6_echo_reply(ctx); + + /* Check that attempting RA with another ll src addr won't work, packet dropped: */ + var OCT16 saddr_ll_wrong := f_ipv6_mangle(saddr_ll, 8); + f_send_gtpu(ctx, f_gen_icmpv6_router_solicitation(saddr_ll_wrong)); + f_wait_gtpu_fail(ctx); + + /* Check if we can use valid global src addr, should work */ + var OCT16 saddr_glob := f_ipv6_global(ctx.eua.endUserAddress.endUserAddressIPv6.ipv6_address); + f_send_gtpu(ctx, f_gen_icmpv6_echo(saddr_glob, dns1_addr)); + f_wait_icmp6_echo_reply(ctx); + + /* Assert that packets with wrong global src addr are dropped by GGSN */ + var OCT16 saddr_wrong := f_ipv6_mangle(saddr_glob); + f_send_gtpu(ctx, f_gen_icmpv6_echo(saddr_wrong, dns1_addr)); + f_wait_gtpu_fail(ctx); + + /* Send an IPv4 ICMP ECHO REQUEST to APN6, should fail (packet dropped) */ + var OCT4 saddr_v4 := f_inet_addr("192.168.10.2"); + var OCT4 daddr_v4 := f_inet_addr("8.8.8.8"); + f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr_v4, daddr_v4)); + f_wait_gtpu_fail(ctx); + + f_pdp_ctx_del(ctx, '1'B); + } + /* Test PDP context activation for dynamic IPv4 EUA without DNS request */ testcase TC_pdp4_act_deact() runs on GT_CT { f_init(); @@ -1017,6 +1236,33 @@ module GGSN_Tests { f_pdp_ctx_del(ctx, '1'B); } + /* Test PDP context activation for dynamic IPv4 EUA. + Test we can send ICMPv6 ping over GTPU to DNS server. */ + testcase TC_pdp4_act_deact_gtpu_access() runs on GT_CT { + f_init(); + var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn))); + ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT); + f_pdp_ctx_act(ctx); + + var OCT4 dns1_addr := f_PCO_extract_proto(ctx.pco_neg, '000d'O); + + /* Check if we can use valid global src addr, should work */ + var OCT4 saddr := ctx.eua.endUserAddress.endUserAddressIPv4.ipv4_address; + f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr)); + f_wait_icmp4_echo_reply(ctx); + + /* Assert that packets with wrong global src addr are dropped by GGSN */ + var OCT4 saddr_wrong := substr(saddr, 0, 3) & (saddr[3] xor4b '11'O); + f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr_wrong, dns1_addr)); + f_wait_gtpu_fail(ctx); + + /* Send an IPv6 RA to APN4, should fail (packet dropped) */ + var OCT16 saddr_v6 := f_inet6_addr("fde4:8dba:82e1:2000:1:2:3:4"); + f_send_gtpu(ctx, f_gen_icmpv6_router_solicitation(saddr_v6)); + f_wait_gtpu_fail(ctx); + f_pdp_ctx_del(ctx, '1'B); + } + testcase TC_echo_req_resp() runs on GT_CT { f_init(); f_send_gtpc(ts_GTPC_PING(g_peer_c, g_c_seq_nr)); @@ -1033,10 +1279,12 @@ module GGSN_Tests { execute(TC_pdp4_act_deact()); execute(TC_pdp4_act_deact_ipcp()); execute(TC_pdp4_act_deact_pcodns()); + execute(TC_pdp4_act_deact_gtpu_access()); execute(TC_pdp6_act_deact()); execute(TC_pdp6_act_deact_pcodns()); execute(TC_pdp6_act_deact_icmp6()); + execute(TC_pdp6_act_deact_gtpu_access()); execute(TC_echo_req_resp()); } diff --git a/ggsn_tests/gen_links.sh b/ggsn_tests/gen_links.sh index 8098f9ba..58c681f9 100755 --- a/ggsn_tests/gen_links.sh +++ b/ggsn_tests/gen_links.sh @@ -27,6 +27,10 @@ DIR=$BASEDIR/titan.TestPorts.IPL4asp/src FILES="IPL4asp_Functions.ttcn IPL4asp_PT.cc IPL4asp_PT.hh IPL4asp_PortType.ttcn IPL4asp_Types.ttcn IPL4asp_discovery.cc IPL4asp_protocol_L234.hh" gen_links $DIR $FILES +DIR=$BASEDIR/titan.ProtocolModules.ICMP/src +FILES="ICMP_EncDec.cc ICMP_Types.ttcn" +gen_links $DIR $FILES + DIR=$BASEDIR/titan.ProtocolModules.ICMPv6/src FILES="ICMPv6_EncDec.cc ICMPv6_Types.ttcn" gen_links $DIR $FILES diff --git a/ggsn_tests/regen_makefile.sh b/ggsn_tests/regen_makefile.sh index 3970187c..2fc74f70 100755 --- a/ggsn_tests/regen_makefile.sh +++ b/ggsn_tests/regen_makefile.sh @@ -1,5 +1,5 @@ #!/bin/sh -FILES="*.ttcn IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc GTPC_EncDec.cc GTPU_EncDec.cc GTP_CodecPort_CtrlFunctDef.cc ICMPv6_EncDec.cc IP_EncDec.cc Native_FunctionDefs.cc UDP_EncDec.cc" +FILES="*.ttcn IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc GTPC_EncDec.cc GTPU_EncDec.cc GTP_CodecPort_CtrlFunctDef.cc ICMPv6_EncDec.cc IP_EncDec.cc Native_FunctionDefs.cc UDP_EncDec.cc ICMP_EncDec.cc" ../regen-makefile.sh GGSN_Tests.ttcn $FILES -- cgit v1.2.3