ICMPv6 is implemented. But kernel didn't send ping6 reply. Sigh!

This commit is contained in:
Sukchan Lee 2017-12-14 04:01:56 +00:00
parent 05c95dbfef
commit 1864509cbb
6 changed files with 152 additions and 32 deletions

View File

@ -254,7 +254,7 @@ AC_CHECK_HEADERS( \
sys/uio.h \
)
AC_CHECK_HEADERS(netinet/ip.h net/route.h,,,[[
AC_CHECK_HEADERS(netinet/ip.h netinet/ip6.h net/route.h,,,[[
#include <sys/types.h>
#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>

View File

@ -136,6 +136,10 @@
#include <netinet/ip.h>
#endif
#if HAVE_NETINET_IP6_H
#include <netinet/ip6.h>
#endif
#if HAVE_NETINET_UDP_H
#include <netinet/udp.h>
#endif

35
support/network/ipv6_restart.sh Executable file
View File

@ -0,0 +1,35 @@
#!/bin/sh
SYSTEM=`uname`;
if [ "$SYSTEM" = "Linux" ]; then
if ! grep "pgwtun" /proc/net/dev > /dev/null; then
ip tuntap add name pgwtun mode tun
fi
ip addr del 45.45.0.1/16 dev pgwtun 2> /dev/null
ip addr add 45.45.0.1/16 dev pgwtun
ip addr del cafe::1/64 dev pgwtun 2> /dev/null
ip addr add cafe::1/64 dev pgwtun
ip link set pgwtun up
ip addr del fe80::2 dev lo 2> /dev/null
ip addr del fe80::3 dev lo 2> /dev/null
ip addr del fe80::4 dev lo 2> /dev/null
ip addr del fe80::5 dev lo 2> /dev/null
ip addr add fe80::2 dev lo
ip addr add fe80::3 dev lo
ip addr add fe80::4 dev lo
ip addr add fe80::5 dev lo
else
ifconfig lo0 alias 127.0.0.2 netmask 255.255.255.255
ifconfig lo0 alias 127.0.0.3 netmask 255.255.255.255
ifconfig lo0 alias 127.0.0.4 netmask 255.255.255.255
ifconfig lo0 alias 127.0.0.5 netmask 255.255.255.255
ifconfig lo0 inet6 delete fe80::2 prefixlen 128 2> /dev/null
ifconfig lo0 inet6 delete fe80::3 prefixlen 128 2> /dev/null
ifconfig lo0 inet6 delete fe80::4 prefixlen 128 2> /dev/null
ifconfig lo0 inet6 delete fe80::5 prefixlen 128 2> /dev/null
ifconfig lo0 inet6 add fe80::2 prefixlen 128
ifconfig lo0 inet6 add fe80::3 prefixlen 128
ifconfig lo0 inet6 add fe80::4 prefixlen 128
ifconfig lo0 inet6 add fe80::5 prefixlen 128
fi

View File

@ -302,8 +302,7 @@ static void attach_test1(abts_case *tc, void *data)
core_sleep(time_from_msec(300));
/* Send GTP-U ICMP Packet */
rv = testgtpu_enb_send(inet_addr("45.45.0.2"), inet_addr("45.45.0.1"));
ABTS_INT_EQUAL(tc, CORE_OK, rv);
rv = testgtpu_enb_send("45.45.0.2", "45.45.0.1");
/* Receive GTP-U ICMP Packet */
recvbuf = pkbuf_alloc(0, MAX_SDU_LEN);
@ -311,6 +310,11 @@ static void attach_test1(abts_case *tc, void *data)
ABTS_INT_EQUAL(tc, CORE_OK, rv);
pkbuf_free(recvbuf);
#if 0
rv = testgtpu_enb_send("cafe::2", "cafe::1");
ABTS_INT_EQUAL(tc, CORE_OK, rv);
#endif
/*****************************************************************
* Attach Request : Known GUTI, Integrity Protected, MAC Matched
* Send Initial-UE Message + Attach Request + PDN Connectivity */

View File

@ -154,7 +154,7 @@ static uint16_t in_cksum(uint16_t *addr, int len)
return answer;
}
status_t testgtpu_enb_send(c_uint32_t src_ip, c_uint32_t dst_ip)
status_t testgtpu_enb_send(const char *src_ip, const char *dst_ip)
{
sock_id sock = 0;
hash_index_t *hi = NULL;
@ -166,6 +166,7 @@ status_t testgtpu_enb_send(c_uint32_t src_ip, c_uint32_t dst_ip)
pkbuf_t *pkbuf = NULL;
gtp_header_t *gtp_h = NULL;
ssize_t sent;
ipsubnet_t src_ipsub, dst_ipsub;
c_sockaddr_t sgw;
struct ip *ip_h = NULL;
struct icmp_header_t {
@ -188,49 +189,124 @@ status_t testgtpu_enb_send(c_uint32_t src_ip, c_uint32_t dst_ip)
} un;
} *icmp_h = NULL;
struct ip6_hdr *ip6_h = NULL;
struct icmp6_hdr
{
uint8_t icmp6_type; /* type field */
uint8_t icmp6_code; /* code field */
uint16_t icmp6_cksum; /* checksum field */
union
{
uint32_t icmp6_un_data32[1]; /* type-specific field */
#define icmp6_data16 icmp6_dataun.icmp6_un_data16
#define icmp6_id icmp6_data16[0] /* echo request/reply */
#define icmp6_seq icmp6_data16[1] /* echo request/reply */
uint16_t icmp6_un_data16[2]; /* type-specific field */
uint8_t icmp6_un_data8[4]; /* type-specific field */
} icmp6_dataun;
} *icmp6_h = NULL;
if (test_only_control_plane) return 0;
d_assert(src_ip, return -1,);
d_assert(dst_ip, return -1,);
rv = core_ipsubnet(&src_ipsub, src_ip, NULL);
d_assert(rv == CORE_OK, return -1,);
rv = core_ipsubnet(&dst_ipsub, dst_ip, NULL);
d_assert(rv == CORE_OK, return -1,);
hi = mme_ue_first();
if (!hi) return -1;
d_assert(hi, return -1,);
mme_ue = mme_ue_this(hi);
if (!mme_ue) return -1;
d_assert(mme_ue, return -1,);
sess = mme_sess_first(mme_ue);
if (!sess) return -1;
d_assert(sess, return -1,);
bearer = mme_bearer_first(sess);
if (!bearer) return -1;
d_assert(bearer, return -1,);
pkbuf = pkbuf_alloc(0, 100 /* enough for ICMP; use smaller buffer */);
d_assert(pkbuf, return CORE_ERROR,);
memset(pkbuf->payload, 0, pkbuf->len);
gtp_h = (gtp_header_t *)pkbuf->payload;
ip_h = (struct ip *)(pkbuf->payload + GTPV1U_HEADER_LEN);
icmp_h = (struct icmp_header_t *)
(pkbuf->payload + GTPV1U_HEADER_LEN + sizeof(struct ip));
gtp_h->flags = 0x30;
gtp_h->type = GTPU_MSGTYPE_GPDU;
gtp_h->teid = htonl(1);
gtp_h->length = htons(sizeof(struct ip) + sizeof(struct icmp_header_t));
ip_h->ip_v = 4;
ip_h->ip_hl = 5;
ip_h->ip_tos = 0;
ip_h->ip_id = rand();
ip_h->ip_off = 0;
ip_h->ip_ttl = 255;
ip_h->ip_p = IPPROTO_ICMP;
ip_h->ip_len = gtp_h->length;
ip_h->ip_src.s_addr = src_ip;
ip_h->ip_dst.s_addr = dst_ip;
ip_h->ip_sum = in_cksum(
(unsigned short *)ip_h, sizeof(struct ip));
icmp_h->type = 8;
icmp_h->un.echo.sequence = rand();
icmp_h->un.echo.id = rand();
icmp_h->checksum = in_cksum(
(unsigned short *)icmp_h, sizeof(struct icmp_header_t));
if (dst_ipsub.family == AF_INET)
{
gtp_h->length = htons(sizeof(struct ip) + sizeof(struct icmp_header_t));
ip_h = (struct ip *)(pkbuf->payload + GTPV1U_HEADER_LEN);
ip_h->ip_v = 4;
ip_h->ip_hl = 5;
ip_h->ip_tos = 0;
ip_h->ip_id = rand();
ip_h->ip_off = 0;
ip_h->ip_ttl = 255;
ip_h->ip_p = IPPROTO_ICMP;
ip_h->ip_len = gtp_h->length;
ip_h->ip_src.s_addr = src_ipsub.sub[0];
ip_h->ip_dst.s_addr = dst_ipsub.sub[0];
ip_h->ip_sum = in_cksum(
(unsigned short *)ip_h, sizeof(struct ip));
icmp_h = (struct icmp_header_t *)
(pkbuf->payload + GTPV1U_HEADER_LEN + sizeof(struct ip));
icmp_h->type = 8;
icmp_h->un.echo.sequence = rand();
icmp_h->un.echo.id = rand();
icmp_h->checksum = in_cksum(
(unsigned short *)icmp_h, sizeof(struct icmp_header_t));
}
else if (dst_ipsub.family == AF_INET6)
{
char cksumbuf[100];
char *ptr = NULL;
gtp_h->length =
htons(sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr));
ip6_h = (struct ip6_hdr *)(pkbuf->payload + GTPV1U_HEADER_LEN);
ip6_h->ip6_flow = htonl(0x600857c7);
ip6_h->ip6_plen = htons(sizeof(struct icmp6_hdr));
ip6_h->ip6_nxt = 58; /* ICMPv6 */
ip6_h->ip6_hlim = 64;
memcpy(ip6_h->ip6_src.s6_addr, src_ipsub.sub, sizeof src_ipsub.sub);
memcpy(ip6_h->ip6_dst.s6_addr, dst_ipsub.sub, sizeof dst_ipsub.sub);
icmp6_h = (struct icmp6_hdr *)
(pkbuf->payload + GTPV1U_HEADER_LEN + sizeof(struct ip6_hdr));
icmp6_h->icmp6_type = 128;
icmp6_h->icmp6_code = 8;
icmp6_h->icmp6_seq = rand();
icmp6_h->icmp6_id = rand();
/* create pseudo-header */
memset(cksumbuf, 0, sizeof cksumbuf);
ptr = cksumbuf;
memcpy(ptr, src_ipsub.sub, sizeof src_ipsub.sub);
ptr += sizeof src_ipsub.sub;
memcpy(ptr, dst_ipsub.sub, sizeof dst_ipsub.sub);
ptr += sizeof dst_ipsub.sub;
ptr += 2;
memcpy(ptr, &ip6_h->ip6_plen, 2);
ptr += 2;
ptr += 3;
*ptr = ip6_h->ip6_nxt;
ptr += 1;
memcpy(ptr, icmp6_h, sizeof(struct icmp6_hdr));
#define IPV6_PSEUDO_HDR 48
#define CKSUM_SIZE 2
icmp6_h->icmp6_cksum = in_cksum( (unsigned short *)cksumbuf,
IPV6_PSEUDO_HDR+sizeof(struct icmp6_hdr)+CKSUM_SIZE);
}
else
d_assert(0, return -1,);
memset(&sgw, 0, sizeof(c_sockaddr_t));
sgw.c_sa_port = htons(GTPV1_U_UDP_PORT);

View File

@ -21,7 +21,8 @@ CORE_DECLARE(status_t) tests1ap_enb_read(sock_id id, pkbuf_t *recvbuf);
CORE_DECLARE(status_t) testgtpu_enb_connect(sock_id *new);
CORE_DECLARE(status_t) testgtpu_enb_close(sock_id sock);
CORE_DECLARE(status_t) testgtpu_enb_read(sock_id sock, pkbuf_t *recvbuf);
CORE_DECLARE(status_t) testgtpu_enb_send(c_uint32_t src_ip, c_uint32_t dst_ip);
CORE_DECLARE(status_t) testgtpu_enb_send(
const char *src_ip, const char *dst_ip);
CORE_DECLARE(status_t) tests1ap_build_setup_req(
pkbuf_t **pkbuf, S1ap_ENB_ID_PR present, c_uint32_t enb_id);