forked from acouzens/open5gs
Support TAP interfaces, with ARP/ND.
This commit is contained in:
parent
64508c2e5c
commit
caa73e1f5e
|
@ -104,6 +104,10 @@ Install Meson using Homebrew.
|
||||||
$ brew install meson
|
$ brew install meson
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Install libtins.
|
||||||
|
|
||||||
|
Follow the instructions at https://libtins.github.io to install libtins.
|
||||||
|
|
||||||
Git clone.
|
Git clone.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
|
@ -103,6 +103,10 @@ Install Meson using Homebrew.
|
||||||
$ brew install meson
|
$ brew install meson
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Install libtins.
|
||||||
|
|
||||||
|
Follow the instructions at https://libtins.github.io to install libtins.
|
||||||
|
|
||||||
Git clone.
|
Git clone.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
|
@ -121,6 +121,10 @@ $ export LIBRARY_PATH=/usr/local/lib
|
||||||
$ export C_INCLUDE_PATH=/usr/local/include
|
$ export C_INCLUDE_PATH=/usr/local/include
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Install libtins.
|
||||||
|
|
||||||
|
Follow the instructions at https://libtins.github.io to install libtins.
|
||||||
|
|
||||||
Git clone.
|
Git clone.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
|
@ -289,6 +289,8 @@ typedef struct ogs_pfcp_dev_s {
|
||||||
|
|
||||||
ogs_sockaddr_t *link_local_addr;
|
ogs_sockaddr_t *link_local_addr;
|
||||||
ogs_poll_t *poll;
|
ogs_poll_t *poll;
|
||||||
|
bool is_tap;
|
||||||
|
uint8_t mac_addr[6];
|
||||||
} ogs_pfcp_dev_t;
|
} ogs_pfcp_dev_t;
|
||||||
|
|
||||||
typedef struct ogs_pfcp_subnet_s {
|
typedef struct ogs_pfcp_subnet_s {
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
project('open5gs', 'c',
|
project('open5gs', 'c', 'cpp',
|
||||||
version : '2.2.9',
|
version : '2.2.9',
|
||||||
license : 'AGPL-3.0-or-later',
|
license : 'AGPL-3.0-or-later',
|
||||||
meson_version : '>= 0.43.0',
|
meson_version : '>= 0.43.0',
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* 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 <tins/arp.h>
|
||||||
|
#include <tins/ethernetII.h>
|
||||||
|
#include <tins/hw_address.h>
|
||||||
|
#include <tins/icmpv6.h>
|
||||||
|
|
||||||
|
#include "arp-nd.h"
|
||||||
|
|
||||||
|
using namespace::Tins;
|
||||||
|
|
||||||
|
|
||||||
|
void _serialize_reply(uint8_t *reply_data, EthernetII &reply) {
|
||||||
|
PDU::serialization_type serialized = reply.serialize();
|
||||||
|
memcpy(reply_data, serialized.data(), reply.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _parse_arp(EthernetII &pdu) {
|
||||||
|
if (pdu.payload_type() == ETHERTYPE_ARP) {
|
||||||
|
const ARP& arp = pdu.rfind_pdu<ARP>();
|
||||||
|
return arp.opcode() == ARP::REQUEST && pdu.dst_addr().is_broadcast();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_arp_req(uint8_t *data, uint len)
|
||||||
|
{
|
||||||
|
EthernetII pdu(data, len);
|
||||||
|
return _parse_arp(pdu);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool arp_reply(uint8_t *reply_data, uint8_t *request_data, uint len, const uint8_t *mac) {
|
||||||
|
EthernetII pdu(request_data, len);
|
||||||
|
if (_parse_arp(pdu)) {
|
||||||
|
HWAddress<ETHER_ADDR_LEN> source_mac(mac);
|
||||||
|
const ARP& arp = pdu.rfind_pdu<ARP>();
|
||||||
|
EthernetII reply = ARP::make_arp_reply(
|
||||||
|
arp.sender_ip_addr(),
|
||||||
|
arp.target_ip_addr(),
|
||||||
|
arp.sender_hw_addr(),
|
||||||
|
source_mac);
|
||||||
|
_serialize_reply(reply_data, reply);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _parse_nd(EthernetII &pdu) {
|
||||||
|
if (pdu.payload_type() == ETHERTYPE_IPV6) {
|
||||||
|
const ICMPv6& icmp6 = pdu.rfind_pdu<ICMPv6>();
|
||||||
|
return icmp6.type() == ICMPv6::NEIGHBOUR_SOLICIT;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_nd_req(uint8_t *data, uint len)
|
||||||
|
{
|
||||||
|
if (len < MAX_ND_SIZE) {
|
||||||
|
EthernetII pdu(data, len);
|
||||||
|
return _parse_nd(pdu);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nd_reply(uint8_t *reply_data, uint8_t *request_data, uint len, const uint8_t *mac) {
|
||||||
|
EthernetII pdu(request_data, len);
|
||||||
|
if (_parse_nd(pdu)) {
|
||||||
|
HWAddress<ETHER_ADDR_LEN> source_mac(mac);
|
||||||
|
const ICMPv6& icmp6 = pdu.rfind_pdu<ICMPv6>();
|
||||||
|
EthernetII reply(pdu.src_addr(), pdu.dst_addr());
|
||||||
|
ICMPv6 nd_reply(ICMPv6::NEIGHBOUR_ADVERT);
|
||||||
|
nd_reply.target_link_layer_addr(source_mac);
|
||||||
|
nd_reply.target_addr(icmp6.target_addr());
|
||||||
|
reply /= nd_reply;
|
||||||
|
_serialize_reply(reply_data, reply);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* 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 "upf-config.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_NET_ETHERNET_H
|
||||||
|
#include <net/ethernet.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAX_ND_SIZE 128
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void set_source_mac(uint8_t *data);
|
||||||
|
bool is_arp_req(uint8_t *data, uint len);
|
||||||
|
bool arp_reply(uint8_t *reply_data, uint8_t *request_data, uint len, const uint8_t *mac);
|
||||||
|
bool is_nd_req(uint8_t *data, uint len);
|
||||||
|
bool nd_reply(uint8_t *reply_data, uint8_t *request_data, uint len, const uint8_t *mac);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -35,6 +35,19 @@
|
||||||
#include <netinet/icmp6.h>
|
#include <netinet/icmp6.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_SYS_IOCTL_H
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_NET_IF_DL_H
|
||||||
|
#include <net/if_dl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_IFADDRS_H
|
||||||
|
#include <ifaddrs.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "arp-nd.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
#include "gtp-path.h"
|
#include "gtp-path.h"
|
||||||
#include "pfcp-path.h"
|
#include "pfcp-path.h"
|
||||||
|
@ -42,11 +55,21 @@
|
||||||
|
|
||||||
#define UPF_GTP_HANDLED 1
|
#define UPF_GTP_HANDLED 1
|
||||||
|
|
||||||
|
const uint8_t proxy_mac_addr[] = { 0x0e, 0x00, 0x00, 0x00, 0x00, 0x01 };
|
||||||
|
|
||||||
static ogs_pkbuf_pool_t *packet_pool = NULL;
|
static ogs_pkbuf_pool_t *packet_pool = NULL;
|
||||||
|
|
||||||
static void upf_gtp_handle_multicast(ogs_pkbuf_t *recvbuf);
|
static void upf_gtp_handle_multicast(ogs_pkbuf_t *recvbuf);
|
||||||
|
|
||||||
static void _gtpv1_tun_recv_cb(short when, ogs_socket_t fd, void *data)
|
static uint16_t _get_eth_type(uint8_t *data, uint len) {
|
||||||
|
if (len > ETHER_HDR_LEN) {
|
||||||
|
struct ether_header *hdr = (struct ether_header*)data;
|
||||||
|
return htobe16(hdr->ether_type);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _gtpv1_tun_recv_common_cb(short when, ogs_socket_t fd, bool has_eth, void *data)
|
||||||
{
|
{
|
||||||
ogs_pkbuf_t *recvbuf = NULL;
|
ogs_pkbuf_t *recvbuf = NULL;
|
||||||
|
|
||||||
|
@ -62,6 +85,42 @@ static void _gtpv1_tun_recv_cb(short when, ogs_socket_t fd, void *data)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (has_eth) {
|
||||||
|
ogs_pkbuf_t *replybuf = NULL;
|
||||||
|
uint16_t eth_type = _get_eth_type(recvbuf->data, recvbuf->len);
|
||||||
|
|
||||||
|
if (eth_type == ETHERTYPE_ARP) {
|
||||||
|
if (is_arp_req(recvbuf->data, recvbuf->len)) {
|
||||||
|
replybuf = ogs_pkbuf_alloc(packet_pool, OGS_MAX_PKT_LEN);
|
||||||
|
ogs_assert(replybuf);
|
||||||
|
ogs_pkbuf_reserve(replybuf, OGS_TUN_MAX_HEADROOM);
|
||||||
|
ogs_pkbuf_put(replybuf, OGS_MAX_PKT_LEN-OGS_TUN_MAX_HEADROOM);
|
||||||
|
arp_reply(replybuf->data, recvbuf->data, recvbuf->len, proxy_mac_addr);
|
||||||
|
ogs_debug("[SEND] reply to ARP request");
|
||||||
|
} else {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
} else if (eth_type == ETHERTYPE_IPV6 && is_nd_req(recvbuf->data, recvbuf->len)) {
|
||||||
|
replybuf = ogs_pkbuf_alloc(packet_pool, OGS_MAX_PKT_LEN);
|
||||||
|
ogs_assert(replybuf);
|
||||||
|
ogs_pkbuf_reserve(replybuf, OGS_TUN_MAX_HEADROOM);
|
||||||
|
ogs_pkbuf_put(replybuf, OGS_MAX_PKT_LEN-OGS_TUN_MAX_HEADROOM);
|
||||||
|
nd_reply(replybuf->data, recvbuf->data, recvbuf->len, proxy_mac_addr);
|
||||||
|
ogs_debug("[SEND] reply to ND solicit");
|
||||||
|
}
|
||||||
|
if (replybuf) {
|
||||||
|
if (ogs_tun_write(fd, replybuf) != OGS_OK)
|
||||||
|
ogs_warn("ogs_tun_write() for reply failed");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (eth_type != ETHERTYPE_IP && eth_type != ETHERTYPE_IPV6) {
|
||||||
|
ogs_error("[DROP] Invalid eth_type [%x]]", eth_type);
|
||||||
|
ogs_log_hexdump(OGS_LOG_ERROR, recvbuf->data, recvbuf->len);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
ogs_pkbuf_pull(recvbuf, ETHER_HDR_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
sess = upf_sess_find_by_ue_ip_address(recvbuf);
|
sess = upf_sess_find_by_ue_ip_address(recvbuf);
|
||||||
if (!sess)
|
if (!sess)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
@ -127,6 +186,14 @@ cleanup:
|
||||||
ogs_pkbuf_free(recvbuf);
|
ogs_pkbuf_free(recvbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _gtpv1_tun_recv_cb(short when, ogs_socket_t fd, void *data) {
|
||||||
|
_gtpv1_tun_recv_common_cb(when, fd, false, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _gtpv1_tun_recv_eth_cb(short when, ogs_socket_t fd, void *data) {
|
||||||
|
_gtpv1_tun_recv_common_cb(when, fd, true, data);
|
||||||
|
}
|
||||||
|
|
||||||
static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
@ -326,10 +393,15 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
||||||
ogs_assert(far);
|
ogs_assert(far);
|
||||||
|
|
||||||
if (far->dst_if == OGS_PFCP_INTERFACE_CORE) {
|
if (far->dst_if == OGS_PFCP_INTERFACE_CORE) {
|
||||||
if (ip_h->ip_v == 4 && sess->ipv4)
|
uint16_t eth_type = 0;
|
||||||
|
|
||||||
|
if (ip_h->ip_v == 4 && sess->ipv4) {
|
||||||
subnet = sess->ipv4->subnet;
|
subnet = sess->ipv4->subnet;
|
||||||
else if (ip_h->ip_v == 6 && sess->ipv6)
|
eth_type = ETHERTYPE_IP;
|
||||||
|
} else if (ip_h->ip_v == 6 && sess->ipv6) {
|
||||||
subnet = sess->ipv6->subnet;
|
subnet = sess->ipv6->subnet;
|
||||||
|
eth_type = ETHERTYPE_IPV6;
|
||||||
|
}
|
||||||
|
|
||||||
if (!subnet) {
|
if (!subnet) {
|
||||||
#if 0 /* It's redundant log message */
|
#if 0 /* It's redundant log message */
|
||||||
|
@ -342,6 +414,19 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
||||||
|
|
||||||
dev = subnet->dev;
|
dev = subnet->dev;
|
||||||
ogs_assert(dev);
|
ogs_assert(dev);
|
||||||
|
|
||||||
|
if (dev->is_tap) {
|
||||||
|
ogs_assert(eth_type);
|
||||||
|
eth_type = htobe16(eth_type);
|
||||||
|
ogs_pkbuf_push(pkbuf, sizeof(eth_type));
|
||||||
|
memcpy(pkbuf->data, ð_type, sizeof(eth_type));
|
||||||
|
ogs_pkbuf_push(pkbuf, ETHER_ADDR_LEN);
|
||||||
|
memcpy(pkbuf->data, proxy_mac_addr, ETHER_ADDR_LEN);
|
||||||
|
ogs_pkbuf_push(pkbuf, ETHER_ADDR_LEN);
|
||||||
|
memcpy(pkbuf->data, dev->mac_addr, ETHER_ADDR_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: if destined to another UE, hairpin back out. */
|
||||||
if (ogs_tun_write(dev->fd, pkbuf) != OGS_OK)
|
if (ogs_tun_write(dev->fd, pkbuf) != OGS_OK)
|
||||||
ogs_warn("ogs_tun_write() failed");
|
ogs_warn("ogs_tun_write() failed");
|
||||||
|
|
||||||
|
@ -389,7 +474,6 @@ cleanup:
|
||||||
ogs_pkbuf_free(pkbuf);
|
ogs_pkbuf_free(pkbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int upf_gtp_init(void)
|
int upf_gtp_init(void)
|
||||||
{
|
{
|
||||||
ogs_pkbuf_config_t config;
|
ogs_pkbuf_config_t config;
|
||||||
|
@ -407,6 +491,32 @@ void upf_gtp_final(void)
|
||||||
ogs_pkbuf_pool_destroy(packet_pool);
|
ogs_pkbuf_pool_destroy(packet_pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _get_dev_mac_addr(char *ifname, uint8_t *mac_addr)
|
||||||
|
{
|
||||||
|
#ifdef SIOCGIFHWADDR
|
||||||
|
int fd = socket(PF_INET, SOCK_DGRAM, 0);
|
||||||
|
ogs_assert(fd);
|
||||||
|
struct ifreq req;
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
strncpy(req.ifr_name, ifname, IF_NAMESIZE-1);
|
||||||
|
ogs_assert(ioctl(fd, SIOCGIFHWADDR, &req) == 0);
|
||||||
|
memcpy(mac_addr, req.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
|
||||||
|
#else
|
||||||
|
struct ifaddrs *ifap;
|
||||||
|
ogs_assert(getifaddrs(&ifap) == 0);
|
||||||
|
struct ifaddrs *p;
|
||||||
|
for (p = ifap; p; p = p->ifa_next) {
|
||||||
|
if (strncmp(ifname, p->ifa_name, IF_NAMESIZE-1) == 0) {
|
||||||
|
struct sockaddr_dl* sdp = (struct sockaddr_dl*) p->ifa_addr;
|
||||||
|
memcpy(mac_addr, sdp->sdl_data + sdp->sdl_nlen, ETHER_ADDR_LEN);
|
||||||
|
freeifaddrs(ifap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ogs_assert(0); /* interface not found. */
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int upf_gtp_open(void)
|
int upf_gtp_open(void)
|
||||||
{
|
{
|
||||||
ogs_pfcp_dev_t *dev = NULL;
|
ogs_pfcp_dev_t *dev = NULL;
|
||||||
|
@ -444,14 +554,22 @@ int upf_gtp_open(void)
|
||||||
|
|
||||||
/* Open Tun interface */
|
/* Open Tun interface */
|
||||||
ogs_list_for_each(&ogs_pfcp_self()->dev_list, dev) {
|
ogs_list_for_each(&ogs_pfcp_self()->dev_list, dev) {
|
||||||
dev->fd = ogs_tun_open(dev->ifname, OGS_MAX_IFNAME_LEN, 0);
|
dev->is_tap = strstr(dev->ifname, "tap");
|
||||||
|
dev->fd = ogs_tun_open(dev->ifname, OGS_MAX_IFNAME_LEN, dev->is_tap);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->poll = ogs_pollset_add(ogs_app()->pollset,
|
if (dev->is_tap) {
|
||||||
OGS_POLLIN, dev->fd, _gtpv1_tun_recv_cb, NULL);
|
_get_dev_mac_addr(dev->ifname, dev->mac_addr);
|
||||||
|
dev->poll = ogs_pollset_add(ogs_app()->pollset,
|
||||||
|
OGS_POLLIN, dev->fd, _gtpv1_tun_recv_eth_cb, NULL);
|
||||||
|
} else {
|
||||||
|
dev->poll = ogs_pollset_add(ogs_app()->pollset,
|
||||||
|
OGS_POLLIN, dev->fd, _gtpv1_tun_recv_cb, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
ogs_assert(dev->poll);
|
ogs_assert(dev->poll);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -533,4 +651,4 @@ static void upf_gtp_handle_multicast(ogs_pkbuf_t *recvbuf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,17 @@
|
||||||
upf_conf = configuration_data()
|
upf_conf = configuration_data()
|
||||||
|
|
||||||
upf_headers = ('''
|
upf_headers = ('''
|
||||||
|
ifaddrs.h
|
||||||
|
net/ethernet.h
|
||||||
net/if.h
|
net/if.h
|
||||||
|
net/if_dl.h
|
||||||
|
netinet/in.h
|
||||||
netinet/ip.h
|
netinet/ip.h
|
||||||
netinet/ip6.h
|
netinet/ip6.h
|
||||||
netinet/ip_icmp.h
|
netinet/ip_icmp.h
|
||||||
netinet/icmp6.h
|
netinet/icmp6.h
|
||||||
|
sys/ioctl.h
|
||||||
|
sys/socket.h
|
||||||
'''.split())
|
'''.split())
|
||||||
|
|
||||||
foreach h : upf_headers
|
foreach h : upf_headers
|
||||||
|
@ -60,19 +66,30 @@ libupf_sources = files('''
|
||||||
pfcp-path.c
|
pfcp-path.c
|
||||||
n4-build.c
|
n4-build.c
|
||||||
n4-handler.c
|
n4-handler.c
|
||||||
|
arp-nd.h
|
||||||
'''.split())
|
'''.split())
|
||||||
|
|
||||||
|
tins_dep = cc.find_library('tins', required : true)
|
||||||
|
libarp_nd = static_library('arp_nd',
|
||||||
|
sources : files('''
|
||||||
|
arp-nd.cpp
|
||||||
|
arp-nd.h
|
||||||
|
'''.split()),
|
||||||
|
dependencies : tins_dep,
|
||||||
|
install : false)
|
||||||
|
libarp_nd_dep = declare_dependency(link_with : libarp_nd, dependencies : tins_dep)
|
||||||
|
|
||||||
libupf = static_library('upf',
|
libupf = static_library('upf',
|
||||||
sources : libupf_sources,
|
sources : libupf_sources,
|
||||||
dependencies : [
|
dependencies : [
|
||||||
libapp_dep, libdiameter_gx_dep, libgtp_dep, libpfcp_dep, libtun_dep
|
libapp_dep, libdiameter_gx_dep, libgtp_dep, libpfcp_dep, libtun_dep, libarp_nd_dep,
|
||||||
],
|
],
|
||||||
install : false)
|
install : false)
|
||||||
|
|
||||||
libupf_dep = declare_dependency(
|
libupf_dep = declare_dependency(
|
||||||
link_with : libupf,
|
link_with : libupf,
|
||||||
dependencies : [
|
dependencies : [
|
||||||
libapp_dep, libdiameter_gx_dep, libgtp_dep, libpfcp_dep, libtun_dep
|
libapp_dep, libdiameter_gx_dep, libgtp_dep, libpfcp_dep, libtun_dep, libarp_nd_dep,
|
||||||
])
|
])
|
||||||
|
|
||||||
upf_sources = files('''
|
upf_sources = files('''
|
||||||
|
|
Loading…
Reference in New Issue