Fix the bug (#194)

This commit is contained in:
Sukchan Lee 2019-06-11 22:39:23 +09:00
parent 3c61858f21
commit c530e1cbcf
2 changed files with 74 additions and 60 deletions

View File

@ -1,3 +1,22 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "base/base.h" #include "base/base.h"
#if HAVE_NETINET_IP_H #if HAVE_NETINET_IP_H
@ -46,8 +65,7 @@ static void _gtpv1_tun_recv_cb(short when, ogs_socket_t fd, void *data)
ogs_pkbuf_put(recvbuf, MAX_SDU_LEN-GTPV1U_HEADER_LEN); ogs_pkbuf_put(recvbuf, MAX_SDU_LEN-GTPV1U_HEADER_LEN);
n = ogs_read(fd, recvbuf->data, recvbuf->len); n = ogs_read(fd, recvbuf->data, recvbuf->len);
if (n <= 0) if (n <= 0) {
{
ogs_log_message(OGS_LOG_WARN, ogs_socket_errno, "ogs_read() failed"); ogs_log_message(OGS_LOG_WARN, ogs_socket_errno, "ogs_read() failed");
ogs_pkbuf_free(recvbuf); ogs_pkbuf_free(recvbuf);
return; return;
@ -57,16 +75,12 @@ static void _gtpv1_tun_recv_cb(short when, ogs_socket_t fd, void *data)
/* Find the bearer by packet filter */ /* Find the bearer by packet filter */
bearer = pgw_bearer_find_by_packet(recvbuf); bearer = pgw_bearer_find_by_packet(recvbuf);
if (bearer) if (bearer) {
{
/* Unicast */ /* Unicast */
rv = pgw_gtp_send_to_bearer(bearer, recvbuf); rv = pgw_gtp_send_to_bearer(bearer, recvbuf);
ogs_assert(rv == OGS_OK); ogs_assert(rv == OGS_OK);
} } else {
else if (context_self()->config.parameter.multicast) {
{
if (context_self()->config.parameter.multicast)
{
rv = pgw_gtp_handle_multicast(recvbuf); rv = pgw_gtp_handle_multicast(recvbuf);
ogs_assert(rv != OGS_ERROR); ogs_assert(rv != OGS_ERROR);
} }
@ -133,8 +147,7 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
if (size <= 0) { if (size <= 0) {
ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
"ogs_recv() failed"); "ogs_recv() failed");
ogs_pkbuf_free(pkbuf); goto cleanup;
return;
} }
ogs_pkbuf_trim(pkbuf, size); ogs_pkbuf_trim(pkbuf, size);
@ -155,7 +168,10 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
ogs_assert(ip_h); ogs_assert(ip_h);
bearer = pgw_bearer_find_by_pgw_s5u_teid(teid); bearer = pgw_bearer_find_by_pgw_s5u_teid(teid);
ogs_assert(bearer); if (!bearer) {
ogs_warn("[DROP] Cannot find PGW S5U bearer : TEID[0x%x]", teid);
goto cleanup;
}
sess = bearer->sess; sess = bearer->sess;
ogs_assert(sess); ogs_assert(sess);
@ -164,8 +180,7 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
else if (ip_h->ip_v == 6 && sess->ipv6) else if (ip_h->ip_v == 6 && sess->ipv6)
subnet = sess->ipv6->subnet; subnet = sess->ipv6->subnet;
if (!subnet) if (!subnet) {
{
ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data, pkbuf->len); ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data, pkbuf->len);
ogs_trace("[DROP] Cannot find subnet V:%d, IPv4:%p, IPv6:%p", ogs_trace("[DROP] Cannot find subnet V:%d, IPv4:%p, IPv6:%p",
ip_h->ip_v, sess->ipv4, sess->ipv6); ip_h->ip_v, sess->ipv4, sess->ipv6);
@ -173,13 +188,10 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
} }
/* Check IPv6 */ /* Check IPv6 */
if (context_self()->config.parameter.no_slaac == 0 && ip_h->ip_v == 6) if (context_self()->config.parameter.no_slaac == 0 && ip_h->ip_v == 6) {
{
rv = pgw_gtp_handle_slaac(sess, pkbuf); rv = pgw_gtp_handle_slaac(sess, pkbuf);
if (rv == PGW_GTP_HANDLED) if (rv == PGW_GTP_HANDLED) {
{ goto cleanup;
ogs_pkbuf_free(pkbuf);
return;
} }
ogs_assert(rv == OGS_OK); ogs_assert(rv == OGS_OK);
} }
@ -201,16 +213,14 @@ int pgw_gtp_open()
ogs_sock_t *sock = NULL; ogs_sock_t *sock = NULL;
int rc; int rc;
ogs_list_for_each(&pgw_self()->gtpc_list, node) ogs_list_for_each(&pgw_self()->gtpc_list, node) {
{
ogs_socknode_set_poll(node, pgw_self()->pollset, ogs_socknode_set_poll(node, pgw_self()->pollset,
OGS_POLLIN, _gtpv2_c_recv_cb, NULL); OGS_POLLIN, _gtpv2_c_recv_cb, NULL);
sock = gtp_server(node); sock = gtp_server(node);
ogs_assert(sock); ogs_assert(sock);
} }
ogs_list_for_each(&pgw_self()->gtpc_list6, node) ogs_list_for_each(&pgw_self()->gtpc_list6, node) {
{
ogs_socknode_set_poll(node, pgw_self()->pollset, ogs_socknode_set_poll(node, pgw_self()->pollset,
OGS_POLLIN, _gtpv2_c_recv_cb, NULL); OGS_POLLIN, _gtpv2_c_recv_cb, NULL);
@ -225,16 +235,14 @@ int pgw_gtp_open()
ogs_assert(pgw_self()->gtpc_addr || pgw_self()->gtpc_addr6); ogs_assert(pgw_self()->gtpc_addr || pgw_self()->gtpc_addr6);
ogs_list_for_each(&pgw_self()->gtpu_list, node) ogs_list_for_each(&pgw_self()->gtpu_list, node) {
{
ogs_socknode_set_poll(node, pgw_self()->pollset, ogs_socknode_set_poll(node, pgw_self()->pollset,
OGS_POLLIN, _gtpv1_u_recv_cb, NULL); OGS_POLLIN, _gtpv1_u_recv_cb, NULL);
sock = gtp_server(node); sock = gtp_server(node);
ogs_assert(sock); ogs_assert(sock);
} }
ogs_list_for_each(&pgw_self()->gtpu_list6, node) ogs_list_for_each(&pgw_self()->gtpu_list6, node) {
{
ogs_socknode_set_poll(node, pgw_self()->pollset, ogs_socknode_set_poll(node, pgw_self()->pollset,
OGS_POLLIN, _gtpv1_u_recv_cb, NULL); OGS_POLLIN, _gtpv1_u_recv_cb, NULL);
@ -261,11 +269,9 @@ int pgw_gtp_open()
*/ */
/* Open Tun interface */ /* Open Tun interface */
for (dev = pgw_dev_first(); dev; dev = pgw_dev_next(dev)) for (dev = pgw_dev_first(); dev; dev = pgw_dev_next(dev)) {
{
dev->fd = ogs_tun_open(dev->ifname, IFNAMSIZ, 0); dev->fd = ogs_tun_open(dev->ifname, IFNAMSIZ, 0);
if (dev->fd == INVALID_SOCKET) if (dev->fd == INVALID_SOCKET) {
{
ogs_error("tun_open(dev:%s) failed", dev->ifname); ogs_error("tun_open(dev:%s) failed", dev->ifname);
return OGS_ERROR; return OGS_ERROR;
} }
@ -286,12 +292,11 @@ int pgw_gtp_open()
/* Set P-to-P IP address with Netmask /* Set P-to-P IP address with Netmask
* Note that Linux will skip this configuration */ * Note that Linux will skip this configuration */
for (subnet = pgw_subnet_first(); subnet; subnet = pgw_subnet_next(subnet)) for (subnet = pgw_subnet_first();
{ subnet; subnet = pgw_subnet_next(subnet)) {
ogs_assert(subnet->dev); ogs_assert(subnet->dev);
rc = ogs_tun_set_ip(subnet->dev->ifname, &subnet->gw, &subnet->sub); rc = ogs_tun_set_ip(subnet->dev->ifname, &subnet->gw, &subnet->sub);
if (rc != OGS_OK) if (rc != OGS_OK) {
{
ogs_error("ogs_tun_set_ip(dev:%s) failed", subnet->dev->ifname); ogs_error("ogs_tun_set_ip(dev:%s) failed", subnet->dev->ifname);
return OGS_ERROR; return OGS_ERROR;
} }
@ -313,8 +318,7 @@ void pgw_gtp_close()
ogs_socknode_remove_all(&pgw_self()->gtpu_list); ogs_socknode_remove_all(&pgw_self()->gtpu_list);
ogs_socknode_remove_all(&pgw_self()->gtpu_list6); ogs_socknode_remove_all(&pgw_self()->gtpu_list6);
for (dev = pgw_dev_first(); dev; dev = pgw_dev_next(dev)) for (dev = pgw_dev_first(); dev; dev = pgw_dev_next(dev)) {
{
ogs_pollset_remove(dev->poll); ogs_pollset_remove(dev->poll);
ogs_closesocket(dev->fd); ogs_closesocket(dev->fd);
} }
@ -327,8 +331,7 @@ static int pgw_gtp_handle_multicast(ogs_pkbuf_t *recvbuf)
struct ip6_hdr *ip6_h = NULL; struct ip6_hdr *ip6_h = NULL;
ip_h = (struct ip *)recvbuf->data; ip_h = (struct ip *)recvbuf->data;
if (ip_h->ip_v == 6) if (ip_h->ip_v == 6) {
{
#if COMPILE_ERROR_IN_MAC_OS_X /* Compiler error in Mac OS X platform */ #if COMPILE_ERROR_IN_MAC_OS_X /* Compiler error in Mac OS X platform */
ip6_h = (struct ip6_hdr *)recvbuf->data; ip6_h = (struct ip6_hdr *)recvbuf->data;
if (IN6_IS_ADDR_MULTICAST(&ip6_h->ip6_dst)) if (IN6_IS_ADDR_MULTICAST(&ip6_h->ip6_dst))
@ -342,12 +345,10 @@ static int pgw_gtp_handle_multicast(ogs_pkbuf_t *recvbuf)
ogs_hash_index_t *hi = NULL; ogs_hash_index_t *hi = NULL;
/* IPv6 Multicast */ /* IPv6 Multicast */
for (hi = pgw_sess_first(); hi; hi = pgw_sess_next(hi)) for (hi = pgw_sess_first(); hi; hi = pgw_sess_next(hi)) {
{
pgw_sess_t *sess = pgw_sess_this(hi); pgw_sess_t *sess = pgw_sess_this(hi);
ogs_assert(sess); ogs_assert(sess);
if (sess->ipv6) if (sess->ipv6) {
{
/* PDN IPv6 is avaiable */ /* PDN IPv6 is avaiable */
pgw_bearer_t *bearer = pgw_default_bearer_in_sess(sess); pgw_bearer_t *bearer = pgw_default_bearer_in_sess(sess);
ogs_assert(bearer); ogs_assert(bearer);
@ -373,18 +374,14 @@ static int pgw_gtp_handle_slaac(pgw_sess_t *sess, ogs_pkbuf_t *recvbuf)
ogs_assert(recvbuf); ogs_assert(recvbuf);
ogs_assert(recvbuf->len); ogs_assert(recvbuf->len);
ip_h = (struct ip *)recvbuf->data; ip_h = (struct ip *)recvbuf->data;
if (ip_h->ip_v == 6) if (ip_h->ip_v == 6) {
{
struct ip6_hdr *ip6_h = (struct ip6_hdr *)recvbuf->data; struct ip6_hdr *ip6_h = (struct ip6_hdr *)recvbuf->data;
if (ip6_h->ip6_nxt == IPPROTO_ICMPV6) if (ip6_h->ip6_nxt == IPPROTO_ICMPV6) {
{
struct icmp6_hdr *icmp_h = struct icmp6_hdr *icmp_h =
(struct icmp6_hdr *)(recvbuf->data + sizeof(struct ip6_hdr)); (struct icmp6_hdr *)(recvbuf->data + sizeof(struct ip6_hdr));
if (icmp_h->icmp6_type == ND_ROUTER_SOLICIT) if (icmp_h->icmp6_type == ND_ROUTER_SOLICIT) {
{
ogs_debug("[PGW] Router Solict"); ogs_debug("[PGW] Router Solict");
if (sess->ipv6) if (sess->ipv6) {
{
rv = pgw_gtp_send_router_advertisement( rv = pgw_gtp_send_router_advertisement(
sess, ip6_h->ip6_src.s6_addr); sess, ip6_h->ip6_src.s6_addr);
ogs_assert(rv == OGS_OK); ogs_assert(rv == OGS_OK);
@ -531,16 +528,14 @@ uint16_t in_cksum(uint16_t *addr, int len)
uint16_t answer = 0; uint16_t answer = 0;
// Adding 16 bits sequentially in sum // Adding 16 bits sequentially in sum
while (nleft > 1) while (nleft > 1) {
{
sum += *w; sum += *w;
nleft -= 2; nleft -= 2;
w++; w++;
} }
// If an odd byte is left // If an odd byte is left
if (nleft == 1) if (nleft == 1) {
{
*(uint8_t *) (&answer) = *(uint8_t *) w; *(uint8_t *) (&answer) = *(uint8_t *) w;
sum += answer; sum += answer;
} }

View File

@ -1,5 +1,24 @@
#ifndef __PGW_PATH_H__ /*
#define __PGW_PATH_H__ * Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef PGW_PATH_H
#define PGW_PATH_H
#include "ogs-tun.h" #include "ogs-tun.h"
#include "gtp/gtp-xact.h" #include "gtp/gtp-xact.h"
@ -13,6 +32,6 @@ void pgw_gtp_close();
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif
#endif /* __PGW_PATH_H__ */ #endif /* PGW_PATH_H */