Compare commits

...

111 Commits

Author SHA1 Message Date
Sukchan Lee
d9ab53bbf0 update changelog for launchpad ppa 2017-11-02 07:52:37 +00:00
Sukchan Lee
561c041010 remove README 2017-11-02 16:08:34 +09:00
Sukchan Lee
fbe3e3685f debug log change to trace 2017-11-02 16:07:40 +09:00
Sukchan Lee
2f43079fc6 update pgw.postinstall
introduce systemctl.sh
2017-11-01 01:11:55 +00:00
Sukchan Lee
0bdbee24cf fix the bug for pgw post install script 2017-10-31 14:42:02 +00:00
Sukchan Lee
081f8c8808 MongoDB re-connect using systemd 2017-10-31 12:29:39 +00:00
Sukchan Lee
a9dd6be8e8 Ubuntu artful update 2017-10-31 05:54:13 +00:00
Sukchan Lee
a25de7b287 fix the PGW installation 2017-10-31 04:44:11 +00:00
Sukchan Lee
46b403c43d all running error is fixed 2017-10-31 09:32:18 +09:00
James Park
b060ea1714 Add sleep so that server is ready to accept connection. 2017-10-30 15:26:30 -07:00
Sukchan Lee
f627565696 Upload Launchpad PPA for Ubuntu 17.10 i386 2017-10-30 13:34:17 +00:00
Sukchan Lee
badc1f2da3 fix compile error 2017-10-30 10:39:05 +00:00
Sukchan Lee
10cda2cfd7 exclude TCP test in testnetlib because sometimes this test is failed as
follows.

 OpenSUSE OBS
 - Ubuntu 17.04 i586 failed

[  542s] testnetlib          :  Line 262: expected <0>, but saw <-1>
[  542s] [10/30 07:48:38.730] ERRR: connect error(111:Connection refused)(proto:6 remote:127.0.0.1 dport:5121 lport:0) (net_lib.c:353)
[  542s] [10/30 07:48:38.730] ERRR: connect error(111:Connection refused)(proto:6 remote:127.0.0.1 dport:5121 lport:0) (net_lib.c:353)
[  542s] [10/30 07:48:38.730] ERRR: connect error(111:Connection refused)(proto:6 remote:127.0.0.1 dport:5121 lport:0) (net_lib.c:353)
[  542s] [10/30 07:48:38.730] ERRR: connect error(111:Connection refused)(proto:6 remote:127.0.0.1 dport:5121 lport:0) (net_lib.c:353)
[  542s] [10/30 07:48:38.730] ASSERT: !(net_sock && buffer). Invalid params
[  542s]  (net_lib.c:590)
[  542s] [10/30 07:48:38.730] ASSERT: !(net_sock). net_sock is NULL
[  542s]  (net_lib.c:408)
[  542s] [10/30 07:48:38.730] ASSERT: !(net_sock). net_sock is NULL
2017-10-30 10:37:33 +00:00
Sukchan Lee
abdcbe7b7a change names of ubuntu package version 2017-10-30 07:10:43 +00:00
Sukchan Lee
377f725f26 update debian changelog
add Ubuntu Zesty(Ubuntu 17.04-amd64, i586)
add Ubuntu Artful(Ubuntu 17.10-amd64)
2017-10-30 05:46:42 +00:00
Sukchan Lee
ff31858a81 update debian changelog 2017-10-30 04:50:11 +00:00
Sukchan Lee
9e27685cd0 disable test code. will be fixed later. 2017-10-30 02:14:33 +00:00
Sukchan Lee
c09483b540 at this point, I'm not sure how to handle this file.
I'll just rollback it.
2017-10-29 13:03:39 +00:00
Sukchan Lee
44f0155f5a add metapackage 2017-10-29 12:54:03 +00:00
Sukchan Lee
a0eb08a2fa PID command line option(-p) is added 2017-10-29 20:48:17 +09:00
Sukchan Lee
8c289c6d6e update logrotate and newsyslog following previous modification 2017-10-29 20:16:18 +09:00
Sukchan Lee
baf6af79d6 LOG configuration is changed.
We'll juse file log as a default log.
Older logger name is changed socket logger and default configuration is
disabled
2017-10-29 10:22:22 +00:00
Sukchan Lee
2d1983cfb0 /var/run bug is fixed
For systemd environment, we define runtime directory like the follwings
MME : /var/run/nextepc-mmed
SGW : /var/run/nextepc-sgwd
PGW : /var/run/nextepc-pgwd
HSS : /var/run/nextepc-hssd
PCRF : /var/run/nextepc-pcrfd

In each directory, PID File is created as follows.
MME : /var/run/nextepc-mmed/pid
SGW : /var/run/nextepc-sgwd/pid
PGW : /var/run/nextepc-pgwd/pid
HSS : /var/run/nextepc-hssd/pid
PCRF : /var/run/nextepc-pcrfd/pid
2017-10-29 10:57:15 +09:00
Sukchan Lee
5c4c4498d2 logging disunite to each individual 2017-10-29 00:44:09 +09:00
Sukchan Lee
f72aa7a468 systemd update 2017-10-28 19:50:50 +09:00
Sukchan Lee
c8ec3702d0 update debian rule for override_dh_auto_test
VM(like OBS) may not support SCTP
At this point, I disabled SCTP-needed test code.
2017-10-28 10:09:44 +00:00
Sukchan Lee
4e33365bf4 debian packaging is initially done.
network script is added
move testscript in debian/rules
2017-10-27 16:15:14 +00:00
Sukchan Lee
fdae399c74 debian packaging (stage 2)
make check re-enabled, but data plane is disabled at this point
user(nextepc/nextec) created
pgwtun interface is created when PGW-preinstall script
2017-10-27 06:01:59 +00:00
Sukchan Lee
e367b00d2c do debian packaging (stage-1) 2017-10-27 03:15:14 +00:00
Sukchan Lee
b08c91190a remove to install systemd, logrotate, newsyslog
I'm not sure where is good things for this system file.
We need to decide when these stuffs are installed in Debian package or `make install`

At this point, I'll remove to install them for other developer.
Later, I'll fix it!
2017-10-26 13:26:10 +09:00
Sukchan Lee
52080092b6 GTP-U is re-enabled in test program.
I'll use src : 45.45.0.2 dst ip : 45.45.0.1 for data plane loopback test
2017-10-25 19:49:28 +09:00
Sukchan Lee
88b5560a2a change test packet to loopback address 2017-10-25 19:33:18 +09:00
Sukchan Lee
6d99061b17 permit even though SGW fails to send gtp end marker 2017-10-25 19:04:35 +09:00
Sukchan Lee
f624adf540 change default configuration using loopback addresses
mme : 127.76.0.1
sgw : 127.76.0.2
pgw : 127.76.0.3
hss : 127.76.0.4
pcrf : 127.76.0.5

If you would like to connect internet, you need to change MME.S1AP_IPV4
and SGW.GTPU_IPV4 with external IP address
2017-10-25 16:30:19 +09:00
Sukchan Lee
67827d5ea4 change assert to d_error for log file permission problem 2017-10-25 14:43:54 +09:00
Sukchan Lee
20800c611b HSS update for supporting OPc 2017-10-25 14:37:12 +09:00
Sukchan Lee
6c8d4328fb fix the bug when profile is changes 2017-10-25 12:45:08 +09:00
Sukchan Lee
588a6ba012 add OPc field to Subscriber and Profile Document 2017-10-25 12:17:52 +09:00
Sukchan Lee
d4dd8bb72d missing files for newsyslog 2017-10-24 22:48:29 +09:00
Sukchan Lee
6d25211f3b add newsyslog for Mac OS X 2017-10-24 22:46:09 +09:00
Sukchan Lee
4ae9673935 Merge branch 'r0.2' of https://github.com/acetcom/nextepc into r0.2
Conflicts:
	test/checkepc.sh
2017-10-24 21:00:10 +09:00
Sukchan Lee
cd36e9a334 update .gitignore 2017-10-24 20:58:22 +09:00
Sukchan Lee
0897c36947 logrotate is now working. 2017-10-24 20:52:58 +09:00
Sukchan Lee
6989a8ae91 to permit 'make install' in user privilege for developer. 2017-10-24 19:40:47 +09:00
Sukchan Lee
df1f35e92b Logrotate is added. But more test is needed 2017-10-24 19:14:09 +09:00
Sukchan Lee
6f5ec19388 PID file is created for logrotate 2017-10-24 15:55:28 +09:00
Sukchan Lee
6eb05495aa change test configuration directory to /tmp 2017-10-24 11:00:58 +09:00
Sukchan Lee
81a8b00d78 Merge branch 'master' into r0.2 2017-10-24 09:54:47 +09:00
Sukchan Lee
382c909ffc Merge pull request #10 from laf0rge/laforge/pending
Allow loopback/link-local/site-local addresses
2017-10-24 09:53:59 +09:00
Sukchan Lee
92ba86f1fd update script for Non-GNU sed 2017-10-24 01:40:01 +09:00
Sukchan Lee
adcc473d6e 'make check` before 'make install'
checkepc.sh script is created.
this script generates necessary configuration file before `make
install`. And then, execute `./testepc -f ./etc/nextepc.conf`
2017-10-24 01:03:25 +09:00
Sukchan Lee
5314bcb687 change @localstatedir@/@sysconfdir@ to the LOCALESTATE_DIR and SYSCONF_DIR in nextepc.conf.in 2017-10-23 15:00:07 +09:00
Sukchan Lee
30e7beb84c Merge branch 'laforge/debian-packaging' of https://github.com/laf0rge/nextepc into debian-packaging 2017-10-23 14:22:07 +09:00
Harald Welte
e8071fa544 freeDiameter: Allow bind to loopback, link-local and site-lcoal addrs
Why would it be illegal to configure/operate freeDiameter to bind to
loopback, link-local or site-local addresses?  Loopback is used a lot
in testing.  link-local and site-local adresses can very well be used
in non-public applications/use cases that don't involve public IPv6
networks.
2017-10-22 18:42:20 +02:00
Sukchan Lee
32b7183483 thread delete location is changed.
See [the issue discussion](https://github.com/sctplab/usrsctp/issues/179)
2017-10-21 07:34:12 +09:00
Sukchan Lee
f6f1720fee update netconfig.sh 2017-10-20 23:51:54 +09:00
Sukchan Lee
6b8cdafbbd Now, we'll use loopback interface for internal socket 2017-10-20 19:15:58 +09:00
Sukchan Lee
074b7b41e8 fix the bug GTP-U testing code 2017-10-20 18:01:47 +09:00
Sukchan Lee
2223dfef0e remove hard-corded code 2017-10-20 17:19:27 +09:00
Sukchan Lee
7b046c75b2 add usrsctp_finish 2017-10-20 16:32:57 +09:00
Sukchan Lee
3bf6326763 create testsctp.c and testusrsctp.c 2017-10-20 16:15:32 +09:00
Sukchan Lee
c2d962d4d1 rollback privous commit 2017-10-20 15:52:30 +09:00
Sukchan Lee
34270825a7 fix the bug usrsctp_finish() 2017-10-20 15:46:06 +09:00
Sukchan Lee
d971a9c9ae testepc is passed in Userland SCTP 2017-10-20 15:14:14 +09:00
Sukchan Lee
d40ba2a67c Oops! re-add net_read() in testcode 2017-10-20 13:47:43 +09:00
Sukchan Lee
7b1949da6c Merge branch 'r0.2' of https://github.com/acetcom/nextepc into r0.2 2017-10-20 13:19:20 +09:00
Sukchan Lee
2a3fe018e8 S1Setup Test is passed in Userland SCTP 2017-10-20 13:18:58 +09:00
Sukchan Lee
36985520f9 send/recv function is tested for only 1 eNB. 2017-10-19 13:42:07 +09:00
Sukchan Lee
cca9f6d521 recv function is tested for Userland SCTP library 2017-10-19 12:50:39 +09:00
Sukchan Lee
da1a50e9d3 Merge branch 'master' into r0.2 2017-10-19 10:15:13 +09:00
Sukchan Lee
c460386d39 Merge pull request #6 from laf0rge/laforge/s1ap-ppid-fix
net_accept(): Inherit PPID from listening socket
2017-10-19 09:50:42 +09:00
Harald Welte
1c64000431 net_accept(): Inherit PPID from listening socket
When we call accept() on a listening socket, we need to inherit
the sctp PPID from the master socket to the new socket of the
just-accepted connection.  Otherwise any sent packets (such as S1AP)
will be sent to PPID=0 rather than the configured PPID (e.g. 18 for
S1AP).
2017-10-18 23:18:53 +02:00
Sukchan Lee
1df4fc9a41 continue to porting Userland SCTP
connection is done.
will implement send/recv function
2017-10-19 01:09:06 +09:00
Harald Welte
ae6f1001f8 Add systemd service files for nextepc daemons 2017-10-18 12:27:53 +02:00
Harald Welte
4bce6df238 Add 'debian' subdirectory for building dpkg packages
Adding this 'debian' subdirectory will allow users to build
binary packages using 'dpkg-buildpackage' and related tools.

Tested so far on Debian unstable and 9 as well as Ubuntu 17.04
and 17.10 on OpenSuSE Build Service.
2017-10-18 12:27:49 +02:00
Sukchan Lee
bb806e492e Finally, I've remove net_sock_t->app_index in core_net.h
Now, we are done to porting SCTP using Userland SCTP
2017-10-18 14:36:12 +09:00
Sukchan Lee
c3ffd52771 mme_enb_t context structure is changed using hash table.
I'll remove net_sock_t->app_index if poosible.
2017-10-18 14:05:22 +09:00
Harald Welte
ec91b9e8da Fix directory mix-up. @prefix@ vs. @sysconfdir@ vs @libdir@ vs @localstatedir@
Installing to @prefix@/etc is wrong, this will end up in /usr/etc
on most linux distributions, where /etc (@sysconfdir@) would be correct.

The same is true for /var (@localstatedir@), we don't want log files
suddenly to be in /usr/var/log rather than /var/log

However, this is further complicated by the fact that @libdir@ is not
recursively resolved but could expand to "${prefix}/lib" which
of course makes no sense inside a config file.  So instead, let's
introduce adl_RECURSIVE_EVAL and define @LIB_DIR@ and @SYSCONF_DIR@
with recursively-expanded versions of those variables.
2017-10-17 23:43:51 +02:00
Harald Welte
cd8f29aa59 Makefile.am: install_data_hook was missing $(DESTDIR)
When creating the /var/log directory, we must create it relative
to the $(DESTDIR) of the installation, and not at it's system-wide
default path without any DESTDIR.
2017-10-17 21:49:29 +02:00
Harald Welte
bb74b173ca Add 'nextepc-' prefix to executables
'mmed' and the like all are a bit of a generic name. Let's prefix the
project name to ensure there will be no clashes with other programs that
also implement a 'MME daemon' or the like.
2017-10-17 21:28:29 +02:00
Sukchan Lee
10b23bb64e fix compile error for usrsctp 2017-10-17 22:18:48 +09:00
Sukchan Lee
ea253016fc autoconf update for supporting Userland SCTP(libusrsctp) 2017-10-17 20:44:05 +09:00
Sukchan Lee
a020b587c1 Merge branch 'master' into r0.2 2017-10-17 16:19:20 +09:00
Sukchan Lee
0eb9ae4792 fix the compile error 2017-10-17 23:04:24 +09:00
Sukchan Lee
f275617225 Merge pull request #1 from laf0rge/master
Add .gitingore file to have clean 'git status' output
2017-10-17 16:16:14 +09:00
Harald Welte
92ecad5118 Add .gitingore file to have clean 'git status' output 2017-10-17 08:12:58 +02:00
Sukchan Lee
d486e84816 improve netconfig
modify GTP packet sending function interface
2017-10-17 13:53:55 +09:00
Sukchan Lee
b287a3b022 fix the bug multiple tun driver 2017-10-17 13:14:10 +09:00
Sukchan Lee
83a21c5840 configuration is changed 2017-10-17 13:04:45 +09:00
Sukchan Lee
b9f4dcf4ea MAC OSX is needed to enable IP fowwarding 2017-10-17 07:44:48 +09:00
Sukchan Lee
a20c96bc21 fix the Makefile errata 2017-10-17 01:25:28 +09:00
Sukchan Lee
291a5ce514 merge MacOSX and FreeBSD code related tun ip config 2017-10-17 01:03:34 +09:00
Sukchan Lee
cdbc8d1ab0 MAC OSX ping loopback test done 2017-10-17 00:56:00 +09:00
Sukchan Lee
689c3b95e7 routing table is automatically added in FreeBSD 2017-10-17 08:24:30 +09:00
Sukchan Lee
b8a37b0ea1 net_tun library is updated for supporting FreeBSD and MacOSX
In FreeBSD and MacOSX, tun driver is automatically configured.
2017-10-17 07:03:37 +09:00
Sukchan Lee
86908cdbe9 ping src:45.45.0.2 dst:45.45.0.1 is only enabled in Linux platform
Linux Kernel reply the icmp message.
FreeBSD/MacOSX is not working.
More study is needed about TUN
2017-10-15 20:43:05 +09:00
Sukchan Lee
0f08c2a624 Ping loopback is added in Linux platform 2017-10-15 20:33:51 +09:00
Sukchan Lee
47bad3794e PGW IP assign rule is updated 2017-10-15 20:33:20 +09:00
Sukchan Lee
fb566fd94c fix the compile error for high GCC version 2017-10-15 01:18:45 +09:00
Sukchan Lee
3bbbd1b5b1 fix the bug for One SGW IP assign 2017-10-15 01:07:27 +09:00
Sukchan Lee
172266b0c5 GTP Loopback Test Module is Added.
1. ping(src:45.45.0.1, dst:45.45.0.1)
2. MME emulates GTP-U instead of eNB, and send GTP-U to the SGW
3. SGW relay to PGW using GTP-U
4. PGW TUN reponse ping reply
5. PGW sends GTP-U to the SGW
6. SGW sends GTP-U to the MME
7. GTP-U decapsulates and sends ping packet to the kernel
2017-10-15 00:45:49 +09:00
Sukchan Lee
1f14b132c2 Merge branch 'r0.2' of https://github.com/acetcom/nextepc into r0.2 2017-10-13 21:51:50 +09:00
Sukchan Lee
3613b27ca7 MME/PGW Configuration is also changed to support One SGW IP assign
Control Plane Test Done.
Data Plan Test is Needed.
2017-10-13 21:31:49 +09:00
Sukchan Lee
4672ee559f One IP assign for SGW
Configuration is changed
Remove S11_XXXX, S1U_XXXX, S5C_XXXX, S5U_XXXX

Introduce GTPC_IPV4, GTPU_IPV4
2017-10-13 21:13:39 +09:00
Sukchan Lee
02773eff40 FreeBSD Porting done. 2017-10-13 18:12:15 +09:00
Sukchan Lee
5d6e63c20e Reduce SGW IP assign to One.
Initially, I've started to update Control Plane related to this issue.
Context Accessing is re-arraged based Thread for finding GTP Node Context.

[MME]
mme_sgw_t : SM thread(Control-Plane)

[SGW]
sgw_mme_t : Net thread(Data-Plane)
sgw_pgw_t : SM thread(Control-Plane)

[PGW]
pgw_sgw_t : Net thread(Data-Plane)
2017-10-13 14:41:55 +09:00
Sukchan Lee
ee4dd7732e Porting to FreeBSD (Stage-1)
I'd just fix the compile error at this point.
2017-10-12 23:01:51 +09:00
Sukchan Lee
8d343221d2 update VERSION to 0.2.0 2017-10-11 15:50:00 +09:00
Sukchan Lee
7c20ac5c64 update VERSION to 0.1.1 2017-10-11 15:46:45 +09:00
Sukchan Lee
dac66d0b80 BUILT_SOURCE is missing.
fdd.tab.h is a file generated from lex & yacc. If we do not tell it to
automake, the dependency issue occurs in `make -j 8`.
2017-10-11 06:25:21 +00:00
Sukchan Lee
4245502ae2 Fix the bug under mongo c driver v1.5
I misunderstand the interface when querying with projection
when the version of Mongo C Driver is lower than 1.5.

For reference, in case of Ubuntu 16.04, Mongo C Driver v1.3.1
will be installed, so when using 'Dedicated Bearer', v0.1.1
should be used because it does not work normally.
2017-10-11 06:08:19 +00:00
129 changed files with 10246 additions and 2353 deletions

59
.gitignore vendored Normal file
View File

@@ -0,0 +1,59 @@
# compiler output
*.o
*.lo
*.a
*.la
*.conf
.deps
.libs
# generated files
lib/freeDiameter-*/libfdcore/fdd.tab.[chy]
lib/freeDiameter-*/libfdcore/lex.fdd.[cl]
lib/freeDiameter-*/include/freeDiameter/version.h
lib/freeDiameter-*/include/freeDiameter/config.h.in
lib/freeDiameter-*/include/freeDiameter/freeDiameter-host.h
lib/core/include/core.h
support/systemd/nextepc-*.service
support/logrotate/nextepc
# autotools
stamp-h1
config.h
config.in
config.nice
config.log
configure
aclocal.m4
config.status
libtool
autom4te.cache
build-aux
Makefile
Makefile.in
m4
# executables
lib/core/test/testcore
test/testepc
nextepc-mmed
nextepc-pcrfd
nextepc-pgwd
nextepc-sgwd
nextepc-epcd
nextepc-hssd
# debian
debian/*.debhelper.log
debian/*.debhelper
debian/*.substvars
debian/tmp
debian/files
debian/autoreconf.before
debian/autoreconf.after
debian/nextepc-core
debian/nextepc-mme
debian/nextepc-sgw
debian/nextepc-pgw
debian/nextepc-pcrf
debian/nextepc-hss

View File

@@ -2,62 +2,48 @@
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = lib src test
SUBDIRS = lib src support test
bin_PROGRAMS = mmed hssd sgwd pgwd pcrfd epcd
bin_PROGRAMS = nextepc-mmed nextepc-hssd nextepc-sgwd nextepc-pgwd nextepc-pcrfd nextepc-epcd
dist_mmed_SOURCES = main.c
mmed_LDADD = $(top_srcdir)/src/libmme.la
mmed_LDFLAGS = -export-dynamic
dist_nextepc_mmed_SOURCES = main.c
nextepc_mmed_LDADD = $(top_srcdir)/src/libmme.la
nextepc_mmed_LDFLAGS = -export-dynamic
dist_hssd_SOURCES = main.c
hssd_LDADD = $(top_srcdir)/src/libhss.la
hssd_LDFLAGS = -export-dynamic
dist_nextepc_hssd_SOURCES = main.c
nextepc_hssd_LDADD = $(top_srcdir)/src/libhss.la
nextepc_hssd_LDFLAGS = -export-dynamic
dist_sgwd_SOURCES = main.c
sgwd_LDADD = $(top_srcdir)/src/libsgw.la
sgwd_LDFLAGS = -export-dynamic
dist_nextepc_sgwd_SOURCES = main.c
nextepc_sgwd_LDADD = $(top_srcdir)/src/libsgw.la
nextepc_sgwd_LDFLAGS = -export-dynamic
dist_pgwd_SOURCES = main.c
pgwd_LDADD = $(top_srcdir)/src/libpgw.la
pgwd_LDFLAGS = -export-dynamic
dist_nextepc_pgwd_SOURCES = main.c
nextepc_pgwd_LDADD = $(top_srcdir)/src/libpgw.la
nextepc_pgwd_LDFLAGS = -export-dynamic
dist_pcrfd_SOURCES = main.c
pcrfd_LDADD = $(top_srcdir)/src/libpcrf.la
pcrfd_LDFLAGS = -export-dynamic
dist_nextepc_pcrfd_SOURCES = main.c
nextepc_pcrfd_LDADD = $(top_srcdir)/src/libpcrf.la
nextepc_pcrfd_LDFLAGS = -export-dynamic
dist_epcd_SOURCES = main.c
epcd_LDADD = $(top_srcdir)/src/libepc.la
epcd_LDFLAGS = -export-dynamic
dist_nextepc_epcd_SOURCES = main.c
nextepc_epcd_LDADD = $(top_srcdir)/src/libepc.la
nextepc_epcd_LDFLAGS = -export-dynamic
AM_CPPFLAGS = \
-I$(top_srcdir)/lib/core/include \
-I$(top_srcdir)/src
sysconf_DATA = \
support/nextepc.conf
freeDiameterdir = ${prefix}/etc/freeDiameter
freeDiameter_DATA = \
support/freeDiameter/mme.conf \
support/freeDiameter/hss.conf \
support/freeDiameter/pgw.conf \
support/freeDiameter/pcrf.conf
dist_freeDiameter_DATA = \
support/freeDiameter/cacert.pem \
support/freeDiameter/mme.key.pem \
support/freeDiameter/mme.cert.pem \
support/freeDiameter/hss.key.pem \
support/freeDiameter/hss.cert.pem \
support/freeDiameter/pgw.key.pem \
support/freeDiameter/pgw.cert.pem \
support/freeDiameter/pcrf.key.pem \
support/freeDiameter/pcrf.cert.pem
install-data-hook:
$(MKDIR_P) $(prefix)/var/log
$(MKDIR_P) $(DESTDIR)/$(localstatedir)/log/nextepc
$(MKDIR_P) $(DESTDIR)/$(localstatedir)/run/nextepc-mmed
$(MKDIR_P) $(DESTDIR)/$(localstatedir)/run/nextepc-sgwd
$(MKDIR_P) $(DESTDIR)/$(localstatedir)/run/nextepc-pgwd
$(MKDIR_P) $(DESTDIR)/$(localstatedir)/run/nextepc-pcrfd
$(MKDIR_P) $(DESTDIR)/$(localstatedir)/run/nextepc-hssd
$(MKDIR_P) $(DESTDIR)/$(localstatedir)/run/nextepc-epcd
CLEANFILES = symtbl.c
CLEANFILES = -R data debian/test
DISTCLEANFILES = $(DIST_ARCHIVES)
MAINTAINERCLEANFILES = \
configure config.in \
@@ -66,6 +52,5 @@ MAINTAINERCLEANFILES = \
build-aux/ar-lib build-aux/config.guess build-aux/depcomp \
build-aux/ltmain.sh build-aux/test-driver build-aux/compile \
build-aux/config.sub build-aux/missing build-aux/install-sh \
.cscope.out .cscope.out.in .cscope.files .cscope.out.po \
Makefile.in
MOSTLYCLEANFILES = core *.stackdump

View File

@@ -88,3 +88,21 @@ AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes],
[m4_default([$3], :)])
AS_VAR_POPDEF([CACHEVAR])dnl
])dnl AX_CHECK_COMPILE_FLAGS
# adl_RECURSIVE_EVAL(VALUE, RESULT)
# =================================
# Interpolate the VALUE in loop until it doesn't change,
# and set the result to $RESULT.
# WARNING: It's easy to get an infinite loop with some unsane input.
# For example ${datadir} becomes ${datarootdir}, and then ${prefix}/share, and
# finally ${prefix} is replaced by the prefix.
AC_DEFUN([adl_RECURSIVE_EVAL],
[_lcl_receval="$1"
$2=`(test "x$prefix" = xNONE && prefix="$ac_default_prefix"
test "x$exec_prefix" = xNONE && exec_prefix="${prefix}"
_lcl_receval_old=''
while test "[$]_lcl_receval_old" != "[$]_lcl_receval"; do
_lcl_receval_old="[$]_lcl_receval"
eval _lcl_receval="\"[$]_lcl_receval\""
done
echo "[$]_lcl_receval")`])

View File

@@ -8,7 +8,7 @@ dnl This program is distributed in the hope that it will be useful, but
dnl WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
AC_INIT([NEXTEPC], [0.1.0], [acetcom@gmail.com])
AC_INIT([NEXTEPC], [0.2.0], [acetcom@gmail.com])
CORE_CONFIG_NICE(config.nice)
@@ -16,9 +16,6 @@ dnl Must come before AM_INIT_AUTOMAKE.
AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE([1.10 -Wall -Werror foreign])
# Minimum Autoconf version required.
AC_PREREQ(2.63)
# Where to generate output; srcdir location.
AC_CONFIG_HEADERS([config.h:config.in])dnl Keep filename to 8.3 for MS-DOS.
AC_CONFIG_SRCDIR([main.c])
@@ -32,7 +29,7 @@ case $host in
;;
*-apple-darwin*)
OSDIR="unix"
OSPPCFLAGS="-DDARWIN -DSIGPROCMASK_SETS_THREAD_MASK"
OSCPPFLAGS="-DDARWIN -DSIGPROCMASK_SETS_THREAD_MASK"
;;
*)
OSDIR="unix"
@@ -63,19 +60,23 @@ AH_VERBATIM([_REENTRANT],
#endif
])
dnl Checks CC and freinds
AC_PROG_CC
AC_PROG_CPP
AC_PROG_INSTALL
AC_PROG_AWK
AC_PROG_SED
#AC_PROG_YACC
#AC_PROG_LEX
AM_PROG_AR
dnl kernel style compile messages
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
dnl libtool
dnl Checks CC and freinds
AC_PROG_MAKE_SET
AC_PROG_MKDIR_P
AC_PROG_CC
AC_PROG_INSTALL
AM_PROG_AR
LT_INIT
AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
if test "x$PKG_CONFIG" = "xno"; then
AC_MSG_ERROR([You need to install pkg-config])
fi
PKG_PROG_PKG_CONFIG([0.20])
dnl Checks for compile flag
AX_CHECK_COMPILE_FLAG([-Wno-unused-result], [CFLAGS="$CFLAGS -Wno-unused-result"])
@@ -153,6 +154,32 @@ AC_SUBST(uint64_t_hex_fmt)
AC_SUBST(int64_literal)
AC_SUBST(uint64_literal)
AC_CHECK_SIZEOF(pid_t, 8)
if test "$ac_cv_sizeof_pid_t" = "$ac_cv_sizeof_short"; then
pid_t_fmt='#define C_PID_T_FMT "hd"'
elif test "$ac_cv_sizeof_pid_t" = "$ac_cv_sizeof_int"; then
pid_t_fmt='#define C_PID_T_FMT "d"'
elif test "$ac_cv_sizeof_pid_t" = "$ac_cv_sizeof_long"; then
pid_t_fmt='#define C_PID_T_FMT "ld"'
elif test "$ac_cv_sizeof_pid_t" = "$ac_cv_sizeof_long_long"; then
pid_t_fmt='#define C_PID_T_FMT APR_INT64_T_FMT'
else
pid_t_fmt='#error Can not determine the proper size for pid_t'
fi
case $host in
*-solaris*)
if test "$ac_cv_sizeof_long" = "8"; then
pid_t_fmt='#define C_PID_T_FMT "d"'
else
pid_t_fmt='#define C_PID_T_FMT "ld"'
fi
;;
esac
AC_SUBST(pid_t_fmt)
AC_DEFINE_UNQUOTED([PACKAGE_VERSION_MAJOR],
[`echo $PACKAGE_VERSION | $SED 's/^\([[^\.]]\+\)\.\([[^\.]]\+\)\.\([[^\.]]\+\).*/\1/'`],
[Major version of this package])
@@ -163,6 +190,19 @@ AC_DEFINE_UNQUOTED([PACKAGE_VERSION_PATCHLEVEL],
[`echo $PACKAGE_VERSION | $SED 's/^\([[^\.]]\+\)\.\([[^\.]]\+\)\.\([[^\.]]\+\).*/\3/'`],
[Patch version of this package])
##################################
#### Checks for Directories. #####
##################################
adl_RECURSIVE_EVAL(["${bindir}"], [BIN_DIR])
adl_RECURSIVE_EVAL(["${libdir}"], [LIB_DIR])
adl_RECURSIVE_EVAL(["${sysconfdir}"], [SYSCONF_DIR])
adl_RECURSIVE_EVAL(["${localstatedir}"], [LOCALSTATE_DIR])
AC_SUBST(BIN_DIR)
AC_SUBST(LIB_DIR)
AC_SUBST(SYSCONF_DIR)
AC_SUBST(LOCALSTATE_DIR)
##################################
#### Checks for header files. ####
##################################
@@ -192,10 +232,11 @@ AC_CHECK_HEADERS( \
net/if.h \
netinet/ether.h \
netinet/in.h \
netinet/ip.h \
netinet/in_systm.h \
netinet/udp.h \
netinet/tcp.h \
netinet/sctp.h \
usrsctp.h \
sys/ioctl.h \
sys/param.h \
sys/socket.h \
@@ -207,6 +248,19 @@ AC_CHECK_HEADERS( \
sys/uio.h \
)
AC_CHECK_HEADERS(netinet/ip.h net/route.h,,,[[
#include <sys/types.h>
#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/in.h>
#if HAVE_NETINET_IN_SYSTM_H
#include <netinet/in_systm.h>
#endif
]])
AC_CHECK_HEADERS(netinet/ip_icmp.h, [], [], [#include <netinet/ip.h>])
##########################################
#### Checks for typedefs, structures, ####
#### and compiler characteristics. ####
@@ -218,6 +272,41 @@ AC_CHECK_MEMBERS([struct tm.tm_gmtoff, struct tm.__tm_gmtoff],,,[
#include <sys/types.h>
#include <time.h>])
AC_CHECK_MEMBER(struct sockaddr.sa_len,
AC_DEFINE(HAVE_SA_LEN, 1, [Define this if your stack has sa_len in sockaddr struct.]),,
[#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <sys/socket.h>])
AC_CHECK_MEMBER(struct sockaddr_in.sin_len,
AC_DEFINE(HAVE_SIN_LEN, 1, [Define this if your IPv4 has sin_len in sockaddr_in struct.]),,
[#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <netinet/in.h>])
AC_CHECK_MEMBER(struct sockaddr_in6.sin6_len,
AC_DEFINE(HAVE_SIN6_LEN, 1, [Define this if your IPv6 has sin6_len in sockaddr_in6 struct.]),,
[#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <netinet/in.h>])
AC_CHECK_MEMBER(struct sockaddr_conn.sconn_len,
AC_DEFINE(HAVE_SCONN_LEN, 1, [Define this if your userland stack has sconn_len in sockaddr_conn struct.]),,
[#include "usrsctplib/usrsctp.h"])
AC_MSG_CHECKING(for socklen_t)
AC_TRY_COMPILE([#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <sys/socket.h>],
[socklen_t x; x = 1; return ((int)x);],
[AC_MSG_RESULT(yes)],
[AC_MSG_RESULT(int)
AC_DEFINE(socklen_t, int, [Define a type for socklen_t.])])
AC_CHECK_FILE(/dev/random,
AC_DEFINE([HAVE_DEV_RANDOM], [1],
[Define to 1 if you have the /dev/random file.]))
@@ -292,19 +381,43 @@ AC_CHECK_FUNCS(\
sched_yield \
)
AC_CHECK_FUNCS(socket, , AC_CHECK_LIB(socket, socket))
AC_CHECK_FUNCS(inet_addr, , AC_CHECK_LIB(nsl, inet_addr))
AC_CHECK_LIB([pthread], [pthread_mutex_init], [LIBS="${LIBS} -lpthread"])
AC_CHECK_LIB([dl], [dlopen], [LIBS="${LIBS} -ldl"])
AC_CHECK_LIB([sctp], [sctp_sendmsg], [LIBS="${LIBS} -lsctp"])
AC_CHECK_LIB([gnutls], [gnutls_global_init], [LIBS="${LIBS} -lgnutls"])
AC_CHECK_LIB([gcrypt], [gcry_control], [LIBS="${LIBS} -lgcrypt"])
AC_CHECK_LIB([idn], [idna_strerror], [LIBS="${LIBS} -lidn"])
#AC_CHECK_LIB([fdcore], [fd_core_initialize], [LIBS="${LIBS} -lfdcore"])
#AC_CHECK_LIB([fdproto], [fd_libproto_init], [LIBS="${LIBS} -lfdproto"])
AC_CHECK_LIB([sctp], [sctp_sendmsg], [have_sctp_lib=yes], [have_sctp_lib=no])
if test "$have_sctp_lib" == "yes"; then
LIBS="${LIBS} -lsctp"
else
AC_CHECK_LIB([usrsctp], [usrsctp_init], [have_usrsctp_lib=yes], [have_usrsctp_lib=no])
if test "$have_usrsctp_lib" == "yes"; then
LIBS="${LIBS} -lusrsctp"
AC_DEFINE([USE_USRSCTP], [1], [Define to 1 if you have the usrsctp library.])
fi
fi
AM_CONDITIONAL([USRSCTP], [test x$have_usrsctp_lib = xyes])
AC_CHECK_LIB([gnutls], [gnutls_global_init], [have_gnutls_lib=yes], [have_gnutls_lib=no])
if test "$have_gnutls_lib" == "yes"; then
LIBS="${LIBS} -lgnutls"
else
AC_MSG_ERROR([You must install the GnuTLS libraries and development headers to enable GnuTLS support.])
fi
AC_CHECK_LIB([gcrypt], [gcry_control], [have_gcrypt_lib=yes], [have_gcrypt_lib=no])
if test "$have_gcrypt_lib" == "yes"; then
LIBS="${LIBS} -lgcrypt"
else
AC_MSG_ERROR([You must install the Libgcrypt libraries and development headers to enable Libgcrypt support.])
fi
AC_CHECK_LIB([idn], [idna_strerror], [have_idn_lib=yes], [have_idn_lib=no])
if test "$have_idn_lib" == "yes"; then
LIBS="${LIBS} -lidn"
else
AC_MSG_ERROR([You must install the GNU Libidn libraries and development headers to enable GNU Libidn support.])
fi
PKG_CHECK_MODULES([MONGOC], libmongoc-1.0 >= 1.3.1)
LIBS="$LIBS $MONGOC_LIBS"
#PKG_CHECK_MODULES([LIBXML2], libxml-2.0 >= 2.9.1)
#LIBS="$LIBS $LIBXML2_LIBS"
FREEDIAMETER_DIR=freeDiameter-1.2.1
AC_SUBST(FREEDIAMETER_DIR)
@@ -316,20 +429,14 @@ AC_CONFIG_SUBDIRS([lib/freeDiameter-1.2.1])
AC_CONFIG_FILES([lib/core/include/core.h])
AC_CONFIG_FILES([lib/core/src/Makefile])
case $host in
*)
AC_CONFIG_FILES([lib/core/src/unix/Makefile])
;;
esac
AC_CONFIG_FILES([lib/core/src/unix/Makefile])
AC_CONFIG_FILES([lib/core/test/Makefile])
AC_CONFIG_FILES([lib/core/Makefile])
AC_CONFIG_FILES([lib/logger/Makefile])
AC_CONFIG_FILES([lib/base/Makefile])
AC_CONFIG_FILES([lib/s1ap/asn1c/Makefile])
AC_CONFIG_FILES([lib/s1ap/Makefile])
AC_CONFIG_FILES([lib/nas/Makefile])
AC_CONFIG_FILES([lib/fd/extensions/dbg_msg_dumps/Makefile])
#AC_CONFIG_FILES([lib/fd/extensions/dict_legacy_xml/Makefile])
AC_CONFIG_FILES([lib/fd/extensions/dict_rfc5777/Makefile])
AC_CONFIG_FILES([lib/fd/extensions/dict_mip6i/Makefile])
AC_CONFIG_FILES([lib/fd/extensions/dict_nasreq/Makefile])
@@ -350,13 +457,30 @@ AC_CONFIG_FILES([src/sgw/Makefile])
AC_CONFIG_FILES([src/pgw/Makefile])
AC_CONFIG_FILES([src/pcrf/Makefile])
AC_CONFIG_FILES([src/Makefile])
AC_CONFIG_FILES([test/Makefile])
AC_CONFIG_FILES([support/nextepc.conf])
AC_CONFIG_FILES([support/config/nextepc.conf])
AC_CONFIG_FILES([support/config/mme.conf])
AC_CONFIG_FILES([support/config/sgw.conf])
AC_CONFIG_FILES([support/config/pgw.conf])
AC_CONFIG_FILES([support/config/hss.conf])
AC_CONFIG_FILES([support/config/pcrf.conf])
AC_CONFIG_FILES([support/config/Makefile])
AC_CONFIG_FILES([support/freeDiameter/mme.conf])
AC_CONFIG_FILES([support/freeDiameter/hss.conf])
AC_CONFIG_FILES([support/freeDiameter/pgw.conf])
AC_CONFIG_FILES([support/freeDiameter/hss.conf])
AC_CONFIG_FILES([support/freeDiameter/pcrf.conf])
#AC_CONFIG_FILES([support/freeDiameter/dict_legacy_xml.conf])
AC_CONFIG_FILES([support/freeDiameter/Makefile])
AC_CONFIG_FILES([support/systemd/nextepc-mmed.service])
AC_CONFIG_FILES([support/systemd/nextepc-sgwd.service])
AC_CONFIG_FILES([support/systemd/nextepc-pgwd.service])
AC_CONFIG_FILES([support/systemd/nextepc-hssd.service])
AC_CONFIG_FILES([support/systemd/nextepc-pcrfd.service])
AC_CONFIG_FILES([support/systemd/Makefile])
AC_CONFIG_FILES([support/logrotate/nextepc])
AC_CONFIG_FILES([support/logrotate/Makefile])
AC_CONFIG_FILES([support/newsyslog/nextepc.conf])
AC_CONFIG_FILES([support/newsyslog/Makefile])
AC_CONFIG_FILES([support/Makefile])
AC_CONFIG_FILES([test/Makefile])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
@@ -369,6 +493,8 @@ source code location : ${srcdir}
compiler : ${CC}
compiler flags : ${CFLAGS}
linker flags : ${LDFLAGS} ${LIBS}
config file directory : `eval echo \`echo ${sysconfdir}\``
log file directory : `eval echo \`echo ${prefix}/var/log\``
bin directory : ${BIN_DIR}
lib directory : ${LIB_DIR}/nextepc
config directory : ${SYSCONF_DIR}/nextepc
log directory : ${LOCALSTATE_DIR}/log/nextepc
"

109
debian/changelog vendored Normal file
View File

@@ -0,0 +1,109 @@
nextepc (0.2-5~artful) artful; urgency=medium
* Relase 0.2
-- Sukchan Lee <acetcom@gmail.com> Thu, 02 Nov 2017 07:13:23 +0000
nextepc (0.2-5~zesty) zesty; urgency=medium
* Relase 0.2
-- Sukchan Lee <acetcom@gmail.com> Thu, 02 Nov 2017 07:12:17 +0000
nextepc (0.2-5~xenial) xenial; urgency=medium
* Release 0.2
-- Sukchan Lee <acetcom@gmail.com> Thu, 02 Nov 2017 07:11:16 +0000
nextepc (0.2-4~xenial2) xenial; urgency=medium
* Fix the bug nextepc-pgwd post install script
-- Sukchan Lee <acetcom@gmail.com> Tue, 31 Oct 2017 14:07:54 +0000
nextepc (0.2-4~artful) artful; urgency=medium
* Fix the bug nextepc-pgwd post install script
-- Sukchan Lee <acetcom@gmail.com> Tue, 31 Oct 2017 14:06:31 +0000
nextepc (0.2-4~zesty) zesty; urgency=medium
* Fix the bug nextepc-pgwd post install script
-- Sukchan Lee <acetcom@gmail.com> Tue, 31 Oct 2017 14:04:23 +0000
nextepc (0.2-4~xenial) xenial; urgency=medium
* Fix the bug nextepc-pgwd post install script
-- Sukchan Lee <acetcom@gmail.com> Tue, 31 Oct 2017 14:01:58 +0000
nextepc (0.2-3~artful) artful; urgency=medium
* MongoDB re-connect using systemd
-- Sukchan Lee <acetcom@gmail.com> Tue, 31 Oct 2017 12:10:18 +0000
nextepc (0.2-3~zesty) zesty; urgency=medium
* MongoDB re-connect using systemd
-- Sukchan Lee <acetcom@gmail.com> Tue, 31 Oct 2017 12:07:36 +0000
nextepc (0.2-3~xenial) xenial; urgency=medium
* MongoDB re-connect using systemd
-- Sukchan Lee <acetcom@gmail.com> Tue, 31 Oct 2017 12:00:16 +0000
nextepc (0.2-2~artful) artful; urgency=medium
* Fix PGW installation
-- Sukchan Lee <acetcom@gmail.com> Tue, 31 Oct 2017 05:02:03 +0000
nextepc (0.2-2~xenial) xenial; urgency=medium
* Fix PGW installation
-- Sukchan Lee <acetcom@gmail.com> Tue, 31 Oct 2017 03:16:02 +0000
nextepc (0.2-1~artful2) artful; urgency=medium
* Fix the compile error [-Werror=pointer]
-- Sukchan Lee <acetcom@gmail.com> Mon, 30 Oct 2017 13:14:42 +0000
nextepc (0.2-1~artful1) artful; urgency=medium
* Remove mongodb build-dependancy for Ubuntu 17.10(i386)
-- Sukchan Lee <acetcom@gmail.com> Mon, 30 Oct 2017 12:46:58 +0000
nextepc (0.2-1~artful) artful; urgency=medium
* Ubuntu 17.10(amd64)
* Currently, `mongodb` is not available in Ubuntu 17.10(i386)
-- Sukchan Lee <acetcom@gmail.com> Mon, 30 Oct 2017 06:50:47 +0000
nextepc (0.2-1~zesty) zesty; urgency=medium
* Ubuntu 17.04
-- Sukchan Lee <acetcom@gmail.com> Mon, 30 Oct 2017 06:47:55 +0000
nextepc (0.2-1~xenial) xenial; urgency=medium
* Add matapackage
* dh_overide_auto_test is re-enabled
-- Sukchan Lee <acetcom@gmail.com> Mon, 30 Oct 2017 03:48:39 +0000
nextepc (0.1.1) UNRELEASED; urgency=medium
* Initial release.
-- Harald Welte <laforge@gnumonks.org> Tue, 17 Oct 2017 08:19:54 +0200

1
debian/compat vendored Normal file
View File

@@ -0,0 +1 @@
9

132
debian/control vendored Normal file
View File

@@ -0,0 +1,132 @@
Source: nextepc
Maintainer: Harald Welte <laforge@gnumonks.org>
Section: net
Priority: optional
Build-Depends: debhelper (>= 9),
autotools-dev,
pkg-config,
git,
dh-autoreconf,
dh-systemd,
flex,
bison,
libsctp-dev,
libgnutls28-dev,
libgcrypt-dev,
libssl-dev,
libmongoc-dev,
libbson-dev
Standards-Version: 3.9.6
Vcs-Browser: https://github.com/acetcom/nextepc
Vcs-Git: git://github.com/acetcom/nextepc
Homepage: http://nextepc.org/
Package: nextepc-core
Architecture: any
Multi-Arch: same
Depends: ${shlibs:Depends},
${misc:Depends}
Description: Open Source based 3GPP EPC (Shared Files)
NextEPC is a C-language Open Source implementation of the 3GPP Evolved
Packet Core, i.e. the core network of an LTE network.
.
This package contains some core libraries/plugins required by the other
binary packages such as nextepc-{mme,sgw,pgw,pcrf,hss}.
Package: nextepc-mme
Architecture: any
Multi-Arch: same
Depends: ${shlibs:Depends},
${misc:Depends},
nextepc-core (= ${binary:Version})
Description: Open Source based 3GPP EPC MME (Mobility Management Entity)
NextEPC is a C-language Open Source implementation of the 3GPP Evolved
Packet Core, i.e. the core network of an LTE network.
.
This package provides the MME (Mobility Management Engine), which
terminates the S1 interfaces from the eNodeBs cells in the cellular
network, and interfaces via S11 to the SGW as well as via S6a to the
HSS.
Package: nextepc-sgw
Architecture: any
Multi-Arch: same
Depends: ${shlibs:Depends},
${misc:Depends},
nextepc-core (= ${binary:Version})
Description: Open Source based 3GPP EPC SGW (Serving Gateway)
NextEPC is a C-language Open Source implementation of the 3GPP Evolved
Packet Core, i.e. the core network of an LTE network.
.
This package provides the SGW (Serving Gateway) which is situated
between the MME and PGW. It implements the S11 interface to the MME,
and the S5 interface to the PGW.
Package: nextepc-pgw
Architecture: any
Multi-Arch: same
Depends: ${shlibs:Depends},
${misc:Depends},
nextepc-core (= ${binary:Version}),
ifupdown
Description: Open Source based 3GPP EPC PGW (Packet Data Network Gateway)
NextEPC is a C-language Open Source implementation of the 3GPP Evolved
Packet Core, i.e. the core network of an LTE network.
.
This package provides the PGW or PDN-GW (Packet Data Network Gateway)
element f the EPC, i.e. the gateway between the EPC and the external
packet data network, such as the public Internet. It implements the S5
interface towards the S-GW, the SGi interface towards the Internet,
and the S7 interface towards the PCRF.
Package: nextepc-pcrf
Architecture: any
Multi-Arch: same
Depends: ${shlibs:Depends},
${misc:Depends},
mongodb,
nextepc-core (= ${binary:Version})
Description: Open Source based 3GPP EPC PCRF (Policy and Charging Rules Function)
NextEPC is a C-language Open Source implementation of the 3GPP Evolved
Packet Core, i.e. the core network of an LTE network.
.
This package contains the PCRF (Policy and Charging Rules Function),
which controls the service quality (QoS) of individual connections and
how to account/charge related traffic. It implements the Gx interface
towards the PGW using the DIAMETER protocol.
Package: nextepc-hss
Architecture: any
Multi-Arch: same
Depends: ${shlibs:Depends},
${misc:Depends},
mongodb,
nextepc-core (= ${binary:Version})
Description: Open Source based 3GPP EPC HSS (Home Subscriber Server)
NextEPC is a C-language Open Source implementation of the 3GPP Evolved
Packet Core, i.e. the core network of an LTE network.
.
This package provides the HSS (Home Subscriber Server) element of the
EPC, i.e. the central database of mobile network subscribers, with
their IMSI, MSISDN, cryptographic key materials, service subscription
information, etc. It implements the S6a interface towards the MME
using the DIAMETER protocol.
Package: nextepc
Architecture: any
Multi-Arch: same
Depends: ${shlibs:Depends},
${misc:Depends},
mongodb,
nextepc-core (= ${binary:Version}),
nextepc-mme (= ${binary:Version}),
nextepc-sgw (= ${binary:Version}),
nextepc-pgw (= ${binary:Version}),
nextepc-hss (= ${binary:Version}),
nextepc-pcrf (= ${binary:Version})
Description: Open Source based 3GPP EPC (metapackage)
NextEPC is a C-language Open Source implementation of the 3GPP Evolved
Packet Core, i.e. the core network of an LTE network.
.
This is a metapackage that depends on all the nextepc parts.
(MME, SGW, PGW, HSS, PCRF)

55
debian/copyright vendored Normal file
View File

@@ -0,0 +1,55 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: nextepc
Source: https://github.com/acetcom/nextepc
Files: *
Copyright: 2017 NextEPC Group
License: GPL-3
Files: lib/freeDiameter-1.2.1/*
Copyright: 2008-2011, WIDE Project and NICT
License: BSD-3-clause
Files: debian/*
Copyright: 2017 Harald Welte <laforge@gnumonks.org>
License: GPL-3
License: GPL-3
This package is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; version 3 of the License
.
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 <http://www.gnu.org/licenses/>.
.
On Debian systems, the complete text of the GNU General Public
License version 3 can be found in "/usr/share/common-licenses/GPL-3".
License: BSD-3-clause
Software License Agreement (BSD License)
.
Copyright (c) 2008-2011, WIDE Project and NICT
All rights reserved.
.
Redistribution and use of this software in source and binary forms, with or without modification, are·
permitted provided that the following conditions are met:
.
* Redistributions of source code must retain the above·
copyright notice, this list of conditions and the·
following disclaimer.
···
* Redistributions in binary form must reproduce the above·
copyright notice, this list of conditions and the·
following disclaimer in the documentation and/or other
materials provided with the distribution.
.
* Neither the name of the WIDE Project or NICT nor the·
names of its contributors may be used to endorse or·
promote products derived from this software without·
specific prior written permission of WIDE Project and·
NICT.

5
debian/nextepc-core.install vendored Normal file
View File

@@ -0,0 +1,5 @@
usr/lib/*/nextepc/*
var/log/nextepc
etc/nextepc/nextepc.conf
etc/nextepc/freeDiameter/cacert.pem
support/logrotate/nextepc /etc/logrotate.d

52
debian/nextepc-core.postinst vendored Normal file
View File

@@ -0,0 +1,52 @@
#!/bin/sh
# postinst script for nextepc
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <postinst> `configure' <most-recently-configured-version>
# * <old-postinst> `abort-upgrade' <new version>
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
# <new-version>
# * <postinst> `abort-remove'
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
# <failed-install-package> <version> `removing'
# <conflicting-package> <version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
configure)
# create a nextepc group and user
if ! getent passwd nextepc >/dev/null; then
adduser --system --disabled-password --disabled-login \
--home /var/run/nextepc --no-create-home \
--quiet --group nextepc
fi
for dir in /var/log/nextepc; do
if ! dpkg-statoverride --list "$dir" >/dev/null 2>&1; then
dpkg-statoverride --update --add nextepc nextepc 0755 "$dir"
fi
done
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

6
debian/nextepc-hss.install vendored Normal file
View File

@@ -0,0 +1,6 @@
usr/bin/nextepc-hssd
etc/nextepc/freeDiameter/hss.conf
etc/nextepc/freeDiameter/hss.cert.pem
etc/nextepc/freeDiameter/hss.key.pem
etc/nextepc/hss.conf
support/systemd/nextepc-hssd.service lib/systemd/system

6
debian/nextepc-mme.install vendored Normal file
View File

@@ -0,0 +1,6 @@
usr/bin/nextepc-mmed
etc/nextepc/freeDiameter/mme.conf
etc/nextepc/freeDiameter/mme.cert.pem
etc/nextepc/freeDiameter/mme.key.pem
etc/nextepc/mme.conf
support/systemd/nextepc-mmed.service lib/systemd/system

6
debian/nextepc-pcrf.install vendored Normal file
View File

@@ -0,0 +1,6 @@
usr/bin/nextepc-pcrfd
etc/nextepc/freeDiameter/pcrf.conf
etc/nextepc/freeDiameter/pcrf.cert.pem
etc/nextepc/freeDiameter/pcrf.key.pem
etc/nextepc/pcrf.conf
support/systemd/nextepc-pcrfd.service lib/systemd/system

7
debian/nextepc-pgw.install vendored Normal file
View File

@@ -0,0 +1,7 @@
usr/bin/nextepc-pgwd
etc/nextepc/freeDiameter/pgw.conf
etc/nextepc/freeDiameter/pgw.cert.pem
etc/nextepc/freeDiameter/pgw.key.pem
etc/nextepc/pgw.conf
support/network/nextepc etc/network/interfaces.d
support/systemd/nextepc-pgwd.service lib/systemd/system

47
debian/nextepc-pgw.postinst vendored Normal file
View File

@@ -0,0 +1,47 @@
#!/bin/sh
# postinst script for nextepc
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <postinst> `configure' <most-recently-configured-version>
# * <old-postinst> `abort-upgrade' <new version>
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
# <new-version>
# * <postinst> `abort-remove'
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
# <failed-install-package> <version> `removing'
# <conflicting-package> <version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
configure)
if ! grep "source-directory" /etc/network/interfaces | grep "/etc/network/interfaces.d" > /dev/null; then
echo "source-directory /etc/network/interfaces.d" >> /etc/network/interfaces
fi
if ! grep "pgwtun" /proc/net/dev > /dev/null; then
ifup pgwtun
fi
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

3
debian/nextepc-sgw.install vendored Normal file
View File

@@ -0,0 +1,3 @@
usr/bin/nextepc-sgwd
etc/nextepc/sgw.conf
support/systemd/nextepc-sgwd.service lib/systemd/system

43
debian/rules vendored Executable file
View File

@@ -0,0 +1,43 @@
#!/usr/bin/make -f
# Uncomment this to turn on verbose mode.
export DH_VERBOSE=1
DEBIAN := $(shell dpkg-parsechangelog | grep ^Version: | cut -d' ' -f2)
DEBVERS := $(shell echo '$(DEBIAN)' | cut -d- -f1)
VERSION := $(shell echo '$(DEBVERS)' | sed -e 's/[+-].*//' -e 's/~//g')
# This has to be exported to make some magic below work.
#export DH_OPTIONS
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
%:
dh $@ --with autoreconf --with systemd
override_dh_auto_test:
mongodb_exclude_list=; \
sctp_exclude_list=; \
mongodb_forked=no; \
remove_db_uri_conf=; \
if which mongod > /dev/null; then \
if ! ps -ef | grep mongod | grep -v grep > /dev/null; then \
mongodb_forked=yes; \
mongod --fork --logpath debian/test/var/log/mongodb.log --dbpath debian/test/db; \
fi; \
else \
remove_db_uri_conf="/DB_URI/d"; \
mongodb_exclude_list="-x s1setup_test attach_test volte_test handover_test"; \
fi; \
mkdir -p debian/test/db debian/test/etc/nextepc/freeDiameter debian/test/var/log/nextepc; \
sed -e 's?@SYSCONF_DIR@?'`pwd`'/debian/test/etc?g;s?@LOCALSTATE_DIR@?'`pwd`'/debian/test/var?g;'$$remove_db_uri_conf'' support/config/nextepc.conf.in > debian/test/etc/nextepc/nextepc.conf; \
for i in `find support/freeDiameter -name '*.conf.in' -printf "%f\n" | sed 's/.in$$//g'`; do \
sed 's?@SYSCONF_DIR@/nextepc?'`pwd`'/support?g;s?@LIB_DIR@/nextepc/\([_a-z0-9]*\)\.so?'`pwd`'/lib/fd/extensions/\1/.libs/\1.so?g' support/freeDiameter/$$i.in > debian/test/etc/nextepc/freeDiameter/$$i; \
done; \
if ! cat /proc/net/protocols | grep SCTP > /dev/null; then \
sctp_exclude_list="-x testsctp s1setup_test attach_test volte_test handover_test"; \
fi; \
lib/core/test/testcore $$sctp_exclude_list || exit; \
test/testepc -f debian/test/etc/nextepc/nextepc.conf -c $$sctp_exclude_list $$mongodb_exclude_list || exit; \
if test "x$$mongodb_forked" = xyes; then \
pkill mongod; \
fi;

1
debian/source/format vendored Normal file
View File

@@ -0,0 +1 @@
3.0 (native)

View File

@@ -1,6 +1,6 @@
## Process this file with automake to produce Makefile.in
SUBDIRS = @FREEDIAMETER_DIR@ core logger base s1ap nas fd gtp ipfw
SUBDIRS = @FREEDIAMETER_DIR@ core base s1ap nas fd gtp ipfw
MAINTAINERCLEANFILES = Makefile.in
MOSTLYCLEANFILES = *.stackdump

View File

@@ -13,7 +13,7 @@ AM_CPPFLAGS = \
AM_CFLAGS = \
-Wall -Werror
DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
DEFS = @DEFS@ -DSYSCONF_DIR=\"$(sysconfdir)/\"
MAINTAINERCLEANFILES = Makefile.in
MOSTLYCLEANFILES = *.stackdump

View File

@@ -2,12 +2,11 @@
#include "core_file.h"
#include "core_debug.h"
#include "core_lib.h"
#include <mongoc.h>
#include "context.h"
#define DEFAULT_CONFIG_FILE_PATH SYSCONFDIR PACKAGE ".conf"
static context_t self;
static int context_initialized = 0;
@@ -29,6 +28,9 @@ status_t context_final()
d_assert(context_initialized == 1, return CORE_ERROR,
"Context already has been finalized");
if (self.config.bson)
bson_destroy(self.config.bson);
context_initialized = 0;
return CORE_OK;
@@ -39,19 +41,19 @@ context_t* context_self()
return &self;
}
status_t context_read_file(char *file_path)
status_t context_read_file()
{
char buf[MAX_ERROR_STRING_LEN];
config_t *config = &self.config;
status_t rv;
file_t *file;
jsmn_parser parser;
bson_error_t error;
size_t json_len;
jsmn_parser parser;
int result;
config->path = file_path;
if (config->path == NULL) config->path = DEFAULT_CONFIG_FILE_PATH;
d_assert(config->path, return CORE_ERROR,);
rv = file_open(&file, config->path, FILE_READ, FILE_OS_DEFAULT);
if (rv != CORE_OK)
@@ -88,6 +90,13 @@ status_t context_read_file(char *file_path)
return CORE_ERROR;
}
config->bson = bson_new_from_json((const uint8_t *)config->json, -1, &error);;
if (config->bson == NULL)
{
d_fatal("Failed to parse configuration file '%s'", config->path);
return CORE_ERROR;
}
d_print(" Config '%s'\n", config->path);
return CORE_OK;
@@ -96,132 +105,137 @@ status_t context_read_file(char *file_path)
status_t context_parse_config()
{
config_t *config = &self.config;
bson_iter_t iter, child1_iter, child2_iter;
c_uint32_t length = 0;
char *json = config->json;
jsmntok_t *token = config->token;
d_assert(config, return CORE_ERROR, );
typedef enum { START, ROOT, SKIP, STOP } parse_state;
parse_state state = START;
self.log.console = -1;
size_t root_tokens = 0;
size_t skip_tokens = 0;
size_t i, j, m, n;
for (i = 0, j = 1; j > 0; i++, j--)
if (!bson_iter_init(&iter, config->bson))
{
jsmntok_t *t = &token[i];
d_error("bson_iter_init failed in this document");
return CORE_ERROR;
}
j += t->size;
switch (state)
while(bson_iter_next(&iter))
{
const char *key = bson_iter_key(&iter);
if (!strcmp(key, "DB_URI") && BSON_ITER_HOLDS_UTF8(&iter))
{
case START:
self.db_uri = bson_iter_utf8(&iter, &length);
}
else if (!strcmp(key, "LOG") && BSON_ITER_HOLDS_DOCUMENT(&iter))
{
bson_iter_recurse(&iter, &child1_iter);
while(bson_iter_next(&child1_iter))
{
state = ROOT;
root_tokens = t->size;
break;
}
case ROOT:
{
if (jsmntok_equal(json, t, "DB_URI") == 0)
const char *child1_key = bson_iter_key(&child1_iter);
if (!strcmp(child1_key, "CONSOLE") &&
BSON_ITER_HOLDS_INT32(&child1_iter))
{
self.db_uri = jsmntok_to_string(json, t+1);
self.log.console = bson_iter_int32(&child1_iter);
}
else if (jsmntok_equal(json, t, "LOG_PATH") == 0)
else if (!strcmp(child1_key, "SYSLOG") &&
BSON_ITER_HOLDS_UTF8(&child1_iter))
{
self.log_path = jsmntok_to_string(json, t+1);
self.log.syslog = bson_iter_utf8(&child1_iter, &length);
}
else if (jsmntok_equal(json, t, "TRACE") == 0)
else if (!strcmp(child1_key, "SOCKET") &&
BSON_ITER_HOLDS_DOCUMENT(&iter))
{
for (m = 1, n = 1; n > 0; m++, n--)
bson_iter_recurse(&child1_iter, &child2_iter);
while(bson_iter_next(&child2_iter))
{
n += (t+m)->size;
char *v = jsmntok_to_string(json, t+m+1);
if (jsmntok_equal(json, t+m, "S1AP") == 0)
const char *child2_key = bson_iter_key(&child2_iter);
if (!strcmp(child2_key, "FILE") &&
BSON_ITER_HOLDS_UTF8(&child2_iter))
{
if (v) self.trace_level.s1ap = atoi(v);
self.log.socket.file =
bson_iter_utf8(&child2_iter, &length);
}
else if (jsmntok_equal(json, t+m, "NAS") == 0)
else if (!strcmp(child2_key, "UNIX_DOMAIN") &&
BSON_ITER_HOLDS_UTF8(&child2_iter))
{
if (v) self.trace_level.nas = atoi(v);
}
else if (jsmntok_equal(json, t+m, "FD") == 0)
{
if (v) self.trace_level.fd = atoi(v);
}
else if (jsmntok_equal(json, t+m, "GTP") == 0)
{
if (v) self.trace_level.gtp = atoi(v);
}
else if (jsmntok_equal(json, t+m, "OTHERS") == 0)
{
if (v) self.trace_level.others = atoi(v);
self.log.socket.unix_domain =
bson_iter_utf8(&child2_iter, &length);
}
}
}
else if (jsmntok_equal(json, t, "HIDDEN") == 0)
else if (!strcmp(child1_key, "FILE") &&
BSON_ITER_HOLDS_UTF8(&child1_iter))
{
for (m = 1, n = 1; n > 0; m++, n--)
{
n += (t+m)->size;
char *v = jsmntok_to_string(json, t+m+1);
if (jsmntok_equal(json, t+m, "DISABLE_HSS") == 0)
{
if (v) self.hidden.disable_hss = atoi(v);
}
else if (jsmntok_equal(json, t+m, "DISABLE_SGW") == 0)
{
if (v) self.hidden.disable_sgw = atoi(v);
}
else if (jsmntok_equal(json, t+m, "DISABLE_PGW") == 0)
{
if (v) self.hidden.disable_pgw = atoi(v);
}
else if (jsmntok_equal(json, t+m, "DISABLE_PCRF") == 0)
{
if (v) self.hidden.disable_pcrf = atoi(v);
}
}
self.log.file = bson_iter_utf8(&child1_iter, &length);
}
state = SKIP;
skip_tokens = t->size;
root_tokens--;
if (root_tokens == 0) state = STOP;
break;
}
case SKIP:
}
else if (!strcmp(key, "TRACE") && BSON_ITER_HOLDS_DOCUMENT(&iter))
{
bson_iter_recurse(&iter, &child1_iter);
while(bson_iter_next(&child1_iter))
{
skip_tokens += t->size;
skip_tokens--;
if (skip_tokens == 0) state = ROOT;
break;
const char *child1_key = bson_iter_key(&child1_iter);
if (!strcmp(child1_key, "S1AP") &&
BSON_ITER_HOLDS_INT32(&child1_iter))
{
self.trace_level.s1ap = bson_iter_int32(&child1_iter);
}
else if (!strcmp(child1_key, "NAS") &&
BSON_ITER_HOLDS_INT32(&child1_iter))
{
self.trace_level.nas = bson_iter_int32(&child1_iter);
}
else if (!strcmp(child1_key, "FD") &&
BSON_ITER_HOLDS_INT32(&child1_iter))
{
self.trace_level.fd = bson_iter_int32(&child1_iter);
}
else if (!strcmp(child1_key, "GTP") &&
BSON_ITER_HOLDS_INT32(&child1_iter))
{
self.trace_level.gtp = bson_iter_int32(&child1_iter);
}
else if (!strcmp(child1_key, "OTHERS") &&
BSON_ITER_HOLDS_INT32(&child1_iter))
{
self.trace_level.others = bson_iter_int32(&child1_iter);
}
}
case STOP:
}
else if (!strcmp(key, "NODE") && BSON_ITER_HOLDS_DOCUMENT(&iter))
{
bson_iter_recurse(&iter, &child1_iter);
while(bson_iter_next(&child1_iter))
{
break;
const char *child1_key = bson_iter_key(&child1_iter);
if (!strcmp(child1_key, "DISABLE_HSS") &&
BSON_ITER_HOLDS_INT32(&child1_iter))
{
self.node.disable_hss = bson_iter_int32(&child1_iter);
}
else if (!strcmp(child1_key, "DISABLE_SGW") &&
BSON_ITER_HOLDS_INT32(&child1_iter))
{
self.node.disable_sgw = bson_iter_int32(&child1_iter);
}
else if (!strcmp(child1_key, "DISABLE_PGW") &&
BSON_ITER_HOLDS_INT32(&child1_iter))
{
self.node.disable_pgw = bson_iter_int32(&child1_iter);
}
else if (!strcmp(child1_key, "DISABLE_PCRF") &&
BSON_ITER_HOLDS_INT32(&child1_iter))
{
self.node.disable_pcrf = bson_iter_int32(&child1_iter);
}
}
default:
{
d_error("Failed to parse configuration in the state(%u)",
state);
break;
}
}
}
return CORE_OK;
}
status_t context_db_init(char *db_uri)
status_t context_db_init(const char *db_uri)
{
bson_t reply;
bson_error_t error;
@@ -257,7 +271,7 @@ status_t context_db_init(char *db_uri)
if (!mongoc_client_get_server_status(self.db_client, NULL, &reply, &error))
{
d_error("Failed to conect to server [%s]", db_uri);
return CORE_ERROR;
return CORE_EAGAIN;
}
d_assert(bson_iter_init_find(&iter, &reply, "ok"),

View File

@@ -13,9 +13,10 @@ extern "C" {
#define MAX_NUM_OF_CONFIG_TOKEN 256
typedef struct _config_t {
char *path;
const char *path;
char json[MAX_CONFIG_FILE_SIZE+1];
jsmntok_t token[MAX_NUM_OF_CONFIG_TOKEN];
void *bson;
} config_t;
#define MAX_DB_URI_LEN 256
@@ -23,13 +24,22 @@ typedef struct _config_t {
typedef struct _context_t {
config_t config;
char *log_path;
char *db_uri;
const char *db_uri;
void *db_client;
char *db_name;
void *database;
struct {
const char *path;
int console;
const char *syslog;
struct {
const char *unix_domain;
const char *file;
} socket;
const char *file;
} log;
struct {
int s1ap;
int nas;
@@ -43,7 +53,7 @@ typedef struct _context_t {
int disable_sgw;
int disable_pgw;
int disable_pcrf;
} hidden;
} node;
} context_t;
@@ -51,11 +61,11 @@ CORE_DECLARE(status_t) context_init(void);
CORE_DECLARE(status_t) context_final(void);
CORE_DECLARE(context_t*) context_self(void);
CORE_DECLARE(status_t) context_read_file(char *file_path);
CORE_DECLARE(status_t) context_read_file(void);
CORE_DECLARE(status_t) context_parse_config(void);
CORE_DECLARE(status_t) context_setup_trace_module(void);
CORE_DECLARE(status_t) context_db_init(char *db_uri);
CORE_DECLARE(status_t) context_db_init(const char *db_uri);
CORE_DECLARE(status_t) context_db_final(void);
#ifdef __cplusplus

View File

@@ -144,10 +144,6 @@
#include <netinet/tcp.h>
#endif
#if HAVE_NETINET_SCTP_H
#include <netinet/sctp.h>
#endif
#if HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
@@ -215,6 +211,8 @@ typedef c_int32_t c_intptr_t;
@uint64_t_fmt@
@uint64_t_hex_fmt@
@pid_t_fmt@
#ifdef INT16_MIN
#define C_INT16_MIN INT16_MIN
#else

View File

@@ -25,9 +25,11 @@ extern int g_trace_mask;
#define D_MSG_TO_CONSOLE 0x00000001
#define D_MSG_TO_STDOUT 0x00000002
#define D_MSG_TO_SYSLOG 0x00000004
#define D_MSG_TO_LOGD 0x00000008
#define D_MSG_TO_SOCKET 0x00000008
#define D_MSG_TO_FILE 0x00000010
#define D_MSG_TO_ALL (D_MSG_TO_CONSOLE | D_MSG_TO_STDOUT | \
D_MSG_TO_SYSLOG | D_MSG_TO_LOGD)
D_MSG_TO_SYSLOG | D_MSG_TO_SOCKET | \
D_MSG_TO_FILE )
#define D_LOG_LEVEL_NONE 0
#define D_LOG_LEVEL_FATAL 1
@@ -138,13 +140,17 @@ CORE_DECLARE(int) d_msg(int tp, int lv, c_time_t t, char *fn, int ln,
expr; \
}
void d_msg_init();
void d_msg_final();
void d_msg_register_console(int console_fd);
void d_msg_deregister_console();
status_t d_msg_console_init(int console_fd);
void d_msg_console_final();
void d_msg_syslog_init(const char *name);
void d_msg_syslog_final();
status_t d_msg_socket_init(const char *name);
void d_msg_socket_final();
status_t d_msg_socket_start(const char *file);
void d_msg_socket_stop();
void d_msg_socket_final();
status_t d_msg_file_init(const char *file);
void d_msg_file_final();
void d_msg_to(int to, int on_off);
@@ -198,8 +204,6 @@ void d_trace_level(int *mod_name, int level);
*/
void d_trace_off(int *mod_name);
#define D_LOGD_IPC_PATH "/tmp/dlogmesg"
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@@ -47,7 +47,6 @@ typedef struct {
struct sockaddr_in remote;
int opt;
index_t app_index;
int sndrcv_errno;
} net_sock_t;
@@ -114,7 +113,7 @@ CORE_DECLARE(int) net_write(net_sock_t *net_sock, char *buffer, size_t size,
CORE_DECLARE(int) net_send(net_sock_t *net_sock, char *buffer, size_t size);
CORE_DECLARE(int) net_sendto(net_sock_t *net_sock, char *buffer, size_t size,
c_uint32_t ip_addr, c_uint16_t port);
c_uint32_t addr, c_uint16_t port);
/** Close the socket
@@ -263,10 +262,10 @@ CORE_DECLARE(int) net_unregister_link(net_link_t *net_link);
CORE_DECLARE(int) net_fds_read_run(long timeout);
/** TunTap interface */
CORE_DECLARE(int) net_tuntap_open(net_link_t **net_link, char *tuntap_dev_name,
int is_tap);
CORE_DECLARE(int) net_tuntap_close(net_link_t *net_link);
CORE_DECLARE(int) net_tun_open(net_link_t **net_link, char *name, int is_tap);
CORE_DECLARE(int) net_tun_set_ipv4(
net_link_t *net_link, c_uint32_t addr, c_uint8_t bits);
CORE_DECLARE(int) net_tun_close(net_link_t *net_link);
#ifdef __cplusplus
}

View File

@@ -1,6 +1,7 @@
#include "core_debug.h"
#include "core_param.h"
#include "core_file.h"
#include "core_thread.h"
#include <syslog.h>
#include <sys/socket.h>
@@ -9,61 +10,258 @@
int g_trace_mask = 1;
int g_msg_to = D_MSG_TO_LOGD | D_MSG_TO_STDOUT;
int g_msg_to = D_MSG_TO_STDOUT;
int g_console_connected = 0;
int g_syslog_connected = 0;
int g_logd_connected = 0;
int g_socket_connected = 0;
int g_file_connected = 0;
int g_log_level_console = D_LOG_LEVEL_FULL;
int g_log_level_stdout = D_LOG_LEVEL_FULL;
int g_log_level_syslog = D_LOG_LEVEL_FULL;
int g_log_level_logd = D_LOG_LEVEL_FULL;
int g_log_level_socket = D_LOG_LEVEL_FULL;
int g_log_level_file = D_LOG_LEVEL_FULL;
int g_console_fd = -1;
int g_logd_fd = -1;
struct sockaddr_un g_logd_addr;
static int g_console_fd = -1;
static int g_socket_fd = -1;
static struct sockaddr_un g_socket_addr;
void d_msg_init()
static thread_id socket_thread = 0;
static void *THREAD_FUNC socket_main(thread_id id, void *data);
static int socket_handler(const char *path);
static file_t *g_file = NULL;
status_t d_msg_console_init(int console_fd)
{
openlog("libcore", 0, LOG_DAEMON);
g_syslog_connected = 1;
g_logd_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
d_assert(g_logd_fd >= 0, return,
"socket() failed. (%d:%s)\n", errno, strerror(errno));
g_logd_addr.sun_family = AF_UNIX;
strcpy(g_logd_addr.sun_path, D_LOGD_IPC_PATH);
g_logd_connected = 1;
}
void d_msg_final()
{
g_syslog_connected = 0;
closelog();
g_logd_connected = 0;
close(g_logd_fd);
g_logd_fd = -1;
}
void d_msg_register_console(int console_fd)
{
d_assert(console_fd >= 0, return, "param 'console_fd' is invalid");
d_assert(console_fd >= 0, return CORE_ERROR,
"param 'console_fd' is invalid");
g_console_fd = console_fd;
g_console_connected = 1;
return CORE_OK;
}
void d_msg_deregister_console()
void d_msg_console_final()
{
g_console_connected = 0;
g_console_fd = -1;
}
void d_msg_syslog_init(const char *name)
{
d_assert(name, return, );
openlog(name, 0, LOG_DAEMON);
g_syslog_connected = 1;
}
void d_msg_syslog_final()
{
g_syslog_connected = 0;
closelog();
}
status_t d_msg_socket_init(const char *name)
{
d_assert(name, return CORE_ERROR, );
g_socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
d_assert(g_socket_fd >= 0, return CORE_ERROR,
"socket() failed. (%d:%s)\n", errno, strerror(errno));
g_socket_addr.sun_family = AF_UNIX;
strcpy(g_socket_addr.sun_path, name);
return CORE_OK;
}
status_t d_msg_socket_start(const char *file)
{
status_t rv;
d_assert(file, return CORE_ERROR, );
rv = thread_create(&socket_thread, NULL, socket_main, (void*)file);
d_assert(rv == CORE_OK, return CORE_ERROR,
"socket thread creation failed");
g_socket_connected = 1;
d_msg_to(D_MSG_TO_SOCKET, 1);
return CORE_OK;
}
void d_msg_socket_stop()
{
d_msg_to(D_MSG_TO_SOCKET, 0);
g_socket_connected = 0;
if (socket_thread)
thread_delete(socket_thread);
}
void d_msg_socket_final()
{
close(g_socket_fd);
g_socket_fd = -1;
}
static void *THREAD_FUNC socket_main(thread_id id, void *data)
{
int ret;
char *path = data;
ret = socket_handler(path);
if (ret != 0)
{
d_error("Failed to initialize logger.");
d_error("Check file permission for `%s`", path);
}
return NULL;
}
static int socket_handler(const char *path)
{
status_t rv;
int ret;
size_t nbytes;
ssize_t r;
int us;
fd_set readfd;
struct timeval timer_val;
struct sockaddr_un svaddr;
file_t *file = NULL;
char g_buffer[1024];
us = socket(AF_UNIX, SOCK_DGRAM, 0);
if (us < 0)
{
d_error("socket() failed. (%d:%s)", errno, strerror(errno));
return -1;
}
memcpy(&svaddr, &g_socket_addr, sizeof(struct sockaddr_un));
ret = bind(us, (struct sockaddr *)&svaddr, sizeof(svaddr));
if (ret != 0)
{
if (errno == EADDRINUSE)
{
ret = file_remove(svaddr.sun_path);
if (ret != 0)
{
d_error("unlink(`%s`) failed. (%d:%s)",
svaddr.sun_path, errno, strerror(errno));
return -1;
}
ret = bind(us, (struct sockaddr *)&svaddr, sizeof(svaddr));
if (ret != 0)
{
d_error("bind() failed 2. (%d:%s)", errno, strerror(errno));
return -1;
}
}
else
{
d_error("bind() failed. (%d:%s)", errno, strerror(errno));
return -1;
}
}
rv = file_open(&file, path,
FILE_CREATE | FILE_WRITE| FILE_APPEND,
FILE_UREAD | FILE_UWRITE | FILE_GREAD);
if (rv != CORE_OK)
{
d_error("Cannot open log file '%s'", path);
close(us);
return -1;
}
while (!thread_should_stop())
{
timer_val.tv_sec = 0;
timer_val.tv_usec = 50000;
FD_ZERO(&readfd);
FD_SET(us, &readfd);
r = select (us+1, &readfd, NULL, NULL, &timer_val);
if (r == -1)
{
if (errno == EINTR)
break;
d_error("select() error(%d: %s)", errno, strerror(errno));
}
if (r == 0)
continue;
if (FD_ISSET(us, &readfd))
{
r = read(us, g_buffer, sizeof(g_buffer));
if (r < 0)
{
if (errno == EINTR)
break;
d_error("read() failed. (%d:%s)", errno, strerror(errno));
continue;
}
if (r == 0)
continue;
nbytes = r;
rv = file_write(file, g_buffer, &nbytes);
if (rv != CORE_OK || r != nbytes)
{
d_error("Cannot write %ld bytes to log file (%ld written)",
(long)r, (long)nbytes);
}
}
}
file_close(file);
close(us);
file_remove(svaddr.sun_path);
return 0;
}
status_t d_msg_file_init(const char *file)
{
status_t rv;
d_assert(file, return CORE_ERROR, );
rv = file_open(&g_file, file,
FILE_CREATE | FILE_WRITE| FILE_APPEND,
FILE_UREAD | FILE_UWRITE | FILE_GREAD);
if (rv != CORE_OK)
{
d_error("Cannot open log file '%s'", file);
return CORE_ERROR;
}
g_file_connected = 1;
d_msg_to(D_MSG_TO_FILE, 1);
return CORE_OK;
}
void d_msg_file_final()
{
d_msg_to(D_MSG_TO_FILE, 0);
g_file_connected = 0;
file_close(g_file);
}
void d_msg_to(int to, int on_off)
{
switch (to)
@@ -83,10 +281,15 @@ void d_msg_to(int to, int on_off)
g_msg_to | D_MSG_TO_SYSLOG :
g_msg_to & ~D_MSG_TO_SYSLOG;
break;
case D_MSG_TO_LOGD:
case D_MSG_TO_SOCKET:
g_msg_to = on_off ?
g_msg_to | D_MSG_TO_LOGD :
g_msg_to & ~D_MSG_TO_LOGD;
g_msg_to | D_MSG_TO_SOCKET :
g_msg_to & ~D_MSG_TO_SOCKET;
break;
case D_MSG_TO_FILE:
g_msg_to = on_off ?
g_msg_to | D_MSG_TO_FILE :
g_msg_to & ~D_MSG_TO_FILE;
break;
case D_MSG_TO_ALL:
g_msg_to = on_off ? D_MSG_TO_ALL : 0;
@@ -114,14 +317,17 @@ void d_log_set_level(int to, int level)
case D_MSG_TO_SYSLOG:
g_log_level_syslog = level;
break;
case D_MSG_TO_LOGD:
g_log_level_logd = level;
case D_MSG_TO_SOCKET:
g_log_level_socket = level;
break;
case D_MSG_TO_FILE:
g_log_level_socket = level;
break;
case D_MSG_TO_ALL:
g_log_level_console = level;
g_log_level_stdout = level;
g_log_level_syslog = level;
g_log_level_logd = level;
g_log_level_socket = level;
break;
default:
break;
@@ -138,8 +344,10 @@ int d_log_get_level(int to)
return g_log_level_stdout;
case D_MSG_TO_SYSLOG:
return g_log_level_syslog;
case D_MSG_TO_LOGD:
return g_log_level_logd;
case D_MSG_TO_SOCKET:
return g_log_level_socket;
case D_MSG_TO_FILE:
return g_log_level_socket;
default:
break;
}
@@ -160,14 +368,17 @@ void d_log_full(int to)
case D_MSG_TO_SYSLOG:
g_log_level_syslog = D_LOG_LEVEL_FULL;
break;
case D_MSG_TO_LOGD:
g_log_level_logd = D_LOG_LEVEL_FULL;
case D_MSG_TO_SOCKET:
g_log_level_socket = D_LOG_LEVEL_FULL;
break;
case D_MSG_TO_FILE:
g_log_level_socket = D_LOG_LEVEL_FULL;
break;
case D_MSG_TO_ALL:
g_log_level_console = D_LOG_LEVEL_FULL;
g_log_level_stdout = D_LOG_LEVEL_FULL;
g_log_level_syslog = D_LOG_LEVEL_FULL;
g_log_level_logd = D_LOG_LEVEL_FULL;
g_log_level_socket = D_LOG_LEVEL_FULL;
break;
default:
break;
@@ -187,14 +398,17 @@ void d_log_off(int to)
case D_MSG_TO_SYSLOG:
g_log_level_syslog = D_LOG_LEVEL_NONE;
break;
case D_MSG_TO_LOGD:
g_log_level_logd = D_LOG_LEVEL_NONE;
case D_MSG_TO_SOCKET:
g_log_level_socket = D_LOG_LEVEL_NONE;
break;
case D_MSG_TO_FILE:
g_log_level_socket = D_LOG_LEVEL_NONE;
break;
case D_MSG_TO_ALL:
g_log_level_console = D_LOG_LEVEL_NONE;
g_log_level_stdout = D_LOG_LEVEL_NONE;
g_log_level_syslog = D_LOG_LEVEL_NONE;
g_log_level_logd = D_LOG_LEVEL_NONE;
g_log_level_socket = D_LOG_LEVEL_NONE;
break;
default:
break;
@@ -283,10 +497,15 @@ int d_msg(int tp, int lv, c_time_t t, char *fn, int ln, char *fmt, ...)
{
syslog(LOG_DEBUG, "%s", fstr);
}
if (g_logd_connected && (g_msg_to & D_MSG_TO_LOGD))
if (g_socket_connected && (g_msg_to & D_MSG_TO_SOCKET))
{
sendto(g_logd_fd, fstr, n, 0,
(struct sockaddr *)&g_logd_addr, sizeof(g_logd_addr));
sendto(g_socket_fd, fstr, n, 0,
(struct sockaddr *)&g_socket_addr, sizeof(g_socket_addr));
}
if (g_file_connected && (g_msg_to & D_MSG_TO_FILE))
{
size_t nbytes = n;
file_write(g_file, fstr, &nbytes);
}
if (g_console_connected && (g_msg_to & D_MSG_TO_CONSOLE))
{
@@ -310,10 +529,15 @@ int d_msg(int tp, int lv, c_time_t t, char *fn, int ln, char *fmt, ...)
{
syslog(LOG_DEBUG, "%s", fstr);
}
if (g_logd_connected && (g_msg_to & D_MSG_TO_LOGD))
if (g_socket_connected && (g_msg_to & D_MSG_TO_SOCKET))
{
sendto(g_logd_fd, fstr, n, 0,
(struct sockaddr *)&g_logd_addr, sizeof(g_logd_addr));
sendto(g_socket_fd, fstr, n, 0,
(struct sockaddr *)&g_socket_addr, sizeof(g_socket_addr));
}
if (g_file_connected && (g_msg_to & D_MSG_TO_FILE))
{
size_t nbytes = n;
file_write(g_file, fstr, &nbytes);
}
if (g_console_connected && (g_msg_to & D_MSG_TO_CONSOLE))
{
@@ -353,12 +577,20 @@ int d_msg(int tp, int lv, c_time_t t, char *fn, int ln, char *fmt, ...)
{
syslog(LOG_INFO, "[%s\n", fstr + 13);
}
if (g_logd_connected && (g_msg_to & D_MSG_TO_LOGD) &&
lv <= g_log_level_logd)
if (g_socket_connected && (g_msg_to & D_MSG_TO_SOCKET) &&
lv <= g_log_level_socket)
{
fstr[n++] = '\n';
sendto(g_logd_fd, fstr, n, 0,
(struct sockaddr *)&g_logd_addr, sizeof(g_logd_addr));
sendto(g_socket_fd, fstr, n, 0,
(struct sockaddr *)&g_socket_addr, sizeof(g_socket_addr));
}
if (g_file_connected && (g_msg_to & D_MSG_TO_FILE))
{
size_t nbytes;
fstr[n++] = '\n';
nbytes = n;
file_write(g_file, fstr, &nbytes);
}
if (g_console_connected && (g_msg_to & D_MSG_TO_CONSOLE) &&
lv <= g_log_level_console)
@@ -384,11 +616,19 @@ int d_msg(int tp, int lv, c_time_t t, char *fn, int ln, char *fmt, ...)
{
syslog(LOG_CRIT, "[%s\n", fstr + 13);
}
if (g_logd_connected && (g_msg_to & D_MSG_TO_LOGD))
if (g_socket_connected && (g_msg_to & D_MSG_TO_SOCKET))
{
fstr[n++] = '\n';
sendto(g_logd_fd, fstr, n, 0,
(struct sockaddr *)&g_logd_addr, sizeof(g_logd_addr));
sendto(g_socket_fd, fstr, n, 0,
(struct sockaddr *)&g_socket_addr, sizeof(g_socket_addr));
}
if (g_file_connected && (g_msg_to & D_MSG_TO_FILE))
{
size_t nbytes;
fstr[n++] = '\n';
nbytes = n;
file_write(g_file, fstr, &nbytes);
}
if (g_console_connected && (g_msg_to & D_MSG_TO_CONSOLE))
{

View File

@@ -20,7 +20,7 @@ void fsm_init(void *s, void *_e)
fsm_t *fsm = s;
event_t *e = _e;
if (fsm->initial != (fsm_state_t)0)
if (fsm->initial != NULL)
{
(*fsm->initial)(s, e);
if (fsm->initial != fsm->state)
@@ -46,7 +46,7 @@ void fsm_dispatch(void *s, void *_e)
fsm->state = (fsm_handler_t)0;
(*tmp)(s, e);
if (fsm->state != (fsm_state_t)0)
if (fsm->state != NULL)
{
if (e)
{
@@ -91,7 +91,7 @@ void fsm_final(void *s, void *_e)
}
}
if (fsm->final != (fsm_state_t)0)
if (fsm->final != NULL)
{
(*fsm->final)(s, e);
}

View File

@@ -7,11 +7,25 @@
#include "core_errno.h"
#include "core_time.h"
#if USE_USRSCTP == 1
#if HAVE_USRSCTP_H
#include <usrsctp.h>
#endif
#else
#if HAVE_NETINET_SCTP_H
#include <netinet/sctp.h>
#endif
#endif
#if LINUX == 1
#include <netpacket/packet.h>
#include <linux/if_tun.h>
#endif
#if HAVE_NET_ROUTE_H
#include <net/route.h>
#endif
#define NET_FD_TYPE_SOCK 0
#define NET_FD_TYPE_LINK 1
@@ -136,8 +150,13 @@ static net_sock_t *net_sock_create(int type, int protocol)
event.sctp_send_failure_event = 1;
event.sctp_shutdown_event = 1;
#if USE_USRSCTP == 1
if (setsockopt(sock, IPPROTO_SCTP, SCTP_EVENT,
&event, sizeof( event)) != 0 )
#else
if (setsockopt(sock, IPPROTO_SCTP, SCTP_EVENTS,
&event, sizeof( event)) != 0 )
#endif
{
d_error("Unable to subscribe to SCTP events: (%d:%s)",
errno, strerror( errno ));
@@ -327,7 +346,9 @@ int net_open_ext(net_sock_t **net_sock,
(struct sockaddr *)&sock_addr, sizeof(sock_addr));
if (rc < 0)
{
d_error("connect error(proto:%d remote:%s dport:%d lport:%d)",
d_error("connect error(%d:%s)(proto:%d remote:%s dport:%d lport:%d)",
errno,
strerror(errno),
proto,
remote_host,
rport,
@@ -428,14 +449,20 @@ int net_read(net_sock_t *net_sock, char *buffer, size_t size, int timeout)
}
else if (net_sock->proto == IPPROTO_SCTP)
{
struct sctp_sndrcvinfo sndrcvinfo;
int flags = 0;
struct sockaddr remote_addr;
socklen_t addr_len = sizeof(struct sockaddr);
#if USE_USRSCTP == 1
rc = usrsctp_recvv((struct socket *)net_sock, buffer, size,
(struct sockaddr *)&remote_addr, &addr_len,
NULL, NULL, NULL, &flags);
#else
struct sctp_sndrcvinfo sndrcvinfo;
rc = sctp_recvmsg(net_sock->sock_id, buffer, size,
(struct sockaddr *)&remote_addr, &addr_len,
&sndrcvinfo, &flags);
#endif
if (rc < 0) net_sock->sndrcv_errno = errno;
/* Save the remote address */
@@ -469,6 +496,7 @@ int net_read(net_sock_t *net_sock, char *buffer, size_t size, int timeout)
SCTP_COMM_LOST)
net_sock->sndrcv_errno = ECONNREFUSED;
break;
#if USE_USRSCTP != 1
case SCTP_SEND_FAILED :
d_error("SCTP_SEND_FAILED"
"(type:0x%x, flags:0x%x, error:0x%x)\n",
@@ -476,6 +504,7 @@ int net_read(net_sock_t *net_sock, char *buffer, size_t size, int timeout)
not->sn_send_failed.ssf_flags,
not->sn_send_failed.ssf_error);
break;
#endif
case SCTP_SHUTDOWN_EVENT :
d_trace(3, "SCTP_SHUTDOWN_EVENT\n");
net_sock->sndrcv_errno = ECONNREFUSED;
@@ -541,6 +570,7 @@ int net_write(net_sock_t *net_sock, char *buffer, size_t size,
}
else if (net_sock->proto == IPPROTO_SCTP)
{
#if USE_USRSCTP != 1
rc = sctp_sendmsg(net_sock->sock_id, buffer, size,
(struct sockaddr *)dest_addr, addrsize,
htonl(net_sock->ppid),
@@ -551,12 +581,10 @@ int net_write(net_sock_t *net_sock, char *buffer, size_t size,
if (rc < 0) net_sock->sndrcv_errno = errno;
return rc;
}
else
{
return -1;
#endif
}
return -1;
}
int net_send(net_sock_t *net_sock, char *buffer, size_t size)
@@ -568,7 +596,7 @@ int net_send(net_sock_t *net_sock, char *buffer, size_t size)
}
int net_sendto(net_sock_t *net_sock, char *buffer, size_t size,
c_uint32_t ip_addr, c_uint16_t port)
c_uint32_t addr, c_uint16_t port)
{
struct sockaddr_in sock_addr;
d_assert(net_sock && buffer, return -1, "Invalid params\n");
@@ -576,10 +604,9 @@ int net_sendto(net_sock_t *net_sock, char *buffer, size_t size,
memset(&sock_addr, 0, sizeof(sock_addr));
sock_addr.sin_family = AF_INET;
sock_addr.sin_port = htons(port);
sock_addr.sin_addr.s_addr = ip_addr;
sock_addr.sin_addr.s_addr = addr;
return net_write(net_sock, buffer, size,
&sock_addr, sizeof(sock_addr));
return net_write(net_sock, buffer, size, &sock_addr, sizeof(sock_addr));
}
/** Close the socket */
@@ -638,6 +665,7 @@ int net_accept(net_sock_t **new_accept_sock, net_sock_t *net_sock, int timeout)
node->sock_id = new_sock;
node->proto = net_sock->proto;
node->ppid = net_sock->ppid;
*new_accept_sock = node;
/* Save local and remote address */
@@ -1167,6 +1195,7 @@ int net_raw_open(net_link_t **net_link, int proto)
}
/** Create tuntap socket */
#if 0 /* deprecated */
int net_tuntap_open(net_link_t **net_link, char *tuntap_dev_name,
int is_tap)
{
@@ -1220,7 +1249,179 @@ cleanup:
return -1;
#endif
}
#endif
/** Create tun socket */
int net_tun_open(net_link_t **net_link, char *ifname, int is_tap)
{
int sock;
net_link_t *new_link = NULL;
#if LINUX == 1
char *dev = "/dev/net/tun";
int rc;
struct ifreq ifr;
int flags = IFF_NO_PI;
sock = open(dev, O_RDWR);
if (sock < 0)
{
d_error("Can not open %s",dev);
return -1;
}
#else
char name[C_PATH_MAX];
int tun = 0;
#define TUNTAP_ID_MAX 255
for (tun = 0; tun < TUNTAP_ID_MAX; tun++)
{
(void)snprintf(name, sizeof(name), "/dev/tun%i", tun);
if ((sock = open(name, O_RDWR)) > 0)
{
(void)snprintf(name, sizeof(name), "tun%i", tun);
ifname = name;
break;
}
}
#endif
pool_alloc_node(&link_pool, &new_link);
d_assert(new_link != NULL, return -1,"No link pool is availabe\n");
#if LINUX == 1
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = (is_tap ? (flags | IFF_TAP) : (flags | IFF_TUN));
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
rc = ioctl(sock, TUNSETIFF, (void *)&ifr);
if (rc < 0)
{
d_error("iotcl error(dev:%s flags = %d)", ifname, flags);
goto cleanup;
}
#endif
/* Save socket descriptor */
new_link->fd = sock;
/* Save the interface name */
strncpy(new_link->ifname, ifname, IFNAMSIZ);
*net_link = new_link;
return 0;
#if LINUX == 1
cleanup:
pool_free_node(&link_pool, new_link);
close(sock);
return -1;
#endif
}
int net_tun_set_ipv4(net_link_t *link, c_uint32_t ip_addr, c_uint8_t bits)
{
#if LINUX != 1
int sock;
struct ifaliasreq ifa;
struct ifreq ifr;
struct sockaddr_in addr;
struct sockaddr_in mask;
c_uint32_t mask_addr = htonl(0xffffffff << (32 - bits));
char buf[512];
int len;
struct rt_msghdr *rtm;
struct sockaddr_in dst, gw;
struct sockaddr_in *paddr;
sock = socket(AF_INET, SOCK_DGRAM, 0);
(void)memset(&ifa, '\0', sizeof ifa);
(void)strlcpy(ifa.ifra_name, link->ifname, sizeof ifa.ifra_name);
(void)memset(&ifr, '\0', sizeof ifr);
(void)strlcpy(ifr.ifr_name, link->ifname, sizeof ifr.ifr_name);
/* Delete previously assigned address */
(void)ioctl(sock, SIOCDIFADDR, &ifr);
(void)memset(&addr, '\0', sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = ip_addr;
addr.sin_len = sizeof(addr);
(void)memcpy(&ifa.ifra_addr, &addr, sizeof(addr));
(void)memcpy(&ifa.ifra_broadaddr, &addr, sizeof(addr));
(void)memset(&mask, '\0', sizeof(mask));
mask.sin_family = AF_INET;
mask.sin_addr.s_addr = 0xffffffff;
mask.sin_len = sizeof(mask);
(void)memcpy(&ifa.ifra_mask, &mask, sizeof(ifa.ifra_mask));
if (ioctl(sock, SIOCAIFADDR, &ifa) == -1) {
d_error("Can't IP address(dev:%s err:%s)",
link->ifname, strerror(errno));
return -1;
}
close(sock); /* AF_INET, SOCK_DGRAM */
sock = socket(PF_ROUTE, SOCK_RAW, 0);
if (sock < 0)
{
d_error("Can't open PF_ROUTE(%s)", strerror(errno));
return -1;
}
(void)memset(&buf, 0, sizeof(buf));
rtm = (struct rt_msghdr *)buf;
rtm->rtm_type = RTM_ADD;
rtm->rtm_version = RTM_VERSION;
rtm->rtm_pid = getpid();
rtm->rtm_seq = 0;
rtm->rtm_flags = RTF_UP | RTF_GATEWAY;
rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
paddr = (struct sockaddr_in *)(rtm + 1);
(void)memset(&dst, '\0', sizeof(dst));
dst.sin_family = AF_INET;
dst.sin_addr.s_addr = ip_addr & mask_addr;
dst.sin_len = sizeof(dst);
(void)memcpy(paddr, &dst, sizeof(dst));
paddr = (struct sockaddr_in *)((char *)paddr +
CORE_ALIGN(sizeof(*paddr), sizeof(c_uintptr_t)));
(void)memset(&gw, '\0', sizeof(gw));
gw.sin_family = AF_INET;
gw.sin_addr.s_addr = ip_addr;
gw.sin_len = sizeof(gw);
(void)memcpy(paddr, &gw, sizeof(gw));
paddr = (struct sockaddr_in *)((char *)paddr +
CORE_ALIGN(sizeof(*paddr), sizeof(c_uintptr_t)));
(void)memset(&mask, '\0', sizeof(mask));
mask.sin_family = AF_INET;
mask.sin_addr.s_addr = mask_addr;
mask.sin_len = sizeof(mask);
(void)memcpy(paddr, &mask, sizeof(mask));
paddr = (struct sockaddr_in *)((char *)paddr +
CORE_ALIGN(sizeof(*paddr), sizeof(c_uintptr_t)));
len = (char*)paddr - buf;
rtm->rtm_msglen = len;
if (write(sock, buf, len) < 0)
{
d_error("Can't add routing(%s)", strerror(errno));
return -1;
}
close(sock); /* PF_ROUTE, SOCK_RAW */
#endif /* LINUX == 1 */
return 0;
}
#if LINUX == 1
int net_link_open(net_link_t **net_link, char *device, int proto)
@@ -1367,7 +1568,7 @@ int net_raw_close(net_link_t *net_link)
return 0;
}
int net_tuntap_close(net_link_t *net_link)
int net_tun_close(net_link_t *net_link)
{
d_assert(net_link,return -1, "net_link is NULL\n");
close(net_link->fd);

View File

@@ -51,7 +51,6 @@ status_t core_initialize(void)
tlv_init();
tm_init();
msgq_init();
d_msg_init();
signal_init();
return CORE_OK;
@@ -65,7 +64,6 @@ void core_terminate(void)
}
/* Reverse ordered finalization */
d_msg_final();
msgq_final();
tm_final();
tlv_final();

View File

@@ -9,6 +9,10 @@ testcore_SOURCES = \
testpkbuf.c testmisc.c testhash.c \
abts.h abts_tests.h testutil.c testutil.h
if !USRSCTP
testcore_SOURCES += testsctp.c
endif
testcore_LDADD = \
$(top_srcdir)/lib/core/src/libcore.la

View File

@@ -29,6 +29,9 @@ const struct testlist {
{testaes},
{testsha2},
{testnetlib},
#if USE_USRSCTP != 1
{testsctp},
#endif
{testtime},
{testtimer},
{testthread},

View File

@@ -14,11 +14,9 @@
static char buffer[TEST_BUFFER_SIZE];
static int tcp_server_started = 0;
static int udp_server_started = 0;
static int sctp_stream_server_started = 0;
static int sctp_seq_server_started = 0;
pthread_t tserver_tid,userver_tid,streamserver_tid, seqserver_tid;
net_sock_t *tserver_sock,*userver_sock,*streamserver_sock,*seqserver_sock;
pthread_t tserver_tid,userver_tid;
net_sock_t *tserver_sock,*userver_sock;
static void *tcp_session_main(void *param)
{
@@ -108,6 +106,7 @@ static void start_tcp_server()
{
sleep(1);
}
sleep(1);
return;
}
@@ -183,171 +182,6 @@ static void stop_udp_server()
pthread_join(userver_tid, NULL);
}
static void *sctp_stream_session_main(void *param)
{
int rc;
net_sock_t *net_sock = (net_sock_t *)param;
while (1)
{
rc = net_read(net_sock, buffer, TEST_BUFFER_SIZE, 1);
if (rc > 0)
{
if (!strncmp(buffer, "QUIT",4))
{
break;
}
else
{
/* Send received data */
rc = net_send(net_sock, buffer, rc);
}
}
else if (rc == 0)
{
/* Timeout */
}
else
{
if (rc != -2 && net_sock->sndrcv_errno != EAGAIN)
break;
}
}
net_close(net_sock);
return NULL;
}
static void start_stream_sctp_session(net_sock_t *net_sock)
{
pthread_t tid;
pthread_create(&tid, NULL, sctp_stream_session_main, (void *)net_sock);
pthread_detach(tid);
return;
}
static void *sctp_stream_server_main(void *param)
{
int rc;
net_sock_t *new_sock;
rc = net_listen(&streamserver_sock,
SOCK_STREAM, IPPROTO_SCTP, TEST_SERVER_PORT);
if (rc != 0)
{
d_error("net_sctp_listen Error(rc = %d)\n",rc);
return NULL;
}
sctp_stream_server_started = 1;
while (1)
{
rc = net_accept(&new_sock, streamserver_sock, 1);
if (rc >0)
{
/* New connection arrived. Start session */
start_stream_sctp_session(new_sock);
}
else if (rc == 0)
{
/* Timeout */
}
else
{
/* Error occured */
break;
}
}
return NULL;
}
static void start_stream_sctp_server()
{
pthread_create(&streamserver_tid, NULL, sctp_stream_server_main, NULL);
while (sctp_stream_server_started == 0)
{
sleep(1);
}
return;
}
static void stop_stream_sctp_server()
{
net_close(streamserver_sock);
pthread_join(streamserver_tid, NULL);
}
static void *sctp_seq_server_main(void *param)
{
int rc;
rc = net_listen(&seqserver_sock,
SOCK_SEQPACKET, IPPROTO_SCTP, TEST_SERVER_PORT);
if (rc != 0)
{
d_error("net_sctp Error(rc = %d)\n",rc);
return NULL;
}
sctp_seq_server_started = 1;
while (1)
{
d_trace(1,"Wait for data....\n");
rc = net_read(seqserver_sock, buffer, TEST_BUFFER_SIZE, 2);
if (rc >0)
{
d_trace(1,"RECV %d bytes\n", rc);
if (!strncmp(buffer, "QUIT",4))
{
break;
}
else
{
/* Send received data */
rc = net_send(seqserver_sock, buffer, rc);
d_trace(1,"SEND %d bytes\n", rc);
if (rc == -1)
{
printf("error = %d\n", seqserver_sock->sndrcv_errno);
}
}
}
else if (rc == 0)
{
/* Timeout */
}
else
{
/* Error occured */
if (rc != -2 && seqserver_sock->sndrcv_errno != EAGAIN)
break;
}
}
return NULL;
}
static void start_seq_sctp_server()
{
pthread_create(&seqserver_tid, NULL, sctp_seq_server_main, NULL);
while (sctp_seq_server_started == 0)
{
sleep(1);
}
return;
}
static void stop_seq_sctp_server()
{
net_close(seqserver_sock);
pthread_join(seqserver_tid, NULL);
}
static void netlib1(abts_case *tc, void *data)
{
int rc = 0;
@@ -529,139 +363,6 @@ static void netlib3(abts_case *tc, void *data)
}
static void netlib4(abts_case *tc, void *data)
{
int rc = 0;
net_sock_t *net_sock[TEST_MAX_NUM];
char inputbuf[TEST_MAX_NUM][25];
char outputbuf[TEST_MAX_NUM][25];
int i;
/* Start SCTP Server */
start_stream_sctp_server();
/* Connect to invalid port */
d_log_set_level(D_MSG_TO_STDOUT, D_LOG_LEVEL_FATAL);
for (i =0 ; i<TEST_MAX_NUM; i++)
{
net_sock[i] = NULL;
rc = net_open(&net_sock[i], "127.0.0.1", 0,TEST_SERVER_PORT + 1,
SOCK_STREAM, IPPROTO_SCTP);
ABTS_INT_EQUAL(tc, -1, rc);
ABTS_PTR_NULL(tc, net_sock[i]);
}
d_log_set_level(D_MSG_TO_STDOUT, D_LOG_LEVEL_FULL);
for (i =0 ; i<TEST_MAX_NUM; i++)
{
net_sock[i] = NULL;
rc = net_open(&net_sock[i], "127.0.0.1", 0, TEST_SERVER_PORT,
SOCK_STREAM, IPPROTO_SCTP);
ABTS_INT_EQUAL(tc, 0, rc);
ABTS_PTR_NOTNULL(tc, net_sock[i]);
}
for (i=0; i< TEST_MAX_NUM; i++)
{
sprintf(inputbuf[i],"asdf%d",i);
memset(outputbuf[i], 0, sizeof(outputbuf[i]));
rc = net_send(net_sock[i], inputbuf[i], strlen(inputbuf[i])+1);
ABTS_INT_EQUAL(tc, strlen(inputbuf[i])+1, rc);
rc = 0;
while (1)
{
int n;
n = net_read(net_sock[i], outputbuf[i], sizeof(outputbuf[1]), 1);
if (n < 0 && net_sock[i]->sndrcv_errno == EAGAIN)
continue;
rc += n;
if (n == 0 || n == 6)
break;
}
ABTS_INT_EQUAL(tc, 6, rc);
ABTS_INT_EQUAL(tc, 6, strlen(outputbuf[i])+1);
ABTS_STR_EQUAL(tc, inputbuf[i], outputbuf[i]);
}
for (i = 0 ; i< TEST_MAX_NUM; i++)
{
rc = net_close(net_sock[i]);
ABTS_INT_EQUAL(tc, 0, rc);
}
stop_stream_sctp_server();
}
static void netlib5(abts_case *tc, void *data)
{
int rc = 0;
net_sock_t *net_sock[TEST_MAX_NUM];
char inputbuf[TEST_MAX_NUM][25];
char outputbuf[TEST_MAX_NUM][25];
int i;
/* Connect to invalid port.
* In SCTP cases, net_open should be success always
*/
for (i =0 ; i<TEST_MAX_NUM; i++)
{
net_sock[i] = NULL;
rc = net_open(&net_sock[i], "127.0.0.1", 0, TEST_SERVER_PORT + 1,
SOCK_SEQPACKET, IPPROTO_SCTP);
ABTS_INT_EQUAL(tc, 0, rc);
ABTS_PTR_NOTNULL(tc, net_sock[i]);
}
for (i = 0 ; i< TEST_MAX_NUM; i++)
{
rc = net_close(net_sock[i]);
ABTS_INT_EQUAL(tc, 0, rc);
}
/* Start SCTP Server */
start_seq_sctp_server();
for (i =0 ; i<TEST_MAX_NUM; i++)
{
net_sock[i] = NULL;
rc = net_open(&net_sock[i], "127.0.0.1", 0, TEST_SERVER_PORT,
SOCK_SEQPACKET, IPPROTO_SCTP);
ABTS_INT_EQUAL(tc, 0, rc);
ABTS_PTR_NOTNULL(tc, net_sock[i]);
}
for (i=0; i< TEST_MAX_NUM; i++)
{
sprintf(inputbuf[i],"asdf%d",i);
memset(outputbuf[i], 0, sizeof(outputbuf[i]));
rc = net_sendto(net_sock[i], inputbuf[i], strlen(inputbuf[i])+1,
inet_addr("127.0.0.1"), TEST_SERVER_PORT);
ABTS_INT_EQUAL(tc, strlen(inputbuf[i])+1, rc);
rc = 0;
while (1)
{
int n;
n = net_read(net_sock[i], outputbuf[i], sizeof(outputbuf[i]), 1);
if (n < 0 && net_sock[i]->sndrcv_errno == EAGAIN)
continue;
rc += n;
if (n == 0 || n == 6)
break;
}
ABTS_INT_EQUAL(tc, 6, rc);
ABTS_INT_EQUAL(tc, 6, strlen(outputbuf[i])+1);
ABTS_STR_EQUAL(tc, inputbuf[i], outputbuf[i]);
}
for (i = 0 ; i< TEST_MAX_NUM; i++)
{
rc = net_close(net_sock[i]);
ABTS_INT_EQUAL(tc, 0, rc);
}
stop_seq_sctp_server();
}
static void netlib6(abts_case *tc, void *data)
{
int rc;
net_ftp_t *ftp_session = NULL;
@@ -741,7 +442,7 @@ static void filter_updu(char *buf, int len)
}
}
static void netlib7(abts_case *tc, void *data)
static void netlib5(abts_case *tc, void *data)
{
net_link_t *net_link = NULL;
int promisc = 1;
@@ -788,7 +489,7 @@ static int make_test_updu(char *src_addr, char *dst_addr, char *buf, int len)
return rc;
}
static void netlib8(abts_case *tc, void *data)
static void netlib6(abts_case *tc, void *data)
{
net_link_t *net_link = NULL;
int promisc = 1;
@@ -827,14 +528,28 @@ abts_suite *testnetlib(abts_suite *suite)
suite = ADD_SUITE(suite);
abts_run_test(suite, netlib1, NULL);
/*
* OpenSUSE OBS
* - Ubuntu 17.04 i586 failed
* - Jinyoung Fixed
*
[ 542s] testnetlib : Line 262: expected <0>, but saw <-1>
[ 542s] [10/30 07:48:38.730] ERRR: connect error(111:Connection refused)(proto:6 remote:127.0.0.1 dport:5121 lport:0) (net_lib.c:353)
[ 542s] [10/30 07:48:38.730] ERRR: connect error(111:Connection refused)(proto:6 remote:127.0.0.1 dport:5121 lport:0) (net_lib.c:353)
[ 542s] [10/30 07:48:38.730] ERRR: connect error(111:Connection refused)(proto:6 remote:127.0.0.1 dport:5121 lport:0) (net_lib.c:353)
[ 542s] [10/30 07:48:38.730] ERRR: connect error(111:Connection refused)(proto:6 remote:127.0.0.1 dport:5121 lport:0) (net_lib.c:353)
[ 542s] [10/30 07:48:38.730] ASSERT: !(net_sock && buffer). Invalid params
[ 542s] (net_lib.c:590)
[ 542s] [10/30 07:48:38.730] ASSERT: !(net_sock). net_sock is NULL
[ 542s] (net_lib.c:408)
[ 542s] [10/30 07:48:38.730] ASSERT: !(net_sock). net_sock is NULL
*/
abts_run_test(suite, netlib2, NULL);
abts_run_test(suite, netlib3, NULL);
abts_run_test(suite, netlib4, NULL);
#if LINUX == 1
abts_run_test(suite, netlib5, NULL);
abts_run_test(suite, netlib6, NULL);
#if LINUX == 1
abts_run_test(suite, netlib7, NULL);
abts_run_test(suite, netlib8, NULL);
#endif
return suite;

325
lib/core/test/testsctp.c Normal file
View File

@@ -0,0 +1,325 @@
#define TRACE_MODULE _testsctp
#include "core_debug.h"
#include "core_net.h"
#include "testutil.h"
#define TEST_SERVER_PORT 5121
#define TEST_BUFFER_SIZE 1024
#define TEST_MAX_NUM 4
static char buffer[TEST_BUFFER_SIZE];
static int sctp_stream_server_started = 0;
static int sctp_seq_server_started = 0;
pthread_t streamserver_tid, seqserver_tid;
net_sock_t *streamserver_sock,*seqserver_sock;
static void *sctp_stream_session_main(void *param)
{
int rc;
net_sock_t *net_sock = (net_sock_t *)param;
while (1)
{
rc = net_read(net_sock, buffer, TEST_BUFFER_SIZE, 1);
if (rc > 0)
{
if (!strncmp(buffer, "QUIT",4))
{
break;
}
else
{
/* Send received data */
rc = net_send(net_sock, buffer, rc);
}
}
else if (rc == 0)
{
/* Timeout */
}
else
{
if (rc != -2 && net_sock->sndrcv_errno != EAGAIN)
break;
}
}
net_close(net_sock);
return NULL;
}
static void start_stream_sctp_session(net_sock_t *net_sock)
{
pthread_t tid;
pthread_create(&tid, NULL, sctp_stream_session_main, (void *)net_sock);
pthread_detach(tid);
return;
}
static void *sctp_stream_server_main(void *param)
{
int rc;
net_sock_t *new_sock;
rc = net_listen(&streamserver_sock,
SOCK_STREAM, IPPROTO_SCTP, TEST_SERVER_PORT);
if (rc != 0)
{
d_error("net_sctp_listen Error(rc = %d)\n",rc);
return NULL;
}
sctp_stream_server_started = 1;
while (1)
{
rc = net_accept(&new_sock, streamserver_sock, 1);
if (rc >0)
{
/* New connection arrived. Start session */
start_stream_sctp_session(new_sock);
}
else if (rc == 0)
{
/* Timeout */
}
else
{
/* Error occured */
break;
}
}
return NULL;
}
static void start_stream_sctp_server()
{
pthread_create(&streamserver_tid, NULL, sctp_stream_server_main, NULL);
while (sctp_stream_server_started == 0)
{
sleep(1);
}
sleep(1);
return;
}
static void stop_stream_sctp_server()
{
net_close(streamserver_sock);
pthread_join(streamserver_tid, NULL);
}
static void *sctp_seq_server_main(void *param)
{
int rc;
rc = net_listen(&seqserver_sock,
SOCK_SEQPACKET, IPPROTO_SCTP, TEST_SERVER_PORT);
if (rc != 0)
{
d_error("net_sctp Error(rc = %d)\n",rc);
return NULL;
}
sctp_seq_server_started = 1;
while (1)
{
d_trace(1,"Wait for data....\n");
rc = net_read(seqserver_sock, buffer, TEST_BUFFER_SIZE, 2);
if (rc >0)
{
d_trace(1,"RECV %d bytes\n", rc);
if (!strncmp(buffer, "QUIT",4))
{
break;
}
else
{
/* Send received data */
rc = net_send(seqserver_sock, buffer, rc);
d_trace(1,"SEND %d bytes\n", rc);
if (rc == -1)
{
printf("error = %d\n", seqserver_sock->sndrcv_errno);
}
}
}
else if (rc == 0)
{
/* Timeout */
}
else
{
/* Error occured */
if (rc != -2 && seqserver_sock->sndrcv_errno != EAGAIN)
break;
}
}
return NULL;
}
static void start_seq_sctp_server()
{
pthread_create(&seqserver_tid, NULL, sctp_seq_server_main, NULL);
while (sctp_seq_server_started == 0)
{
sleep(1);
}
return;
}
static void stop_seq_sctp_server()
{
net_close(seqserver_sock);
pthread_join(seqserver_tid, NULL);
}
static void test_sctp1(abts_case *tc, void *data)
{
int rc = 0;
net_sock_t *net_sock[TEST_MAX_NUM];
char inputbuf[TEST_MAX_NUM][25];
char outputbuf[TEST_MAX_NUM][25];
int i;
/* Start SCTP Server */
start_stream_sctp_server();
/* Connect to invalid port */
d_log_set_level(D_MSG_TO_STDOUT, D_LOG_LEVEL_FATAL);
for (i =0 ; i<TEST_MAX_NUM; i++)
{
net_sock[i] = NULL;
rc = net_open(&net_sock[i], "127.0.0.1", 0,TEST_SERVER_PORT + 1,
SOCK_STREAM, IPPROTO_SCTP);
ABTS_INT_EQUAL(tc, -1, rc);
ABTS_PTR_NULL(tc, net_sock[i]);
}
d_log_set_level(D_MSG_TO_STDOUT, D_LOG_LEVEL_FULL);
for (i =0 ; i<TEST_MAX_NUM; i++)
{
net_sock[i] = NULL;
rc = net_open(&net_sock[i], "127.0.0.1", 0, TEST_SERVER_PORT,
SOCK_STREAM, IPPROTO_SCTP);
ABTS_INT_EQUAL(tc, 0, rc);
ABTS_PTR_NOTNULL(tc, net_sock[i]);
}
for (i=0; i< TEST_MAX_NUM; i++)
{
sprintf(inputbuf[i],"asdf%d",i);
memset(outputbuf[i], 0, sizeof(outputbuf[i]));
rc = net_send(net_sock[i], inputbuf[i], strlen(inputbuf[i])+1);
ABTS_INT_EQUAL(tc, strlen(inputbuf[i])+1, rc);
rc = 0;
while (1)
{
int n;
n = net_read(net_sock[i], outputbuf[i], sizeof(outputbuf[1]), 1);
if (n < 0 && net_sock[i]->sndrcv_errno == EAGAIN)
continue;
rc += n;
if (n == 0 || n == 6)
break;
}
ABTS_INT_EQUAL(tc, 6, rc);
ABTS_INT_EQUAL(tc, 6, strlen(outputbuf[i])+1);
ABTS_STR_EQUAL(tc, inputbuf[i], outputbuf[i]);
}
for (i = 0 ; i< TEST_MAX_NUM; i++)
{
rc = net_close(net_sock[i]);
ABTS_INT_EQUAL(tc, 0, rc);
}
stop_stream_sctp_server();
}
static void test_sctp2(abts_case *tc, void *data)
{
int rc = 0;
net_sock_t *net_sock[TEST_MAX_NUM];
char inputbuf[TEST_MAX_NUM][25];
char outputbuf[TEST_MAX_NUM][25];
int i;
/* Connect to invalid port.
* In SCTP cases, net_open should be success always
*/
for (i =0 ; i<TEST_MAX_NUM; i++)
{
net_sock[i] = NULL;
rc = net_open(&net_sock[i], "127.0.0.1", 0, TEST_SERVER_PORT + 1,
SOCK_SEQPACKET, IPPROTO_SCTP);
ABTS_INT_EQUAL(tc, 0, rc);
ABTS_PTR_NOTNULL(tc, net_sock[i]);
}
for (i = 0 ; i< TEST_MAX_NUM; i++)
{
rc = net_close(net_sock[i]);
ABTS_INT_EQUAL(tc, 0, rc);
}
/* Start SCTP Server */
start_seq_sctp_server();
for (i =0 ; i<TEST_MAX_NUM; i++)
{
net_sock[i] = NULL;
rc = net_open(&net_sock[i], "127.0.0.1", 0, TEST_SERVER_PORT,
SOCK_SEQPACKET, IPPROTO_SCTP);
ABTS_INT_EQUAL(tc, 0, rc);
ABTS_PTR_NOTNULL(tc, net_sock[i]);
}
for (i=0; i< TEST_MAX_NUM; i++)
{
sprintf(inputbuf[i],"asdf%d",i);
memset(outputbuf[i], 0, sizeof(outputbuf[i]));
rc = net_sendto(net_sock[i], inputbuf[i], strlen(inputbuf[i])+1,
inet_addr("127.0.0.1"), TEST_SERVER_PORT);
ABTS_INT_EQUAL(tc, strlen(inputbuf[i])+1, rc);
rc = 0;
while (1)
{
int n;
n = net_read(net_sock[i], outputbuf[i], sizeof(outputbuf[i]), 1);
if (n < 0 && net_sock[i]->sndrcv_errno == EAGAIN)
continue;
rc += n;
if (n == 0 || n == 6)
break;
}
ABTS_INT_EQUAL(tc, 6, rc);
ABTS_INT_EQUAL(tc, 6, strlen(outputbuf[i])+1);
ABTS_STR_EQUAL(tc, inputbuf[i], outputbuf[i]);
}
for (i = 0 ; i< TEST_MAX_NUM; i++)
{
rc = net_close(net_sock[i]);
ABTS_INT_EQUAL(tc, 0, rc);
}
stop_seq_sctp_server();
}
abts_suite *testsctp(abts_suite *suite)
{
suite = ADD_SUITE(suite);
abts_run_test(suite, test_sctp1, NULL);
abts_run_test(suite, test_sctp2, NULL);
return suite;
}

View File

@@ -378,6 +378,15 @@ abts_suite *testtimer(abts_suite *suite)
{
suite = ADD_SUITE(suite)
/*
* OpenSUSE OBS
* - Ubuntu 16.10 i586 failed
* - It is probably VM issue
* [ 661s] testtimer : Line 176: expected <1449351760>, but saw <0>
* [ 661s] Line 305: expected <1019>, but saw <1024>
* [ 661s] Line 372: expected <1019>, but saw <1024>
* [ 661s] FAILED 3 of 4
*/
abts_run_test(suite, test_now, NULL);
abts_run_test(suite, timer_test_1, NULL);
abts_run_test(suite, timer_test_2, NULL);

View File

@@ -63,6 +63,7 @@ abts_suite *testtlv(abts_suite *suite);
abts_suite *testaes(abts_suite *suite);
abts_suite *testsha2(abts_suite *suite);
abts_suite *testnetlib(abts_suite *suite);
abts_suite *testsctp(abts_suite *suite);
abts_suite *testtime(abts_suite *suite);
abts_suite *testtimer(abts_suite *suite);
abts_suite *testthread(abts_suite *suite);

View File

@@ -14,22 +14,22 @@ dnl Must come before AM_INIT_AUTOMAKE.
AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE([1.10 -Wall -Werror foreign])
# Minimum Autoconf version required.
AC_PREREQ(2.63)
# Where to generate output; srcdir location.
AC_CONFIG_HEADERS([include/freeDiameter/config.h])
AC_CANONICAL_HOST
case $host in
*linux*)
sctp=true;
;;
*-apple-darwin*)
AC_DEFINE_UNQUOTED([DISABLE_SCTP],
[1], [Disable SCTP])
sctp=false;
;;
*-freebsd*)
AC_DEFINE_UNQUOTED([SCTP_USE_MAPPED_ADDRESSES],
[1], [Disable SCTP])
sctp=true;
;;
*)
sctp=true;
;;
esac
AM_CONDITIONAL([SCTP], [test x$sctp = xtrue])
@@ -63,17 +63,16 @@ AH_BOTTOM([
#endif /* FD_IS_CONFIG */
])
dnl kernel style compile messages
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
dnl Checks CC and freinds
AC_PROG_MAKE_SET
AC_PROG_CC
AC_PROG_CPP
AC_PROG_INSTALL
AC_PROG_AWK
AC_PROG_SED
AC_PROG_YACC
AC_PROG_LEX
AM_PROG_AR
dnl libtool
LT_INIT([dlopen])
dnl Check Endian
@@ -105,14 +104,29 @@ AC_DEFINE_UNQUOTED([FD_PROJECT_VERSION_API],
[6],
[API version of this package])
PREFIX=$ac_default_prefix
if test "x$prefix" != "xNONE"; then
PREFIX=$prefix
fi
# adl_RECURSIVE_EVAL(VALUE, RESULT)
# =================================
# Interpolate the VALUE in loop until it doesn't change,
# and set the result to $RESULT.
# WARNING: It's easy to get an infinite loop with some unsane input.
# For example ${datadir} becomes ${datarootdir}, and then ${prefix}/share, and
# finally ${prefix} is replaced by the prefix.
AC_DEFUN([adl_RECURSIVE_EVAL],
[_lcl_receval="$1"
$2=`(test "x$prefix" = xNONE && prefix="$ac_default_prefix"
test "x$exec_prefix" = xNONE && exec_prefix="${prefix}"
_lcl_receval_old=''
while test "[$]_lcl_receval_old" != "[$]_lcl_receval"; do
_lcl_receval_old="[$]_lcl_receval"
eval _lcl_receval="\"[$]_lcl_receval\""
done
echo "[$]_lcl_receval")`])
adl_RECURSIVE_EVAL(["${libdir}"], [LIB_DIR])
adl_RECURSIVE_EVAL(["${sysconfdir}"], [SYSCONF_DIR])
AC_DEFINE_UNQUOTED([DEFAULT_CONF_PATH],
["${PREFIX}/etc/freeDiameter"], [Default Configuration Path])
["${SYSCONF_DIR}/nextepc/freeDiameter"], [Default Configuration Path])
AC_DEFINE_UNQUOTED([DEFAULT_EXTENSIONS_PATH],
["${PREFIX}/lib/freeDiameter"], [Default Configuration Path])
["${LIB_DIR}/nextepc"], [Default Extensions Path])
AC_SUBST(PREFIX)
@@ -173,6 +187,6 @@ source code location : ${srcdir}
compiler : ${CC}
compiler flags : ${CFLAGS}
linker flags : ${LDFLAGS} ${LIBS}
default conf path : `eval echo \`echo ${prefix}/etc/freeDiameter\``
default extention path : `eval echo \`echo ${prefix}/lib/freeDiameter\``
config directory : ${SYSCONF_DIR}/nextepc/freeDiameter
extensions directory : ${LIB_DIR}/nextepc
"

View File

@@ -17,6 +17,8 @@ endif
AM_YFLAGS = -p fdd -d
AM_LFLAGS = -p -Cem -Pfdd
BUILT_SOURCES = fdd.tab.h
AM_CPPFLAGS = \
-I$(top_srcdir)/include

View File

@@ -64,7 +64,6 @@ int fd_ep_add_merge( struct fd_list * list, sSA * sa, socklen_t sl, uint32_t fla
case AF_INET:
if (! (flags & EP_ACCEPTALL)) {
if (IN_IS_ADDR_UNSPECIFIED(&ptr.sin->sin_addr)
|| IN_IS_ADDR_LOOPBACK(&ptr.sin->sin_addr)
/* the next one filters both EXPERIMENTAL, BADCLASS and MULTICAST. */
|| ((ntohl(ptr.sin->sin_addr.s_addr) & 0xe0000000) == 0xe0000000)
|| (ptr.sin->sin_addr.s_addr == INADDR_BROADCAST)) {
@@ -78,10 +77,7 @@ int fd_ep_add_merge( struct fd_list * list, sSA * sa, socklen_t sl, uint32_t fla
case AF_INET6:
if (! (flags & EP_ACCEPTALL)) {
if (IN6_IS_ADDR_UNSPECIFIED(&ptr.sin6->sin6_addr)
|| IN6_IS_ADDR_LOOPBACK(&ptr.sin6->sin6_addr)
|| IN6_IS_ADDR_MULTICAST(&ptr.sin6->sin6_addr)
|| IN6_IS_ADDR_LINKLOCAL(&ptr.sin6->sin6_addr)
|| IN6_IS_ADDR_SITELOCAL(&ptr.sin6->sin6_addr)) {
|| IN6_IS_ADDR_MULTICAST(&ptr.sin6->sin6_addr)) {
LOG_A(" DEBUG:fd_ep_add_merge Address was ignored, not added.");
return 0;
}

View File

@@ -347,10 +347,11 @@ struct sysctlhead {
#endif /* EMULATE_SYSCTL */
#ifndef __FreeBSD__
int sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp,
size_t newlen);
#ifndef __FreeBSD__
#define test_bit(ix, pData) ((*pData) & (1<<(ix)))
#define __set_bit(ix, pData) (*pData) |= (1<<(ix))
#define __clear_bit(ix, pData) (*pData) &= ~(1<<(ix))

View File

@@ -122,8 +122,8 @@ int logger_start(const char *path)
ret = unlink(D_LOGD_IPC_PATH);
if (ret != 0)
{
fprintf(stderr, "unlink() failed. (%d:%s)\n",
errno, strerror(errno));
fprintf(stderr, "unlink(`%s`) failed. (%d:%s)\n",
D_LOGD_IPC_PATH, errno, strerror(errno));
return -1;
}
ret = bind(us, (struct sockaddr *)&svaddr, sizeof(svaddr));
@@ -212,5 +212,7 @@ int logger_start(const char *path)
close(us);
unlink(D_LOGD_IPC_PATH);
return 0;
}

23
main.c
View File

@@ -30,7 +30,8 @@ static void show_help(const char *name)
" -h Show help\n"
" -d Start as daemon\n"
" -f Set configuration file name\n"
" -l log_path Fork log daemon with file path to be logged to\n"
" -l log_file Log file path to be logged to\n"
" -p pid_file PID file path\n"
"\n", name);
}
@@ -46,6 +47,12 @@ static int check_signal(int signum)
return 1;
}
case SIGHUP:
{
d_info("SIGHUP received");
app_logger_restart();
break;
}
case SIGUSR1:
{
break;
@@ -73,12 +80,14 @@ int main(int argc, char *argv[])
*
* Keep the order of starting-up
*/
status_t rv;
char *config_path = NULL;
char *log_path = NULL;
char *pid_path = NULL;
while (1)
{
int opt = getopt (argc, argv, "vhdf:l:");
int opt = getopt (argc, argv, "vhdf:l:p:");
if (opt == -1)
break;
@@ -114,6 +123,9 @@ int main(int argc, char *argv[])
case 'l':
log_path = optarg;
break;
case 'p':
pid_path = optarg;
break;
default:
show_help(argv[0]);
return EXIT_FAILURE;
@@ -126,8 +138,13 @@ int main(int argc, char *argv[])
atexit(terminate);
core_initialize();
if (app_initialize(config_path, log_path) != CORE_OK)
app_log_pid(pid_path);
rv = app_initialize(config_path, log_path);
if (rv != CORE_OK)
{
if (rv == CORE_EAGAIN)
return EXIT_SUCCESS;
d_fatal("NextEPC initialization failed. Aborted");
return EXIT_FAILURE;
}

View File

@@ -10,57 +10,46 @@ COMMON_INCLUDES = app.h
libmme_la_SOURCES = $(COMMON_INCLUDES) mme.c $(COMMON_SOURCES)
libmme_la_DEPENDENCIES = \
$(top_srcdir)/lib/base/libbase.la \
$(top_srcdir)/lib/logger/liblogger.la \
$(top_srcdir)/src/mme/libmme.la
libmme_la_LIBADD = \
$(top_srcdir)/lib/base/libbase.la \
$(top_srcdir)/lib/logger/liblogger.la \
$(top_srcdir)/src/mme/libmme.la
libhss_la_SOURCES = $(COMMON_INCLUDES) hss.c $(COMMON_SOURCES)
libhss_la_DEPENDENCIES = \
$(top_srcdir)/lib/base/libbase.la \
$(top_srcdir)/lib/logger/liblogger.la \
$(top_srcdir)/src/hss/libhss.la
libhss_la_LIBADD = \
$(top_srcdir)/lib/base/libbase.la \
$(top_srcdir)/lib/logger/liblogger.la \
$(top_srcdir)/src/hss/libhss.la
libsgw_la_SOURCES = $(COMMON_INCLUDES) sgw.c $(COMMON_SOURCES)
libsgw_la_DEPENDENCIES = \
$(top_srcdir)/lib/base/libbase.la \
$(top_srcdir)/lib/logger/liblogger.la \
$(top_srcdir)/src/sgw/libsgw.la
libsgw_la_LIBADD = \
$(top_srcdir)/lib/base/libbase.la \
$(top_srcdir)/lib/logger/liblogger.la \
$(top_srcdir)/src/sgw/libsgw.la
libpgw_la_SOURCES = $(COMMON_INCLUDES) pgw.c $(COMMON_SOURCES)
libpgw_la_DEPENDENCIES = \
$(top_srcdir)/lib/base/libbase.la \
$(top_srcdir)/lib/logger/liblogger.la \
$(top_srcdir)/src/pgw/libpgw.la
libpgw_la_LIBADD = \
$(top_srcdir)/lib/base/libbase.la \
$(top_srcdir)/lib/logger/liblogger.la \
$(top_srcdir)/src/pgw/libpgw.la
libpcrf_la_SOURCES = $(COMMON_INCLUDES) pcrf.c $(COMMON_SOURCES)
libpcrf_la_DEPENDENCIES = \
$(top_srcdir)/lib/base/libbase.la \
$(top_srcdir)/lib/logger/liblogger.la \
$(top_srcdir)/src/pcrf/libpcrf.la
libpcrf_la_LIBADD = \
$(top_srcdir)/lib/base/libbase.la \
$(top_srcdir)/lib/logger/liblogger.la \
$(top_srcdir)/src/pcrf/libpcrf.la
libepc_la_SOURCES = $(COMMON_INCLUDES) epc.c $(COMMON_SOURCES)
libepc_la_DEPENDENCIES = \
$(top_srcdir)/lib/base/libbase.la \
$(top_srcdir)/lib/logger/liblogger.la \
$(top_srcdir)/src/mme/libmme.la \
$(top_srcdir)/src/hss/libhss.la \
$(top_srcdir)/src/sgw/libsgw.la \
@@ -68,7 +57,6 @@ libepc_la_DEPENDENCIES = \
$(top_srcdir)/src/pcrf/libpcrf.la
libepc_la_LIBADD = \
$(top_srcdir)/lib/base/libbase.la \
$(top_srcdir)/lib/logger/liblogger.la \
$(top_srcdir)/src/mme/libmme.la \
$(top_srcdir)/src/hss/libhss.la \
$(top_srcdir)/src/sgw/libsgw.la \
@@ -77,13 +65,14 @@ libepc_la_LIBADD = \
AM_CPPFLAGS = \
-I$(top_srcdir)/lib/core/include \
-I$(top_srcdir)/lib/logger \
-I$(top_srcdir)/lib/base
AM_CFLAGS = \
-Wall -Werror
DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
DEFS = @DEFS@ \
-DSYSCONF_DIR=\"$(sysconfdir)/\" \
-DLOCALSTATE_DIR=\"$(localstatedir)/\"
MAINTAINERCLEANFILES = Makefile.in
MOSTLYCLEANFILES = core *.stackdump

View File

@@ -8,17 +8,24 @@
extern "C" {
#endif /* __cplusplus */
CORE_DECLARE(status_t) app_initialize(char *config_path, char *log_path);
extern const char *app_name;
CORE_DECLARE(status_t) app_initialize(
const char *config_path, const char *log_path);
CORE_DECLARE(void) app_terminate(void);
CORE_DECLARE(status_t) app_will_initialize(char *config_path, char *log_path);
CORE_DECLARE(status_t) app_did_initialize(char *config_path, char *log_path);
CORE_DECLARE(status_t) app_will_initialize(
const char *config_path, const char *log_path);
CORE_DECLARE(status_t) app_did_initialize(void);
CORE_DECLARE(void) app_will_terminate(void);
CORE_DECLARE(void) app_did_terminate(void);
CORE_DECLARE(status_t) config_initialize(char *config_path);
CORE_DECLARE(status_t) config_initialize(const char *config_path);
CORE_DECLARE(void) config_terminate(void);
CORE_DECLARE(status_t) app_logger_restart(void);
CORE_DECLARE(status_t) app_log_pid(const char *pid_path);
CORE_DECLARE(status_t) mme_initialize();
CORE_DECLARE(void) mme_terminate(void);

View File

@@ -19,7 +19,9 @@ static semaphore_id sgw_sem2 = 0;
static semaphore_id hss_sem1 = 0;
static semaphore_id hss_sem2 = 0;
status_t app_initialize(char *config_path, char *log_path)
const char *app_name = "epc";
status_t app_initialize(const char *config_path, const char *log_path)
{
pid_t pid;
status_t rv;
@@ -39,7 +41,7 @@ status_t app_initialize(char *config_path, char *log_path)
semaphore_create(&pcrf_sem1, 0); /* copied to PCRF/PGW/SGW/HSS process */
semaphore_create(&pcrf_sem2, 0); /* copied to PCRF/PGW/SGW/HSS process */
if (context_self()->hidden.disable_pcrf == 0)
if (context_self()->node.disable_pcrf == 0)
{
pid = fork();
d_assert(pid >= 0, _exit(EXIT_FAILURE), "fork() failed");
@@ -83,7 +85,7 @@ status_t app_initialize(char *config_path, char *log_path)
semaphore_create(&pgw_sem1, 0); /* copied to PGW/SGW/HSS process */
semaphore_create(&pgw_sem2, 0); /* copied to PGW/SGW/HSS process */
if (context_self()->hidden.disable_pgw == 0)
if (context_self()->node.disable_pgw == 0)
{
pid = fork();
d_assert(pid >= 0, _exit(EXIT_FAILURE), "fork() failed");
@@ -131,7 +133,7 @@ status_t app_initialize(char *config_path, char *log_path)
semaphore_create(&sgw_sem1, 0); /* copied to SGW/HSS process */
semaphore_create(&sgw_sem2, 0); /* copied to SGW/HSS process */
if (context_self()->hidden.disable_sgw == 0)
if (context_self()->node.disable_sgw == 0)
{
pid = fork();
d_assert(pid >= 0, _exit(EXIT_FAILURE), "fork() failed");
@@ -181,7 +183,7 @@ status_t app_initialize(char *config_path, char *log_path)
semaphore_create(&hss_sem1, 0); /* copied to HSS process */
semaphore_create(&hss_sem2, 0); /* copied to HSS process */
if (context_self()->hidden.disable_hss == 0)
if (context_self()->node.disable_hss == 0)
{
pid = fork();
d_assert(pid >= 0, _exit(EXIT_FAILURE), "fork() failed");
@@ -226,7 +228,7 @@ status_t app_initialize(char *config_path, char *log_path)
if (hss_sem1) semaphore_wait(hss_sem1);
}
rv = app_did_initialize(config_path, log_path);
rv = app_did_initialize();
if (rv != CORE_OK) return rv;
d_trace(1, "MME try to initialize\n");
@@ -245,7 +247,7 @@ void app_terminate(void)
mme_terminate();
d_trace(1, "MME terminate...done\n");
if (context_self()->hidden.disable_hss == 0)
if (context_self()->node.disable_hss == 0)
{
if (hss_sem2) semaphore_post(hss_sem2);
if (hss_sem1) semaphore_wait(hss_sem1);
@@ -253,7 +255,7 @@ void app_terminate(void)
if (hss_sem1) semaphore_delete(hss_sem1);
if (hss_sem2) semaphore_delete(hss_sem2);
if (context_self()->hidden.disable_sgw == 0)
if (context_self()->node.disable_sgw == 0)
{
if (sgw_sem2) semaphore_post(sgw_sem2);
if (sgw_sem1) semaphore_wait(sgw_sem1);
@@ -261,7 +263,7 @@ void app_terminate(void)
if (sgw_sem1) semaphore_delete(sgw_sem1);
if (sgw_sem2) semaphore_delete(sgw_sem2);
if (context_self()->hidden.disable_pgw == 0)
if (context_self()->node.disable_pgw == 0)
{
if (pgw_sem2) semaphore_post(pgw_sem2);
if (pgw_sem1) semaphore_wait(pgw_sem1);
@@ -269,7 +271,7 @@ void app_terminate(void)
if (pgw_sem1) semaphore_delete(pgw_sem1);
if (pgw_sem2) semaphore_delete(pgw_sem2);
if (context_self()->hidden.disable_pcrf == 0)
if (context_self()->node.disable_pcrf == 0)
{
if (pcrf_sem2) semaphore_post(pcrf_sem2);
if (pcrf_sem1) semaphore_wait(pcrf_sem1);

View File

@@ -7,7 +7,9 @@
#include "context.h"
#include "app.h"
status_t app_initialize(char *config_path, char *log_path)
const char *app_name = "hss";
status_t app_initialize(const char *config_path, const char *log_path)
{
status_t rv;
int others = 0;
@@ -26,7 +28,7 @@ status_t app_initialize(char *config_path, char *log_path)
d_assert(rv == CORE_OK, return rv, "Failed to intialize HSS");
d_trace(1, "HSS initialize...done\n");
rv = app_did_initialize(config_path, log_path);
rv = app_did_initialize();
if (rv != CORE_OK) return rv;
return CORE_OK;

View File

@@ -297,6 +297,12 @@ status_t hss_db_auth_info(
utf8 = (char *)bson_iter_utf8(&inner_iter, &length);
memcpy(auth_info->k, CORE_HEX(utf8, length, buf), HSS_KEY_LEN);
}
else if (!strcmp(key, "opc") && BSON_ITER_HOLDS_UTF8(&inner_iter))
{
utf8 = (char *)bson_iter_utf8(&inner_iter, &length);
auth_info->use_opc = 1;
memcpy(auth_info->opc, CORE_HEX(utf8, length, buf), HSS_KEY_LEN);
}
else if (!strcmp(key, "op") && BSON_ITER_HOLDS_UTF8(&inner_iter))
{
utf8 = (char *)bson_iter_utf8(&inner_iter, &length);

View File

@@ -15,6 +15,8 @@ extern "C" {
typedef struct _hss_db_auth_info_t {
c_uint8_t k[HSS_KEY_LEN];
c_uint8_t use_opc;
c_uint8_t opc[HSS_KEY_LEN];
c_uint8_t op[HSS_KEY_LEN];
c_uint8_t amf[HSS_AMF_LEN];
c_uint8_t rand[RAND_LEN];

View File

@@ -105,7 +105,10 @@ static int hss_s6a_air_cb( struct msg **msg, struct avp *avp,
memcpy(visited_plmn_id, hdr->avp_value->os.data, hdr->avp_value->os.len);
#endif
milenage_opc(auth_info.k, auth_info.op, opc);
if (auth_info.use_opc)
memcpy(opc, auth_info.opc, sizeof(opc));
else
milenage_opc(auth_info.k, auth_info.op, opc);
milenage_generate(opc, auth_info.amf, auth_info.k,
core_uint64_to_buffer(auth_info.sqn, HSS_SQN_LEN, sqn), auth_info.rand,
autn, ik, ck, ak, xres, &xres_len);

View File

@@ -2,23 +2,32 @@
#include "core_debug.h"
#include "core_thread.h"
#include "core_file.h"
#include "context.h"
#include "logger.h"
#include "app.h"
static thread_id logger_thread = 0;
static void *THREAD_FUNC logger_main(thread_id id, void *data);
#define DEFAULT_CONFIG_FILE_PATH SYSCONF_DIR PACKAGE "/nextepc.conf"
#define DEFAULT_RUNTIME_DIR_PATH LOCALSTATE_DIR "run/"
status_t app_will_initialize(char *config_path, char *log_path)
static status_t app_logger_init();
static status_t app_logger_final();
static status_t app_logger_start();
static status_t app_logger_stop();
status_t app_will_initialize(const char *config_path, const char *log_path)
{
status_t rv;
int others = 0;
context_init();
rv = context_read_file(config_path);
context_self()->config.path = config_path;
if (context_self()->config.path == NULL)
context_self()->config.path = DEFAULT_CONFIG_FILE_PATH;
rv = context_read_file();
if (rv != CORE_OK) return rv;
rv = context_parse_config();
@@ -29,6 +38,10 @@ status_t app_will_initialize(char *config_path, char *log_path)
{
d_trace_level(&_app_init, others);
}
context_self()->log.path = log_path;
rv = app_logger_init();
if (rv != CORE_OK) return rv;
if (context_self()->db_uri)
{
@@ -36,34 +49,20 @@ status_t app_will_initialize(char *config_path, char *log_path)
if (rv != CORE_OK) return rv;
}
return CORE_OK;
return rv;
}
status_t app_did_initialize(char *config_path, char *log_path)
status_t app_did_initialize(void)
{
status_t rv;
status_t rv = app_logger_start();
if (rv != CORE_OK) return rv;
if (log_path)
context_self()->log_path = log_path;
if (context_self()->log_path)
{
d_print(" Logging '%s'\n", context_self()->log_path);
rv = thread_create(&logger_thread, NULL,
logger_main, context_self()->log_path);
if (rv != CORE_OK) return rv;
}
return CORE_OK;
return rv;
}
void app_will_terminate(void)
{
if (logger_thread)
{
thread_delete(logger_thread);
}
app_logger_stop();
}
void app_did_terminate(void)
@@ -73,16 +72,172 @@ void app_did_terminate(void)
context_db_final();
}
app_logger_final();
context_final();
}
static void *THREAD_FUNC logger_main(thread_id id, void *data)
status_t app_log_pid(const char *pid_path)
{
int ret;
char *path = data;
file_t *pid_file = NULL;
file_info_t finfo;
static pid_t saved_pid = -1;
pid_t mypid;
status_t rv;
char default_pid_path[MAX_FILEPATH_LEN];
char buf[128];
ret = logger_start(path);
d_assert(ret == 0, return NULL, "Failed to intialize Logger");
if (pid_path == NULL)
{
snprintf(default_pid_path, sizeof(default_pid_path),
"%snextepc-%sd/pid", DEFAULT_RUNTIME_DIR_PATH, app_name);
pid_path = default_pid_path;
}
return NULL;
mypid = getpid();
if (mypid != saved_pid
&& file_stat(&finfo, pid_path, FILE_INFO_MTIME) == CORE_OK)
{
d_warn("pid file %s overwritten -- Unclean "
"shutdown of previous NextEPC run?", pid_path);
}
if ((rv = file_open(&pid_file, pid_path,
FILE_WRITE | FILE_CREATE | FILE_TRUNCATE,
FILE_UREAD | FILE_UWRITE | FILE_GREAD | FILE_WREAD)) != CORE_OK)
{
d_error("could not create %s", pid_path);
return CORE_ERROR;
}
snprintf(buf, sizeof(buf), "%" C_PID_T_FMT "\r\n", mypid);
file_puts(buf, pid_file);
file_close(pid_file);
saved_pid = mypid;
d_print(" PID[%" C_PID_T_FMT "] : '%s'\n", saved_pid, pid_path);
return CORE_OK;
}
status_t app_logger_restart()
{
app_logger_stop();
app_logger_final();
app_logger_init();
app_logger_start();
return CORE_OK;
}
static status_t app_logger_init()
{
status_t rv;
if (context_self()->log.console >= 0)
{
rv = d_msg_console_init(context_self()->log.console);
if (rv != CORE_OK)
{
d_error("console logger init failed : (file:%d)",
context_self()->log.console);
return rv;
}
d_print(" Console Logging '%d'\n", context_self()->log.console);
}
if (context_self()->log.syslog)
{
d_msg_syslog_init(context_self()->log.syslog);
d_print(" Syslog Logging '%s'\n", context_self()->log.syslog);
}
if (context_self()->log.socket.file &&
context_self()->log.socket.unix_domain)
{
if (context_self()->log.path)
context_self()->log.socket.file = context_self()->log.path;
rv = d_msg_socket_init(context_self()->log.socket.unix_domain);
if (rv != CORE_OK)
{
d_error("socket logger init failed : (unix_domain:%s, file:%s)",
context_self()->log.socket.unix_domain,
context_self()->log.socket.file);
return rv;
}
d_print(" Socket Logging '%s' on %s\n",
context_self()->log.socket.file,
context_self()->log.socket.unix_domain);
}
if (context_self()->log.file)
{
if (context_self()->log.path)
context_self()->log.file = context_self()->log.path;
rv = d_msg_file_init(context_self()->log.file);
if (rv != CORE_OK)
{
d_error("file logger init failed : (file:%s)",
context_self()->log.file);
return rv;
}
d_print(" File Logging '%s'\n", context_self()->log.file);
}
return CORE_OK;
}
static status_t app_logger_start()
{
status_t rv;
if (context_self()->log.socket.file &&
context_self()->log.socket.unix_domain)
{
rv = d_msg_socket_start(context_self()->log.socket.file);
if (rv != CORE_OK)
{
d_error("socket logger start failed : (unix_domain:%s, file:%s)",
context_self()->log.socket.unix_domain,
context_self()->log.socket.file);
return rv;
}
}
return CORE_OK;
}
static status_t app_logger_stop()
{
if (context_self()->log.socket.file &&
context_self()->log.socket.unix_domain)
{
d_msg_socket_stop();
}
return CORE_OK;
}
static status_t app_logger_final()
{
if (context_self()->log.console >= 0)
{
d_msg_console_final();
}
if (context_self()->log.syslog)
{
d_msg_syslog_final();
}
if (context_self()->log.socket.file &&
context_self()->log.socket.unix_domain)
{
d_msg_socket_final();
}
if (context_self()->log.file)
{
d_msg_file_final();
}
return CORE_OK;
}

View File

@@ -7,7 +7,9 @@
#include "context.h"
#include "app.h"
status_t app_initialize(char *config_path, char *log_path)
const char *app_name = "mme";
status_t app_initialize(const char *config_path, const char *log_path)
{
status_t rv;
int others = 0;
@@ -26,7 +28,7 @@ status_t app_initialize(char *config_path, char *log_path)
d_assert(rv == CORE_OK, return rv, "Failed to intialize MME");
d_trace(1, "MME initialize...done\n");
rv = app_did_initialize(config_path, log_path);
rv = app_did_initialize();
if (rv != CORE_OK) return rv;
return CORE_OK;
@@ -42,3 +44,4 @@ void app_terminate(void)
app_did_terminate();
}

View File

@@ -22,6 +22,12 @@ libmme_la_SOURCES = \
mme_gtp_path.c mme_s11_build.c mme_s11_handler.c \
mme_sm.c
if USRSCTP
libmme_la_SOURCES += s1ap_usrsctp.c
else
libmme_la_SOURCES += s1ap_sctp.c
endif
libmme_la_DEPENDENCIES = \
$(top_srcdir)/lib/core/src/libcore.la \
$(top_srcdir)/lib/s1ap/libs1ap.la \

View File

@@ -12,6 +12,7 @@
#include "nas_conv.h"
#include "mme_context.h"
#include "mme_event.h"
#include "s1ap_path.h"
#define MAX_CELL_PER_ENB 8
@@ -41,13 +42,13 @@ status_t mme_context_init()
list_init(&self.sgw_list);
index_init(&mme_enb_pool, MAX_NUM_OF_ENB);
list_init(&self.enb_list);
index_init(&mme_ue_pool, MAX_POOL_OF_UE);
index_init(&enb_ue_pool, MAX_POOL_OF_UE);
index_init(&mme_sess_pool, MAX_POOL_OF_SESS);
index_init(&mme_bearer_pool, MAX_POOL_OF_BEARER);
self.s1ap_sock_hash = hash_make();
self.enb_id_hash = hash_make();
self.mme_ue_s1ap_id_hash = hash_make();
self.imsi_ue_hash = hash_make();
self.guti_ue_hash = hash_make();
@@ -69,12 +70,15 @@ status_t mme_context_final()
mme_enb_remove_all();
mme_ue_remove_all();
d_assert(self.s1ap_sock_hash, , "Null param");
hash_destroy(self.s1ap_sock_hash);
d_assert(self.enb_id_hash, , "Null param");
hash_destroy(self.enb_id_hash);
d_assert(self.mme_ue_s1ap_id_hash, , "Null param");
hash_destroy(self.mme_ue_s1ap_id_hash);
d_assert(self.imsi_ue_hash, , "Null param");
hash_destroy(self.imsi_ue_hash);
d_assert(self.guti_ue_hash, , "Null param");
hash_destroy(self.guti_ue_hash);
@@ -101,7 +105,7 @@ static status_t mme_context_prepare()
self.relative_capacity = 0xff;
self.s1ap_port = S1AP_SCTP_PORT;
self.s11_port = GTPV2_C_UDP_PORT;
self.gtpc_port = GTPV2_C_UDP_PORT;
self.s5c_port = GTPV2_C_UDP_PORT;
return CORE_OK;
@@ -121,9 +125,9 @@ static status_t mme_context_validation()
context_self()->config.path);
return CORE_ERROR;
}
if (self.s11_addr == 0)
if (self.gtpc_addr == 0)
{
d_error("No MME.NEWORK.S11_IPV4 in '%s'",
d_error("No MME.NEWORK.GTPC_IPV4 in '%s'",
context_self()->config.path);
return CORE_ERROR;
}
@@ -139,7 +143,7 @@ static status_t mme_context_validation()
{
if (sgw->addr == 0)
{
d_error("No SGW.NEWORK.S11_IPV4 in '%s'",
d_error("No SGW.NEWORK.GTPC_IPV4 in '%s'",
context_self()->config.path);
return CORE_ERROR;
}
@@ -312,15 +316,15 @@ status_t mme_context_parse_config()
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s1ap_port = atoi(v);
}
else if (jsmntok_equal(json, t+m, "S11_IPV4") == 0)
else if (jsmntok_equal(json, t+m, "GTPC_IPV4") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s11_addr = inet_addr(v);
if (v) self.gtpc_addr = inet_addr(v);
}
else if (jsmntok_equal(json, t+m, "S11_PORT") == 0)
else if (jsmntok_equal(json, t+m, "GTPC_PORT") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s11_port = atoi(v);
if (v) self.gtpc_port = atoi(v);
}
}
}
@@ -645,12 +649,12 @@ status_t mme_context_parse_config()
{
n += (t+m)->size;
if (jsmntok_equal(json, t+m, "S11_IPV4") == 0)
if (jsmntok_equal(json, t+m, "GTPC_IPV4") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) sgw->addr = inet_addr(v);
}
else if (jsmntok_equal(json, t+m, "S11_PORT") == 0)
else if (jsmntok_equal(json, t+m, "GTPC_PORT") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) sgw->port = atoi(v);
@@ -693,12 +697,12 @@ status_t mme_context_parse_config()
{
n += (t+m)->size;
if (jsmntok_equal(json, t+m, "S5C_IPV4") == 0)
if (jsmntok_equal(json, t+m, "GTPC_IPV4") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s5c_addr = inet_addr(v);
}
else if (jsmntok_equal(json, t+m, "S5C_PORT") == 0)
else if (jsmntok_equal(json, t+m, "GTPC_PORT") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s5c_port = atoi(v);
@@ -759,6 +763,13 @@ status_t mme_context_setup_trace_module()
d_trace_level(&_s1ap_build, s1ap);
extern int _s1ap_handler;
d_trace_level(&_s1ap_handler, s1ap);
#if USE_USRSCTP == 1
extern int _s1ap_usrsctp;
d_trace_level(&_s1ap_usrsctp, s1ap);
#else
extern int _s1ap_sctp;
d_trace_level(&_s1ap_sctp, s1ap);
#endif
extern int _s1ap_path;
d_trace_level(&_s1ap_path, s1ap);
extern int _s1ap_recv;
@@ -908,7 +919,7 @@ mme_sgw_t* mme_sgw_next(mme_sgw_t *sgw)
return list_next(sgw);
}
mme_enb_t* mme_enb_add(net_sock_t *s1ap_sock)
mme_enb_t* mme_enb_add(net_sock_t *sock)
{
mme_enb_t *enb = NULL;
event_t e;
@@ -916,18 +927,16 @@ mme_enb_t* mme_enb_add(net_sock_t *s1ap_sock)
index_alloc(&mme_enb_pool, &enb);
d_assert(enb, return NULL, "Null param");
/* IMPORTANT!
* eNB Index is saved in net_sock_t structure */
s1ap_sock->app_index = enb->index;
enb->s1ap_sock = s1ap_sock;
enb->s1ap_sock = sock;
list_init(&enb->enb_ue_list);
list_append(&self.enb_list, enb);
event_set_param1(&e, (c_uintptr_t)enb->index);
hash_set(self.s1ap_sock_hash,
&enb->s1ap_sock, sizeof(enb->s1ap_sock), enb);
event_set_param1(&e, (c_uintptr_t)enb->s1ap_sock);
fsm_create(&enb->sm, s1ap_state_initial, s1ap_state_final);
fsm_init(&enb->sm, &e);
return enb;
}
@@ -936,17 +945,21 @@ status_t mme_enb_remove(mme_enb_t *enb)
event_t e;
d_assert(enb, return CORE_ERROR, "Null param");
d_assert(enb->s1ap_sock, return CORE_ERROR, "Null param");
event_set_param1(&e, (c_uintptr_t)enb->index);
event_set_param1(&e, (c_uintptr_t)enb->s1ap_sock);
fsm_final(&enb->sm, &e);
fsm_clear(&enb->sm);
hash_set(self.s1ap_sock_hash,
&enb->s1ap_sock, sizeof(enb->s1ap_sock), NULL);
if (enb->enb_id)
hash_set(self.enb_id_hash, &enb->enb_id, sizeof(enb->enb_id), NULL);
enb_ue_remove_in_enb(enb);
net_unregister_sock(enb->s1ap_sock);
net_close(enb->s1ap_sock);
s1ap_sctp_close(enb->s1ap_sock);
list_remove(&self.enb_list, enb);
index_free(&mme_enb_pool, enb);
return CORE_OK;
@@ -954,16 +967,13 @@ status_t mme_enb_remove(mme_enb_t *enb)
status_t mme_enb_remove_all()
{
mme_enb_t *enb = NULL, *next_enb = NULL;
enb = mme_enb_first();
while (enb)
hash_index_t *hi = NULL;
mme_enb_t *enb = NULL;
for (hi = mme_enb_first(); hi; hi = mme_enb_next(hi))
{
next_enb = mme_enb_next(enb);
enb = mme_enb_this(hi);
mme_enb_remove(enb);
enb = next_enb;
}
return CORE_OK;
@@ -977,44 +987,44 @@ mme_enb_t* mme_enb_find(index_t index)
mme_enb_t* mme_enb_find_by_sock(net_sock_t *sock)
{
mme_enb_t *enb = NULL;
enb = mme_enb_first();
while (enb)
{
if (sock == enb->s1ap_sock)
break;
d_assert(sock, return NULL,"Invalid param");
return (mme_enb_t *)hash_get(self.s1ap_sock_hash, &sock, sizeof(sock));
enb = mme_enb_next(enb);
}
return enb;
return NULL;
}
mme_enb_t* mme_enb_find_by_enb_id(c_uint32_t enb_id)
{
mme_enb_t *enb = NULL;
enb = list_first(&self.enb_list);
while (enb)
{
if (enb_id == enb->enb_id)
break;
enb = list_next(enb);
}
return enb;
d_assert(enb_id, return NULL,"Invalid param");
return (mme_enb_t *)hash_get(self.enb_id_hash, &enb_id, sizeof(enb_id));
}
mme_enb_t* mme_enb_first()
status_t mme_enb_set_enb_id(mme_enb_t *enb, c_uint32_t enb_id)
{
return list_first(&self.enb_list);
d_assert(enb, return CORE_ERROR, "Invalid param");
d_assert(enb_id, return CORE_ERROR, "Invalid param");
enb->enb_id = enb_id;
hash_set(self.enb_id_hash, &enb->enb_id, sizeof(enb->enb_id), enb);
return CORE_OK;
}
mme_enb_t* mme_enb_next(mme_enb_t *enb)
hash_index_t* mme_enb_first()
{
return list_next(enb);
d_assert(self.s1ap_sock_hash, return NULL, "Null param");
return hash_first(self.s1ap_sock_hash);
}
hash_index_t* mme_enb_next(hash_index_t *hi)
{
return hash_next(hi);
}
mme_enb_t *mme_enb_this(hash_index_t *hi)
{
d_assert(hi, return NULL, "Null param");
return hash_this_val(hi);
}
/** enb_ue_context handling function */
@@ -1152,7 +1162,7 @@ mme_ue_t* mme_ue_add(enb_ue_t *enb_ue)
list_init(&mme_ue->sess_list);
mme_ue->mme_s11_teid = mme_ue->index;
mme_ue->mme_s11_addr = mme_self()->s11_addr;
mme_ue->mme_s11_addr = mme_self()->gtpc_addr;
/* Create t3413 timer */
mme_ue->t3413 = timer_create(&self.tm_service, MME_EVT_EMM_T3413,

View File

@@ -55,9 +55,9 @@ typedef struct _mme_context_t {
c_uint16_t s1ap_port; /* MME S1AP local port */
net_sock_t *s1ap_sock; /* MME S1AP local listen socket */
c_uint32_t s11_addr; /* MME S11 local address */
c_uint16_t s11_port; /* MME S11 local port */
net_sock_t *s11_sock; /* MME S11 local listen socket */
c_uint32_t gtpc_addr; /* MME GTPC local address */
c_uint16_t gtpc_port; /* MME GTPC local port */
net_sock_t *gtpc_sock; /* MME GTPC local listen socket */
c_uint32_t s5c_addr; /* PGW S5C remote address */
c_uint16_t s5c_port; /* PGW S5C remote port */
@@ -99,8 +99,9 @@ typedef struct _mme_context_t {
c_uint32_t t3413_value; /* Paging retry timer */
list_t sgw_list; /* SGW GTP Node List */
list_t enb_list; /* eNB S1AP Node List */
hash_t *s1ap_sock_hash; /* hash table for S1AP IP address */
hash_t *enb_id_hash; /* hash table for ENB-ID */
hash_t *mme_ue_s1ap_id_hash; /* hash table for MME-UE-S1AP-ID */
hash_t *imsi_ue_hash; /* hash table (IMSI : MME_UE) */
hash_t *guti_ue_hash; /* hash table (GUTI : MME_UE) */
@@ -111,8 +112,10 @@ typedef struct _mme_enb_t {
index_t index; /* An index of this node */
fsm_t sm; /* A state machine */
c_uint32_t enb_id; /* eNB_ID received from eNB */
net_sock_t *s1ap_sock;
c_uint32_t enb_id; /* eNB_ID received from eNB */
c_uint32_t s1ap_addr; /* eNB S1AP IP address */
c_uint16_t s1ap_port; /* eNB S1AP Port */
net_sock_t *s1ap_sock; /* eNB S1AP Socket */
c_uint8_t num_of_tai;
tai_t tai[MAX_NUM_OF_TAC * MAX_NUM_OF_BPLMN];
@@ -441,14 +444,17 @@ CORE_DECLARE(mme_sgw_t*) mme_sgw_find(c_uint32_t addr, c_uint16_t port);
CORE_DECLARE(mme_sgw_t*) mme_sgw_first(void);
CORE_DECLARE(mme_sgw_t*) mme_sgw_next(mme_sgw_t *sgw);
CORE_DECLARE(mme_enb_t*) mme_enb_add(net_sock_t *s1ap_sock);
CORE_DECLARE(mme_enb_t*) mme_enb_add(net_sock_t *sock);
CORE_DECLARE(status_t) mme_enb_remove(mme_enb_t *enb);
CORE_DECLARE(status_t) mme_enb_remove_all(void);
CORE_DECLARE(mme_enb_t*) mme_enb_find(index_t index);
CORE_DECLARE(mme_enb_t*) mme_enb_find_by_sock(net_sock_t *sock);
CORE_DECLARE(mme_enb_t*) mme_enb_find_by_enb_id(c_uint32_t enb_id);
CORE_DECLARE(mme_enb_t*) mme_enb_first(void);
CORE_DECLARE(mme_enb_t*) mme_enb_next(mme_enb_t *enb);
CORE_DECLARE(status_t) mme_enb_set_enb_id(
mme_enb_t *enb, c_uint32_t enb_id);
CORE_DECLARE(hash_index_t *) mme_enb_first();
CORE_DECLARE(hash_index_t *) mme_enb_next(hash_index_t *hi);
CORE_DECLARE(mme_enb_t *) mme_enb_this(hash_index_t *hi);
CORE_DECLARE(mme_ue_t*) mme_ue_add(enb_ue_t *enb_ue);
CORE_DECLARE(status_t) mme_ue_remove(mme_ue_t *mme_ue);

View File

@@ -15,7 +15,6 @@ static int _gtpv2_c_recv_cb(net_sock_t *sock, void *data)
pkbuf_t *pkbuf = NULL;
c_uint32_t addr;
c_uint16_t port;
mme_sgw_t *sgw = NULL;
d_assert(sock, return -1, "Null param");
@@ -31,19 +30,14 @@ static int _gtpv2_c_recv_cb(net_sock_t *sock, void *data)
addr = sock->remote.sin_addr.s_addr;
port = ntohs(sock->remote.sin_port);
sgw = mme_sgw_find(addr, port);
d_assert(sgw, return -1, "Can't find SGW from [%s:%d]",
INET_NTOP(&addr, buf), port);
sgw->sock = sock; /* Is it needed? */
d_trace(10, "S11_PDU is received from SGW[%s:%d]\n",
INET_NTOP(&addr, buf), port);
d_trace_hex(10, pkbuf->payload, pkbuf->len);
event_set(&e, MME_EVT_S11_MESSAGE);
event_set_param1(&e, (c_uintptr_t)sgw);
event_set_param2(&e, (c_uintptr_t)pkbuf);
event_set_param1(&e, (c_uintptr_t)addr);
event_set_param2(&e, (c_uintptr_t)port);
event_set_param3(&e, (c_uintptr_t)pkbuf);
rv = mme_event_send(&e);
if (rv != CORE_OK)
{
@@ -59,18 +53,18 @@ status_t mme_gtp_open()
status_t rv;
mme_sgw_t *sgw = mme_sgw_first();
rv = gtp_listen(&mme_self()->s11_sock, _gtpv2_c_recv_cb,
mme_self()->s11_addr, mme_self()->s11_port, NULL);
rv = gtp_listen(&mme_self()->gtpc_sock, _gtpv2_c_recv_cb,
mme_self()->gtpc_addr, mme_self()->gtpc_port, NULL);
if (rv != CORE_OK)
{
d_error("Can't establish S11 Path for SGW");
d_error("Can't establish GTP-C Path for SGW");
return rv;
}
/* socket descriptor needs in gnode when packet is sending initilly */
while(sgw)
{
sgw->sock = mme_self()->s11_sock;
sgw->sock = mme_self()->gtpc_sock;
sgw = mme_sgw_next(sgw);
}
@@ -81,10 +75,10 @@ status_t mme_gtp_close()
{
status_t rv;
rv = gtp_close(mme_self()->s11_sock);
rv = gtp_close(mme_self()->gtpc_sock);
if (rv != CORE_OK)
{
d_error("Can't close S11 Path for SGW");
d_error("Can't close GTP-C Path for SGW");
return rv;
}

View File

@@ -6,6 +6,7 @@
#include "mme_event.h"
#include "mme_fd_path.h"
#include "s1ap_path.h"
static thread_id sm_thread;
static void *THREAD_FUNC sm_main(thread_id id, void *data);
@@ -36,7 +37,7 @@ status_t mme_initialize()
if (rv != CORE_OK) return rv;
rv = thread_create(&net_thread, NULL, net_main, NULL);
if (rv != CORE_OK) return rv;
initialized = 1;
return CORE_OK;
@@ -53,6 +54,8 @@ void mme_terminate(void)
mme_context_final();
s1ap_final();
gtp_xact_final();
}

View File

@@ -50,16 +50,16 @@ void mme_state_operational(fsm_t *s, event_t *e)
rv = mme_gtp_open();
if (rv != CORE_OK)
{
d_error("Can't establish S11 path");
d_error("Can't establish S11-GTP path");
break;
}
rv = s1ap_open();
if (rv != CORE_OK)
{
d_error("Can't establish S1AP path");
break;
}
break;
}
case FSM_EXIT_SIG:
@@ -67,43 +67,47 @@ void mme_state_operational(fsm_t *s, event_t *e)
rv = mme_gtp_close();
if (rv != CORE_OK)
{
d_error("Can't close S11 path");
break;
d_error("Can't close S11-GTP path");
}
rv = s1ap_close();
rv = s1ap_close(mme_self()->s1ap_sock);
if (rv != CORE_OK)
{
d_error("Can't close S1AP path");
break;
}
mme_self()->s1ap_sock = NULL;
break;
}
case MME_EVT_S1AP_LO_ACCEPT:
{
int rc;
net_sock_t *sock = (net_sock_t *)event_get_param1(e);
d_assert(sock, break, "Null param");
c_uint32_t addr = (c_uint32_t)event_get_param2(e);
c_uint16_t port = (c_uint16_t)event_get_param3(e);
d_trace(1, "eNB-S1 accepted[%s] in master_sm module\n",
INET_NTOP(&sock->remote.sin_addr.s_addr, buf));
INET_NTOP(&addr, buf));
mme_enb_t *enb = mme_enb_find_by_sock(sock);
if (!enb)
{
rc = net_register_sock(sock, _s1ap_recv_cb, NULL);
#if USE_USRSCTP != 1
int rc = net_register_sock(sock, s1ap_recv_cb, NULL);
d_assert(rc == 0, break, "register _s1ap_recv_cb failed");
#endif
mme_enb_t *enb = mme_enb_add(sock);
d_assert(enb, break, "Null param");
enb->s1ap_addr = addr;
enb->s1ap_port = port;
}
else
{
d_warn("eNB context duplicated with IP-address [%s]!!!",
INET_NTOP(&sock->remote.sin_addr.s_addr, buf));
INET_NTOP(&addr, buf));
#if USE_USRSCTP != 1
net_close(sock);
#endif
d_warn("S1 Socket Closed");
}
@@ -111,7 +115,13 @@ void mme_state_operational(fsm_t *s, event_t *e)
}
case MME_EVT_S1AP_LO_CONNREFUSED:
{
mme_enb_t *enb = mme_enb_find(event_get_param1(e));
mme_enb_t *enb = NULL;
net_sock_t *sock = NULL;
sock = (net_sock_t *)event_get_param1(e);
d_assert(sock, break, "Null param");
enb = mme_enb_find_by_sock(sock);
if (enb)
{
d_trace(1, "eNB-S1[%x] connection refused!!!\n",
@@ -129,14 +139,19 @@ void mme_state_operational(fsm_t *s, event_t *e)
{
s1ap_message_t message;
mme_enb_t *enb = NULL;
net_sock_t *sock = NULL;
pkbuf_t *pkbuf = NULL;
sock = (net_sock_t *)event_get_param1(e);
d_assert(sock, break, "Null param");
enb = mme_enb_find(event_get_param1(e));
pkbuf = (pkbuf_t *)event_get_param2(e);
d_assert(pkbuf, break, "Null param");
enb = mme_enb_find_by_sock(sock);
d_assert(enb, break, "No eNB context");
d_assert(FSM_STATE(&enb->sm), break, "No S1AP State Machine");
pkbuf = (pkbuf_t *)event_get_param2(e);
d_assert(pkbuf, break, "Null param");
d_assert(s1ap_decode_pdu(&message, pkbuf) == CORE_OK,
pkbuf_free(pkbuf); break, "Can't decode S1AP_PDU");
event_set_param3(e, (c_uintptr_t)&message);
@@ -329,13 +344,16 @@ void mme_state_operational(fsm_t *s, event_t *e)
case MME_EVT_S11_MESSAGE:
{
status_t rv;
gtp_node_t *gnode = (gtp_node_t *)event_get_param1(e);
pkbuf_t *pkbuf = (pkbuf_t *)event_get_param2(e);
gtp_node_t *gnode = NULL;
c_uint32_t addr = (c_uint32_t)event_get_param1(e);
c_uint16_t port = (c_uint16_t)event_get_param2(e);
pkbuf_t *pkbuf = (pkbuf_t *)event_get_param3(e);
gtp_xact_t *xact = NULL;
gtp_message_t message;
mme_ue_t *mme_ue = NULL;
d_assert(pkbuf, break, "Null param");
gnode = mme_sgw_find(addr, port);
d_assert(gnode, pkbuf_free(pkbuf); break, "Null param");
rv = gtp_xact_receive(gnode, pkbuf, &xact, &message);

View File

@@ -143,8 +143,7 @@ status_t s1ap_build_downlink_nas_transport(
d_trace(3, "[S1AP] downlinkNASTransport : "
"UE[eNB-UE-S1AP-ID(%d)] <-- eNB[%s:%d]\n",
enb_ue->enb_ue_s1ap_id,
INET_NTOP(&enb_ue->enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb_ue->enb->enb_id);
INET_NTOP(&enb_ue->enb->s1ap_addr, buf), enb_ue->enb->enb_id);
return CORE_OK;
}
@@ -303,8 +302,7 @@ status_t s1ap_build_initial_context_setup_request(
d_trace(3, "[S1AP] Initial Context Setup Request : "
"UE[eNB-UE-S1AP-ID(%d)] <-- eNB[%s:%d]\n",
enb_ue->enb_ue_s1ap_id,
INET_NTOP(&enb_ue->enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb_ue->enb->enb_id);
INET_NTOP(&enb_ue->enb->s1ap_addr, buf), enb_ue->enb->enb_id);
if (emmbuf && emmbuf->len)
{
@@ -404,8 +402,7 @@ status_t s1ap_build_e_rab_setup_request(
d_trace(3, "[S1AP] E-RAB Setup Request : "
"UE[eNB-UE-S1AP-ID(%d)] <-- eNB[%s:%d]\n",
enb_ue->enb_ue_s1ap_id,
INET_NTOP(&enb_ue->enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb_ue->enb->enb_id);
INET_NTOP(&enb_ue->enb->s1ap_addr, buf), enb_ue->enb->enb_id);
pkbuf_free(esmbuf);
@@ -473,8 +470,7 @@ status_t s1ap_build_e_rab_release_command(pkbuf_t **s1apbuf,
d_trace(3, "[S1AP] E-RAB Release Command : "
"UE[eNB-UE-S1AP-ID(%d)] <-- eNB[%s:%d]\n",
enb_ue->enb_ue_s1ap_id,
INET_NTOP(&enb_ue->enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb_ue->enb->enb_id);
INET_NTOP(&enb_ue->enb->s1ap_addr, buf), enb_ue->enb->enb_id);
pkbuf_free(esmbuf);
@@ -530,8 +526,7 @@ status_t s1ap_build_ue_context_release_commmand(
d_trace(3, "[S1AP] UE Context Release Command : "
"UE[mME-UE-S1AP-ID(%d)] <-- eNB[%s:%d]\n",
enb_ue->mme_ue_s1ap_id,
INET_NTOP(&enb_ue->enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb_ue->enb->enb_id);
INET_NTOP(&enb_ue->enb->s1ap_addr, buf), enb_ue->enb->enb_id);
return CORE_OK;
}
@@ -638,8 +633,7 @@ status_t s1ap_build_path_switch_ack(pkbuf_t **s1apbuf, mme_ue_t *mme_ue)
d_trace(3, "[S1AP] Path Switch Ack : "
"UE[mME-UE-S1AP-ID(%d)] <-- eNB[%s:%d]\n",
enb_ue->mme_ue_s1ap_id,
INET_NTOP(&enb_ue->enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb_ue->enb->enb_id);
INET_NTOP(&enb_ue->enb->s1ap_addr, buf), enb_ue->enb->enb_id);
return CORE_OK;
}
@@ -778,8 +772,7 @@ status_t s1ap_build_handover_command(pkbuf_t **s1apbuf, enb_ue_t *source_ue)
d_trace(3, "[S1AP] Handover Command : ",
"UE[mME-UE-S1AP-ID(%d)] <-- eNB[%s:%d]\n",
source_ue->mme_ue_s1ap_id,
INET_NTOP(&source_ue->enb->s1ap_sock->remote.sin_addr.s_addr, buf),
source_ue->enb->enb_id);
INET_NTOP(&source_ue->enb->s1ap_addr, buf), source_ue->enb->enb_id);
return CORE_OK;
}
@@ -811,8 +804,7 @@ status_t s1ap_build_handover_preparation_failure(
d_trace(3, "[S1AP] Handover Preparation Failure : ",
"UE[mME-UE-S1AP-ID(%d)] <-- eNB[%s:%d]\n",
source_ue->mme_ue_s1ap_id,
INET_NTOP(&source_ue->enb->s1ap_sock->remote.sin_addr.s_addr, buf),
source_ue->enb->enb_id);
INET_NTOP(&source_ue->enb->s1ap_addr, buf), source_ue->enb->enb_id);
return CORE_OK;
}
@@ -954,8 +946,7 @@ status_t s1ap_build_handover_request(
d_trace(3, "[S1AP] Handover Request : ",
"UE[mME-UE-S1AP-ID(%d)] <-- eNB[%s:%d]\n",
target_ue->mme_ue_s1ap_id,
INET_NTOP(&target_ue->enb->s1ap_sock->remote.sin_addr.s_addr, buf),
target_ue->enb->enb_id);
INET_NTOP(&target_ue->enb->s1ap_addr, buf), target_ue->enb->enb_id);
return CORE_OK;
}
@@ -987,8 +978,7 @@ status_t s1ap_build_handover_cancel_ack(pkbuf_t **s1apbuf, enb_ue_t *source_ue)
d_trace(3, "[S1AP] Handover Cancel Ack : ",
"UE[mME-UE-S1AP-ID(%d)] <-- eNB[%s:%d]\n",
source_ue->mme_ue_s1ap_id,
INET_NTOP(&source_ue->enb->s1ap_sock->remote.sin_addr.s_addr, buf),
source_ue->enb->enb_id);
INET_NTOP(&source_ue->enb->s1ap_addr, buf), source_ue->enb->enb_id);
return CORE_OK;
}
@@ -1040,8 +1030,7 @@ status_t s1ap_build_mme_status_transfer(pkbuf_t **s1apbuf,
d_trace(3, "[S1AP] MME Status Transfer : ",
"UE[mME-UE-S1AP-ID(%d)] <-- eNB[%s:%d]\n",
target_ue->mme_ue_s1ap_id,
INET_NTOP(&target_ue->enb->s1ap_sock->remote.sin_addr.s_addr, buf),
target_ue->enb->enb_id);
INET_NTOP(&target_ue->enb->s1ap_addr, buf), target_ue->enb->enb_id);
return CORE_OK;
}

View File

@@ -66,10 +66,10 @@ void s1ap_handle_s1_setup_request(mme_enb_t *enb, s1ap_message_t *message)
d_assert(enb->s1ap_sock, return,);
d_trace(3, "[S1AP] S1SetupRequest : eNB[%s:%d] --> MME\n",
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb_id);
INET_NTOP(&enb->s1ap_addr, buf), enb_id);
enb->enb_id = enb_id;
d_assert(mme_enb_set_enb_id(enb, enb_id) == CORE_OK,
return, "hash add error");
d_assert(s1ap_build_setup_rsp(&s1apbuf) == CORE_OK,
return, "build error");
@@ -77,8 +77,7 @@ void s1ap_handle_s1_setup_request(mme_enb_t *enb, s1ap_message_t *message)
d_assert(enb->s1ap_sock, return,);
d_trace(3, "[S1AP] S1SetupResponse: eNB[%s:%d] <-- MME\n",
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb_id);
INET_NTOP(&enb->s1ap_addr, buf), enb_id);
}
void s1ap_handle_initial_ue_message(mme_enb_t *enb, s1ap_message_t *message)
@@ -167,8 +166,7 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, s1ap_message_t *message)
d_trace(3, "[S1AP] InitialUEMessage : "
"UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]\n",
enb_ue->enb_ue_s1ap_id,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
INET_NTOP(&enb->s1ap_addr, buf), enb->enb_id);
d_assert(s1ap_send_to_nas(enb_ue, &ies->nas_pdu) == CORE_OK,,
"s1ap_send_to_nas failed");
@@ -191,8 +189,7 @@ void s1ap_handle_uplink_nas_transport(
d_trace(3, "[S1AP] uplinkNASTransport : "
"UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]\n",
enb_ue->enb_ue_s1ap_id,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
INET_NTOP(&enb->s1ap_addr, buf), enb->enb_id);
d_assert(s1ap_send_to_nas(enb_ue, &ies->nas_pdu) == CORE_OK,,
"s1ap_send_to_nas failed");
@@ -245,8 +242,7 @@ void s1ap_handle_ue_capability_info_indication(
d_trace(3, "[S1AP] UE Capability Info Indication : "
"UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]\n",
enb_ue->enb_ue_s1ap_id,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
INET_NTOP(&enb->s1ap_addr, buf), enb->enb_id);
}
void s1ap_handle_initial_context_setup_response(
@@ -271,8 +267,7 @@ void s1ap_handle_initial_context_setup_response(
d_trace(3, "[S1AP] Initial Context Setup Response : "
"UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]\n",
enb_ue->enb_ue_s1ap_id,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
INET_NTOP(&enb->s1ap_addr, buf), enb->enb_id);
for (i = 0; i < ies->e_RABSetupListCtxtSURes.
s1ap_E_RABSetupItemCtxtSURes.count; i++)
@@ -332,8 +327,7 @@ void s1ap_handle_e_rab_setup_response(
d_trace(3, "[S1AP] E-RAB Setup Response : "
"UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]\n",
enb_ue->enb_ue_s1ap_id,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
INET_NTOP(&enb->s1ap_addr, buf), enb->enb_id);
for (i = 0; i < ies->e_RABSetupListBearerSURes.
s1ap_E_RABSetupItemBearerSURes.count; i++)
@@ -394,8 +388,7 @@ void s1ap_handle_ue_context_release_request(
d_trace(3, "[S1AP] UE Context Release Request : "
"UE[mME-UE-S1AP-ID(%d)] --> eNB[%s:%d]\n",
enb_ue->mme_ue_s1ap_id,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
INET_NTOP(&enb->s1ap_addr, buf), enb->enb_id);
switch(ies->cause.present)
{
@@ -473,8 +466,7 @@ void s1ap_handle_ue_context_release_complete(
d_trace(3, "[S1AP] UE Context Release Complete : "
"UE[mME-UE-S1AP-ID(%d)] --> eNB[%s:%d]\n",
enb_ue->mme_ue_s1ap_id,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
INET_NTOP(&enb->s1ap_addr, buf), enb->enb_id);
enb_ue_remove(enb_ue);
@@ -514,14 +506,15 @@ void s1ap_handle_ue_context_release_complete(
void s1ap_handle_paging(mme_ue_t *mme_ue)
{
pkbuf_t *s1apbuf = NULL;
hash_index_t *hi = NULL;
mme_enb_t *enb = NULL;
int i;
status_t rv;
/* Find enB with matched TAI */
enb = mme_enb_first();
while (enb)
for (hi = mme_enb_first(); hi; hi = mme_enb_next(hi))
{
enb = mme_enb_this(hi);
for (i = 0; i < enb->num_of_tai; i++)
{
if (!memcmp(&enb->tai[i], &mme_ue->tai, sizeof(tai_t)))
@@ -544,7 +537,6 @@ void s1ap_handle_paging(mme_ue_t *mme_ue)
"s1ap send error");
}
}
enb = mme_enb_next(enb);
}
}
@@ -601,8 +593,7 @@ void s1ap_handle_path_switch_request(
{
d_error("Cannot find UE from sourceMME-UE-S1AP-ID[%d] and eNB[%s:%d]",
ies->sourceMME_UE_S1AP_ID,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
INET_NTOP(&enb->s1ap_addr, buf), enb->enb_id);
cause.present = S1ap_Cause_PR_radioNetwork;
cause.choice.radioNetwork =
@@ -684,8 +675,7 @@ void s1ap_handle_path_switch_request(
d_trace(3, "[S1AP] PathSwitchRequest : "
"UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]\n",
enb_ue->enb_ue_s1ap_id,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
INET_NTOP(&enb->s1ap_addr, buf), enb->enb_id);
}
void s1ap_handle_handover_required(mme_enb_t *enb, s1ap_message_t *message)
@@ -707,8 +697,7 @@ void s1ap_handle_handover_required(mme_enb_t *enb, s1ap_message_t *message)
d_assert(source_ue, return,
"Cannot find UE for eNB-UE-S1AP-ID[%d] and eNB[%s:%d]",
ies->eNB_UE_S1AP_ID,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
INET_NTOP(&enb->s1ap_addr, buf), enb->enb_id);
d_assert(source_ue->mme_ue_s1ap_id == ies->mme_ue_s1ap_id, return,
"Conflict MME-UE-S1AP-ID : %d != %d\n",
source_ue->mme_ue_s1ap_id, ies->mme_ue_s1ap_id);
@@ -737,8 +726,7 @@ void s1ap_handle_handover_required(mme_enb_t *enb, s1ap_message_t *message)
d_trace(3, "[S1AP] Handover Required : "
"UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]\n",
source_ue->enb_ue_s1ap_id,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
INET_NTOP(&enb->s1ap_addr, buf), enb->enb_id);
}
void s1ap_handle_handover_request_ack(mme_enb_t *enb, s1ap_message_t *message)
@@ -762,8 +750,7 @@ void s1ap_handle_handover_request_ack(mme_enb_t *enb, s1ap_message_t *message)
d_assert(target_ue, return,
"Cannot find UE for MME-UE-S1AP-ID[%d] and eNB[%s:%d]",
ies->mme_ue_s1ap_id,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
INET_NTOP(&enb->s1ap_addr, buf), enb->enb_id);
target_ue->enb_ue_s1ap_id = ies->eNB_UE_S1AP_ID;
@@ -832,8 +819,7 @@ void s1ap_handle_handover_request_ack(mme_enb_t *enb, s1ap_message_t *message)
d_trace(3, "[S1AP] Handover Request Ack : "
"UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]\n",
target_ue->enb_ue_s1ap_id,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
INET_NTOP(&enb->s1ap_addr, buf), enb->enb_id);
}
void s1ap_handle_handover_failure(mme_enb_t *enb, s1ap_message_t *message)
@@ -855,8 +841,7 @@ void s1ap_handle_handover_failure(mme_enb_t *enb, s1ap_message_t *message)
d_assert(target_ue, return,
"Cannot find UE for MME-UE-S1AP-ID[%d] and eNB[%s:%d]",
ies->mme_ue_s1ap_id,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
INET_NTOP(&enb->s1ap_addr, buf), enb->enb_id);
source_ue = target_ue->source_ue;
d_assert(source_ue, return,);
@@ -872,8 +857,7 @@ void s1ap_handle_handover_failure(mme_enb_t *enb, s1ap_message_t *message)
d_trace(3, "[S1AP] Handover Failure : "
"UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]\n",
target_ue->enb_ue_s1ap_id,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
INET_NTOP(&enb->s1ap_addr, buf), enb->enb_id);
}
void s1ap_handle_handover_cancel(mme_enb_t *enb, s1ap_message_t *message)
@@ -896,8 +880,7 @@ void s1ap_handle_handover_cancel(mme_enb_t *enb, s1ap_message_t *message)
d_assert(source_ue, return,
"Cannot find UE for eNB-UE-S1AP-ID[%d] and eNB[%s:%d]",
ies->eNB_UE_S1AP_ID,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
INET_NTOP(&enb->s1ap_addr, buf), enb->enb_id);
d_assert(source_ue->mme_ue_s1ap_id == ies->mme_ue_s1ap_id, return,
"Conflict MME-UE-S1AP-ID : %d != %d\n",
source_ue->mme_ue_s1ap_id, ies->mme_ue_s1ap_id);
@@ -917,8 +900,7 @@ void s1ap_handle_handover_cancel(mme_enb_t *enb, s1ap_message_t *message)
d_trace(3, "[S1AP] Handover Cancel : "
"UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]\n",
source_ue->enb_ue_s1ap_id,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
INET_NTOP(&enb->s1ap_addr, buf), enb->enb_id);
}
void s1ap_handle_enb_status_transfer(mme_enb_t *enb, s1ap_message_t *message)
@@ -939,8 +921,7 @@ void s1ap_handle_enb_status_transfer(mme_enb_t *enb, s1ap_message_t *message)
d_assert(source_ue, return,
"Cannot find UE for eNB-UE-S1AP-ID[%d] and eNB[%s:%d]",
ies->eNB_UE_S1AP_ID,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
INET_NTOP(&enb->s1ap_addr, buf), enb->enb_id);
d_assert(source_ue->mme_ue_s1ap_id == ies->mme_ue_s1ap_id, return,
"Conflict MME-UE-S1AP-ID : %d != %d\n",
source_ue->mme_ue_s1ap_id, ies->mme_ue_s1ap_id);
@@ -993,8 +974,7 @@ void s1ap_handle_handover_notification(mme_enb_t *enb, s1ap_message_t *message)
d_assert(target_ue, return,
"Cannot find UE for eNB-UE-S1AP-ID[%d] and eNB[%s:%d]",
ies->eNB_UE_S1AP_ID,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
INET_NTOP(&enb->s1ap_addr, buf), enb->enb_id);
d_assert(target_ue->mme_ue_s1ap_id == ies->mme_ue_s1ap_id, return,
"Conflict MME-UE-S1AP-ID : %d != %d\n",
target_ue->mme_ue_s1ap_id, ies->mme_ue_s1ap_id);

View File

@@ -1,6 +1,7 @@
#define TRACE_MODULE _s1ap_path
#include "core_debug.h"
#include "core_thread.h"
#include "mme_event.h"
@@ -11,193 +12,6 @@
#include "s1ap_build.h"
#include "s1ap_path.h"
static int _s1ap_accept_cb(net_sock_t *net_sock, void *data);
status_t s1ap_open(void)
{
char buf[INET_ADDRSTRLEN];
int rc;
rc = net_listen_ext(&mme_self()->s1ap_sock,
SOCK_STREAM, IPPROTO_SCTP, SCTP_S1AP_PPID,
mme_self()->s1ap_addr, mme_self()->s1ap_port);
if (rc != 0)
{
d_error("Can't establish S1-ENB(port:%d) path(%d:%s)",
mme_self()->s1ap_port, errno, strerror(errno));
mme_self()->s1ap_sock = NULL;
return CORE_ERROR;
}
rc = net_register_sock(
mme_self()->s1ap_sock, _s1ap_accept_cb, NULL);
if (rc != 0)
{
d_error("Can't establish S1-ENB path(%d:%s)",
errno, strerror(errno));
net_close(mme_self()->s1ap_sock);
mme_self()->s1ap_sock = NULL;
return CORE_ERROR;
}
d_trace(1, "s1_enb_listen() %s:%d\n",
INET_NTOP(&mme_self()->s1ap_addr, buf), mme_self()->s1ap_port);
return CORE_OK;
}
status_t s1ap_close()
{
d_assert(mme_self(), return CORE_ERROR, "Null param");
d_assert(mme_self()->s1ap_sock != NULL, return CORE_ERROR,
"S1-ENB path already opened");
net_unregister_sock(mme_self()->s1ap_sock);
net_close(mme_self()->s1ap_sock);
mme_self()->s1ap_sock = NULL;
return CORE_OK;
}
static int _s1ap_accept_cb(net_sock_t *net_sock, void *data)
{
char buf[INET_ADDRSTRLEN];
ssize_t r;
net_sock_t *remote_sock;
d_assert(net_sock, return -1, "Null param");
r = net_accept(&remote_sock, net_sock, 0);
if (r > 0)
{
d_trace(1, "eNB-S1 accepted[%s] in s1_path module\n",
INET_NTOP(&remote_sock->remote.sin_addr.s_addr, buf));
event_t e;
event_set(&e, MME_EVT_S1AP_LO_ACCEPT);
event_set_param1(&e, (c_uintptr_t)remote_sock);
/* FIXME : how to close remote_sock */
mme_event_send(&e);
}
else
{
d_error("net_accept failed(r = %d, errno = %d)", r, errno);
}
return r;
}
static status_t s1ap_recv(net_sock_t *sock, pkbuf_t *pkbuf)
{
event_t e;
d_assert(sock, return CORE_ERROR, "Null param");
d_assert(pkbuf, return CORE_ERROR, "Null param");
d_trace(10, "S1AP_PDU is received from eNB-Inf\n");
d_trace_hex(10, pkbuf->payload, pkbuf->len);
event_set(&e, MME_EVT_S1AP_MESSAGE);
event_set_param1(&e, (c_uintptr_t)sock->app_index);
event_set_param2(&e, (c_uintptr_t)pkbuf);
return mme_event_send(&e);
}
int _s1ap_recv_cb(net_sock_t *sock, void *data)
{
status_t rv;
pkbuf_t *pkbuf;
ssize_t r;
d_assert(sock, return -1, "Null param");
pkbuf = pkbuf_alloc(0, MAX_SDU_LEN);
if (pkbuf == NULL)
{
char tmp_buf[MAX_SDU_LEN];
d_fatal("Can't allocate pkbuf");
/* Read data from socket to exit from select */
net_read(sock, tmp_buf, MAX_SDU_LEN, 0);
return -1;
}
r = net_read(sock, pkbuf->payload, pkbuf->len, 0);
if (r == -2)
{
pkbuf_free(pkbuf);
}
else if (r <= 0)
{
pkbuf_free(pkbuf);
if (sock->sndrcv_errno == EAGAIN)
{
d_warn("net_read failed(%d:%s)",
sock->sndrcv_errno, strerror(sock->sndrcv_errno));
return 0;
}
else if (sock->sndrcv_errno == ECONNREFUSED)
{
d_warn("net_read failed(%d:%s)",
sock->sndrcv_errno, strerror(sock->sndrcv_errno));
}
else
{
d_error("net_read failed(%d:%s)",
sock->sndrcv_errno, strerror(sock->sndrcv_errno));
}
event_t e;
event_set(&e, MME_EVT_S1AP_LO_CONNREFUSED);
event_set_param1(&e, (c_uintptr_t)sock->app_index);
mme_event_send(&e);
return -1;
}
else
{
pkbuf->len = r;
rv = s1ap_recv(sock, pkbuf);
if (rv != CORE_OK)
{
pkbuf_free(pkbuf);
d_error("s1_recv() failed");
return -1;
}
}
return 0;
}
status_t s1ap_send(net_sock_t *s, pkbuf_t *pkbuf)
{
char buf[INET_ADDRSTRLEN];
ssize_t sent;
d_assert(s, return CORE_ERROR, "Null param");
d_assert(pkbuf, return CORE_ERROR, "Null param");
sent = net_send(s, pkbuf->payload, pkbuf->len);
d_trace(10,"Sent %d->%d bytes to [%s:%d]\n",
pkbuf->len, sent, INET_NTOP(&s->remote.sin_addr.s_addr, buf),
ntohs(s->remote.sin_port));
d_trace_hex(10, pkbuf->payload, pkbuf->len);
if (sent < 0 || sent != pkbuf->len)
{
d_error("net_send error (%d:%s)",
s->sndrcv_errno, strerror(s->sndrcv_errno));
return CORE_ERROR;
}
pkbuf_free(pkbuf);
return CORE_OK;
}
status_t s1ap_send_to_enb(mme_enb_t *enb, pkbuf_t *pkbuf)
{
status_t rv = CORE_ERROR;
@@ -205,7 +19,7 @@ status_t s1ap_send_to_enb(mme_enb_t *enb, pkbuf_t *pkbuf)
d_assert(pkbuf,,);
d_assert(enb->s1ap_sock,,);
rv = s1ap_send(enb->s1ap_sock, pkbuf);
rv = s1ap_sendto(enb->s1ap_sock, pkbuf, enb->s1ap_addr, enb->s1ap_port);
if (rv != CORE_OK)
{
d_error("s1_send error");

View File

@@ -14,7 +14,15 @@ extern "C" {
CORE_DECLARE(status_t) s1ap_open();
CORE_DECLARE(status_t) s1ap_close();
CORE_DECLARE(status_t) s1ap_sctp_close(net_sock_t *sock);
CORE_DECLARE(status_t) s1ap_final();
#if 0 /* depreciated */
CORE_DECLARE(status_t) s1ap_send(net_sock_t *s, pkbuf_t *pkb);
#endif
CORE_DECLARE(status_t) s1ap_sendto(net_sock_t *s, pkbuf_t *pkb,
c_uint32_t addr, c_uint16_t port);
CORE_DECLARE(status_t) s1ap_send_to_enb(mme_enb_t *enb, pkbuf_t *pkb);
CORE_DECLARE(status_t) s1ap_delayed_send_to_enb(mme_enb_t *enb,
pkbuf_t *pkbuf, c_uint32_t duration);
@@ -43,7 +51,7 @@ CORE_DECLARE(status_t) s1ap_send_handover_cancel_ack(enb_ue_t *source_ue);
CORE_DECLARE(status_t) s1ap_send_mme_status_transfer(
enb_ue_t *target_ue, S1ap_ENBStatusTransferIEs_t *ies);
int _s1ap_recv_cb(net_sock_t *net_sock, void *data);
int s1ap_recv_cb(net_sock_t *net_sock, void *data);
#ifdef __cplusplus
}

234
src/mme/s1ap_sctp.c Normal file
View File

@@ -0,0 +1,234 @@
#define TRACE_MODULE _s1ap_sctp
#include "core_debug.h"
#include "core_thread.h"
#include "mme_event.h"
#include "s1ap_path.h"
static int s1ap_accept_cb(net_sock_t *net_sock, void *data);
status_t s1ap_open(void)
{
char buf[INET_ADDRSTRLEN];
int rc;
rc = net_listen_ext(&mme_self()->s1ap_sock,
SOCK_STREAM, IPPROTO_SCTP, SCTP_S1AP_PPID,
mme_self()->s1ap_addr, mme_self()->s1ap_port);
if (rc != 0)
{
d_error("Can't establish S1-ENB(port:%d) path(%d:%s)",
mme_self()->s1ap_port, errno, strerror(errno));
mme_self()->s1ap_sock = NULL;
return CORE_ERROR;
}
rc = net_register_sock(
mme_self()->s1ap_sock, s1ap_accept_cb, NULL);
if (rc != 0)
{
d_error("Can't establish S1-ENB path(%d:%s)",
errno, strerror(errno));
net_close(mme_self()->s1ap_sock);
mme_self()->s1ap_sock = NULL;
return CORE_ERROR;
}
d_trace(1, "s1_enb_listen() %s:%d\n",
INET_NTOP(&mme_self()->s1ap_addr, buf), mme_self()->s1ap_port);
return CORE_OK;
}
status_t s1ap_close()
{
s1ap_sctp_close(mme_self()->s1ap_sock);
mme_self()->s1ap_sock = NULL;
return CORE_OK;
}
status_t s1ap_sctp_close(net_sock_t *sock)
{
net_unregister_sock(sock);
net_close(sock);
return CORE_OK;
}
status_t s1ap_final()
{
return CORE_OK;
}
static int s1ap_accept_cb(net_sock_t *net_sock, void *data)
{
char buf[INET_ADDRSTRLEN];
ssize_t r;
net_sock_t *remote_sock;
d_assert(net_sock, return -1, "Null param");
r = net_accept(&remote_sock, net_sock, 0);
if (r > 0)
{
event_t e;
c_uint32_t addr = remote_sock->remote.sin_addr.s_addr;
c_uint16_t port = ntohs(remote_sock->remote.sin_port);
d_trace(1, "eNB-S1 accepted[%s] in s1_path module\n",
INET_NTOP(&addr, buf));
event_set(&e, MME_EVT_S1AP_LO_ACCEPT);
event_set_param1(&e, (c_uintptr_t)remote_sock);
event_set_param2(&e, (c_uintptr_t)addr);
event_set_param3(&e, (c_uintptr_t)port);
/* FIXME : how to close remote_sock */
mme_event_send(&e);
}
else
{
d_error("net_accept failed(r = %d, errno = %d)", r, errno);
}
return r;
}
static status_t s1ap_recv(net_sock_t *sock, pkbuf_t *pkbuf)
{
event_t e;
d_assert(sock, return CORE_ERROR, "Null param");
d_assert(pkbuf, return CORE_ERROR, "Null param");
d_trace(10, "S1AP_PDU is received from eNB-Inf\n");
d_trace_hex(10, pkbuf->payload, pkbuf->len);
event_set(&e, MME_EVT_S1AP_MESSAGE);
event_set_param1(&e, (c_uintptr_t)sock);
event_set_param2(&e, (c_uintptr_t)pkbuf);
return mme_event_send(&e);
}
int s1ap_recv_cb(net_sock_t *sock, void *data)
{
status_t rv;
pkbuf_t *pkbuf;
ssize_t r;
d_assert(sock, return -1, "Null param");
pkbuf = pkbuf_alloc(0, MAX_SDU_LEN);
if (pkbuf == NULL)
{
char tmp_buf[MAX_SDU_LEN];
d_fatal("Can't allocate pkbuf");
/* Read data from socket to exit from select */
net_read(sock, tmp_buf, MAX_SDU_LEN, 0);
return -1;
}
r = net_read(sock, pkbuf->payload, pkbuf->len, 0);
if (r == -2)
{
pkbuf_free(pkbuf);
}
else if (r <= 0)
{
pkbuf_free(pkbuf);
if (sock->sndrcv_errno == EAGAIN)
{
d_warn("net_read failed(%d:%s)",
sock->sndrcv_errno, strerror(sock->sndrcv_errno));
return 0;
}
else if (sock->sndrcv_errno == ECONNREFUSED)
{
d_warn("net_read failed(%d:%s)",
sock->sndrcv_errno, strerror(sock->sndrcv_errno));
}
else
{
d_error("net_read failed(%d:%s)",
sock->sndrcv_errno, strerror(sock->sndrcv_errno));
}
event_t e;
event_set(&e, MME_EVT_S1AP_LO_CONNREFUSED);
event_set_param1(&e, (c_uintptr_t)sock);
mme_event_send(&e);
return -1;
}
else
{
pkbuf->len = r;
rv = s1ap_recv(sock, pkbuf);
if (rv != CORE_OK)
{
pkbuf_free(pkbuf);
d_error("s1_recv() failed");
return -1;
}
}
return 0;
}
#if 0 /* deprecated */
status_t s1ap_send(net_sock_t *s, pkbuf_t *pkbuf)
{
char buf[INET_ADDRSTRLEN];
ssize_t sent;
d_assert(s, return CORE_ERROR, "Null param");
d_assert(pkbuf, return CORE_ERROR, "Null param");
sent = net_send(s, pkbuf->payload, pkbuf->len);
d_trace(10,"Sent %d->%d bytes to [%s:%d]\n",
pkbuf->len, sent, INET_NTOP(&s->remote.sin_addr.s_addr, buf),
ntohs(s->remote.sin_port));
d_trace_hex(10, pkbuf->payload, pkbuf->len);
if (sent < 0 || sent != pkbuf->len)
{
d_error("net_send error (%d:%s)",
s->sndrcv_errno, strerror(s->sndrcv_errno));
return CORE_ERROR;
}
pkbuf_free(pkbuf);
return CORE_OK;
}
#endif
status_t s1ap_sendto(net_sock_t *s, pkbuf_t *pkbuf,
c_uint32_t addr, c_uint16_t port)
{
char buf[INET_ADDRSTRLEN];
ssize_t sent;
d_assert(s, return CORE_ERROR, "Null param");
d_assert(pkbuf, return CORE_ERROR, "Null param");
sent = net_sendto(s, pkbuf->payload, pkbuf->len, addr, port);
d_trace(10,"Sent %d->%d bytes to [%s:%d]\n",
pkbuf->len, sent, INET_NTOP(&addr, buf), port);
d_trace_hex(10, pkbuf->payload, pkbuf->len);
if (sent < 0 || sent != pkbuf->len)
{
d_error("net_send error (%d:%s)",
s->sndrcv_errno, strerror(s->sndrcv_errno));
return CORE_ERROR;
}
pkbuf_free(pkbuf);
return CORE_OK;
}

View File

@@ -29,13 +29,16 @@ void s1ap_state_final(fsm_t *s, event_t *e)
void s1ap_state_operational(fsm_t *s, event_t *e)
{
mme_enb_t *enb = NULL;
net_sock_t *sock = NULL;
d_assert(s, return, "Null param");
d_assert(e, return, "Null param");
mme_sm_trace(3, e);
enb = mme_enb_find(event_get_param1(e));
sock = (net_sock_t *)event_get_param1(e);
d_assert(sock, return, "Null param");
enb = mme_enb_find_by_sock(sock);
d_assert(enb, return, "Null param");
switch (event_get(e))

460
src/mme/s1ap_usrsctp.c Normal file
View File

@@ -0,0 +1,460 @@
#define TRACE_MODULE _s1ap_usrsctp
#include "core_debug.h"
#include "core_thread.h"
#include "mme_event.h"
#include "s1ap_path.h"
#if HAVE_USRSCTP_H
#ifndef INET
#define INET 1
#endif
#ifndef INET6
#define INET6 1
#endif
#include <usrsctp.h>
#endif
#define LOCAL_UDP_PORT 9899
static void handle_notification(union sctp_notification *notif, size_t n);
static int s1ap_usrsctp_recv_cb(struct socket *sock,
union sctp_sockstore addr, void *data, size_t datalen,
struct sctp_rcvinfo rcv, int flags, void *ulp_info);
static void debug_printf(const char *format, ...);
int accept_thread_should_stop = 0;
static thread_id accept_thread;
static void *THREAD_FUNC accept_main(thread_id id, void *data);
status_t s1ap_open(void)
{
status_t rv;
char buf[INET_ADDRSTRLEN];
struct socket *psock = NULL;
struct sockaddr_in local_addr;
const int on = 1;
struct sctp_event event;
c_uint16_t event_types[] = {
SCTP_ASSOC_CHANGE,
SCTP_PEER_ADDR_CHANGE,
SCTP_REMOTE_ERROR,
SCTP_SHUTDOWN_EVENT,
SCTP_ADAPTATION_INDICATION,
SCTP_PARTIAL_DELIVERY_EVENT
};
int i;
usrsctp_init(LOCAL_UDP_PORT, NULL, debug_printf);
#ifdef SCTP_DEBUG
usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_ALL);
#endif
usrsctp_sysctl_set_sctp_blackhole(2);
usrsctp_sysctl_set_sctp_enable_sack_immediately(1);
if (!(psock = usrsctp_socket(
AF_INET, SOCK_STREAM, IPPROTO_SCTP, s1ap_usrsctp_recv_cb,
NULL, 0, NULL)))
{
d_error("usrsctp_socket failed");
return CORE_ERROR;
}
mme_self()->s1ap_sock = (net_sock_t *)psock;
if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_RECVRCVINFO,
&on, sizeof(int)) < 0)
{
d_error("usrsctp_setsockopt SCTP_RECVRCVINFO failed");
return CORE_ERROR;
}
memset(&event, 0, sizeof(event));
event.se_assoc_id = SCTP_FUTURE_ASSOC;
event.se_on = 1;
for (i = 0; i < (int)(sizeof(event_types)/sizeof(c_uint16_t)); i++)
{
event.se_type = event_types[i];
if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_EVENT,
&event, sizeof(struct sctp_event)) < 0)
{
d_error("usrsctp_setsockopt SCTP_EVENT failed");
return CORE_ERROR;
}
}
memset((void *)&local_addr, 0, sizeof(struct sockaddr_in));
local_addr.sin_family = AF_INET;
local_addr.sin_len = sizeof(struct sockaddr_in);
local_addr.sin_port = htons(mme_self()->s1ap_port);
local_addr.sin_addr.s_addr = mme_self()->s1ap_addr;
if (usrsctp_bind(psock, (struct sockaddr *)&local_addr,
sizeof(struct sockaddr_in)) == -1)
{
d_error("usrsctp_bind failed(%s:%d)",
INET_NTOP(&mme_self()->s1ap_addr, buf), mme_self()->s1ap_port);
return CORE_ERROR;
}
if (usrsctp_listen(psock, 1) < 0)
{
d_error("usrsctp_listen failed");
return CORE_ERROR;
}
rv = thread_create(&accept_thread, NULL, accept_main, NULL);
if (rv != CORE_OK) return rv;
d_trace(1, "s1_enb_listen() %s:%d\n",
INET_NTOP(&mme_self()->s1ap_addr, buf), mme_self()->s1ap_port);
return CORE_OK;
}
status_t s1ap_final()
{
while(usrsctp_finish() != 0)
{
d_error("try to finsih SCTP\n");
core_sleep(time_from_msec(1000));
}
return CORE_OK;
}
status_t s1ap_close()
{
struct socket *psock = NULL;
d_assert(mme_self(), return CORE_ERROR, "Null param");
d_assert(mme_self()->s1ap_sock != NULL, return CORE_ERROR,
"S1-ENB path already opened");
accept_thread_should_stop = 1;
psock = (struct socket *)mme_self()->s1ap_sock;
usrsctp_close(psock);
#if 0
thread_delete(accept_thread);
#else
d_error("[FIXME] should delete accept_thread : "
"how to release usrsctp_accept() blocking?");
#endif
return CORE_OK;
}
status_t s1ap_sctp_close(net_sock_t *sock)
{
usrsctp_close((struct socket *)sock);
return CORE_OK;
}
status_t s1ap_sendto(net_sock_t *s, pkbuf_t *pkbuf,
c_uint32_t addr, c_uint16_t port)
{
char buf[INET_ADDRSTRLEN];
ssize_t sent;
struct socket *psock = (struct socket *)s;
struct sctp_sndinfo sndinfo;
d_assert(s, return CORE_ERROR, "Null param");
d_assert(pkbuf, return CORE_ERROR, "Null param");
memset((void *)&sndinfo, 0, sizeof(struct sctp_sndinfo));
sndinfo.snd_ppid = htonl(SCTP_S1AP_PPID);
sent = usrsctp_sendv(psock, pkbuf->payload, pkbuf->len,
NULL, 0, /* Only SOCK_STREAM is supported at this time */
(void *)&sndinfo, (socklen_t)sizeof(struct sctp_sndinfo),
SCTP_SENDV_SNDINFO, 0);
d_trace(10,"Sent %d->%d bytes to [%s:%d]\n",
pkbuf->len, sent, INET_NTOP(&addr, buf), port);
d_trace_hex(10, pkbuf->payload, pkbuf->len);
if (sent < 0 || sent != pkbuf->len)
{
d_error("sent : %d, pkbuf->len : %d\n", sent, pkbuf->len);
return CORE_ERROR;
}
pkbuf_free(pkbuf);
return CORE_OK;
}
static void *THREAD_FUNC accept_main(thread_id id, void *data)
{
event_t e;
struct socket *sock = NULL;
struct sockaddr_in remote_addr;
socklen_t addr_len;
while (!accept_thread_should_stop)
{
if ((sock = usrsctp_accept((struct socket *)mme_self()->s1ap_sock,
(struct sockaddr *)&remote_addr, &addr_len)) == NULL)
{
d_error("usrsctp_accept failed");
continue;
}
event_set(&e, MME_EVT_S1AP_LO_ACCEPT);
event_set_param1(&e, (c_uintptr_t)sock);
mme_event_send(&e);
}
return NULL;
}
static int s1ap_usrsctp_recv_cb(struct socket *sock,
union sctp_sockstore addr, void *data, size_t datalen,
struct sctp_rcvinfo rcv, int flags, void *ulp_info)
{
if (data)
{
if (flags & MSG_NOTIFICATION)
{
handle_notification((union sctp_notification *)data, datalen);
}
else
{
c_uint32_t ppid = ntohl(rcv.rcv_ppid);
if ((flags & MSG_EOR) && ppid == SCTP_S1AP_PPID)
{
event_t e;
pkbuf_t *pkbuf;
pkbuf = pkbuf_alloc(0, MAX_SDU_LEN);
d_assert(pkbuf, return 1, );
pkbuf->len = datalen;
memcpy(pkbuf->payload, data, pkbuf->len);
event_set(&e, MME_EVT_S1AP_MESSAGE);
event_set_param1(&e, (c_uintptr_t)sock);
event_set_param2(&e, (c_uintptr_t)pkbuf);
mme_event_send(&e);
}
else
{
d_warn("Unknwon PPID(%d) for data length(%ld)\n",
ppid, datalen);
}
}
free(data);
}
return (1);
}
static void
handle_association_change_event(struct sctp_assoc_change *sac)
{
unsigned int i, n;
printf("Association change ");
switch (sac->sac_state) {
case SCTP_COMM_UP:
printf("SCTP_COMM_UP");
break;
case SCTP_COMM_LOST:
printf("SCTP_COMM_LOST");
break;
case SCTP_RESTART:
printf("SCTP_RESTART");
break;
case SCTP_SHUTDOWN_COMP:
printf("SCTP_SHUTDOWN_COMP");
break;
case SCTP_CANT_STR_ASSOC:
printf("SCTP_CANT_STR_ASSOC");
break;
default:
printf("UNKNOWN");
break;
}
printf(", streams (in/out) = (%u/%u)",
sac->sac_inbound_streams, sac->sac_outbound_streams);
n = sac->sac_length - sizeof(struct sctp_assoc_change);
if (((sac->sac_state == SCTP_COMM_UP) ||
(sac->sac_state == SCTP_RESTART)) && (n > 0)) {
printf(", supports");
for (i = 0; i < n; i++) {
switch (sac->sac_info[i]) {
case SCTP_ASSOC_SUPPORTS_PR:
printf(" PR");
break;
case SCTP_ASSOC_SUPPORTS_AUTH:
printf(" AUTH");
break;
case SCTP_ASSOC_SUPPORTS_ASCONF:
printf(" ASCONF");
break;
case SCTP_ASSOC_SUPPORTS_MULTIBUF:
printf(" MULTIBUF");
break;
case SCTP_ASSOC_SUPPORTS_RE_CONFIG:
printf(" RE-CONFIG");
break;
default:
printf(" UNKNOWN(0x%02x)", sac->sac_info[i]);
break;
}
}
} else if (((sac->sac_state == SCTP_COMM_LOST) ||
(sac->sac_state == SCTP_CANT_STR_ASSOC)) && (n > 0)) {
printf(", ABORT =");
for (i = 0; i < n; i++) {
printf(" 0x%02x", sac->sac_info[i]);
}
}
printf(".\n");
if ((sac->sac_state == SCTP_CANT_STR_ASSOC) ||
(sac->sac_state == SCTP_SHUTDOWN_COMP) ||
(sac->sac_state == SCTP_COMM_LOST)) {
exit(0);
}
return;
}
static void
handle_peer_address_change_event(struct sctp_paddr_change *spc)
{
char addr_buf[INET6_ADDRSTRLEN];
const char *addr;
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
struct sockaddr_conn *sconn;
switch (spc->spc_aaddr.ss_family) {
case AF_INET:
sin = (struct sockaddr_in *)&spc->spc_aaddr;
addr = inet_ntop(AF_INET, &sin->sin_addr, addr_buf, INET_ADDRSTRLEN);
break;
case AF_INET6:
sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr;
addr = inet_ntop(AF_INET6, &sin6->sin6_addr, addr_buf, INET6_ADDRSTRLEN);
break;
case AF_CONN:
sconn = (struct sockaddr_conn *)&spc->spc_aaddr;
#ifdef _WIN32
_snprintf(addr_buf, INET6_ADDRSTRLEN, "%p", sconn->sconn_addr);
#else
snprintf(addr_buf, INET6_ADDRSTRLEN, "%p", sconn->sconn_addr);
#endif
addr = addr_buf;
break;
default:
#ifdef _WIN32
_snprintf(addr_buf, INET6_ADDRSTRLEN, "Unknown family %d", spc->spc_aaddr.ss_family);
#else
snprintf(addr_buf, INET6_ADDRSTRLEN, "Unknown family %d", spc->spc_aaddr.ss_family);
#endif
addr = addr_buf;
break;
}
printf("Peer address %s is now ", addr);
switch (spc->spc_state) {
case SCTP_ADDR_AVAILABLE:
printf("SCTP_ADDR_AVAILABLE");
break;
case SCTP_ADDR_UNREACHABLE:
printf("SCTP_ADDR_UNREACHABLE");
break;
case SCTP_ADDR_REMOVED:
printf("SCTP_ADDR_REMOVED");
break;
case SCTP_ADDR_ADDED:
printf("SCTP_ADDR_ADDED");
break;
case SCTP_ADDR_MADE_PRIM:
printf("SCTP_ADDR_MADE_PRIM");
break;
case SCTP_ADDR_CONFIRMED:
printf("SCTP_ADDR_CONFIRMED");
break;
default:
printf("UNKNOWN");
break;
}
printf(" (error = 0x%08x).\n", spc->spc_error);
return;
}
static void
handle_send_failed_event(struct sctp_send_failed_event *ssfe)
{
size_t i, n;
if (ssfe->ssfe_flags & SCTP_DATA_UNSENT) {
printf("Unsent ");
}
if (ssfe->ssfe_flags & SCTP_DATA_SENT) {
printf("Sent ");
}
if (ssfe->ssfe_flags & ~(SCTP_DATA_SENT | SCTP_DATA_UNSENT)) {
printf("(flags = %x) ", ssfe->ssfe_flags);
}
printf("message with PPID = %u, SID = %u, flags: 0x%04x due to error = 0x%08x",
ntohl(ssfe->ssfe_info.snd_ppid), ssfe->ssfe_info.snd_sid,
ssfe->ssfe_info.snd_flags, ssfe->ssfe_error);
n = ssfe->ssfe_length - sizeof(struct sctp_send_failed_event);
for (i = 0; i < n; i++) {
printf(" 0x%02x", ssfe->ssfe_data[i]);
}
printf(".\n");
return;
}
static void
handle_notification(union sctp_notification *notif, size_t n)
{
if (notif->sn_header.sn_length != (uint32_t)n) {
return;
}
switch (notif->sn_header.sn_type) {
case SCTP_ASSOC_CHANGE:
handle_association_change_event(&(notif->sn_assoc_change));
break;
case SCTP_PEER_ADDR_CHANGE:
handle_peer_address_change_event(&(notif->sn_paddr_change));
break;
case SCTP_REMOTE_ERROR:
break;
case SCTP_SHUTDOWN_EVENT:
break;
case SCTP_ADAPTATION_INDICATION:
break;
case SCTP_PARTIAL_DELIVERY_EVENT:
break;
case SCTP_AUTHENTICATION_EVENT:
break;
case SCTP_SENDER_DRY_EVENT:
break;
case SCTP_NOTIFICATIONS_STOPPED_EVENT:
break;
case SCTP_SEND_FAILED_EVENT:
handle_send_failed_event(&(notif->sn_send_failed_event));
break;
case SCTP_STREAM_RESET_EVENT:
break;
case SCTP_ASSOC_RESET_EVENT:
break;
case SCTP_STREAM_CHANGE_EVENT:
break;
default:
break;
}
}
static void debug_printf(const char *format, ...)
{
va_list ap;
va_start(ap, format);
vprintf(format, ap);
va_end(ap);
}

View File

@@ -7,7 +7,9 @@
#include "context.h"
#include "app.h"
status_t app_initialize(char *config_path, char *log_path)
const char *app_name = "pcrf";
status_t app_initialize(const char *config_path, const char *log_path)
{
status_t rv;
int others = 0;
@@ -26,7 +28,7 @@ status_t app_initialize(char *config_path, char *log_path)
d_assert(rv == CORE_OK, return rv, "Failed to intialize PCRF");
d_trace(1, "PCRF initialize...done\n");
rv = app_did_initialize(config_path, log_path);
rv = app_did_initialize();
if (rv != CORE_OK) return rv;
return CORE_OK;

View File

@@ -256,31 +256,25 @@ status_t pcrf_db_pdn_data(
mutex_lock(self.db_lock);
query = BCON_NEW(
"imsi", BCON_UTF8(imsi_bcd),
"pdn.apn", BCON_UTF8(apn));
#if MONGOC_MAJOR_VERSION >= 1 && MONGOC_MINOR_VERSION >= 5
opts = BCON_NEW(
"projection", "{",
"imsi", BCON_INT64(1),
"pdn.$", BCON_INT64(1),
"}"
);
#if MONGOC_MAJOR_VERSION >= 1 && MONGOC_MINOR_VERSION >= 5
query = BCON_NEW(
"imsi", BCON_UTF8(imsi_bcd),
"pdn.apn", BCON_UTF8(apn));
cursor = mongoc_collection_find_with_opts(
self.subscriberCollection, query, opts, NULL);
#else
query = BCON_NEW(
"$query", "{",
"imsi", BCON_UTF8(imsi_bcd),
"pdn.apn", BCON_UTF8(apn),
"}",
"$projection", "{",
"imsi", BCON_INT64(1),
"pdn.$", BCON_INT64(1),
"}"
opts = BCON_NEW(
"imsi", BCON_INT64(1),
"pdn.$", BCON_INT64(1)
);
cursor = mongoc_collection_find(self.subscriberCollection,
MONGOC_QUERY_NONE, 0, 0, 0, query, NULL, NULL);
MONGOC_QUERY_NONE, 0, 0, 0, query, opts, NULL);
#endif
if (!mongoc_cursor_next(cursor, &document))

View File

@@ -7,7 +7,9 @@
#include "context.h"
#include "app.h"
status_t app_initialize(char *config_path, char *log_path)
const char *app_name = "pgw";
status_t app_initialize(const char *config_path, const char *log_path)
{
status_t rv;
int others = 0;
@@ -26,7 +28,7 @@ status_t app_initialize(char *config_path, char *log_path)
d_assert(rv == CORE_OK, return rv, "Failed to intialize PGW");
d_trace(1, "PGW initialize...done\n");
rv = app_did_initialize(config_path, log_path);
rv = app_did_initialize();
if (rv != CORE_OK) return rv;
return CORE_OK;

View File

@@ -94,8 +94,8 @@ pgw_context_t* pgw_self()
static status_t pgw_context_prepare()
{
self.s5c_port = GTPV2_C_UDP_PORT;
self.s5u_port = GTPV1_U_UDP_PORT;
self.gtpc_port = GTPV2_C_UDP_PORT;
self.gtpu_port = GTPV1_U_UDP_PORT;
return CORE_OK;
}
@@ -108,27 +108,21 @@ static status_t pgw_context_validation()
context_self()->config.path);
return CORE_ERROR;
}
if (self.s5c_addr == 0)
if (self.gtpc_addr == 0)
{
d_error("No PGW.NEWORK.S5C_IPV4 in '%s'",
d_error("No PGW.NEWORK.GTPC_IPV4 in '%s'",
context_self()->config.path);
return CORE_ERROR;
}
if (self.s5u_addr == 0)
if (self.gtpu_addr == 0)
{
d_error("No PGW.NEWORK.S5U_IPV4 in '%s'",
d_error("No PGW.NEWORK.GTPU_IPV4 in '%s'",
context_self()->config.path);
return CORE_ERROR;
}
if (self.tun_dev_name == NULL)
if (self.num_of_ue_network == 0)
{
d_error("No PGW.TUNNEL.DEV_NAME in '%s'",
context_self()->config.path);
return CORE_ERROR;
}
if (self.num_of_ip_pool == 0)
{
d_error("No PGW.IP_POOL.CIDR in '%s'",
d_error("No PGW.UE_NETWORK.IPV4_POOL in '%s'",
context_self()->config.path);
return CORE_ERROR;
}
@@ -227,54 +221,30 @@ status_t pgw_context_parse_config()
{
n += (t+m)->size;
if (jsmntok_equal(json, t+m, "S5C_IPV4") == 0)
if (jsmntok_equal(json, t+m, "GTPC_IPV4") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s5c_addr = inet_addr(v);
if (v) self.gtpc_addr = inet_addr(v);
}
else if (jsmntok_equal(json, t+m, "S5C_PORT") == 0)
else if (jsmntok_equal(json, t+m, "GTPC_PORT") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s5c_port = atoi(v);
if (v) self.gtpc_port = atoi(v);
}
else if (jsmntok_equal(json, t+m, "S5U_IPV4") == 0)
else if (jsmntok_equal(json, t+m, "GTPU_IPV4") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s5u_addr = inet_addr(v);
if (v) self.gtpu_addr = inet_addr(v);
}
else if (jsmntok_equal(json, t+m, "S5U_PORT") == 0)
else if (jsmntok_equal(json, t+m, "GTPU_PORT") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s5u_port = atoi(v);
if (v) self.gtpu_port = atoi(v);
}
}
}
}
else if (jsmntok_equal(json, t, "TUNNEL") == 0)
{
m = 1;
size = 1;
if ((t+1)->type == JSMN_ARRAY)
{
m = 2;
}
for (arr = 0; arr < size; arr++)
{
for (n = 1; n > 0; m++, n--)
{
n += (t+m)->size;
if (jsmntok_equal(json, t+m, "DEV_NAME") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
self.tun_dev_name = v;
}
}
}
}
else if (jsmntok_equal(json, t, "IP_POOL") == 0)
else if (jsmntok_equal(json, t, "UE_NETWORK") == 0)
{
m = 1;
size = 1;
@@ -287,28 +257,42 @@ status_t pgw_context_parse_config()
for (arr = 0; arr < size; arr++)
{
char *if_name = NULL;
c_uint32_t addr = 0;
c_uint8_t bits = 0;
for (n = 1; n > 0; m++, n--)
{
n += (t+m)->size;
if (jsmntok_equal(json, t+m, "CIDR") == 0)
if (jsmntok_equal(json, t+m, "IF_NAME") == 0)
{
if_name = jsmntok_to_string(json, t+m+1);
}
else if (jsmntok_equal(json, t+m, "IPV4_POOL") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v)
{
char *prefix = strsep(&v, "/");
if (prefix)
char *str = strsep(&v, "/");
if (str)
{
self.ip_pool[self.num_of_ip_pool].prefix
= inet_addr(prefix);
self.ip_pool[self.num_of_ip_pool].mask
= atoi(v);
addr = inet_addr(str);
bits = atoi(v);
}
}
self.num_of_ip_pool++;
}
}
if (addr && bits)
{
self.ue_network[self.num_of_ue_network].if_name =
if_name;
self.ue_network[self.num_of_ue_network].ipv4.addr =
addr;
self.ue_network[self.num_of_ue_network].ipv4.bits =
bits;
self.num_of_ue_network++;
}
}
}
else if (jsmntok_equal(json, t, "DNS") == 0)
@@ -513,7 +497,7 @@ pgw_sess_t *pgw_sess_add(
d_assert(sess, return NULL, "Null param");
sess->pgw_s5c_teid = sess->index; /* derived from an index */
sess->pgw_s5c_addr = pgw_self()->s5c_addr;
sess->pgw_s5c_addr = pgw_self()->gtpc_addr;
/* Set IMSI */
sess->imsi_len = imsi_len;
@@ -657,7 +641,7 @@ pgw_bearer_t* pgw_bearer_add(pgw_sess_t *sess)
list_init(&bearer->pf_list);
bearer->pgw_s5u_teid = bearer->index;
bearer->pgw_s5u_addr = pgw_self()->s5u_addr;
bearer->pgw_s5u_addr = pgw_self()->gtpu_addr;
bearer->sess = sess;
list_append(&sess->bearer_list, bearer);
@@ -1049,14 +1033,36 @@ pgw_pf_t* pgw_pf_next(pgw_pf_t *pf)
status_t pgw_ip_pool_generate()
{
int i, j, k;
int i, j;
int pool_index = 0;
for (i = 0; i < self.num_of_ip_pool; i++)
for (i = 0; i < self.num_of_ue_network; i++)
{
c_uint32_t mask = htonl(0xffffffff << (32 - self.ip_pool[i].mask));
c_uint32_t prefix = self.ip_pool[i].prefix & mask;
c_uint32_t mask =
htonl(0xffffffff << (32 - self.ue_network[i].ipv4.bits));
c_uint32_t prefix = self.ue_network[i].ipv4.addr & mask;
#if 1 /* Update IP assign rule from bradon's comment */
c_uint32_t broadcast = prefix + ~mask;
for (j = 1; j < (0xffffffff >> self.ue_network[i].ipv4.bits) &&
pool_index < MAX_POOL_OF_SESS; j++)
{
pgw_ip_pool_t *ip_pool = &pgw_ip_pool_pool.pool[pool_index];
ip_pool->ue_addr = prefix + htonl(j);
/* Exclude Network Address */
if (ip_pool->ue_addr == prefix) continue;
/* Exclude Broadcast Address */
if (ip_pool->ue_addr == broadcast) continue;
/* Exclude TUN IP Address */
if (ip_pool->ue_addr == self.ue_network[i].ipv4.addr) continue;
pool_index++;
}
#else /* Deprecated */
/* Exclude X.X.X.0, X.X.X.255 addresses from ip pool */
c_uint32_t exclude_mask[] = { 0, 255 };
@@ -1081,6 +1087,7 @@ status_t pgw_ip_pool_generate()
}
pool_index++;
}
#endif
}
return CORE_OK;

View File

@@ -11,7 +11,7 @@
#include "pgw_sm.h"
#define MAX_NUM_OF_IP_POOL 16
#define MAX_NUM_OF_UE_NETWORK 16
#ifdef __cplusplus
extern "C" {
@@ -22,27 +22,28 @@ typedef gtp_node_t pgw_sgw_t;
typedef struct _pgw_context_t {
c_uint32_t pgw_addr; /* PGW local address */
c_uint32_t s5c_addr; /* PGW S5-C local address */
c_uint32_t s5c_port; /* PGW S5-C local port */
net_sock_t* s5c_sock; /* PGW S5-C local listen socket */
c_uint32_t gtpc_addr; /* PGW GTP-C local address */
c_uint32_t gtpc_port; /* PGW GTP-C local port */
net_sock_t* gtpc_sock; /* PGW GTP-C local listen socket */
c_uint32_t s5u_addr; /* PGW S5-U local address */
c_uint32_t s5u_port; /* PGW S5-U local port */
net_sock_t* s5u_sock; /* PGW S5-U local listen socket */
c_uint32_t gtpu_addr; /* PGW GTP-U local address */
c_uint32_t gtpu_port; /* PGW GTP-U local port */
net_sock_t* gtpu_sock; /* PGW GTP-U local listen socket */
char* fd_conf_path; /* PGW freeDiameter conf path */
msgq_id queue_id; /* Qsesssess for processing PGW control plane */
tm_service_t tm_service; /* Timer Service */
char *tun_dev_name; /* PGW Tunnel device name */
net_link_t* tun_link; /* PGW Tun Interace for U-plane */
struct {
c_uint32_t prefix;
c_uint8_t mask;
} ip_pool[MAX_NUM_OF_IP_POOL];
c_uint8_t num_of_ip_pool;
net_link_t* tun_link; /* PGW Tun Interace for U-plane */
char *if_name;
struct {
c_uint32_t addr;
c_uint8_t bits;
} ipv4;
} ue_network[MAX_NUM_OF_UE_NETWORK];
c_uint8_t num_of_ue_network;
c_uint32_t primary_dns_addr;
c_uint32_t secondary_dns_addr;

View File

@@ -64,7 +64,7 @@ static int _gtpv1_tun_recv_cb(net_link_t *net_link, void *data)
/* Send to SGW */
gnode.addr = bearer->sgw_s5u_addr;
gnode.port = GTPV1_U_UDP_PORT;
gnode.sock = pgw_self()->s5u_sock;
gnode.sock = pgw_self()->gtpu_sock;
d_trace(50, "Send S5U PDU (teid = 0x%x)to SGW(%s)\n",
bearer->sgw_s5u_teid,
INET_NTOP(&gnode.addr, buf));
@@ -73,7 +73,7 @@ static int _gtpv1_tun_recv_cb(net_link_t *net_link, void *data)
}
else
{
d_error("Can not find bearer");
d_trace(3, "Can not find bearer\n");
}
pkbuf_free(recvbuf);
@@ -160,7 +160,8 @@ static int _gtpv1_u_recv_cb(net_sock_t *sock, void *data)
return -1;
}
if (net_link_write(pgw_self()->tun_link, pkbuf->payload, pkbuf->len) <= 0)
if (net_link_write(pgw_self()->ue_network[(c_uintptr_t)data].tun_link,
pkbuf->payload, pkbuf->len) <= 0)
{
d_error("Can not send packets to tuntap");
}
@@ -173,26 +174,28 @@ static int _gtpv1_u_recv_cb(net_sock_t *sock, void *data)
status_t pgw_gtp_open()
{
status_t rv;
int i;
int rc;
char buf[INET_ADDRSTRLEN];
rv = gtp_listen(&pgw_self()->s5c_sock, _gtpv2_c_recv_cb,
pgw_self()->s5c_addr, pgw_self()->s5c_port, NULL);
rv = gtp_listen(&pgw_self()->gtpc_sock, _gtpv2_c_recv_cb,
pgw_self()->gtpc_addr, pgw_self()->gtpc_port, NULL);
if (rv != CORE_OK)
{
d_error("Can't establish S5-C Path for PGW");
d_error("Can't establish GTP-C Path for PGW");
return rv;
}
rv = gtp_listen(&pgw_self()->s5u_sock, _gtpv1_u_recv_cb,
pgw_self()->s5u_addr, pgw_self()->s5u_port, NULL);
rv = gtp_listen(&pgw_self()->gtpu_sock, _gtpv1_u_recv_cb,
pgw_self()->gtpu_addr, pgw_self()->gtpu_port, NULL);
if (rv != CORE_OK)
{
d_error("Can't establish S5-U Path for PGW");
d_error("Can't establish GTP-U Path for PGW");
return rv;
}
for (i = 0; i < pgw_self()->num_of_ue_network; i++)
{
int rc;
/* NOTE : tun device can be created via following command.
*
* $ sudo ip tuntap add name pgwtun mode tun
@@ -205,21 +208,47 @@ status_t pgw_gtp_open()
*/
/* Open Tun interface */
rc = net_tuntap_open(&pgw_self()->tun_link, pgw_self()->tun_dev_name, 0);
rc = net_tun_open(&pgw_self()->ue_network[i].tun_link,
pgw_self()->ue_network[i].if_name, 0);
if (rc != 0)
{
d_error("Can not open tun(dev : %s)", pgw_self()->tun_dev_name);
d_error("Can not open tun(dev : %s)",
pgw_self()->ue_network[i].if_name);
return CORE_ERROR;
}
rc = net_register_link(pgw_self()->tun_link, _gtpv1_tun_recv_cb, NULL);
/*
* On Linux, it is possible to create a persistent tun/tap
* interface which will continue to exist even if nextepc quit,
* although this is normally not required.
* It can be useful to set up a tun/tap interface owned
* by a non-root user, so nextepc can be started without
* needing any root privileges at all.
*/
/* Set P-to-P IP address with Netmask
* Note that Linux will skip this configuration */
rc = net_tun_set_ipv4(pgw_self()->ue_network[i].tun_link,
pgw_self()->ue_network[i].ipv4.addr,
pgw_self()->ue_network[i].ipv4.bits);
if (rc != 0)
{
d_error("Can not register tun(dev : %s)", pgw_self()->tun_dev_name);
net_tuntap_close(pgw_self()->tun_link);
d_error("Can not configure tun(dev : %s for %s/%d)",
pgw_self()->ue_network[i].if_name,
INET_NTOP(&pgw_self()->ue_network[i].ipv4.addr, buf),
pgw_self()->ue_network[i].ipv4.bits);
return CORE_ERROR;
}
rc = net_register_link(pgw_self()->ue_network[i].tun_link,
_gtpv1_tun_recv_cb, (void *)(c_uintptr_t)i);
if (rc != 0)
{
d_error("Can not register tun(dev : %s)",
pgw_self()->ue_network[i].if_name);
net_tun_close(pgw_self()->ue_network[i].tun_link);
return CORE_ERROR;
}
}
return CORE_OK;
@@ -228,23 +257,27 @@ status_t pgw_gtp_open()
status_t pgw_gtp_close()
{
status_t rv;
int i;
rv = gtp_close(pgw_self()->s5c_sock);
rv = gtp_close(pgw_self()->gtpc_sock);
if (rv != CORE_OK)
{
d_error("Can't close S5-C Path for MME");
d_error("Can't close GTP-C Path for MME");
return rv;
}
rv = gtp_close(pgw_self()->s5u_sock);
rv = gtp_close(pgw_self()->gtpu_sock);
if (rv != CORE_OK)
{
d_error("Can't close S5-U Path for MME");
d_error("Can't close GTP-U Path for MME");
return rv;
}
net_unregister_link(pgw_self()->tun_link);
net_tuntap_close(pgw_self()->tun_link);
for (i = 0; i < pgw_self()->num_of_ue_network; i++)
{
net_unregister_link(pgw_self()->ue_network[i].tun_link);
net_tun_close(pgw_self()->ue_network[i].tun_link);
}
return CORE_OK;
}

View File

@@ -7,7 +7,9 @@
#include "context.h"
#include "app.h"
status_t app_initialize(char *config_path, char *log_path)
const char *app_name = "sgw";
status_t app_initialize(const char *config_path, const char *log_path)
{
status_t rv;
int others = 0;
@@ -26,7 +28,7 @@ status_t app_initialize(char *config_path, char *log_path)
d_assert(rv == CORE_OK, return rv, "Failed to intialize SGW");
d_trace(1, "SGW initialize...done\n");
rv = app_did_initialize(config_path, log_path);
rv = app_did_initialize();
if (rv != CORE_OK) return rv;
return CORE_OK;

View File

@@ -80,37 +80,23 @@ sgw_context_t* sgw_self()
static status_t sgw_context_prepare()
{
self.s11_port = GTPV2_C_UDP_PORT;
self.s5c_port = GTPV2_C_UDP_PORT;
self.s1u_port = GTPV1_U_UDP_PORT;
self.s5u_port = GTPV1_U_UDP_PORT;
self.gtpc_port = GTPV2_C_UDP_PORT;
self.gtpu_port = GTPV1_U_UDP_PORT;
return CORE_OK;
}
static status_t sgw_context_validation()
{
if (self.s11_addr == 0)
if (self.gtpc_addr == 0)
{
d_error("No SGW.NEWORK.S11_IPV4 in '%s'",
d_error("No SGW.NEWORK.GTPC_IPV4 in '%s'",
context_self()->config.path);
return CORE_ERROR;
}
if (self.s5c_addr == 0)
if (self.gtpu_addr == 0)
{
d_error("No SGW.NEWORK.S5C_IPV4 in '%s'",
context_self()->config.path);
return CORE_ERROR;
}
if (self.s1u_addr == 0)
{
d_error("No SGW.NEWORK.S1U_IPV4 in '%s'",
context_self()->config.path);
return CORE_ERROR;
}
if (self.s5u_addr == 0)
{
d_error("No SGW.NEWORK.S5U_IPV4 in '%s'",
d_error("No SGW.NEWORK.GTPU_IPV4 in '%s'",
context_self()->config.path);
return CORE_ERROR;
}
@@ -199,45 +185,25 @@ status_t sgw_context_parse_config()
{
n += (t+m)->size;
if (jsmntok_equal(json, t+m, "S11_IPV4") == 0)
if (jsmntok_equal(json, t+m, "GTPC_IPV4") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s11_addr = inet_addr(v);
if (v) self.gtpc_addr = inet_addr(v);
}
else if (jsmntok_equal(json, t+m, "S11_PORT") == 0)
else if (jsmntok_equal(json, t+m, "GTPC_PORT") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s11_port = atoi(v);
if (v) self.gtpc_port = atoi(v);
}
else if (jsmntok_equal(json, t+m, "S5C_IPV4") == 0)
else if (jsmntok_equal(json, t+m, "GTPU_IPV4") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s5c_addr = inet_addr(v);
if (v) self.gtpu_addr = inet_addr(v);
}
else if (jsmntok_equal(json, t+m, "S5C_PORT") == 0)
else if (jsmntok_equal(json, t+m, "GTPU_PORT") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s5c_port = atoi(v);
}
else if (jsmntok_equal(json, t+m, "S1U_IPV4") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s1u_addr = inet_addr(v);
}
else if (jsmntok_equal(json, t+m, "S1U_PORT") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s1u_port = atoi(v);
}
else if (jsmntok_equal(json, t+m, "S5U_IPV4") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s5u_addr = inet_addr(v);
}
else if (jsmntok_equal(json, t+m, "S5U_PORT") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s5u_port = atoi(v);
if (v) self.gtpu_port = atoi(v);
}
}
}
@@ -472,7 +438,7 @@ sgw_ue_t* sgw_ue_add(
d_assert(sgw_ue, return NULL, "Null param");
sgw_ue->sgw_s11_teid = sgw_ue->index;
sgw_ue->sgw_s11_addr = sgw_self()->s11_addr;
sgw_ue->sgw_s11_addr = sgw_self()->gtpc_addr;
/* Set IMSI */
sgw_ue->imsi_len = imsi_len;
@@ -609,7 +575,7 @@ sgw_sess_t *sgw_sess_add(
d_assert(sess, return NULL, "Null param");
sess->sgw_s5c_teid = sess->index;
sess->sgw_s5c_addr = sgw_self()->s5c_addr;
sess->sgw_s5c_addr = sgw_self()->gtpc_addr;
/* Set APN */
core_cpystrn(sess->pdn.apn, apn, MAX_APN_LEN+1);
@@ -719,9 +685,6 @@ sgw_bearer_t* sgw_bearer_add(sgw_sess_t *sess)
index_alloc(&sgw_bearer_pool, &bearer);
d_assert(bearer, return NULL, "Bearer context allocation failed");
bearer->sgw_s5u_teid = bearer->index;
bearer->sgw_s5u_addr = sgw_self()->s5u_addr;
list_append(&sess->bearer_list, bearer);
bearer->sgw_ue = sgw_ue;
@@ -732,6 +695,9 @@ sgw_bearer_t* sgw_bearer_add(sgw_sess_t *sess)
tunnel = sgw_tunnel_add(bearer, GTP_F_TEID_S1_U_SGW_GTP_U);
d_assert(tunnel, return NULL, "Tunnel context allocation failed");
tunnel = sgw_tunnel_add(bearer, GTP_F_TEID_S5_S8_SGW_GTP_U);
d_assert(tunnel, return NULL, "Tunnel context allocation failed");
return bearer;
}
@@ -849,7 +815,7 @@ sgw_tunnel_t* sgw_tunnel_add(sgw_bearer_t *bearer, c_uint8_t interface_type)
tunnel->interface_type = interface_type;
tunnel->local_teid = tunnel->index;
tunnel->local_addr = sgw_self()->s1u_addr;
tunnel->local_addr = sgw_self()->gtpu_addr;
tunnel->bearer = bearer;
@@ -901,7 +867,8 @@ sgw_tunnel_t* sgw_tunnel_find_by_teid(c_uint32_t teid)
return sgw_tunnel_find(teid);
}
sgw_tunnel_t* sgw_direct_tunnel_in_bearer(sgw_bearer_t *bearer)
sgw_tunnel_t* sgw_tunnel_find_by_interface_type(
sgw_bearer_t *bearer, c_uint8_t interface_type)
{
sgw_tunnel_t *tunnel = NULL;
@@ -910,7 +877,7 @@ sgw_tunnel_t* sgw_direct_tunnel_in_bearer(sgw_bearer_t *bearer)
tunnel = sgw_tunnel_first(bearer);
while(tunnel)
{
if (tunnel->interface_type == GTP_F_TEID_S1_U_SGW_GTP_U)
if (tunnel->interface_type == interface_type)
{
return tunnel;
}
@@ -921,6 +888,17 @@ sgw_tunnel_t* sgw_direct_tunnel_in_bearer(sgw_bearer_t *bearer)
return NULL;
}
sgw_tunnel_t* sgw_s1u_tunnel_in_bearer(sgw_bearer_t *bearer)
{
return sgw_tunnel_find_by_interface_type(
bearer, GTP_F_TEID_S1_U_SGW_GTP_U);
}
sgw_tunnel_t* sgw_s5u_tunnel_in_bearer(sgw_bearer_t *bearer)
{
return sgw_tunnel_find_by_interface_type(
bearer, GTP_F_TEID_S5_S8_SGW_GTP_U);
}
sgw_tunnel_t* sgw_tunnel_first(sgw_bearer_t *bearer)
{
d_assert(bearer, return NULL, "Null param");

View File

@@ -21,26 +21,16 @@ typedef gtp_node_t sgw_mme_t;
typedef gtp_node_t sgw_pgw_t;
typedef struct _sgw_context_t {
c_uint32_t sgw_addr; /* SGW local address */
c_uint32_t gtpc_addr; /* GTP-U local address */
c_uint32_t gtpc_port; /* GTP-U local port */
net_sock_t* gtpc_sock; /* GTP-U local listen socket */
c_uint32_t s11_addr; /* SGW S11 local address */
c_uint32_t s11_port; /* SGW S11 local port */
net_sock_t* s11_sock; /* SGW S11 local listen socket */
c_uint32_t gtpu_addr; /* GTP-U local address */
c_uint32_t gtpu_port; /* GTP-U local port */
net_sock_t* gtpu_sock; /* GTP-U local listen socket */
c_uint32_t s5c_addr; /* SGW S5-C local address */
c_uint32_t s5c_port; /* SGW S5-C local port */
net_sock_t* s5c_sock; /* SGW S5-C local listen socket */
c_uint32_t s1u_addr; /* SGW S1-U local address */
c_uint32_t s1u_port; /* SGW S1-U local port */
net_sock_t* s1u_sock; /* SGW S1-U local listen socket */
c_uint32_t s5u_addr; /* SGW S5-U local address */
c_uint32_t s5u_port; /* SGW S5-U local port */
net_sock_t* s5u_sock; /* SGW S5-U local listen socket */
msgq_id queue_id; /* Queue for processing SGW control plane */
tm_service_t tm_service; /* Timer Service */
msgq_id queue_id; /* Queue for processing SGW control plane */
tm_service_t tm_service;/* Timer Service */
list_t mme_list; /* MME GTP Node List */
list_t pgw_list; /* PGW GTP Node List */
@@ -117,13 +107,6 @@ typedef struct _sgw_bearer_t {
c_uint8_t ebi;
/* IMPORTANT!
* SGW-S5U-TEID is same with an index */
c_uint32_t sgw_s5u_teid;
c_uint32_t sgw_s5u_addr;
c_uint32_t enb_s1u_teid;
c_uint32_t enb_s1u_addr;
/* User-Lication-Info */
tai_t tai;
e_cgi_t e_cgi;
@@ -224,7 +207,10 @@ CORE_DECLARE(status_t) sgw_tunnel_remove(sgw_tunnel_t *tunnel);
CORE_DECLARE(status_t) sgw_tunnel_remove_all(sgw_bearer_t *bearer);
CORE_DECLARE(sgw_tunnel_t*) sgw_tunnel_find(index_t index);
CORE_DECLARE(sgw_tunnel_t*) sgw_tunnel_find_by_teid(c_uint32_t teid);
CORE_DECLARE(sgw_tunnel_t*) sgw_direct_tunnel_in_bearer(sgw_bearer_t *bearer);
CORE_DECLARE(sgw_tunnel_t*) sgw_tunnel_find_by_interface_type(
sgw_bearer_t *bearer, c_uint8_t interface_type);
CORE_DECLARE(sgw_tunnel_t*) sgw_s1u_tunnel_in_bearer(sgw_bearer_t *bearer);
CORE_DECLARE(sgw_tunnel_t*) sgw_s5u_tunnel_in_bearer(sgw_bearer_t *bearer);
CORE_DECLARE(sgw_tunnel_t*) sgw_tunnel_first(sgw_bearer_t *bearer);
CORE_DECLARE(sgw_tunnel_t*) sgw_tunnel_next(sgw_tunnel_t *tunnel);

View File

@@ -15,13 +15,13 @@ static int _gtpv2_c_recv_cb(net_sock_t *sock, void *data)
{
event_t e;
status_t rv;
gtp_header_t *gtp_h = NULL;
pkbuf_t *pkbuf = NULL;
c_uint32_t addr;
c_uint16_t port;
event_e event = (event_e)data;
c_uint32_t addr = 0;
c_uint16_t port = 0;
sgw_mme_t *mme = NULL;
d_assert(sock, return -1, "Null param");
d_assert(data, return -1, "Null param");
pkbuf = gtp_read(sock);
if (pkbuf == NULL)
@@ -32,39 +32,41 @@ static int _gtpv2_c_recv_cb(net_sock_t *sock, void *data)
return -1;
}
gtp_h = (gtp_header_t *)pkbuf->payload;
d_assert(gtp_h, return -1, "Null param");
addr = sock->remote.sin_addr.s_addr;
port = ntohs(sock->remote.sin_port);
event_set(&e, event);
event_set_param2(&e, (c_uintptr_t)pkbuf);
if (event == SGW_EVT_S11_MESSAGE)
mme = sgw_mme_find(addr, port);
if (!mme && gtp_h->teid == 0)
{
sgw_mme_t *mme = sgw_mme_find(addr, port);
if (!mme)
{
mme = sgw_mme_add();
d_assert(mme, return -1, "Can't add MME-GTP node");
mme = sgw_mme_add();
d_assert(mme, return -1, "Can't add MME-GTP node");
mme->addr = addr;
mme->port = port;
mme->sock = sock;
}
mme->addr = addr;
mme->port = port;
mme->sock = sock;
}
if (mme)
{
d_trace(10, "S11 PDU received from MME\n");
event_set(&e, SGW_EVT_S11_MESSAGE);
event_set_param1(&e, (c_uintptr_t)mme);
}
else if (event == SGW_EVT_S5C_MESSAGE)
{
sgw_pgw_t *pgw = sgw_pgw_find(addr, port);
d_assert(pgw, return -1, "Can't add PGW-GTP node");
d_trace(10, "S5-C PDU received from PGW\n");
event_set_param1(&e, (c_uintptr_t)pgw);
event_set_param2(&e, (c_uintptr_t)pkbuf);
}
else
d_assert(0, pkbuf_free(pkbuf); return -1, "Unknown GTP-Node");
{
d_trace(10, "S5C PDU received from PGW\n");
event_set(&e, SGW_EVT_S5C_MESSAGE);
event_set_param1(&e, (c_uintptr_t)addr);
event_set_param2(&e, (c_uintptr_t)port);
event_set_param3(&e, (c_uintptr_t)pkbuf);
}
d_trace_hex(10, pkbuf->payload, pkbuf->len);
@@ -79,6 +81,168 @@ static int _gtpv2_c_recv_cb(net_sock_t *sock, void *data)
return 0;
}
static int _gtpv1_u_recv_cb(net_sock_t *sock, void *data)
{
pkbuf_t *pkbuf = NULL;
gtp_node_t gnode;
gtp_header_t *gtp_h = NULL;
sgw_bearer_t *bearer = NULL;
sgw_tunnel_t *tunnel = NULL;
c_uint32_t teid;
int i;
d_assert(sock, return -1, "Null param");
pkbuf = gtp_read(sock);
if (pkbuf == NULL)
{
if (sock->sndrcv_errno == EAGAIN)
return 0;
return -1;
}
d_trace(50, "GTP-U PDU received\n");
d_trace_hex(50, pkbuf->payload, pkbuf->len);
gtp_h = (gtp_header_t *)pkbuf->payload;
if (gtp_h->type == GTPU_MSGTYPE_ECHO_REQ)
{
pkbuf_t *echo_rsp;
d_trace(3, "Received echo-req\n");
echo_rsp = gtp_handle_echo_req(pkbuf);
if (echo_rsp)
{
/* Echo reply */
d_trace(3, "Send echo-rsp to peer\n");
gnode.addr = sock->remote.sin_addr.s_addr;
gnode.port = ntohs(sock->remote.sin_port);
gnode.sock = sock;
gtp_send(&gnode, echo_rsp);
pkbuf_free(echo_rsp);
}
}
else if (gtp_h->type == GTPU_MSGTYPE_GPDU ||
gtp_h->type == GTPU_MSGTYPE_END_MARKER)
{
teid = ntohl(gtp_h->teid);
d_trace(50, "Recv GPDU (teid = 0x%x)\n", teid);
tunnel = sgw_tunnel_find_by_teid(teid);
d_assert(tunnel, return -1, "No TEID(0x%x)", teid);
bearer = tunnel->bearer;
d_assert(bearer, return -1, "Null param");
/* Convert TEID */
gnode.port = GTPV1_U_UDP_PORT;
gnode.sock = sgw_self()->gtpu_sock;
if (tunnel->interface_type ==
GTP_F_TEID_S1_U_SGW_GTP_U ||
tunnel->interface_type ==
GTP_F_TEID_SGW_GTP_U_FOR_DL_DATA_FORWARDING ||
tunnel->interface_type ==
GTP_F_TEID_SGW_GTP_U_FOR_UL_DATA_FORWARDING)
{
sgw_tunnel_t *s5u_tunnel = NULL;
d_trace(50, "Recv GPDU (teid = 0x%x) from eNB\n", teid);
s5u_tunnel = sgw_s5u_tunnel_in_bearer(bearer);
d_assert(s5u_tunnel, return -1, "Null param");
gnode.addr = s5u_tunnel->remote_addr;
gtp_h->teid = htonl(s5u_tunnel->remote_teid);
gtp_send(&gnode, pkbuf);
}
else if (tunnel->interface_type == GTP_F_TEID_S5_S8_SGW_GTP_U)
{
sgw_tunnel_t *s1u_tunnel = NULL;
d_trace(50, "Recv GPDU (teid = 0x%x) from PGW\n", teid);
s1u_tunnel = sgw_s1u_tunnel_in_bearer(bearer);
d_assert(s1u_tunnel, return -1, "Null param");
gnode.addr = s1u_tunnel->remote_addr;
if (s1u_tunnel->remote_teid)
{
/* If there is buffered packet, send it first */
for (i = 0; i < bearer->num_buffered_pkt; i++)
{
gtp_h = (gtp_header_t *)bearer->buffered_pkts[i]->payload;
gtp_h->teid = htonl(s1u_tunnel->remote_teid);
gtp_send(&gnode, bearer->buffered_pkts[i]);
pkbuf_free(bearer->buffered_pkts[i]);
}
bearer->num_buffered_pkt = 0;
gtp_h->teid = htonl(s1u_tunnel->remote_teid);
gtp_send(&gnode, pkbuf);
}
else
{
/* S1U path is deactivated.
* Send downlink_data_notification to MME.
*
*/
sgw_ue_t *sgw_ue = NULL;
d_assert(bearer->sess, pkbuf_free(pkbuf); return 0,
"Session is NULL");
d_assert(bearer->sess->sgw_ue, pkbuf_free(pkbuf); return 0,
"SGW_UE is NULL");
sgw_ue = bearer->sess->sgw_ue;
if ((SGW_GET_UE_STATE(sgw_ue) & SGW_S1U_INACTIVE))
{
if ( !(SGW_GET_UE_STATE(sgw_ue) & SGW_DL_NOTI_SENT))
{
event_t e;
status_t rv;
event_set(&e, SGW_EVT_LO_DLDATA_NOTI);
event_set_param1(&e, (c_uintptr_t)bearer->index);
rv = sgw_event_send(&e);
if (rv != CORE_OK)
{
d_error("sgw_event_send error");
pkbuf_free(pkbuf);
return -1;
}
SGW_SET_UE_STATE(sgw_ue, SGW_DL_NOTI_SENT);
}
/* Buffer the packet */
if (bearer->num_buffered_pkt < MAX_NUM_BUFFER_PKT)
{
bearer->buffered_pkts[bearer->num_buffered_pkt++] =
pkbuf;
return 0;
}
}
else
{
/* UE is S1U_ACTIVE state but there is no s1u teid */
d_warn("UE is ACITVE but there is no matched "
"s1u_teid(tedid = 0x%x)",teid);
/* Just drop it */
}
}
}
}
pkbuf_free(pkbuf);
return 0;
}
#if 0
static int _gtpv1_s5u_recv_cb(net_sock_t *sock, void *data)
{
pkbuf_t *pkbuf = NULL;
@@ -291,42 +455,25 @@ static int _gtpv1_s1u_recv_cb(net_sock_t *sock, void *data)
pkbuf_free(pkbuf);
return 0;
}
#endif
status_t sgw_gtp_open()
{
status_t rv;
rv = gtp_listen(&sgw_self()->s11_sock, _gtpv2_c_recv_cb,
sgw_self()->s11_addr, sgw_self()->s11_port,
(void*)SGW_EVT_S11_MESSAGE);
rv = gtp_listen(&sgw_self()->gtpc_sock, _gtpv2_c_recv_cb,
sgw_self()->gtpc_addr, sgw_self()->gtpc_port, NULL);
if (rv != CORE_OK)
{
d_error("Can't establish S11 Path for SGW");
d_error("Can't establish GTP-C Path for MME/PGW");
return rv;
}
rv = gtp_listen(&sgw_self()->s5c_sock, _gtpv2_c_recv_cb,
sgw_self()->s5c_addr, sgw_self()->s5c_port,
(void*)SGW_EVT_S5C_MESSAGE);
rv = gtp_listen(&sgw_self()->gtpu_sock, _gtpv1_u_recv_cb,
sgw_self()->gtpu_addr, sgw_self()->gtpu_port, NULL);
if (rv != CORE_OK)
{
d_error("Can't establish S5-C Path for SGW");
return rv;
}
rv = gtp_listen(&sgw_self()->s5u_sock, _gtpv1_s5u_recv_cb,
sgw_self()->s5u_addr, sgw_self()->s5u_port, NULL);
if (rv != CORE_OK)
{
d_error("Can't establish S5-U Path for SGW");
return rv;
}
rv = gtp_listen(&sgw_self()->s1u_sock, _gtpv1_s1u_recv_cb,
sgw_self()->s1u_addr, sgw_self()->s1u_port, NULL);
if (rv != CORE_OK)
{
d_error("Can't establish S1-U Path for SGW");
d_error("Can't establish GTP-U Path for eNB/SGW");
return rv;
}
@@ -337,24 +484,17 @@ status_t sgw_gtp_close()
{
status_t rv;
rv = gtp_close(sgw_self()->s11_sock);
rv = gtp_close(sgw_self()->gtpc_sock);
if (rv != CORE_OK)
{
d_error("Can't close S11 Path for MME");
d_error("Can't close GTP-C Path for MME/PGW");
return rv;
}
rv = gtp_close(sgw_self()->s5c_sock);
rv = gtp_close(sgw_self()->gtpu_sock);
if (rv != CORE_OK)
{
d_error("Can't close S5-C Path for MME");
return rv;
}
rv = gtp_close(sgw_self()->s5u_sock);
if (rv != CORE_OK)
{
d_error("Can't close S5-U Path for MME");
d_error("Can't close GTP-U Path for eNB/PGW");
return rv;
}
@@ -367,8 +507,11 @@ status_t sgw_gtp_send_end_marker(sgw_bearer_t *bearer)
pkbuf_t *pkbuf = NULL;
gtp_header_t *h = NULL;
gtp_node_t gnode;
sgw_tunnel_t *s1u_tunnel = NULL;
d_assert(bearer, return CORE_ERROR,);
s1u_tunnel = sgw_s1u_tunnel_in_bearer(bearer);
d_assert(s1u_tunnel, return CORE_ERROR,);
pkbuf = pkbuf_alloc(0, 100 /* enough for END_MARKER; use smaller buffer */);
d_assert(pkbuf, return CORE_ERROR,);
@@ -383,11 +526,11 @@ status_t sgw_gtp_send_end_marker(sgw_bearer_t *bearer)
*/
h->flags = 0x30;
h->type = GTPU_MSGTYPE_END_MARKER;
h->teid = htonl(bearer->enb_s1u_teid);
h->teid = htonl(s1u_tunnel->remote_teid);
gnode.addr = bearer->enb_s1u_addr;
gnode.addr = s1u_tunnel->remote_addr;
gnode.port = GTPV1_U_UDP_PORT;
gnode.sock = sgw_self()->s1u_sock;
gnode.sock = sgw_self()->gtpu_sock;
rv = gtp_send(&gnode, pkbuf);
d_assert(rv == CORE_OK, , "gtp send failed");

View File

@@ -29,6 +29,7 @@ void sgw_s11_handle_create_session_request(gtp_xact_t *s11_xact,
gtp_xact_t *s5c_xact = NULL;
sgw_sess_t *sess = NULL;
sgw_bearer_t *bearer = NULL;
sgw_tunnel_t *s5u_tunnel = NULL;
d_assert(s11_xact, return, "Null param");
d_assert(sgw_ue, return, "Null param");
@@ -79,6 +80,8 @@ void sgw_s11_handle_create_session_request(gtp_xact_t *s11_xact,
d_assert(sess, return, "Null param");
bearer = sgw_default_bearer_in_sess(sess);
d_assert(bearer, return, "Null param");
s5u_tunnel = sgw_s5u_tunnel_in_bearer(bearer);
d_assert(s5u_tunnel, return, "Null param");
/* Receive Control Plane(DL) : MME-S11 */
mme_s11_teid = req->sender_f_teid_for_control_plane.data;
@@ -110,7 +113,7 @@ void sgw_s11_handle_create_session_request(gtp_xact_t *s11_xact,
pgw->addr = addr;
pgw->port = port;
pgw->sock = sgw_self()->s5c_sock;
pgw->sock = sgw_self()->gtpc_sock;
}
/* Setup GTP Node */
@@ -121,8 +124,8 @@ void sgw_s11_handle_create_session_request(gtp_xact_t *s11_xact,
/* Data Plane(DL) : SGW-S5U */
memset(&sgw_s5u_teid, 0, sizeof(gtp_f_teid_t));
sgw_s5u_teid.teid = htonl(bearer->sgw_s5u_teid);
sgw_s5u_teid.ipv4_addr = bearer->sgw_s5u_addr;
sgw_s5u_teid.teid = htonl(s5u_tunnel->local_teid);
sgw_s5u_teid.ipv4_addr = s5u_tunnel->local_addr;
sgw_s5u_teid.interface_type = GTP_F_TEID_S5_S8_SGW_GTP_U;
req->bearer_contexts_to_be_created.s5_s8_u_sgw_f_teid.presence = 1;
req->bearer_contexts_to_be_created.s5_s8_u_sgw_f_teid.data = &sgw_s5u_teid;
@@ -161,6 +164,7 @@ CORE_DECLARE(void) sgw_s11_handle_modify_bearer_request(gtp_xact_t *s11_xact,
status_t rv;
c_uint16_t decoded;
sgw_bearer_t *bearer = NULL;
sgw_tunnel_t *s1u_tunnel = NULL;
gtp_modify_bearer_response_t *rsp = NULL;
pkbuf_t *pkbuf = NULL;
gtp_message_t gtp_message;
@@ -192,6 +196,8 @@ CORE_DECLARE(void) sgw_s11_handle_modify_bearer_request(gtp_xact_t *s11_xact,
bearer = sgw_bearer_find_by_ue_ebi(sgw_ue,
req->bearer_contexts_to_be_modified.eps_bearer_id.u8);
d_assert(bearer, return, "No Bearer Context");
s1u_tunnel = sgw_s1u_tunnel_in_bearer(bearer);
d_assert(s1u_tunnel, return, "No S1U Tunnel Context");
/* Set User Location Information */
if (req->user_location_information.presence == 1)
@@ -204,7 +210,8 @@ CORE_DECLARE(void) sgw_s11_handle_modify_bearer_request(gtp_xact_t *s11_xact,
if (bearer->e_cgi.cell_id != uli.e_cgi.cell_id)
{
rv = sgw_gtp_send_end_marker(bearer);
d_assert(rv == CORE_OK, return, "gtp send failed");
if (rv != CORE_OK)
d_error("gtp send end marker failed");
bearer->e_cgi.cell_id = uli.e_cgi.cell_id;
}
@@ -212,8 +219,8 @@ CORE_DECLARE(void) sgw_s11_handle_modify_bearer_request(gtp_xact_t *s11_xact,
/* Data Plane(DL) : eNB-S1U */
enb_s1u_teid = req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.data;
bearer->enb_s1u_teid = ntohl(enb_s1u_teid->teid);
bearer->enb_s1u_addr = enb_s1u_teid->ipv4_addr;
s1u_tunnel->remote_teid = ntohl(enb_s1u_teid->teid);
s1u_tunnel->remote_addr = enb_s1u_teid->ipv4_addr;
/* Reset UE state */
SGW_RESET_UE_STATE(sgw_ue, SGW_S1U_INACTIVE);
@@ -296,7 +303,7 @@ void sgw_s11_handle_create_bearer_response(gtp_xact_t *s11_xact,
gtp_xact_t *s5c_xact = NULL;
sgw_sess_t *sess = NULL;
sgw_bearer_t *bearer = NULL;
sgw_tunnel_t *tunnel = NULL;
sgw_tunnel_t *s1u_tunnel = NULL, *s5u_tunnel = NULL;
gtp_create_bearer_response_t *req = NULL;
gtp_f_teid_t *sgw_s1u_teid = NULL, *enb_s1u_teid = NULL;
@@ -344,10 +351,12 @@ void sgw_s11_handle_create_bearer_response(gtp_xact_t *s11_xact,
req->bearer_contexts.s4_u_sgsn_f_teid.presence = 0;
/* Find the Tunnel by SGW-S1U-TEID */
tunnel = sgw_tunnel_find_by_teid(ntohl(sgw_s1u_teid->teid));
d_assert(tunnel, return, "Null param");
bearer = tunnel->bearer;
s1u_tunnel = sgw_tunnel_find_by_teid(ntohl(sgw_s1u_teid->teid));
d_assert(s1u_tunnel, return, "Null param");
bearer = s1u_tunnel->bearer;
d_assert(bearer, return, "Null param");
s5u_tunnel = sgw_s5u_tunnel_in_bearer(bearer);
d_assert(s5u_tunnel, return, "Null param");
sess = bearer->sess;
d_assert(sess, return, "Null param");
@@ -356,8 +365,8 @@ void sgw_s11_handle_create_bearer_response(gtp_xact_t *s11_xact,
/* Data Plane(DL) : eNB-S1U */
enb_s1u_teid = req->bearer_contexts.s1_u_enodeb_f_teid.data;
bearer->enb_s1u_teid = ntohl(enb_s1u_teid->teid);
bearer->enb_s1u_addr = enb_s1u_teid->ipv4_addr;
s1u_tunnel->remote_teid = ntohl(enb_s1u_teid->teid);
s1u_tunnel->remote_addr = enb_s1u_teid->ipv4_addr;
req->bearer_contexts.s1_u_enodeb_f_teid.presence = 0;
decoded = gtp_parse_uli(&uli, &req->user_location_information);
@@ -372,8 +381,8 @@ void sgw_s11_handle_create_bearer_response(gtp_xact_t *s11_xact,
/* Data Plane(DL) : SGW-S5U */
memset(&sgw_s5u_teid, 0, sizeof(gtp_f_teid_t));
sgw_s5u_teid.teid = htonl(bearer->sgw_s5u_teid);
sgw_s5u_teid.ipv4_addr = bearer->sgw_s5u_addr;
sgw_s5u_teid.teid = htonl(s5u_tunnel->local_teid);
sgw_s5u_teid.ipv4_addr = s5u_tunnel->local_addr;
sgw_s5u_teid.interface_type = GTP_F_TEID_S5_S8_SGW_GTP_U;
req->bearer_contexts.s5_s8_u_sgw_f_teid.presence = 1;
req->bearer_contexts.s5_s8_u_sgw_f_teid.data = &sgw_s5u_teid;
@@ -381,8 +390,8 @@ void sgw_s11_handle_create_bearer_response(gtp_xact_t *s11_xact,
/* Data Plane(DL) : PGW-S5U */
memset(&pgw_s5u_teid, 0, sizeof(gtp_f_teid_t));
pgw_s5u_teid.teid = htonl(tunnel->remote_teid);
pgw_s5u_teid.ipv4_addr = tunnel->remote_addr;
pgw_s5u_teid.teid = htonl(s5u_tunnel->remote_teid);
pgw_s5u_teid.ipv4_addr = s5u_tunnel->remote_addr;
pgw_s5u_teid.interface_type = GTP_F_TEID_S5_S8_PGW_GTP_U;
req->bearer_contexts.s5_s8_u_pgw_f_teid.presence = 1;
req->bearer_contexts.s5_s8_u_pgw_f_teid.data = &pgw_s5u_teid;
@@ -412,6 +421,7 @@ void sgw_s11_handle_release_access_bearers_request(gtp_xact_t *s11_xact,
pkbuf_t *pkbuf = NULL;
gtp_message_t gtp_message;
sgw_bearer_t *bearer = NULL, *next_bearer = NULL;
sgw_tunnel_t *s1u_tunnel = NULL;
sgw_sess_t *sess = NULL;
gtp_cause_t cause;
@@ -434,8 +444,11 @@ void sgw_s11_handle_release_access_bearers_request(gtp_xact_t *s11_xact,
{
next_bearer = list_next(bearer);
bearer->enb_s1u_teid = 0;
bearer->enb_s1u_addr = 0;
s1u_tunnel = sgw_s1u_tunnel_in_bearer(bearer);
d_assert(s1u_tunnel, return, "Null param");
s1u_tunnel->remote_teid = 0;
s1u_tunnel->remote_addr = 0;
bearer = next_bearer;
}

View File

@@ -16,7 +16,7 @@ void sgw_s5c_handle_create_session_response(gtp_xact_t *s5c_xact,
status_t rv;
gtp_xact_t *s11_xact = NULL;
sgw_bearer_t *bearer = NULL;
sgw_tunnel_t *tunnel = NULL;
sgw_tunnel_t *s1u_tunnel = NULL, *s5u_tunnel = NULL;
gtp_create_session_response_t *rsp = NULL;
pkbuf_t *pkbuf = NULL;
sgw_ue_t *sgw_ue = NULL;
@@ -61,8 +61,10 @@ void sgw_s5c_handle_create_session_response(gtp_xact_t *s5c_xact,
bearer = sgw_bearer_find_by_sess_ebi(sess,
rsp->bearer_contexts_created.eps_bearer_id.u8);
d_assert(bearer, return, "No Bearer Context");
tunnel = sgw_direct_tunnel_in_bearer(bearer);
d_assert(tunnel, return, "No Tunnel Context");
s1u_tunnel = sgw_s1u_tunnel_in_bearer(bearer);
d_assert(s1u_tunnel, return, "No Tunnel Context");
s5u_tunnel = sgw_s5u_tunnel_in_bearer(bearer);
d_assert(s5u_tunnel, return, "No Tunnel Context");
/* Receive Control Plane(UL) : PGW-S5C */
pgw_s5c_teid = rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.
@@ -76,8 +78,8 @@ void sgw_s5c_handle_create_session_response(gtp_xact_t *s5c_xact,
/* Receive Data Plane(UL) : PGW-S5U */
pgw_s5u_teid = rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.data;
d_assert(pgw_s5u_teid, return, "Null param");
tunnel->remote_teid = ntohl(pgw_s5u_teid->teid);
tunnel->remote_addr = pgw_s5u_teid->ipv4_addr;
s5u_tunnel->remote_teid = ntohl(pgw_s5u_teid->teid);
s5u_tunnel->remote_addr = pgw_s5u_teid->ipv4_addr;
rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.presence = 0;
/* Send Control Plane(UL) : SGW-S11 */
@@ -93,9 +95,9 @@ void sgw_s5c_handle_create_session_response(gtp_xact_t *s5c_xact,
/* Send Data Plane(UL) : SGW-S1U */
memset(&sgw_s1u_teid, 0, sizeof(gtp_f_teid_t));
sgw_s1u_teid.ipv4 = 1;
sgw_s1u_teid.interface_type = tunnel->interface_type;
sgw_s1u_teid.ipv4_addr = tunnel->local_addr;
sgw_s1u_teid.teid = htonl(tunnel->local_teid);
sgw_s1u_teid.interface_type = s1u_tunnel->interface_type;
sgw_s1u_teid.ipv4_addr = s1u_tunnel->local_addr;
sgw_s1u_teid.teid = htonl(s1u_tunnel->local_teid);
rsp->bearer_contexts_created.s1_u_enodeb_f_teid.presence = 1;
rsp->bearer_contexts_created.s1_u_enodeb_f_teid.data = &sgw_s1u_teid;
rsp->bearer_contexts_created.s1_u_enodeb_f_teid.len = GTP_F_TEID_IPV4_LEN;
@@ -190,7 +192,7 @@ void sgw_s5c_handle_create_bearer_request(gtp_xact_t *s5c_xact,
status_t rv;
gtp_xact_t *s11_xact = NULL;
sgw_bearer_t *bearer = NULL;
sgw_tunnel_t *tunnel = NULL;
sgw_tunnel_t *s1u_tunnel = NULL, *s5u_tunnel = NULL;
gtp_create_bearer_request_t *req = NULL;
pkbuf_t *pkbuf = NULL;
sgw_ue_t *sgw_ue = NULL;
@@ -229,22 +231,24 @@ void sgw_s5c_handle_create_bearer_request(gtp_xact_t *s5c_xact,
bearer = sgw_bearer_add(sess);
d_assert(bearer, return, "No Bearer Context");
tunnel = sgw_direct_tunnel_in_bearer(bearer);
d_assert(tunnel, return, "No Tunnel Context");
s1u_tunnel = sgw_s1u_tunnel_in_bearer(bearer);
d_assert(s1u_tunnel, return, "No Tunnel Context");
s5u_tunnel = sgw_s5u_tunnel_in_bearer(bearer);
d_assert(s5u_tunnel, return, "No Tunnel Context");
/* Receive Data Plane(UL) : PGW-S5U */
pgw_s5u_teid = req->bearer_contexts.s5_s8_u_sgw_f_teid.data;
d_assert(pgw_s5u_teid, return, "Null param");
tunnel->remote_teid = ntohl(pgw_s5u_teid->teid);
tunnel->remote_addr = pgw_s5u_teid->ipv4_addr;
s5u_tunnel->remote_teid = ntohl(pgw_s5u_teid->teid);
s5u_tunnel->remote_addr = pgw_s5u_teid->ipv4_addr;
req->bearer_contexts.s5_s8_u_sgw_f_teid.presence = 0;
/* Send Data Plane(UL) : SGW-S1U */
memset(&sgw_s1u_teid, 0, sizeof(gtp_f_teid_t));
sgw_s1u_teid.ipv4 = 1;
sgw_s1u_teid.interface_type = tunnel->interface_type;
sgw_s1u_teid.ipv4_addr = tunnel->local_addr;
sgw_s1u_teid.teid = htonl(tunnel->local_teid);
sgw_s1u_teid.interface_type = s1u_tunnel->interface_type;
sgw_s1u_teid.ipv4_addr = s1u_tunnel->local_addr;
sgw_s1u_teid.teid = htonl(s1u_tunnel->local_teid);
req->bearer_contexts.s1_u_enodeb_f_teid.presence = 1;
req->bearer_contexts.s1_u_enodeb_f_teid.data = &sgw_s1u_teid;
req->bearer_contexts.s1_u_enodeb_f_teid.len = GTP_F_TEID_IPV4_LEN;
@@ -264,6 +268,6 @@ void sgw_s5c_handle_create_bearer_request(gtp_xact_t *s5c_xact,
d_assert(rv == CORE_OK, return, "xact_commit error");
d_trace(3, "[GTP] Create Bearer Request : SGW[%d] <-- PGW[%d]\n",
tunnel->local_teid, tunnel->remote_teid);
s5u_tunnel->local_teid, s5u_tunnel->remote_teid);
}

View File

@@ -121,13 +121,16 @@ void sgw_state_operational(fsm_t *s, event_t *e)
case SGW_EVT_S5C_MESSAGE:
{
status_t rv;
gtp_node_t *gnode = (gtp_node_t *)event_get_param1(e);
pkbuf_t *pkbuf = (pkbuf_t *)event_get_param2(e);
gtp_node_t *gnode = NULL;
c_uint32_t addr = (c_uint32_t)event_get_param1(e);
c_uint16_t port = (c_uint16_t)event_get_param2(e);
pkbuf_t *pkbuf = (pkbuf_t *)event_get_param3(e);
gtp_xact_t *xact = NULL;
gtp_message_t message;
sgw_sess_t *sess = NULL;
d_assert(pkbuf, break, "Null param");
gnode = sgw_pgw_find(addr, port);
d_assert(gnode, pkbuf_free(pkbuf); break, "Null param");
rv = gtp_xact_receive(gnode, pkbuf, &xact, &message);

View File

@@ -25,3 +25,7 @@ Install FreeDiameter, MongoDB C driver
===========================================
- brew install freediamter
- brew install mongo-c-driver
Enable IP Fowarding
====================
- sysctl -w net.inet.ip.forwarding=1

6
support/Makefile.am Normal file
View File

@@ -0,0 +1,6 @@
## Process this file with automake to produce Makefile.in
SUBDIRS = config freeDiameter systemd logrotate newsyslog
MAINTAINERCLEANFILES = Makefile.in
MOSTLYCLEANFILES = *.stackdump

View File

@@ -0,0 +1,15 @@
configfiles = \
nextepc.conf \
mme.conf \
sgw.conf \
pgw.conf \
hss.conf \
pcrf.conf \
$(NULL)
configdir = ${sysconfdir}/nextepc
config_DATA = ${configfiles}
MAINTAINERCLEANFILES = Makefile.in
MOSTLYCLEANFILES = *.stackdump

View File

@@ -0,0 +1,23 @@
{
"DB_URI" : "mongodb://localhost/nextepc",
"LOG" :
{
"FILE" : "@LOCALSTATE_DIR@/log/nextepc/hss.log",
"SOCKET" :
{
"UNIX_DOMAIN" : "/tmp/nextepc-hssd.sock",
"FILE" : 0
}
},
"TRACE" :
{
"FD": 1,
"OTHERS": 1
},
"HSS" :
{
"FD_CONF_PATH" : "@SYSCONF_DIR@/nextepc/freeDiameter/hss.conf"
}
}

View File

@@ -0,0 +1,79 @@
{
"LOG" :
{
"FILE" : "@LOCALSTATE_DIR@/log/nextepc/mme.log",
"SOCKET" :
{
"UNIX_DOMAIN" : "/tmp/nextepc-mmed.sock",
"FILE" : 0
}
},
"TRACE" :
{
"S1AP": 1,
"NAS": 1,
"FD": 1,
"GTP": 1,
"OTHERS": 1
},
"MME" :
{
"FD_CONF_PATH" : "@SYSCONF_DIR@/nextepc/freeDiameter/mme.conf",
"DEFAULT_PAGING_DRX" : "v64",
"NETWORK" :
{
"S1AP_IPV4" : "127.76.0.1",
"GTPC_IPV4" : "127.76.0.1"
},
"GUMMEI" :
[
{
"PLMN_ID" :
{
"MCC" : "001",
"MNC" : "01"
},
"MME_GID" : 2,
"MME_CODE" : 1
}
],
"TAI":
[
{
"PLMN_ID" :
{
"MCC": "001",
"MNC": "01"
},
"TAC": 12345
}
],
"SECURITY" :
{
"INTEGRITY_ORDER" : [ "EIA1", "EIA2", "EIA0" ],
"CIPHERING_ORDER" : [ "EEA0", "EEA1", "EEA2" ]
}
},
"SGW" :
{
"NETWORK" :
[
{
"GTPC_IPV4" : "127.76.0.2",
"GTPU_IPV4" : "127.76.0.2"
}
]
},
"PGW" :
{
"NETWORK" :
{
"GTPC_IPV4" : "127.76.0.3",
"GTPU_IPV4" : "127.76.0.3"
}
}
}

View File

@@ -0,0 +1,110 @@
{
"DB_URI" : "mongodb://localhost/nextepc",
"LOG" :
{
"FILE" : "@LOCALSTATE_DIR@/log/nextepc/nextepc.log",
"SOCKET" :
{
"UNIX_DOMAIN" : "/tmp/nextepc-epcd.sock",
"FILE" : 0
}
},
"TRACE" :
{
"S1AP": 1,
"NAS": 1,
"FD": 1,
"GTP": 1,
"OTHERS": 1
},
"NODE":
{
"DISABLE_HSS": 0,
"DISABLE_SGW": 0,
"DISABLE_PGW": 0,
"DISABLE_PCRF": 0
},
"MME" :
{
"FD_CONF_PATH" : "@SYSCONF_DIR@/nextepc/freeDiameter/mme.conf",
"DEFAULT_PAGING_DRX" : "v64",
"NETWORK" :
{
"S1AP_IPV4" : "127.76.0.1",
"GTPC_IPV4" : "127.76.0.1"
},
"GUMMEI" :
[
{
"PLMN_ID" :
{
"MCC" : "001",
"MNC" : "01"
},
"MME_GID" : 2,
"MME_CODE" : 1
}
],
"TAI":
[
{
"PLMN_ID" :
{
"MCC": "001",
"MNC": "01"
},
"TAC": 12345
}
],
"SECURITY" :
{
"INTEGRITY_ORDER" : [ "EIA1", "EIA2", "EIA0" ],
"CIPHERING_ORDER" : [ "EEA0", "EEA1", "EEA2" ]
}
},
"HSS" :
{
"FD_CONF_PATH" : "@SYSCONF_DIR@/nextepc/freeDiameter/hss.conf"
},
"SGW" :
{
"NETWORK" :
[
{
"GTPC_IPV4" : "127.76.0.2",
"GTPU_IPV4" : "127.76.0.2"
}
]
},
"PGW" :
{
"FD_CONF_PATH" : "@SYSCONF_DIR@/nextepc/freeDiameter/pgw.conf",
"NETWORK" :
{
"GTPC_IPV4" : "127.76.0.3",
"GTPU_IPV4" : "127.76.0.3"
},
"UE_NETWORK":
[
{
"IF_NAME" : "pgwtun",
"IPV4_POOL" : "45.45.0.1/16"
}
],
"DNS" :
{
"PRIMARY_IPV4" : "8.8.8.8",
"SECONDARY_IPV4" : "4.4.4.4"
}
},
"PCRF" :
{
"FD_CONF_PATH" : "@SYSCONF_DIR@/nextepc/freeDiameter/pcrf.conf"
}
}

View File

@@ -0,0 +1,22 @@
{
"DB_URI" : "mongodb://localhost/nextepc",
"LOG" :
{
"FILE" : "@LOCALSTATE_DIR@/log/nextepc/pcrf.log",
"SOCKET" :
{
"UNIX_DOMAIN" : "/tmp/nextepc-pcrfd.sock",
"FILE" : 0
}
},
"TRACE" :
{
"FD": 1,
"OTHERS": 1
},
"PCRF" :
{
"FD_CONF_PATH" : "@SYSCONF_DIR@/nextepc/freeDiameter/pcrf.conf"
}
}

View File

@@ -0,0 +1,40 @@
{
"LOG" :
{
"FILE" : "@LOCALSTATE_DIR@/log/nextepc/pgw.log",
"SOCKET" :
{
"UNIX_DOMAIN" : "/tmp/nextepc-pgwd.sock",
"FILE" : 0
}
},
"TRACE" :
{
"FD": 1,
"GTP": 1,
"OTHERS": 1
},
"PGW" :
{
"FD_CONF_PATH" : "@SYSCONF_DIR@/nextepc/freeDiameter/pgw.conf",
"NETWORK" :
{
"GTPC_IPV4" : "127.76.0.3",
"GTPU_IPV4" : "127.76.0.3"
},
"UE_NETWORK":
[
{
"IF_NAME" : "pgwtun",
"IPV4_POOL" : "45.45.0.1/16"
}
],
"DNS" :
{
"PRIMARY_IPV4" : "8.8.8.8",
"SECONDARY_IPV4" : "4.4.4.4"
}
}
}

View File

@@ -0,0 +1,28 @@
{
"LOG" :
{
"FILE" : "@LOCALSTATE_DIR@/log/nextepc/sgw.log",
"SOCKET" :
{
"UNIX_DOMAIN" : "/tmp/nextepc-sgwd.sock",
"FILE" : 0
}
},
"TRACE" :
{
"GTP": 1,
"OTHERS": 1
},
"SGW" :
{
"NETWORK" :
[
{
"GTPC_IPV4" : "127.76.0.2",
"GTPU_IPV4" : "127.76.0.2"
}
]
}
}

View File

@@ -0,0 +1,25 @@
configfiles = \
mme.conf \
hss.conf \
pgw.conf \
pcrf.conf \
$(NULL)
pemfiles = \
cacert.pem \
mme.key.pem \
mme.cert.pem \
hss.key.pem \
hss.cert.pem \
pgw.key.pem \
pgw.cert.pem \
pcrf.key.pem \
pcrf.cert.pem \
$(NULL)
freeDiameterdir = ${sysconfdir}/nextepc/freeDiameter
freeDiameter_DATA = ${configfiles} ${pemfiles}
MAINTAINERCLEANFILES = Makefile.in
MOSTLYCLEANFILES = *.stackdump

View File

@@ -1,709 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dictionary SYSTEM "dictionary.dtd">
<!--******************* Diccionario Gx === German Barros ******************************************************************* -->
<dictionary>
<!-- ******************************************************** -->
<!-- ********************* Vendors ************************** -->
<!-- ******************************************************** -->
<vendor id="10415" name="3GPP" />
<!-- ******************************************************** -->
<!-- ***************** Gx Application ********************* -->
<!-- ******************************************************** -->
<application id="16777238" name="Gx">
<!-- ====================================================================== -->
<!-- ========================== COMMAND CODES =========================== -->
<!-- ====================================================================== -->
<!-- *** Command-Codes *** -->
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.6.2 and 5.6.3 -->
<command name="CC" code="272" vendor-id="10415">
</command>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.6.4 and 5.6.5 -->
<command name="RA" code="258" vendor-id="10415" />
<!-- ====================================================================== -->
<!-- ========================= Gx Specific AVPs ======================== -->
<!-- ====================================================================== -->
<!-- Ref = [3GPP - 29.214] 5.3.2 -->
<avp name="Access-Network-Charging-Address" code="501" mandatory="must"
may-encrypt="yes" vendor-id="10415">
<type type-name="Address" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.1 -->
<avp name="Bearer-Usage" vendor-id="10415" code="1000" mandatory="must"
may-encrypt="yes">
<type type-name="Enumerated" />
<enum name="GENERAL" code="0" />
<enum name="IMS_SIGNALLING" code="1" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.23 -->
<avp name="Bearer-Control-Mode" vendor-id="10415" code="1023"
mandatory="must" may-encrypt="yes">
<type type-name="Enumerated" />
<enum name="UE_ONLY" code="0" />
<enum name="RESERVED" code="1" />
<enum name="UE_NW" code="2" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.8 -->
<avp name="Metering-Method" vendor-id="10415" code="1007"
mandatory="must" may-encrypt="yes" protected="may" type="Enumerated">
<type type-name="Enumerated" />
<enum name="DURATION" code="0" />
<enum name="VOLUME" code="1" />
<enum name="DURATION_VOLUME" code="2" />
</avp>
<!-- [3GPP TS 29.229 V7.7.0] , clause 6.3.20 -->
<avp name="Primary-Event-Charging-Function-Name" vendor-id="10415"
code="619" mandatory="must" may-encrypt="yes">
<type type-name="DiameterURI" />
</avp>
<!-- [3GPP TS 29.229 V7.7.0] , clause 6.3.21 -->
<avp name="Secondary-Event-Charging-Function-Name" vendor-id="10415"
code="620" mandatory="must" may-encrypt="yes">
<type type-name="DiameterURI" />
</avp>
<!-- [3GPP TS 29.229 V7.7.0] , clause 6.3.22 -->
<avp name="Primary-Charging-Collection-Function-Name" vendor-id="10415"
code="621" mandatory="must" may-encrypt="yes">
<type type-name="DiameterURI" />
</avp>
<!-- [3GPP TS 29.229 V7.7.0] , clause 6.3.23 -->
<avp name="Secondary-Charging-Collection-Function-Name" vendor-id="10415"
code="622" mandatory="must" may-encrypt="yes">
<type type-name="DiameterURI" />
</avp>
<!-- [3GPP TS 29.214 v7.3.0] , clause 5.3.4 -->
<avp name="Access-Network-Charging-Identifier-Value" vendor-id="10415"
code="503" mandatory="must" may-encrypt="yes">
<type type-name="OctetString" />
</avp>
<!-- [3GPP TS 29.061 V7.9.0] , clause 16.4.7 -->
<avp name="3GPP-RAT-Type" vendor-id="10415" code="21" mandatory="mustnot"
may-encrypt="yes">
<type type-name="OctetString" />
</avp>
<!-- Ref = RFC 4006 chap 8.48 -->
<avp name="Subscription-Id-Data" code="444" mandatory="must"
may-encrypt="yes">
<type type-name="UTF8String" />
</avp>
<!-- Ref = RFC 4006 chap 8.47 -->
<avp name="Subscription-Id-Type" code="450" mandatory="must"
protected="may" may-encrypt="yes">
<type type-name="Enumerated" />
<enum name="END_USER_E164" code="0" />
<enum name="END_USER_IMSI" code="1" />
<enum name="END_USER_SIP_URI" code="2" />
<enum name="END_USER_NAI" code="3" />
<enum name="END_USER_PRIVATE" code="4" />
</avp>
<!-- [RFC 4006] , clause 8.2 -->
<avp name="CC-Request-Number" code="415" mandatory="must"
may-encrypt="yes">
<type type-name="Unsigned32" />
</avp>
<!-- [RFC 4006] , clause 8.3 -->
<avp name="CC-Request-Type" code="416" mandatory="must"
may-encrypt="yes">
<type type-name="Enumerated" />
<enum name="INITIAL_REQUEST" code="1" />
<enum name="UPDATE_REQUEST" code="2" />
<enum name="TERMINATION_REQUEST" code="3" />
<enum name="EVENT_REQUEST" code="4" />
</avp>
<!-- [RFC 4006] , clause 8.38 -->
<avp name="Redirect-Address-Type" code="433" mandatory="must"
may-encrypt="yes">
<type type-name="Enumerated" />
<enum name="IPV4_ADDRESS" code="0" />
<enum name="IPV6_ADDRESS" code="1" />
<enum name="URL" code="2" />
<enum name="SIP_URI" code="3" />
</avp>
<!-- [RFC 4006] , clause 8.39 -->
<avp name="Redirect-Server-Address" code="435" mandatory="must"
may-encrypt="yes">
<type type-name="UTF8String" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.19 -->
<avp name="PCC-Rule-Status" vendor-id="10415" code="1019"
mandatory="must" may-encrypt="yes">
<type type-name="Enumerated" />
<enum name="ACTIVE" code="0" />
<enum name="INACTIVE" code="1" />
<enum name="TEMPORARILY INACTIVE" code="2" />
</avp>
<!-- [RFC 4005] , clause 6.11.1 -->
<avp name="Framed-IP-Address" code="8" mandatory="must"
may-encrypt="yes">
<type type-name="OctetString" />
</avp>
<!-- [RFC 4005] , clause 6.11.6 -->
<avp name="Framed-IPv6-Prefix" code="97" mandatory="must"
may-encrypt="yes">
<type type-name="OctetString" />
</avp>
<!-- [RFC 4005] , clause 4.5 -->
<avp name="Called-Station-Id" code="30" mandatory="must"
may-encrypt="yes">
<type type-name="UTF8String" />
</avp>
<!-- [RFC 4005] , clause 6.7 -->
<avp name="Filter-Id" code="11" mandatory="must" may-encrypt="yes">
<type type-name="UTF8String" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.21 -->
<avp name="Bearer-Operation" vendor-id="10415" code="1021"
mandatory="must" may-encrypt="yes">
<type type-name="Enumerated" />
<enum name="TERMINATION" code="0" />
<enum name="ESTABLISHMENT" code="1" />
<enum name="MODIFICATION" code="2" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.24 -->
<avp name="Network-Request-Support" vendor-id="10415" code="1024"
mandatory="must" may-encrypt="yes">
<type type-name="Enumerated"/>
<enum name="NETWORK_REQUEST_NOT_SUPPORTED" code="0" />
<enum name="NETWORK_REQUEST_SUPPORTED" code="1" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.5 -->
<avp name="Charging-Rule-Base-Name" vendor-id="10415" code="1004"
mandatory="must" may-encrypt="yes">
<type type-name="UTF8String" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.15 -->
<avp name="ToS-Traffic-Class" vendor-id="10415" code="1014"
mandatory="must" may-encrypt="yes">
<type type-name="OctetString" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.27 -->
<avp name="IP-CAN-Type" vendor-id="10415" code="1027" mandatory="must"
may-encrypt="yes">
<type type-name="Enumerated" />
<enum name="3GPP" code="0" />
<enum name="DOCSIS" code="1" />
<enum name="xDSL" code="2" />
<enum name="WiMAX" code="3" />
<enum name="3GPP2" code="4" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.28 -->
<avp name="QoS-Negotiation" vendor-id="10415" code="1029"
mandatory="must" may-encrypt="yes">
<type type-name="Enumerated" />
<enum name="NO_QOS_NEGOTIATION" code="0" />
<enum name="QOS_NEGOTIATION_SUPPORTED" code="1" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.29 -->
<avp name="QoS-Upgrade" vendor-id="10415" code="1030" mandatory="must"
may-encrypt="yes">
<type type-name="Enumerated" />
<enum name="QOS_UPGRADE_NOT_SUPPORTED" code="0" />
<enum name="QOS_UPGRADE_SUPPORTED" code="1" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.30 -->
<avp name="Rule-Failure-Code" vendor-id="10415" code="1031"
mandatory="must" may-encrypt="yes">
<type type-name="Enumerated" />
<enum name="UNKNOWN_RULE_NAME" code="1" />
<enum name="RATING_GROUP_ERROR" code="2" />
<enum name="SERVICE_IDENTIFIER_ERROR" code="3" />
<enum name="GW/PCEF_MALFUNCTION" code="4" />
<enum name="RESOURCES_LIMITATION" code="5" />
<enum name="MAX_NR_BEARERS_REACHED" code="6" />
<enum name="UNKNOWN_BEARER_ID" code="7" />
<enum name="MISSING_BEARER_ID" code="8" />
<enum name="MISSING_FLOW_DESCRIPTION" code="9" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.34 -->
<avp name="Session-Release-Cause" vendor-id="10415" code="1035"
mandatory="must" may-encrypt="yes">
<type type-name="Enumerated" />
<enum name="UNSPECIFIED_REASONS" code="0" />
<enum name="UE_SUBSCRIPTION_REASON" code="1" />
<enum name="INSUFFICIENT_SERVER_RESOURCES" code="2" />
</avp>
<!-- [3GPP TS 29.061 V7.9.0] , clause 16.4.7. -->
<avp name="3GPP-SGSN-MCC-MNC" vendor-id="10415" code="18"
mandatory="mustnot" may-encrypt="yes">
<type type-name="UTF8String" />
</avp>
<!-- [3GPP TS 29.061 V7.9.0] , clause 16.4.7 -->
<avp name="3GPP-User-Location-Info" vendor-id="10415" code="22"
mandatory="mustnot" may-encrypt="yes">
<type type-name="OctetString" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.31 -->
<avp name="Revalidation-Time" vendor-id="10415" code="1032"
mandatory="must" may-encrypt="yes">
<type type-name="Time" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.32 -->
<avp name="Rule-Activation-Time" code="1033" mandatory="must"
may-encrypt="yes">
<type type-name="Time" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.33 -->
<avp name="Rule-Deactivation-Time" vendor-id="10415" code="1034"
mandatory="must" may-encrypt="yes">
<type type-name="Time" />
</avp>
<!-- [3GPP TS 29.061 V7.7.0] , clause 16.4.7.1 -->
<avp name="3GPP-SGSN-Address" vendor-id="10415" code="6" mandatory="mustnot"
may-encrypt="yes">
<type type-name="OctetString" />
</avp>
<!-- [3GPP TS 29.061 V7.7.0] , clause 16.4.7.1 -->
<avp name="3GPP-SGSN-IPv6-Address" vendor-id="10415" code="15"
mandatory="mustnot" may-encrypt="yes">
<type type-name="OctetString" />
</avp>
<!-- [3GPP TS 29.061 V7.7.0] , clause 17.7.12 -->
<avp name="RAI" vendor-id="10415" code="909" mandatory="must"
may-encrypt="yes">
<type type-name="UTF8String" />
</avp>
<!-- [3GPP TS 29.061 V7.7.0] , clause 16.4.7 -->
<avp name="3GPP-MS-TimeZone" vendor-id="10415" code="23" mandatory="mustnot"
may-encrypt="yes">
<type type-name="OctetString" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.20 -->
<avp name="Bearer-Identifier" vendor-id="10415" code="1020"
mandatory="must" may-encrypt="yes">
<type type-name="OctetString" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.6 -->
<avp name="Charging-Rule-Name" vendor-id="10415" code="1005"
mandatory="must" may-encrypt="yes">
<type type-name="OctetString" />
</avp>
<!-- [RFC 4006] , clause 8.28 -->
<avp name="Service-Identifier" code="439" mandatory="must"
may-encrypt="yes">
<type type-name="Unsigned32" />
</avp>
<!-- [RFC 4006] , clause 8.29 -->
<avp name="Rating-Group" code="432" mandatory="must" may-encrypt="yes">
<type type-name="Unsigned32" />
</avp>
<!-- [3GPP TS 29.214 V7.3.0] , clause 5.3.11 -->
<avp name="Flow-Status" vendor-id="10415" code="511" mandatory="must"
may-encrypt="yes">
<type type-name="Enumerated" />
<enum name="ENABLED-UPLINK" code="0" />
<enum name="ENABLED-DOWNLINK" code="1" />
<enum name="ENABLED" code="2" />
<enum name="DISABLED" code="3" />
<enum name="REMOVED" code="4" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.17 -->
<avp name="QoS-Class-Identifier" vendor-id="10415" code="1028"
mandatory="must" may-encrypt="yes">
<type type-name="Enumerated" />
<enum name="FINAL_SERVICE_INFORMATION" code="0" />
<enum name="PRELIMINARY_SERVICE_INFORMATION" code="1" />
</avp>
<!-- Ref = [3GPP - 29.214] 5.3.15 -->
<avp name="Max-Requested-Bandwidth-UL" code="516" vendor-id="10415"
mandatory="must" may-encrypt="yes">
<type type-name="Unsigned32" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.25 -->
<avp name="Guaranteed-Bitrate-DL" vendor-id="10415" code="1025"
mandatory="must" may-encrypt="yes">
<type type-name="Unsigned32" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.26 -->
<avp name="Guaranteed-Bitrate-UL" vendor-id="10415" code="1026"
mandatory="must" may-encrypt="yes">
<type type-name="Unsigned32" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.20 -->
<avp name="Bearer-Identifier" vendor-id="10415" code="1020"
mandatory="must" may-encrypt="yes">
<type type-name="OctetString" />
</avp>
<avp name="Max-Requested-Bandwidth-UL" code="516" mandatory="must" vendor-id="10415" may-encrypt="yes">
<type type-name="Unsigned32"/>
</avp>
<avp name="Max-Requested-Bandwidth-DL" code="515" mandatory="must" vendor-id="10415" may-encrypt="yes">
<type type-name="Unsigned32"/>
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.16 -->
<avp name="QoS-Information" vendor-id="10415" code="1016"
mandatory="must" may-encrypt="yes">
<grouped>
<required>
<avprule name="QoS-Class-Identifier" minimum="1" maximum="1" />
<avprule name="Max-Requested-Bandwidth-UL" minimum="1"
maximum="1" />
<avprule name="Max-Requested-Bandwidth-DL" minimum="1"
maximum="1" />
<avprule name="Guaranteed-Bitrate-UL" minimum="1" maximum="1" />
<avprule name="Guaranteed-Bitrate-DL" minimum="1" maximum="1" />
<avprule name="Bearer-Identifier" minimum="1" maximum="1" />
</required>
</grouped>
</avp>
<!-- [3GPP TS 29.214 V7.3.0] , clause 5.3.8 -->
<avp name="Flow-Description" vendor-id="10415" code="507"
mandatory="must" may-encrypt="yes">
<type type-name="IPFilterRule" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.12 -->
<avp name="Reporting-Level" vendor-id="10415" code="1011"
mandatory="must" may-encrypt="yes">
<type type-name="Enumerated" />
<enum name="SERVICE_IDENTIFIER_LEVEL" code="0" />
<enum name="RATING_GROUP_LEVEL" code="1" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.9 -->
<avp name="Offline" vendor-id="10415" code="1008" mandatory="must"
may-encrypt="yes">
<type type-name="Enumerated" />
<enum name="DISABLE_OFFLINE" code="0" />
<enum name="ENABLE_OFFLINE" code="1" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.10 -->
<avp name="Online" vendor-id="10415" code="1009" mandatory="must"
may-encrypt="yes">
<type type-name="Enumerated" />
<enum name="DISABLE_ONLINE" code="0" />
<enum name="ENABLE_ONLINE" code="1" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.11 -->
<avp name="Precedence" vendor-id="10415" code="1010" mandatory="must"
may-encrypt="yes">
<type type-name="Unsigned32" />
</avp>
<!-- [3GPP TS 29.214 V7.3.0] , clause 5.3.6 -->
<avp name="AF-Charging-Identifier" vendor-id="10415" code="505"
mandatory="must" may-encrypt="yes">
<type type-name="OctetString" />
</avp>
<!-- Ref = [3GPP - 29.214] 5.3.14 -->
<avp name="Max-Requested-Bandwidth-DL" code="515" vendor-id="10415"
mandatory="must" may-encrypt="yes">
<type type-name="Unsigned32" />
</avp>
<!-- [3GPP TS 29.214 V7.3.0] , clause 5.3.17 -->
<avp name="Media-Component-Number" vendor-id="10415" code="518"
mandatory="must" may-encrypt="yes">
<type type-name="Unsigned32" />
</avp>
<!-- [3GPP TS 29.214 V7.3.0] , clause 5.3.9 -->
<avp name="Flow-Number" vendor-id="10415" code="509" mandatory="must"
may-encrypt="yes">
<type type-name="Unsigned32" />
</avp>
<!-- [3GPP TS 29.214 V7.3.0] , clause 5.3.10 -->
<avp name="Flows" vendor-id="10415" code="510" mandatory="must"
may-encrypt="yes">
<grouped>
<required>
<avprule name="Media-Component-Number" minimum="1" maximum="1" />
</required>
<optional>
<avprule name="Flow-Number" maximum="1" />
</optional>
</grouped>
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.4 -->
<avp name="Charging-Rule-Definition" vendor-id="10415" code="1003"
mandatory="must" may-encrypt="yes">
<grouped>
<required>
<avprule name="Charging-Rule-Name" minimum="1" maximum="1" />
<avprule name="Service-Identifier" maximum="1" />
<avprule name="Rating-Group" maximum="1" />
</required>
<optional>
<avprule name="Flow-Description" maximum="1" />
</optional>
<required>
<avprule name="Flow-Status" maximum="1" />
<avprule name="QoS-Information" maximum="1" />
<avprule name="Reporting-Level" maximum="1" />
<avprule name="Online" maximum="1" />
<avprule name="Offline" maximum="1" />
<avprule name="Metering-Method" maximum="1" />
<avprule name="Precedence" maximum="1" />
<avprule name="AF-Charging-Identifier" maximum="1" />
</required>
<optional>
<avprule name="Flows" maximum="1" />
</optional>
</grouped>
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.2 -->
<avp name="Charging-Rule-Install" vendor-id="10415" code="1001"
mandatory="must" may-encrypt="yes">
<grouped>
<optional>
<avprule name="Charging-Rule-Definition" maximum="1" />
<avprule name="Charging-Rule-Name" maximum="1" />
<avprule name="Charging-Rule-Base-Name" maximum="1" />
</optional>
<required>
<avprule name="Bearer-Identifier" minumin="1" maximum="1" />
</required>
<optional>
<avprule name="Rule-Activation-Time" maximum="1" />
<avprule name="Rule-Deactivation-Time" maximum="1" />
</optional>
</grouped>
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.3 -->
<avp name="Charging-Rule-Remove" vendor-id="10415" code="1002"
mandatory="must" may-encrypt="yes">
<grouped>
<optional>
<avprule name="Charging-Rule-Name" maximum="1" />
<avprule name="Charging-Rule-Base-Name" maximum="1" />
</optional>
</grouped>
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.7 -->
<avp name="Event-Trigger" vendor-id="10415" code="1006" mandatory="must"
may-encrypt="yes">
<type type-name="Enumerated" />
<enum name="SGSN_CHANGE" code="0" />
<enum name="QOS_CHANGE" code="1" />
<enum name="RAT_CHANGE" code="2" />
<enum name="TFT_CHANGE" code="3" />
<enum name="PLMN_CHANGE" code="4" />
<enum name="LOSS_OF_BEARER" code="5" />
<enum name="RECOVERY_OF_BEARER" code="6" />
<enum name="IP-CAN_CHANGE" code="7" />
<enum name="PCEF_MALFUNCTION" code="8" />
<enum name="RESOURCES_LIMITATION" code="9" />
<enum name="MAX_NR_BEARERS_REACHED" code="10" />
<enum name="QOS_CHANGE_EXCEEDING_AUTHORIZATION" code="11" />
<enum name="RAI_CHANGE" code="12" />
<enum name="USER_LOCATION_CHANGE" code="13" />
<enum name="NO_EVENT_TRIGGERS" code="14" />
<enum name="OUT_OF_CREDIT" code="15" />
<enum name="REALLOCATION_OF_CREDIT" code="16" />
<enum name="REVALIDATION_TIMEOUT" code="17" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.13 -->
<avp name="TFT-Filter" vendor-id="10415" code="1012" mandatory="must"
may-encrypt="yes">
<type type-name="IPFilterRule" />
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.14 -->
<avp name="TFT-Packet-Filter-Information" vendor-id="10415" code="1013"
mandatory="must" may-encrypt="yes">
<grouped>
<required>
<avprule name="Precedence" minimum="1" maximum="1" />
<avprule name="TFT-Filter" minimum="1" maximum="1" />
<avprule name="ToS-Traffic-Class" minimum="1" maximum="1" />
</required>
</grouped>
</avp>
<!-- [RFC 4006] , clause 8.35 -->
<avp name="Final-Unit-Action" code="449" mandatory="must"
may-encrypt="yes">
<type type-name="Enumerated" />
<enum name="TERMINATE" code="0" />
<enum name="REDIRECT" code="1" />
<enum name="RESTRICT_ACCESS" code="2" />
</avp>
<!-- [RFC 4006] , clause 8.36 -->
<avp name="Restriction-Filter-Rule" code="438" mandatory="must"
may-encrypt="yes">
<type type-name="IPFilterRule" />
</avp>
<!-- [RFC 4006] , clause 8.37 -->
<avp name="Redirect-Server" code="434" mandatory="must"
may-encrypt="yes">
<grouped>
<required>
<avprule name="Redirect-Address-Type" minimum="1" maximum="1" />
<avprule name="Redirect-Server-Address" minimum="1"
maximum="1" />
</required>
</grouped>
</avp>
<!-- [RFC 4006] , clause 8.34 -->
<avp name="Final-Unit-Indication" code="430" mandatory="must"
may-encrypt="yes">
<grouped>
<required>
<avprule name="Final-Unit-Action" minimum="1" maximum="1" />
<avprule name="Restriction-Filter-Rule" minimum="1"
maximum="1" />
<avprule name="Filter-Id" minimum="1" maximum="1" />
<avprule name="Redirect-Server" minimum="1" maximum="1" />
</required>
</grouped>
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.18 -->
<avp name="Charging-Rule-Report" vendor-id="10415" code="1018"
mandatory="must" may-encrypt="yes">
<grouped>
<optional>
<avprule name="Charging-Rule-Name" maximum="1" />
<avprule name="Charging-Rule-Base-Name" maximum="1" />
</optional>
<required>
<avprule name="PCC-Rule-Status" minimum="1" maximum="1" />
</required>
<optional>
<avprule name="Rule-Failure-Code" maximum="1" />
<avprule name="Final-Unit-Indication" maximum="1" />
</optional>
</grouped>
</avp>
<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.22 -->
<avp name="Access-Network-Charging-Identifier-Gx" vendor-id="10415"
code="1022" mandatory="must" may-encrypt="yes">
<grouped>
<required>
<avprule name="Access-Network-Charging-Identifier-Value"
minimum="1" maximum="1" />
</required>
<optional>
<avprule name="Charging-Rule-Base-Name" maximum="1" />
<avprule name="Charging-Rule-Name" maximum="1" />
</optional>
</grouped>
</avp>
<!-- [3GPP TS 29.229 V7.7.0] , clause 6.3.19 -->
<avp name="Charging-Information" vendor-id="10415" code="618"
mandatory="must" may-encrypt="yes">
<grouped>
<required>
<avprule name="Primary-Event-Charging-Function-Name"
minimum="1" maximum="1" />
<avprule name="Secondary-Event-Charging-Function-Name"
minimum="1" maximum="1" />
<avprule name="Primary-Charging-Collection-Function-Name"
minimum="1" maximum="1" />
<avprule name="Secondary-Charging-Collection-Function-Name"
minimum="1" maximum="1" />
</required>
</grouped>
</avp>
<!-- Ref = RFC 4006 chap 8.46 -->
<avp name="Subscription-Id" code="443" mandatory="must"
may-encrypt="yes">
<grouped>
<required>
<avprule name="Subscription-Id-Type" />
<avprule name="Subscription-Id-Data" />
</required>
</grouped>
</avp>
</application>
</dictionary>

View File

@@ -1,15 +0,0 @@
# This file documents the configuration format for the dict_legacy_xml.fdx freeDiameter extension.
# In order to load this extension, please refer to main freeDiameter.conf manual.
# This extension allows the use of Diameter dictionary files in XML format,
# as roughly specified in draft-frascone-xml-dictionary-00.
# (the actual format is the one from OpenDiameter latest version)
# Note that this format, although more widely used, is less efficient than the
# internal freeDiameter format. It is recommended when possible to use the later.
# You may refer to the contrib/dict_legacy/README file for information on where to find such resources.
# This file simply consists in a list of XML dictionary files that must be parsed.
# Example:
# "/etc/freeDiameter/dictionary.xml";
"@prefix@/etc/freeDiameter/dict_gx.xml";

View File

@@ -80,7 +80,7 @@ No_SCTP;
#ListenOn = "202.249.37.5";
#ListenOn = "2001:200:903:2::202:1";
#ListenOn = "fe80::21c:5ff:fe98:7d62%eth0";
ListenOn = "10.1.35.214";
ListenOn = "127.76.0.4";
##############################################################
@@ -107,8 +107,7 @@ ListenOn = "10.1.35.214";
# Default : NO DEFAULT
#TLS_Cred = "<x509 certif file.PEM>" , "<x509 private key file.PEM>";
#TLS_Cred = "/etc/ssl/certs/freeDiameter.pem", "/etc/ssl/private/freeDiameter.key";
TLS_Cred = "@prefix@/etc/freeDiameter/hss.cert.pem",
"@prefix@/etc/freeDiameter/hss.key.pem";
TLS_Cred = "@SYSCONF_DIR@/nextepc/freeDiameter/hss.cert.pem", "@SYSCONF_DIR@/nextepc/freeDiameter/hss.key.pem";
# Certificate authority / trust anchors
# The file containing the list of trusted Certificate Authorities (PEM list)
@@ -116,7 +115,7 @@ TLS_Cred = "@prefix@/etc/freeDiameter/hss.cert.pem",
# The directive can appear several times to specify several files.
# Default : GNUTLS default behavior
#TLS_CA = "<file.PEM>";
TLS_CA = "@prefix@/etc/freeDiameter/cacert.pem";
TLS_CA = "@SYSCONF_DIR@/nextepc/freeDiameter/cacert.pem";
# Certificate Revocation List file
# The information about revoked certificates.
@@ -224,14 +223,14 @@ TLS_CA = "@prefix@/etc/freeDiameter/cacert.pem";
# 4 - full - display the complete information on a single long line
# 8 - tree - display the complete information in an easier to read format spanning several lines.
LoadExtension = "@prefix@/lib/nextepc/dbg_msg_dumps.so" : "0x8888";
LoadExtension = "@prefix@/lib/nextepc/dict_rfc5777.so";
LoadExtension = "@prefix@/lib/nextepc/dict_mip6i.so";
LoadExtension = "@prefix@/lib/nextepc/dict_nasreq.so";
LoadExtension = "@prefix@/lib/nextepc/dict_nas_mipv6.so";
LoadExtension = "@prefix@/lib/nextepc/dict_dcca.so";
LoadExtension = "@prefix@/lib/nextepc/dict_dcca_3gpp.so";
LoadExtension = "@prefix@/lib/nextepc/dict_s6a.so";
LoadExtension = "@LIB_DIR@/nextepc/dbg_msg_dumps.so" : "0x8888";
LoadExtension = "@LIB_DIR@/nextepc/dict_rfc5777.so";
LoadExtension = "@LIB_DIR@/nextepc/dict_mip6i.so";
LoadExtension = "@LIB_DIR@/nextepc/dict_nasreq.so";
LoadExtension = "@LIB_DIR@/nextepc/dict_nas_mipv6.so";
LoadExtension = "@LIB_DIR@/nextepc/dict_dcca.so";
LoadExtension = "@LIB_DIR@/nextepc/dict_dcca_3gpp.so";
LoadExtension = "@LIB_DIR@/nextepc/dict_s6a.so";
##############################################################
@@ -263,6 +262,6 @@ LoadExtension = "@prefix@/lib/nextepc/dict_s6a.so";
# Examples:
#ConnectPeer = "aaa.wide.ad.jp";
#ConnectPeer = "old.diameter.serv" { TcTimer = 60; TLS_old_method; No_SCTP; Port=3868; } ;
ConnectPeer = "mme.localdomain" { ConnectTo = "10.1.35.215"; No_TLS; };
ConnectPeer = "mme.localdomain" { ConnectTo = "127.76.0.1"; No_TLS; };
##############################################################

View File

@@ -80,7 +80,7 @@ No_SCTP;
#ListenOn = "202.249.37.5";
#ListenOn = "2001:200:903:2::202:1";
#ListenOn = "fe80::21c:5ff:fe98:7d62%eth0";
ListenOn = "10.1.35.215";
ListenOn = "127.76.0.1";
##############################################################
@@ -107,8 +107,7 @@ ListenOn = "10.1.35.215";
# Default : NO DEFAULT
#TLS_Cred = "<x509 certif file.PEM>" , "<x509 private key file.PEM>";
#TLS_Cred = "/etc/ssl/certs/freeDiameter.pem", "/etc/ssl/private/freeDiameter.key";
TLS_Cred = "@prefix@/etc/freeDiameter/mme.cert.pem",
"@prefix@/etc/freeDiameter/mme.key.pem";
TLS_Cred = "@SYSCONF_DIR@/nextepc/freeDiameter/mme.cert.pem", "@SYSCONF_DIR@/nextepc/freeDiameter/mme.key.pem";
# Certificate authority / trust anchors
# The file containing the list of trusted Certificate Authorities (PEM list)
@@ -116,7 +115,7 @@ TLS_Cred = "@prefix@/etc/freeDiameter/mme.cert.pem",
# The directive can appear several times to specify several files.
# Default : GNUTLS default behavior
#TLS_CA = "<file.PEM>";
TLS_CA = "@prefix@/etc/freeDiameter/cacert.pem";
TLS_CA = "@SYSCONF_DIR@/nextepc/freeDiameter/cacert.pem";
# Certificate Revocation List file
# The information about revoked certificates.
@@ -224,14 +223,14 @@ TLS_CA = "@prefix@/etc/freeDiameter/cacert.pem";
# 4 - full - display the complete information on a single long line
# 8 - tree - display the complete information in an easier to read format spanning several lines.
LoadExtension = "@prefix@/lib/nextepc/dbg_msg_dumps.so" : "0x8888";
LoadExtension = "@prefix@/lib/nextepc/dict_rfc5777.so";
LoadExtension = "@prefix@/lib/nextepc/dict_mip6i.so";
LoadExtension = "@prefix@/lib/nextepc/dict_nasreq.so";
LoadExtension = "@prefix@/lib/nextepc/dict_nas_mipv6.so";
LoadExtension = "@prefix@/lib/nextepc/dict_dcca.so";
LoadExtension = "@prefix@/lib/nextepc/dict_dcca_3gpp.so";
LoadExtension = "@prefix@/lib/nextepc/dict_s6a.so";
LoadExtension = "@LIB_DIR@/nextepc/dbg_msg_dumps.so" : "0x8888";
LoadExtension = "@LIB_DIR@/nextepc/dict_rfc5777.so";
LoadExtension = "@LIB_DIR@/nextepc/dict_mip6i.so";
LoadExtension = "@LIB_DIR@/nextepc/dict_nasreq.so";
LoadExtension = "@LIB_DIR@/nextepc/dict_nas_mipv6.so";
LoadExtension = "@LIB_DIR@/nextepc/dict_dcca.so";
LoadExtension = "@LIB_DIR@/nextepc/dict_dcca_3gpp.so";
LoadExtension = "@LIB_DIR@/nextepc/dict_s6a.so";
##############################################################
@@ -263,7 +262,7 @@ LoadExtension = "@prefix@/lib/nextepc/dict_s6a.so";
# Examples:
#ConnectPeer = "aaa.wide.ad.jp";
#ConnectPeer = "old.diameter.serv" { TcTimer = 60; TLS_old_method; No_SCTP; Port=3868; } ;
ConnectPeer = "hss.localdomain" { ConnectTo = "10.1.35.214"; No_TLS; };
ConnectPeer = "hss.localdomain" { ConnectTo = "127.76.0.4"; No_TLS; };
##############################################################

View File

@@ -80,7 +80,7 @@ No_SCTP;
#ListenOn = "202.249.37.5";
#ListenOn = "2001:200:903:2::202:1";
#ListenOn = "fe80::21c:5ff:fe98:7d62%eth0";
ListenOn = "10.1.35.218";
ListenOn = "127.76.0.5";
##############################################################
@@ -107,7 +107,7 @@ ListenOn = "10.1.35.218";
# Default : NO DEFAULT
#TLS_Cred = "<x509 certif file.PEM>" , "<x509 private key file.PEM>";
#TLS_Cred = "/etc/ssl/certs/freeDiameter.pem", "/etc/ssl/private/freeDiameter.key";
TLS_Cred = "@prefix@/etc/freeDiameter/pcrf.cert.pem", "@prefix@/etc/freeDiameter/pcrf.key.pem";
TLS_Cred = "@SYSCONF_DIR@/nextepc/freeDiameter/pcrf.cert.pem", "@SYSCONF_DIR@/nextepc/freeDiameter/pcrf.key.pem";
# Certificate authority / trust anchors
# The file containing the list of trusted Certificate Authorities (PEM list)
@@ -115,7 +115,7 @@ TLS_Cred = "@prefix@/etc/freeDiameter/pcrf.cert.pem", "@prefix@/etc/freeDiameter
# The directive can appear several times to specify several files.
# Default : GNUTLS default behavior
#TLS_CA = "<file.PEM>";
TLS_CA = "@prefix@/etc/freeDiameter/cacert.pem";
TLS_CA = "@SYSCONF_DIR@/nextepc/freeDiameter/cacert.pem";
# Certificate Revocation List file
# The information about revoked certificates.
@@ -223,14 +223,14 @@ TLS_CA = "@prefix@/etc/freeDiameter/cacert.pem";
# 4 - full - display the complete information on a single long line
# 8 - tree - display the complete information in an easier to read format spanning several lines.
LoadExtension = "@prefix@/lib/nextepc/dbg_msg_dumps.so" : "0x8888";
LoadExtension = "@prefix@/lib/nextepc/dict_rfc5777.so";
LoadExtension = "@prefix@/lib/nextepc/dict_mip6i.so";
LoadExtension = "@prefix@/lib/nextepc/dict_nasreq.so";
LoadExtension = "@prefix@/lib/nextepc/dict_nas_mipv6.so";
LoadExtension = "@prefix@/lib/nextepc/dict_dcca.so";
LoadExtension = "@prefix@/lib/nextepc/dict_dcca_3gpp.so";
#LoadExtension = "@prefix@/lib/nextepc/dict_legacy_xml.so" : "@prefix@/etc/freeDiameter/dict_legacy_xml.conf";
LoadExtension = "@LIB_DIR@/nextepc/dbg_msg_dumps.so" : "0x8888";
LoadExtension = "@LIB_DIR@/nextepc/dict_rfc5777.so";
LoadExtension = "@LIB_DIR@/nextepc/dict_mip6i.so";
LoadExtension = "@LIB_DIR@/nextepc/dict_nasreq.so";
LoadExtension = "@LIB_DIR@/nextepc/dict_nas_mipv6.so";
LoadExtension = "@LIB_DIR@/nextepc/dict_dcca.so";
LoadExtension = "@LIB_DIR@/nextepc/dict_dcca_3gpp.so";
#LoadExtension = "@LIB_DIR@/nextepc/dict_legacy_xml.so" : "@SYSCONF_DIR@/nextepc/freeDiameter/dict_legacy_xml.conf";
##############################################################
@@ -262,6 +262,6 @@ LoadExtension = "@prefix@/lib/nextepc/dict_dcca_3gpp.so";
# Examples:
#ConnectPeer = "aaa.wide.ad.jp";
#ConnectPeer = "old.diameter.serv" { TcTimer = 60; TLS_old_method; No_SCTP; Port=3868; } ;
ConnectPeer = "pgw.localdomain" { ConnectTo = "10.1.35.219"; No_TLS; };
ConnectPeer = "pgw.localdomain" { ConnectTo = "127.76.0.3"; No_TLS; };
##############################################################

View File

@@ -80,7 +80,7 @@ No_SCTP;
#ListenOn = "202.249.37.5";
#ListenOn = "2001:200:903:2::202:1";
#ListenOn = "fe80::21c:5ff:fe98:7d62%eth0";
ListenOn = "10.1.35.219";
ListenOn = "127.76.0.3";
##############################################################
@@ -107,7 +107,7 @@ ListenOn = "10.1.35.219";
# Default : NO DEFAULT
#TLS_Cred = "<x509 certif file.PEM>" , "<x509 private key file.PEM>";
#TLS_Cred = "/etc/ssl/certs/freeDiameter.pem", "/etc/ssl/private/freeDiameter.key";
TLS_Cred = "@prefix@/etc/freeDiameter/pgw.cert.pem", "@prefix@/etc/freeDiameter/pgw.key.pem";
TLS_Cred = "@SYSCONF_DIR@/nextepc/freeDiameter/pgw.cert.pem", "@SYSCONF_DIR@/nextepc/freeDiameter/pgw.key.pem";
# Certificate authority / trust anchors
# The file containing the list of trusted Certificate Authorities (PEM list)
@@ -115,7 +115,7 @@ TLS_Cred = "@prefix@/etc/freeDiameter/pgw.cert.pem", "@prefix@/etc/freeDiameter/
# The directive can appear several times to specify several files.
# Default : GNUTLS default behavior
#TLS_CA = "<file.PEM>";
TLS_CA = "@prefix@/etc/freeDiameter/cacert.pem";
TLS_CA = "@SYSCONF_DIR@/nextepc/freeDiameter/cacert.pem";
# Certificate Revocation List file
# The information about revoked certificates.
@@ -223,14 +223,14 @@ TLS_CA = "@prefix@/etc/freeDiameter/cacert.pem";
# 4 - full - display the complete information on a single long line
# 8 - tree - display the complete information in an easier to read format spanning several lines.
LoadExtension = "@prefix@/lib/nextepc/dbg_msg_dumps.so" : "0x8888";
LoadExtension = "@prefix@/lib/nextepc/dict_rfc5777.so";
LoadExtension = "@prefix@/lib/nextepc/dict_mip6i.so";
LoadExtension = "@prefix@/lib/nextepc/dict_nasreq.so";
LoadExtension = "@prefix@/lib/nextepc/dict_nas_mipv6.so";
LoadExtension = "@prefix@/lib/nextepc/dict_dcca.so";
LoadExtension = "@prefix@/lib/nextepc/dict_dcca_3gpp.so";
#LoadExtension = "@prefix@/lib/nextepc/dict_legacy_xml.so" : "@prefix@/etc/freeDiameter/dict_legacy_xml.conf";
LoadExtension = "@LIB_DIR@/nextepc/dbg_msg_dumps.so" : "0x8888";
LoadExtension = "@LIB_DIR@/nextepc/dict_rfc5777.so";
LoadExtension = "@LIB_DIR@/nextepc/dict_mip6i.so";
LoadExtension = "@LIB_DIR@/nextepc/dict_nasreq.so";
LoadExtension = "@LIB_DIR@/nextepc/dict_nas_mipv6.so";
LoadExtension = "@LIB_DIR@/nextepc/dict_dcca.so";
LoadExtension = "@LIB_DIR@/nextepc/dict_dcca_3gpp.so";
#LoadExtension = "@LIB_DIR@/nextepc/dict_legacy_xml.so" : "@SYSCONF_DIR@/nextepc/freeDiameter/dict_legacy_xml.conf";
##############################################################
@@ -262,7 +262,7 @@ LoadExtension = "@prefix@/lib/nextepc/dict_dcca_3gpp.so";
# Examples:
#ConnectPeer = "aaa.wide.ad.jp";
#ConnectPeer = "old.diameter.serv" { TcTimer = 60; TLS_old_method; No_SCTP; Port=3868; } ;
ConnectPeer = "pcrf.localdomain" { ConnectTo = "10.1.35.218"; No_TLS; };
ConnectPeer = "pcrf.localdomain" { ConnectTo = "127.76.0.5"; No_TLS; };
##############################################################

View File

@@ -1,10 +0,0 @@
#!/bin/sh
ifconfig eth1:hss 10.1.35.214/24 up
ifconfig eth1:mme 10.1.35.215/24 up
ifconfig eth1:sgw_s5 10.1.35.216/24 up
ifconfig eth1:sgw_s11 10.1.35.217/24 up
ifconfig eth1:pcrf 10.1.35.218/24 up
ifconfig eth1:pgw 10.1.35.219/24 up
ifconfig pgwtun 45.45.0.1/16 up

View File

@@ -0,0 +1,4 @@
EXTRA_DIST = nextepc.in
MAINTAINERCLEANFILES = Makefile.in
MOSTLYCLEANFILES = *.stackdump

View File

@@ -0,0 +1,16 @@
@LOCALSTATE_DIR@/log/nextepc/*.log {
daily
sharedscripts
missingok
compress
rotate 14
create 640 nextepc nextepc
postrotate
for i in pcrfd pgwd sgwd hssd mmed epcd; do
if [ -e @LOCALSTATE_DIR@/run/nextepc-$i/pid ] ; then
kill -HUP `cat @LOCALSTATE_DIR@/run/nextepc-$i/pid`
fi
done
endscript
}

View File

@@ -1,9 +0,0 @@
#!/bin/sh
ifconfig en0 alias 10.1.35.214 netmask 255.255.255.255
ifconfig en0 alias 10.1.35.215 netmask 255.255.255.255
ifconfig en0 alias 10.1.35.216 netmask 255.255.255.255
ifconfig en0 alias 10.1.35.217 netmask 255.255.255.255
ifconfig en0 alias 10.1.35.218 netmask 255.255.255.255
ifconfig en0 alias 10.1.35.219 netmask 255.255.255.255

6
support/network/nextepc Normal file
View File

@@ -0,0 +1,6 @@
auto pgwtun
iface pgwtun inet static
address 45.45.0.1
netmask 255.255.0.0
pre-up ip tuntap add name pgwtun mode tun
post-down ip tuntap del name pgwtun mode tun

17
support/network/restart.sh Executable file
View File

@@ -0,0 +1,17 @@
#!/bin/sh
SYSTEM=`uname`;
if [ "$SYSTEM" = "Linux" ]; then
if ! grep "pgwtun" /proc/net/dev > /dev/null; then
ip tuntap add name pgwtun mode tun
ip addr add 45.45.0.1/16 dev pgwtun
ip link set pgwtun up
fi
else
ifconfig lo0 alias 127.76.0.1 netmask 255.255.255.255
ifconfig lo0 alias 127.76.0.2 netmask 255.255.255.255
ifconfig lo0 alias 127.76.0.3 netmask 255.255.255.255
ifconfig lo0 alias 127.76.0.4 netmask 255.255.255.255
ifconfig lo0 alias 127.76.0.5 netmask 255.255.255.255
fi

View File

@@ -0,0 +1,4 @@
EXTRA_DIST = nextepc.conf.in
MAINTAINERCLEANFILES = Makefile.in
MOSTLYCLEANFILES = *.stackdump

Some files were not shown because too many files have changed in this diff Show More