diff --git a/Makefile b/Makefile index eb07143..9081679 100644 --- a/Makefile +++ b/Makefile @@ -5,8 +5,5 @@ obj-m += gtp.o default: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules - $(CC) -lmnl gtp-link-add.c -o gtp-link-add - $(CC) -lmnl gtp-tunnel.c genl.c gtpnl.c -o gtp-tunnel clean: rm -rf *.o *.mod.* modules.order Module.symvers *.ko .tmp_versions .*.cmd - rm -f genl-family-get gtp-link-add gtp-tunnel-add diff --git a/libgtnl/.gitignore b/libgtnl/.gitignore new file mode 100644 index 0000000..9deb3b5 --- /dev/null +++ b/libgtnl/.gitignore @@ -0,0 +1,23 @@ +# Dependency and object files +.*.d +*.o +*.lo +*.la +.deps +.libs +.dirstamp + +# Generated by autoconf/configure +Makefile +Makefile.in +config.* +configure +autom4te.cache +stamp-h1 +aclocal.m4 +libgtpnl.pc +libtool +build-aux + +# Debian package build temporary files +build-stamp diff --git a/libgtnl/Make_global.am b/libgtnl/Make_global.am new file mode 100644 index 0000000..1654f10 --- /dev/null +++ b/libgtnl/Make_global.am @@ -0,0 +1,24 @@ +# This is _NOT_ the library release version, it's an API version. +# Extracted from Chapter 6 "Library interface versions" of the libtool docs. +# +# +# Here are a set of rules to help you update your library version information: +# +# 1. Start with version information of `0:0:0' for each libtool library. +# 2. Update the version information only immediately before a public release +# of your software. More frequent updates are unnecessary, and only guarantee +# that the current interface number gets larger faster. +# 3. If the library source code has changed at all since the last update, +# then increment revision (`c:r:a' becomes `c:r+1:a'). +# 4. If any interfaces have been added, removed, or changed since the last +# update, increment current, and set revision to 0. +# 5. If any interfaces have been added since the last public release, then +# increment age. +# 6. If any interfaces have been removed since the last public release, then +# set age to 0. +# +# +LIBVERSION=0:0:0 + +AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_srcdir}/include ${LIBMNL_CFLAGS} +AM_CFLAGS = ${regular_CFLAGS} ${GCC_FVISIBILITY_HIDDEN} diff --git a/libgtnl/Makefile.am b/libgtnl/Makefile.am new file mode 100644 index 0000000..cb72faf --- /dev/null +++ b/libgtnl/Makefile.am @@ -0,0 +1,11 @@ +include $(top_srcdir)/Make_global.am + +ACLOCAL_AMFLAGS = -I m4 + +SUBDIRS = src include tools +DIST_SUBDIRS = src include tools + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libgtpnl.pc + +${pkgconfig_DATA}: ${top_builddir}/config.status diff --git a/libgtnl/configure.ac b/libgtnl/configure.ac new file mode 100644 index 0000000..a9845ac --- /dev/null +++ b/libgtnl/configure.ac @@ -0,0 +1,34 @@ +dnl Process this file with autoconf to create configure. + +AC_INIT([libgtpnl], [1.0.0]) +AC_CONFIG_AUX_DIR([build-aux]) +AC_CANONICAL_HOST +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_HEADERS([config.h]) +AM_INIT_AUTOMAKE([foreign tar-pax no-dist-gzip dist-bzip2 1.6 subdir-objects]) + +dnl kernel style compile messages +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +dnl Dependencies +PKG_CHECK_MODULES([LIBMNL], [libmnl >= 1.0.0]) + +AC_PROG_CC +AM_PROG_CC_C_O +AC_EXEEXT +AC_DISABLE_STATIC +LT_INIT +CHECK_GCC_FVISIBILITY +case "$host" in +*-*-linux* | *-*-uclinux*) ;; +*) AC_MSG_ERROR([Linux only, dude!]);; +esac + +regular_CPPFLAGS="-D_FILE_OFFSET_BITS=64 -D_REENTRANT" +regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \ + -Wmissing-prototypes -Wshadow -Wstrict-prototypes \ + -Wformat=2 -pipe" +AC_SUBST([regular_CPPFLAGS]) +AC_SUBST([regular_CFLAGS]) +AC_CONFIG_FILES([Makefile src/Makefile include/Makefile include/libgtpnl/Makefile include/linux/Makefile tools/Makefile libgtpnl.pc]) +AC_OUTPUT diff --git a/libgtnl/include/Makefile.am b/libgtnl/include/Makefile.am new file mode 100644 index 0000000..bafe5e3 --- /dev/null +++ b/libgtnl/include/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = libgtpnl linux diff --git a/libgtnl/include/libgtpnl/Makefile.am b/libgtnl/include/libgtpnl/Makefile.am new file mode 100644 index 0000000..b1c2bee --- /dev/null +++ b/libgtnl/include/libgtpnl/Makefile.am @@ -0,0 +1 @@ +pkginclude_HEADERS = gtpnl.h diff --git a/libgtnl/include/libgtpnl/gtpnl.h b/libgtnl/include/libgtpnl/gtpnl.h new file mode 100644 index 0000000..00a60d8 --- /dev/null +++ b/libgtnl/include/libgtpnl/gtpnl.h @@ -0,0 +1,26 @@ +#ifndef _LIBGTPNL_H_ +#define _LIBGTPNL_H_ + +#include + +struct mnl_socket; +struct nlmsghdr; + +struct mnl_socket *genl_socket_open(void); +struct nlmsghdr *genl_nlmsg_build_hdr(char *buf, uint16_t type, uint16_t flags, + uint32_t seq, uint8_t cmd); +int genl_socket_talk(struct mnl_socket *nl, struct nlmsghdr *nlh, uint32_t seq, + int (*cb)(const struct nlmsghdr *nlh, void *data), + void *data); +int genl_lookup_family(struct mnl_socket *nl, const char *family); + +int gtp_dev_create(const char *ifname); + +int gtp_add_tunnel(int genl_id, struct mnl_socket *nl, const char *ifname, + const char *ms_addr, const char *sgsn_addr, uint64_t tid, + int gtp_version); +int gtp_del_tunnel(int genl_id, struct mnl_socket *nl, const char *ifname, + uint64_t tid, uint32_t gtp_version); +int gtp_list_tunnel(int genl_id, struct mnl_socket *nl); + +#endif diff --git a/libgtnl/include/linux/Makefile.am b/libgtnl/include/linux/Makefile.am new file mode 100644 index 0000000..082198e --- /dev/null +++ b/libgtnl/include/linux/Makefile.am @@ -0,0 +1 @@ +noinst_HEADERS = gtp_nl.h diff --git a/libgtnl/include/linux/gtp_nl.h b/libgtnl/include/linux/gtp_nl.h new file mode 100644 index 0000000..968824c --- /dev/null +++ b/libgtnl/include/linux/gtp_nl.h @@ -0,0 +1,45 @@ +#ifndef _UAPI_LINUX_GTP_H_ +#define _UAPI_LINUX_GTP_H__ + +enum { + IFLA_GTP_UNSPEC, + IFLA_GTP_LOCAL_ADDR_IPV4, + IFLA_GTP_HASHSIZE, + __IFLA_GTP_MAX, +}; +#define IFLA_GTP_MAX (__IFLA_GTP_MAX - 1) + +enum gtp_genl_cmds { + GTP_CMD_TUNNEL_NEW, + GTP_CMD_TUNNEL_DELETE, + GTP_CMD_TUNNEL_GET, + + GTP_CMD_TUNNEL_MAX, +}; + +enum gtp_version { + GTP_V0 = 0, + GTP_V1, +}; + +enum gtp_cfg_attrs { + GTPA_CFG_UNSPEC = 0, + GTPA_CFG_LINK, + GTPA_CFG_LOCAL_ADDR_IPV4, + GTPA_CFG_HSIZE, + __GTPA_CFG_MAX, +}; +#define GTPA_CFG_MAX (__GTPA_CFG_MAX + 1) + +enum gtp_attrs { + GTPA_UNSPEC = 0, + GTPA_LINK, + GTPA_VERSION, + GTPA_TID, /* 64 bits for GTPv1 */ + GTPA_SGSN_ADDRESS, + GTPA_MS_ADDRESS, + __GTPA_MAX, +}; +#define GTPA_MAX (__GTPA_MAX + 1) + +#endif /* _UAPI_LINUX_GTP_H_ */ diff --git a/libgtnl/libgtpnl.pc.in b/libgtnl/libgtpnl.pc.in new file mode 100644 index 0000000..2dad5fe --- /dev/null +++ b/libgtnl/libgtpnl.pc.in @@ -0,0 +1,15 @@ +# libgtpnl pkg-config file + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libgtpnl +Description: Netlink library for GTP Linux kernel implementation +URL: http://git.osmocom.org/libgtpnl/ +Version: @VERSION@ +Requires: +Conflicts: +Libs: -L${libdir} -lgtpnl +Cflags: -I${includedir} diff --git a/libgtnl/m4/gcc4_visibility.m4 b/libgtnl/m4/gcc4_visibility.m4 new file mode 100644 index 0000000..214d3f3 --- /dev/null +++ b/libgtnl/m4/gcc4_visibility.m4 @@ -0,0 +1,21 @@ + +# GCC 4.x -fvisibility=hidden + +AC_DEFUN([CHECK_GCC_FVISIBILITY], [ + AC_LANG_PUSH([C]) + saved_CFLAGS="$CFLAGS" + CFLAGS="$saved_CFLAGS -fvisibility=hidden" + AC_CACHE_CHECK([whether compiler accepts -fvisibility=hidden], + [ac_cv_fvisibility_hidden], AC_COMPILE_IFELSE( + [AC_LANG_SOURCE()], + [ac_cv_fvisibility_hidden=yes], + [ac_cv_fvisibility_hidden=no] + )) + if test "$ac_cv_fvisibility_hidden" = "yes"; then + AC_DEFINE([HAVE_VISIBILITY_HIDDEN], [1], + [True if compiler supports -fvisibility=hidden]) + AC_SUBST([GCC_FVISIBILITY_HIDDEN], [-fvisibility=hidden]) + fi + CFLAGS="$saved_CFLAGS" + AC_LANG_POP([C]) +]) diff --git a/libgtnl/src/Makefile.am b/libgtnl/src/Makefile.am new file mode 100644 index 0000000..a9b072f --- /dev/null +++ b/libgtnl/src/Makefile.am @@ -0,0 +1,5 @@ +include $(top_srcdir)/Make_global.am +lib_LTLIBRARIES = libgtpnl.la + +libgtpnl_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libgtpnl.map -version-info $(LIBVERSION) +libgtpnl_la_SOURCES = genl.c gtp-genl.c gtp-rtnl.c libgtpnl.map diff --git a/genl.c b/libgtnl/src/genl.c similarity index 94% rename from genl.c rename to libgtnl/src/genl.c index a89d6cf..099b317 100644 --- a/genl.c +++ b/libgtnl/src/genl.c @@ -6,6 +6,10 @@ #include #include +#include + +#include "internal.h" + struct nlmsghdr * genl_nlmsg_build_hdr(char *buf, uint16_t type, uint16_t flags, uint32_t seq, uint8_t cmd) @@ -24,6 +28,7 @@ genl_nlmsg_build_hdr(char *buf, uint16_t type, uint16_t flags, uint32_t seq, return nlh; } +EXPORT_SYMBOL(genl_nlmsg_build_hdr); static int genl_ctrl_validate_cb(const struct nlattr *attr, void *data) { @@ -77,6 +82,7 @@ struct mnl_socket *genl_socket_open(void) return nl; } +EXPORT_SYMBOL(genl_socket_open); int genl_socket_talk(struct mnl_socket *nl, struct nlmsghdr *nlh, uint32_t seq, int (*cb)(const struct nlmsghdr *nlh, void *data), @@ -101,6 +107,7 @@ int genl_socket_talk(struct mnl_socket *nl, struct nlmsghdr *nlh, uint32_t seq, return ret; } +EXPORT_SYMBOL(genl_socket_talk); static struct nlmsghdr * genl_nlmsg_build_lookup(char *buf, const char *subsys_name) @@ -136,3 +143,4 @@ int genl_lookup_family(struct mnl_socket *nl, const char *family) return genl_id; } +EXPORT_SYMBOL(genl_lookup_family); diff --git a/libgtnl/src/gtp-genl.c b/libgtnl/src/gtp-genl.c new file mode 100644 index 0000000..0dd5473 --- /dev/null +++ b/libgtnl/src/gtp-genl.c @@ -0,0 +1,177 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include "internal.h" + +static void gtp_build_payload(struct nlmsghdr *nlh, uint64_t tid, + uint32_t ifidx, uint32_t sgsn_addr, + uint32_t ms_addr, uint32_t version) +{ + mnl_attr_put_u32(nlh, GTPA_VERSION, version); + mnl_attr_put_u32(nlh, GTPA_LINK, ifidx); + mnl_attr_put_u32(nlh, GTPA_SGSN_ADDRESS, sgsn_addr); + mnl_attr_put_u32(nlh, GTPA_MS_ADDRESS, ms_addr); + mnl_attr_put_u64(nlh, GTPA_TID, tid); +} + +int gtp_add_tunnel(int genl_id, struct mnl_socket *nl, const char *ifname, + const char *ms_addr, const char *sgsn_addr, uint64_t tid, + int gtp_version) +{ + uint32_t gtp_ifidx; + struct in_addr ms, sgsn; + struct nlmsghdr *nlh; + char buf[MNL_SOCKET_BUFFER_SIZE]; + uint32_t seq = time(NULL); + + gtp_ifidx = if_nametoindex(ifname); + if (gtp_ifidx == 0){ + fprintf(stderr, "wrong GTP interface %s\n", ifname); + return -1; + } + + if (inet_aton(ms_addr, &ms) < 0) { + perror("bad address for ms"); + return -1; + } + + if (inet_aton(sgsn_addr, &sgsn) < 0) { + perror("bad address for sgsn"); + return -1; + } + + if (gtp_version > GTP_V1) { + fprintf(stderr, "wrong GTP version %u, use v0 or v1\n", + gtp_version); + return -1; + } + + nlh = genl_nlmsg_build_hdr(buf, genl_id, NLM_F_EXCL | NLM_F_ACK, ++seq, + GTP_CMD_TUNNEL_NEW); + gtp_build_payload(nlh, tid, gtp_ifidx, sgsn.s_addr, + ms.s_addr, gtp_version); + + if (genl_socket_talk(nl, nlh, seq, NULL, NULL) < 0) + perror("genl_socket_talk"); + + return 0; +} +EXPORT_SYMBOL(gtp_add_tunnel); + +int gtp_del_tunnel(int genl_id, struct mnl_socket *nl, const char *ifname, + uint64_t tid, uint32_t gtp_version) +{ + uint32_t gtp_ifidx; + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh; + uint32_t seq = time(NULL); + + gtp_ifidx = if_nametoindex(ifname); + + nlh = genl_nlmsg_build_hdr(buf, genl_id, NLM_F_ACK, ++seq, + GTP_CMD_TUNNEL_DELETE); + gtp_build_payload(nlh, tid, gtp_ifidx, 0, 0, gtp_version); + + if (genl_socket_talk(nl, nlh, seq, NULL, NULL) < 0) + perror("genl_socket_talk"); + + return 0; +} +EXPORT_SYMBOL(gtp_del_tunnel); + +struct gtp_pdp { + uint32_t version; + uint64_t tid; + struct in_addr sgsn_addr; + struct in_addr ms_addr; +}; + +static int genl_gtp_validate_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = data; + int type = mnl_attr_get_type(attr); + + if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case GTPA_TID: + if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + case GTPA_SGSN_ADDRESS: + case GTPA_MS_ADDRESS: + case GTPA_VERSION: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + default: + break; + } + tb[type] = attr; + return MNL_CB_OK; +} + +static int genl_gtp_attr_cb(const struct nlmsghdr *nlh, void *data) +{ + struct nlattr *tb[GTPA_MAX + 1] = {}; + struct gtp_pdp pdp; + struct genlmsghdr *genl; + + mnl_attr_parse(nlh, sizeof(*genl), genl_gtp_validate_cb, tb); + if (tb[GTPA_TID]) + pdp.tid = mnl_attr_get_u64(tb[GTPA_TID]); + if (tb[GTPA_SGSN_ADDRESS]) { + pdp.sgsn_addr.s_addr = + mnl_attr_get_u32(tb[GTPA_SGSN_ADDRESS]); + } + if (tb[GTPA_MS_ADDRESS]) { + pdp.ms_addr.s_addr = mnl_attr_get_u32(tb[GTPA_MS_ADDRESS]); + } + if (tb[GTPA_VERSION]) { + pdp.version = mnl_attr_get_u32(tb[GTPA_VERSION]); + } + + printf("version %u ", pdp.version); + printf("tid %"PRIu64" ms_addr %s ", pdp.tid, inet_ntoa(pdp.sgsn_addr)); + printf("sgsn_addr %s\n", inet_ntoa(pdp.ms_addr)); + + return MNL_CB_OK; +} + +int gtp_list_tunnel(int genl_id, struct mnl_socket *nl) +{ + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh; + uint32_t seq = time(NULL); + + nlh = genl_nlmsg_build_hdr(buf, genl_id, NLM_F_DUMP, 0, + GTP_CMD_TUNNEL_GET); + + if (genl_socket_talk(nl, nlh, seq, genl_gtp_attr_cb, NULL) < 0) { + perror("genl_socket_talk"); + return 0; + } + + return 0; +} +EXPORT_SYMBOL(gtp_list_tunnel); diff --git a/libgtnl/src/gtp-rtnl.c b/libgtnl/src/gtp-rtnl.c new file mode 100644 index 0000000..2cd43ef --- /dev/null +++ b/libgtnl/src/gtp-rtnl.c @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include "internal.h" + +int gtp_dev_create(const char *ifname) +{ + struct mnl_socket *nl; + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh; + struct ifinfomsg *ifm; + int ret; + unsigned int seq, portid; + struct nlattr *nest, *nest2; + + nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = RTM_NEWLINK; + nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK; + nlh->nlmsg_seq = seq = time(NULL); + ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm)); + ifm->ifi_family = AF_INET; + ifm->ifi_change |= IFF_UP; + ifm->ifi_flags |= IFF_UP; + + mnl_attr_put_u32(nlh, IFLA_LINK, if_nametoindex(ifname)); + nest = mnl_attr_nest_start(nlh, IFLA_LINKINFO); + mnl_attr_put_str(nlh, IFLA_INFO_KIND, "gtp"); + nest2 = mnl_attr_nest_start(nlh, IFLA_INFO_DATA); + mnl_attr_put_u32(nlh, IFLA_GTP_LOCAL_ADDR_IPV4, 0); + mnl_attr_put_u32(nlh, IFLA_GTP_HASHSIZE, 131072); + mnl_attr_nest_end(nlh, nest2); + mnl_attr_nest_end(nlh, nest); + + nl = mnl_socket_open(NETLINK_ROUTE); + if (nl == NULL) { + perror("mnl_socket_open"); + return -1; + } + + if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { + perror("mnl_socket_bind"); + return -1; + } + portid = mnl_socket_get_portid(nl); + + mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, + sizeof(struct ifinfomsg)); + + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { + perror("mnl_socket_send"); + return -1; + } + + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + if (ret == -1) { + perror("read"); + return -1; + } + + ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL); + if (ret == -1){ + perror("callback"); + return -1; + } + + mnl_socket_close(nl); + + return 0; +} +EXPORT_SYMBOL(gtp_dev_create); diff --git a/libgtnl/src/internal.h b/libgtnl/src/internal.h new file mode 100644 index 0000000..3a88d1a --- /dev/null +++ b/libgtnl/src/internal.h @@ -0,0 +1,12 @@ +#ifndef INTERNAL_H +#define INTERNAL_H 1 + +#include "config.h" +#ifdef HAVE_VISIBILITY_HIDDEN +# define __visible __attribute__((visibility("default"))) +# define EXPORT_SYMBOL(x) typeof(x) (x) __visible +#else +# define EXPORT_SYMBOL +#endif + +#endif diff --git a/libgtnl/src/libgtpnl.map b/libgtnl/src/libgtpnl.map new file mode 100644 index 0000000..ead02e0 --- /dev/null +++ b/libgtnl/src/libgtpnl.map @@ -0,0 +1,13 @@ +LIBGTPNL_1.0 { +global: + genl_socket_open; + genl_nlmsg_build_hdr; + genl_socket_talk; + genl_lookup_family; + gtp_dev_create; + gtp_add_tunnel; + gtp_del_tunnel; + gtp_list_tunnel; + +local: *; +}; diff --git a/libgtnl/tools/Makefile.am b/libgtnl/tools/Makefile.am new file mode 100644 index 0000000..7880f3c --- /dev/null +++ b/libgtnl/tools/Makefile.am @@ -0,0 +1,10 @@ +include $(top_srcdir)/Make_global.am + +check_PROGRAMS = gtp-link-add \ + gtp-tunnel + +gtp_link_add_SOURCES = gtp-link-add.c gtpnl.c +gtp_link_add_LDADD = ../src/libgtpnl.la ${LIBMNL_LIBS} + +gtp_tunnel_SOURCES = gtp-tunnel.c gtpnl.c +gtp_tunnel_LDADD = ../src/libgtpnl.la ${LIBMNL_LIBS} diff --git a/gtp-link-add.c b/libgtnl/tools/gtp-link-add.c similarity index 98% rename from gtp-link-add.c rename to libgtnl/tools/gtp-link-add.c index 31f893e..c9c50c8 100644 --- a/gtp-link-add.c +++ b/libgtnl/tools/gtp-link-add.c @@ -9,7 +9,7 @@ #include #include -#include "gtp_nl.h" +#include int main(int argc, char *argv[]) { diff --git a/gtp-tunnel.c b/libgtnl/tools/gtp-tunnel.c similarity index 98% rename from gtp-tunnel.c rename to libgtnl/tools/gtp-tunnel.c index aa405ad..ec091db 100644 --- a/gtp-tunnel.c +++ b/libgtnl/tools/gtp-tunnel.c @@ -10,8 +10,8 @@ #include #include -#include "gtp_nl.h" -#include "genl.h" +#include +#include static int add_tunnel(int argc, char *argv[], int genl_id, struct mnl_socket *nl) diff --git a/gtpnl.c b/libgtnl/tools/gtpnl.c similarity index 94% rename from gtpnl.c rename to libgtnl/tools/gtpnl.c index e98b9da..6b2f1e2 100644 --- a/gtpnl.c +++ b/libgtnl/tools/gtpnl.c @@ -1,6 +1,6 @@ #include #include -#include "gtp_nl.h" +#include void gtp_build_payload(struct nlmsghdr *nlh, uint64_t tid, uint32_t ifidx, uint32_t sgsn_addr, uint32_t ms_addr, uint32_t version)