Compare commits

..

97 Commits

Author SHA1 Message Date
Yalu Zhang
82bd89a2fa Rename etc/init.d/dect to etc/init.d/dectmngr
Also remove some files for USB DECT sound driver configuration
2021-05-11 15:12:05 +05:30
Sukru Senli
728bdacd70 endptmngr: remove copyright from init script 2021-05-11 15:12:05 +05:30
Sukru Senli
9613b4b35d endptmngr: add init script and remove ENDPT_OPEN 2021-05-11 15:12:05 +05:30
jjoseph
42c12b9a24 Update feed [iopsys] package [urlfilter] 2021-05-11 15:12:05 +05:30
Suru Dissanaike
18620d19b5 sulu: update pkg_version 2021-05-11 15:12:05 +05:30
Suru Dissanaike
a5f8436b9b Update Makefile 2021-05-11 15:12:05 +05:30
jjoseph
9937972931 urlfilter : Change permission of init.d file 2021-05-11 15:12:05 +05:30
Marin Karamihalev
ff6e67d7ee Update Makefile 2021-05-11 15:12:05 +05:30
Bartlomiej Grzeskowiak
1ba797a43d iopsys-mediatek: Add iopsys-mediatek (bpi_bananapi-r64)
- ./iop genconfig -c bpi_bananapi-r64
2021-05-11 15:12:05 +05:30
Sukru Senli
932d08e35c iop: genconfig: fix juci makefile path 2021-05-07 10:23:46 +05:30
Sukru Senli
6b38477949 easy-soc-libs: remove intel dependency 2021-05-07 10:23:46 +05:30
Sukru Senli
f9b4dea0ad juci: move from juci to iopsys feed 2021-05-07 10:23:46 +05:30
Sukru Senli
182af2c1a5 bulut: move from 3rdparty to iopsys feed 2021-05-07 10:23:46 +05:30
Sukru Senli
e5fb9bf79d sulu: move from 3rdparty to iopsys feed 2021-05-07 10:23:46 +05:30
Yalu Zhang
5ed7c8b79c Update package [ dectmngr ]
Explicitly enable the encryption between the base station and handsets
2021-05-07 10:23:46 +05:30
Andreas Gnau
545054bad4 Update feed [ iopsys ] package [ fdtextract ]
-------------------------------------------------------------------------------
* 485a38b Merge branch 'agnau-print-to-stderr' into 'master'
* bedf694 Print errors to stderr instead of stdout
-------------------------------------------------------------------------------
commit 485a38bc4eaf2a54d080b8529d5130b2955626d1
Author: Jonas Höglund <jonas.hoglund@iopsys.eu>
Date: 2021-05-05 15:06:22 +0000

    Merge branch 'agnau-print-to-stderr' into 'master'

    Print errors to stderr instead of stdout

    See merge request iopsys/fdtextract!1
Base directory -> /
 fdtextract.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)
-------------------------------------------------------------------------------
commit bedf694df0eee164f3b21f3bbffaf4dc379fa002
Author: Andreas Gnau <andreas.gnau@iopsys.eu>
Date: 2021-05-05 10:16:41 +0200

    Print errors to stderr instead of stdout

Base directory -> /
 fdtextract.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)
-------------------------------------------------------------------------------
2021-05-07 10:23:46 +05:30
vdutta
9550947906 obuspa: In usp BulkData collection 2021-05-06 16:43:38 +05:30
Yalu Zhang
a859c42c9a Update package [ dectmngr ]
Reject SUOTA request from the base station as it may cause handset hang
2021-05-06 13:29:12 +05:30
Sukru Senli
a97b005232 crun: use openwrt upstream version 2021-05-06 13:29:12 +05:30
Amin Ben Ramdhane
00aaa8e966 bbf: 4.1.2 2021-05-06 13:29:12 +05:30
vdutta
9fdc4d0d8a obuspa: Updated uci schema 2021-05-04 19:52:47 +05:30
Jakob Olsson
f764e2be69 map-controller: 2.4.12 2021-05-04 15:13:54 +05:30
Amin Ben Ramdhane
b46e64a4a1 bulkdata: fix compilation error 2021-05-04 15:13:54 +05:30
Amin Ben Ramdhane
9c40ae83b0 bbf: 4.1.1 2021-05-04 15:13:54 +05:30
Andreas Gnau
49dff02bf8 iop: Remove tc
The tc-utility from iproute2 is seldomly needed. In OpenWrt 21.02 there
are two variants, tc-full and tc-tiny, but since it is not needed,
remove it.
2021-05-04 15:13:54 +05:30
Jakob Olsson
72e723d8f9 map-agent: add loop detection script 2021-05-04 15:13:54 +05:30
Anjan Chanda
e908c6f6b8 wfadatad: 3.3.1 2021-05-04 15:13:54 +05:30
vdutta
176bed8df4 stunc: Added ci and docs 2021-05-04 15:13:54 +05:30
Andreas Gnau
db20d56e6e iop: Remove usbreset from config
usbreset has been moved to the usbutils package, but it is not needed,
anyways. Remove it.
2021-05-04 15:13:54 +05:30
Andreas Gnau
ea799c2870 iop: Remove alsa-lib from config
One of its dependencies causes issues and alsalib is not used by
anything.
2021-05-04 15:13:54 +05:30
Jakob Olsson
59ab62ae84 map-agent: 3.5.20 2021-05-04 15:13:54 +05:30
Jakob Olsson
8763f54e6e map-agent: 3.5.19 2021-05-04 15:13:54 +05:30
Jakob Olsson
df01b63437 map-topology: 1.5.22 2021-05-04 15:13:54 +05:30
vdutta
79eb07954e Read role json from uci 2021-04-29 12:19:10 +05:30
Anjan Chanda
5497338f67 wifimngr: 9.3.2 2021-04-29 12:19:10 +05:30
Anjan Chanda
9805015b81 easy-soc-libs: 6.2.12 2021-04-29 12:19:10 +05:30
Jonas Höglund
ae13be86c9 Update feed [ iopsys ] package [ fdtextract ]
-------------------------------------------------------------------------------
* e92fb43 Enable output of extrated file to stdout.
-------------------------------------------------------------------------------
commit e92fb432f7ec61d8cb2066dba38cf955dcd6c676
Author: Jonas Höglund <jonas.hoglund@embeddednation.com>
Date: 2021-04-28 10:06:23 +0200

    Enable output of extrated file to stdout.

Base directory -> /
 fdtextract.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)
-------------------------------------------------------------------------------
2021-04-29 12:19:10 +05:30
vdutta
efe8428fb6 Added assigned role for controller 2021-04-28 12:46:19 +05:30
vdutta
b44fcd804c Config options to enable/disable mtp protocols 2021-04-28 11:36:08 +05:30
vdutta
9f1b6b1eff Updated roles definition json file 2021-04-28 11:30:03 +05:30
Sukru Senli
a8f1267239 urlfilter: install default config file 2021-04-28 10:37:01 +05:30
Andreas Gnau
282dec860c peripheral_manager: Remove bcmkernel dependency
As Broadcom has moved to standard interfaces, peripheral_manager no
longer depends on Broadcom headers or executables.

Remove the dependency and preprocessor options.
2021-04-27 18:28:30 +05:30
Andreas Gnau
56879584f1 Update feed [ iopsys ] package [ peripheral_manager ]
-------------------------------------------------------------------------------
* 785166a Remove BRCM_BOARD define
* 86178d8 Remove prox_px3220 driver
* 6069bf5 Remove vox driver
* 3897735 Remove wlctl driver
* 3aadf4a CMakeLists.txt: Run cmake-format
* 636c4e1 update README for doc portal
* d055dd8 update README.md
-------------------------------------------------------------------------------
commit 785166a9861a119623556163179915727896156b
Author: Andreas Gnau <andreas.gnau@iopsys.eu>
Date: 2021-04-23 12:37:22 +0200

    Remove BRCM_BOARD define

    No drivers depend on Broadcom headers anymore, remove the BRCM_BOARD define.

    Peripheral-manager has neither a build nor a runtime dependency on the
    Broadcom SDK.

Base directory -> /
 CMakeLists.txt | 4 ----
 1 file changed, 4 deletions(-)
-------------------------------------------------------------------------------
commit 86178d8dfc51f67b3492ad603106b1fc29d6b285
Author: Andreas Gnau <andreas.gnau@iopsys.eu>
Date: 2021-04-23 12:32:39 +0200

    Remove prox_px3220 driver

    This driver is no longer used by any supported target. Remove it.

Base directory -> /
 src/button.c      |  16 -----
 src/prox_px3220.c | 193 ------------------------------------------------------
 src/prox_px3220.h |   9 ---
 src/server.c      |   6 --
 4 files changed, 224 deletions(-)
-------------------------------------------------------------------------------
commit 6069bf5aea4dbb2ebfdd912ebb2d3c95f90ba86c
Author: Andreas Gnau <andreas.gnau@iopsys.eu>
Date: 2021-04-21 20:10:06 +0200

    Remove vox driver

    This driver is no longer used by any supported target and neither is it
    built or referenced by any other file. Remove it.

Base directory -> /
 src/vox.c      | 176 --------------------------------------------------------
 src/vox_test.c | 178 ---------------------------------------------------------
 2 files changed, 354 deletions(-)
-------------------------------------------------------------------------------
commit 3897735e4b55bed66a2b4a2ffc3ee3766e502ec5
Author: Andreas Gnau <andreas.gnau@iopsys.eu>
Date: 2021-04-21 19:44:50 +0200

    Remove wlctl driver

    This driver is no longer used by any supported target. Remove it.

Base directory -> /
 CMakeLists.txt  |   2 +-
 src/server.c    |   4 --
 src/wlctl_led.c | 133 --------------------------------------------------------
 3 files changed, 1 insertion(+), 138 deletions(-)
-------------------------------------------------------------------------------
commit 3aadf4a6d69ed1db02376e7a20f751e8bbf408c5
Author: Andreas Gnau <andreas.gnau@iopsys.eu>
Date: 2021-04-21 10:49:42 +0200

    CMakeLists.txt: Run cmake-format

    Amongst consistent indendation and following best-practices such as
    lowercase function-names, this puts individual list items on a separate
    line, making diffs easier to read.

Base directory -> /
 CMakeLists.txt | 190 +++++++++++++++++++++++++++++++++++----------------------
 1 file changed, 118 insertions(+), 72 deletions(-)
-------------------------------------------------------------------------------
commit 636c4e1568828d85def657c324c78e341edccaad
Author: Sukru Senli <sukru.senli@iopsys.eu>
Date: 2021-04-11 13:11:29 +0200

    update README for doc portal

Base directory -> /
 README.md                      | 494 ++++++++++-------------------------------
 img/peripheral-manager.png     | Bin 0 -> 60660 bytes
 img/peripheral_led_mapping.png | Bin 0 -> 25497 bytes
 3 files changed, 115 insertions(+), 379 deletions(-)
-------------------------------------------------------------------------------
commit d055dd8a4a3aa53550a1b1f9db94225fe7c0f61b
Author: Benjamin Larsson <benjamin.larsson@iopsys.eu>
Date: 2021-04-11 13:08:18 +0200

    update README.md

Base directory -> /
 README.md | 477 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 420 insertions(+), 57 deletions(-)
-------------------------------------------------------------------------------
2021-04-27 18:28:30 +05:30
Anjan Chanda
9ec95d1b5e wfadatad: 3.3.0 2021-04-27 18:28:30 +05:30
Anjan Chanda
fd569dcb31 prj-unish: 0.7.0 2021-04-27 18:28:30 +05:30
Anjan Chanda
f031ee17a3 wifimngr: 9.3.0 2021-04-27 18:28:30 +05:30
Anjan Chanda
5a3b7602b0 easy-soc-libs: 6.2.10 2021-04-27 18:28:30 +05:30
nevadita.chatterjee
746d3f2c89 host: Adding sighup for network change 2021-04-27 18:28:30 +05:30
Jakob Olsson
0b58bfdf1b map-topology: 1.5.21 2021-04-27 18:28:30 +05:30
Filip Matusiak
0a0633afc1 map-controller: init.d start on reload if not running 2021-04-27 18:28:30 +05:30
Jakob Olsson
e6be8ccff7 map-agent: 3.5.18 2021-04-27 18:28:30 +05:30
Sukru Senli
de675228bc urlfilter: start urlfilter only if globally enabled 2021-04-27 18:28:30 +05:30
Sukru Senli
2b43a91930 iop: select urlfilter by default 2021-04-27 18:28:30 +05:30
Jakob Olsson
1fe8dfa464 rulengd: 1.2.2 2021-04-27 18:28:30 +05:30
Amin Ben Ramdhane
1bf0a38259 bbf: 4.1.0 2021-04-27 18:28:30 +05:30
Amin Ben Ramdhane
75b93ae57b bbf: 4.0.9 2021-04-27 18:28:30 +05:30
Amin Ben Ramdhane
0391f4c509 bbf: 4.0.8 2021-04-27 18:28:30 +05:30
Amin Ben Ramdhane
f57de2675a bbf: 4.0.7 2021-04-27 18:28:30 +05:30
vdutta
7046497a13 wip: Define challenge in uci 2021-04-22 16:29:13 +05:30
Anjan Chanda
d1d455a51d wifimngr: 9.2.3 2021-04-21 22:21:10 +02:00
Simon Tate
fe63598021 shflags: skip PKG_MIRROR_HASH check
with latest OpenWRT, the mirror hash is now checked, even if dl/ item exists. Adding skip, stops it from always downloading again.
2021-04-21 10:45:58 +00:00
Simon Tate
7853733a75 libtrace: skip PKG_MIRROR_HASH check
with latest OpenWRT, the mirror hash is now checked, even if dl/ item exists. Adding skip, stops it from always downloading again.
2021-04-21 10:45:58 +00:00
Sukru Senli
7d991d89be move bulkdata, twamp and udpechoserver to their individual repos 2021-04-20 19:19:26 +02:00
Sukru Senli
88892e5f7c move xmppc & stunc code to their individual repos 2021-04-20 18:58:47 +02:00
jjoseph
b30434d872 Update feed [iopsys] package [urlfilter] 2021-04-20 19:05:10 +05:30
Sukru Senli
9995b4a3f2 icwmp: remove CONFIG_CWMP_SCRIPTS_FULL 2021-04-16 18:45:31 +02:00
Anjan Chanda
27c515e258 wifimngr: 9.2.1 2021-04-16 16:51:52 +02:00
Marek Puzyniak
8373ffae75 easy-soc-libs: update version and hash
Signed-off-by: Marek Puzyniak <marek.puzyniak@iopsys.eu>
2021-04-16 13:39:33 +00:00
sverma
888b247706 wfadatad: HE caps support added (3.2.5). 2021-04-16 15:51:34 +05:30
Jakob Olsson
86eed4ba84 map-agent: 3.5.17 2021-04-16 10:18:23 +02:00
Grzegorz Sluja
63335fb119 Update package [ dectmngr ]
Fix dectmngr crash when caller id is empty
2021-04-16 07:44:44 +02:00
Jakob Olsson
bc3dc5c3db map-controller: 2.4.11 2021-04-15 17:30:38 +02:00
Filip Matusiak
0097bc5d89 map-controller: add external trigger logic to init.d 2021-04-15 15:17:00 +00:00
Yalu Zhang
4b04b8445f Update package [ dectmngr ]
Set RFPI value during the start up
2021-04-15 17:08:59 +02:00
Jakob Olsson
317e644e11 3.5.16 2021-04-15 17:08:34 +02:00
Yalu Zhang
1ac9c4f057 Update package [ dectmngr ]
/etc/init.d/dect: gets DECT RFPI from the board DB and passes it to dectmngr
via a command line argument.
2021-04-15 17:05:34 +02:00
Omar Kallel
35f02d2891 icwmp: 7.0.1-2021-04-15 2021-04-15 12:19:44 +01:00
Omar Kallel
067e3dc7b8 icwmp: Fix compiling error 2021-04-15 11:49:06 +01:00
Omar Kallel
3d9cfc03fb icwmp: 7.0.0-2021-04-15 2021-04-15 11:11:02 +01:00
Erik Karlsson
a6c3c54091 mcastmngr: do not overwrite configuration if snooping section exists 2021-04-15 07:57:06 +00:00
Janusz Dziedzic
dbe1a31d09 easy-soc-libs: by default use MAC80211 target
If TARGET_PLATFORM is not set, by default use
MAC80211 target.

Signed-off-by: Janusz Dziedzic <janusz.dziedzic@iopsys.eu>
2021-04-14 13:24:16 +00:00
Janusz Dziedzic
d5f0c80b2e update easy-soc-libs
Signed-off-by: Janusz Dziedzic <janusz.dziedzic@iopsys.eu>
2021-04-14 13:21:51 +00:00
Jakob Olsson
fd60b8121c map-controller: 2.4.10 2021-04-13 15:11:00 +02:00
Jakob Olsson
0001b91c41 map-agent: 3.5.15 2021-04-13 15:10:03 +02:00
Janusz Dziedzic
733c88df8c update easy-soc-libs and wifimngr
kick to newer version

Signed-off-by: Janusz Dziedzic <janusz.dziedzic@iopsys.eu>
2021-04-12 18:35:01 +00:00
Oskar Viljasaar
1d1c8a25f2 iop: select the nohup utility in the busybox config
This is related to the ubus fwbank.upgrade() work as we would
like to implement this function in an asynchronous way.
2021-04-08 15:45:29 +00:00
Jonas Höglund
c47857f950 Update feed [ iopsys ] package [ fdtextract ]
-------------------------------------------------------------------------------
* 152a2d9 Pad hash hex output
-------------------------------------------------------------------------------
commit 152a2d96fea896c1607bd5259e3076750693dd59
Author: Jonas Höglund <jonas.hoglund@embeddednation.com>
Date: 2021-04-08 11:00:12 +0200

    Pad hash hex output

Base directory -> /
 fdtextract.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
-------------------------------------------------------------------------------
2021-04-08 11:01:20 +02:00
Sukru Senli
d503d4390e iop: select gre by default 2021-04-08 10:12:52 +02:00
Anjan Chanda
15165b3066 prj-unish: 0.2.0 2021-04-07 15:03:49 +02:00
Jonas Höglund
0fe9ac1a0d Update feed [ iopsys ] package [ fdtextract ]
-------------------------------------------------------------------------------
* a15079b Update README
* 97c3897 Update README
* 31e6cc7 Don't print the algo with the hash.
* 9246b1c Get attribute from root node.
* 1d1556a Print hash algo.
* cdb7ee7 Check hash algo.
* 30d1aed Get hash of image.
* b5bb0eb Extract image to file.
* 34c12c4 Write image to file
* 03328f9 Get size and offset of image.
-------------------------------------------------------------------------------
commit a15079b20b8ded68e5f91f69b79993ef8afd52ab
Author: Jonas Höglund <jonas.hoglund@embeddednation.com>
Date: 2021-04-07 09:24:33 +0200

    Update README

Base directory -> /
 README.md | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
-------------------------------------------------------------------------------
commit 97c38977f0f843b02b82c156fbffb56ebd49246c
Author: Jonas Höglund <jonas.hoglund@embeddednation.com>
Date: 2021-04-07 09:23:05 +0200

    Update README

Base directory -> /
 README.md | 28 +++++++++++++++++++++-------
 1 file changed, 21 insertions(+), 7 deletions(-)
-------------------------------------------------------------------------------
commit 31e6cc7e7ecdc6aec29c99c7feedfb19624f3b59
Author: Jonas Höglund <jonas.hoglund@embeddednation.com>
Date: 2021-04-07 09:20:01 +0200

    Don't print the algo with the hash.

Base directory -> /
 fdtextract.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
-------------------------------------------------------------------------------
commit 9246b1c36f083bda292c876273465a7713a5727a
Author: Jonas Höglund <jonas.hoglund@embeddednation.com>
Date: 2021-04-07 09:18:09 +0200

    Get attribute from root node.

Base directory -> /
 fdtextract.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 47 insertions(+), 7 deletions(-)
-------------------------------------------------------------------------------
commit 1d1556a5b1f5a4206bb24430562227e8727b9d88
Author: Jonas Höglund <jonas.hoglund@embeddednation.com>
Date: 2021-04-06 15:05:11 +0200

    Print hash algo.

Base directory -> /
 fdtextract.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
-------------------------------------------------------------------------------
commit cdb7ee7e3365841bd944b897328cebe441083b9c
Author: Jonas Höglund <jonas.hoglund@embeddednation.com>
Date: 2021-04-06 14:53:19 +0200

    Check hash algo.

Base directory -> /
 fdtextract.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
-------------------------------------------------------------------------------
commit 30d1aedc1643f53ea0465a096f5ed1bf6f94b876
Author: Jonas Höglund <jonas.hoglund@embeddednation.com>
Date: 2021-04-06 14:32:29 +0200

    Get hash of image.

Base directory -> /
 fdtextract.c | 34 +++++++++++++++++++++++++++++++---
 1 file changed, 31 insertions(+), 3 deletions(-)
-------------------------------------------------------------------------------
commit b5bb0eb23b47298603553e4a99f7c60c59386018
Author: Jonas Höglund <jonas.hoglund@embeddednation.com>
Date: 2021-04-06 13:49:28 +0200

    Extract image to file.

Base directory -> /
 fdtextract.c | 15 ++++++---------
 1 file changed, 6 insertions(+), 9 deletions(-)
-------------------------------------------------------------------------------
commit 34c12c48bc6900b0c7d70ad95f12fc102507b816
Author: Jonas Höglund <jonas.hoglund@embeddednation.com>
Date: 2021-04-06 11:47:56 +0200

    Write image to file

Base directory -> /
 fdtextract.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)
-------------------------------------------------------------------------------
commit 03328f97927199df098cb1fe49efc842d213a7a4
Author: Jonas Höglund <jonas.hoglund@embeddednation.com>
Date: 2021-04-06 11:13:28 +0200

    Get size and offset of image.

Base directory -> /
 fdtextract.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)
-------------------------------------------------------------------------------
2021-04-07 09:45:24 +02:00
Amin Ben Ramdhane
99a4fe3f05 bbf: 4.0.6 2021-04-06 15:10:52 +01:00
Jonas Höglund
ca1e348b5c Rename dumpimage to fdtextract 2021-04-06 10:46:22 +02:00
Jonas Höglund
550330cb33 Update feed [ iopsys ] package [ dumpimage ]
-------------------------------------------------------------------------------
* 9ca11d5 Check input
-------------------------------------------------------------------------------
commit 9ca11d5171989c728ed80a641c0d405b5db8e96b
Author: Jonas Höglund <jonas.hoglund@embeddednation.com>
Date: 2021-04-01 11:10:08 +0200

    Check input

Base directory -> /
 dumpimage.c | 5 +++++
 1 file changed, 5 insertions(+)
-------------------------------------------------------------------------------
2021-04-01 11:12:40 +02:00
Jonas Höglund
e427dd0f09 Fix spelling error 2021-04-01 11:12:06 +02:00
Jonas Höglund
2eb3c89f36 Update feed [ iopsys ] package [ dumpimage ]
-------------------------------------------------------------------------------
* b70c60b Fix compilation
-------------------------------------------------------------------------------
commit b70c60b751e22d8286028fed3c7bfbf4b576cbf0
Author: Jonas Höglund <jonas.hoglund@embeddednation.com>
Date: 2021-04-01 10:52:38 +0200

    Fix compilation

Base directory -> /
 .gitignore | 8 ++++++++
 Makefile   | 8 ++++----
 2 files changed, 12 insertions(+), 4 deletions(-)
-------------------------------------------------------------------------------
2021-04-01 10:53:04 +02:00
Jonas Höglund
6408e0254c Fix dumpimage Makefile 2021-04-01 10:41:17 +02:00
Jonas Höglund
7db30978e3 Add dumpimage tool. 2021-04-01 10:36:16 +02:00
124 changed files with 1528 additions and 19294 deletions

View File

@@ -5,11 +5,11 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=libbbfdm
PKG_VERSION:=4.0.5
PKG_VERSION:=4.1.2
PKG_FIXUP:=autoreconf
PKG_SOURCE_URL:=https://dev.iopsys.eu/iopsys/bbf.git
PKG_SOURCE_PROTO:=git
PKG_SOURCE_VERSION:=765d43d0e3df2b0b67590887c34c1be6cd4735de
PKG_SOURCE_VERSION:=3034c1b324937fdccafa92e706e5986dc7a78df7
PKG_RELEASE=$(PKG_SOURCE_VERSION)
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
PKG_MIRROR_HASH:=skip

View File

@@ -8,10 +8,20 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=bulkdata
PKG_VERSION:=1.0.0
PKG_VERSION:=1.0.1
PKG_SOURCE_VERSION:=e4f39d1bf4678fc05b9d02e81b194c70719909e4
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://dev.iopsys.eu/iopsys/bulkdata.git
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
PKG_MIRROR_HASH:=skip
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
PKG_LICENSE:=GPL-2.0-only
PKG_LICENSE_FILES:=LICENSE
include $(INCLUDE_DIR)/package.mk
define Package/$(PKG_NAME)
@@ -26,10 +36,6 @@ define Package/$(PKG_NAME)/description
BBF BulkData Collection
endef
define Build/Prepare
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
TARGET_CFLAGS += \
-D_GNU_SOURCE
@@ -41,4 +47,4 @@ define Package/$(PKG_NAME)/install
$(CP) ./files/* $(1)/
endef
$(eval $(call BuildPackage,$(PKG_NAME)))
$(eval $(call BuildPackage,$(PKG_NAME)))

View File

@@ -1,23 +0,0 @@
PROG = bulkdatad
LIB = libbulkdata.so
PROG_OBJS = bulkdata.o common.o config.o http.o log.o report.o times.o buci.o
LIB_OBJS = datamodel.o
PROG_CFLAGS = $(CFLAGS) -Wall -Werror -fPIC
PROG_LDFLAGS = $(LDFLAGS) -lubus -luci -lubox -ljson-c -lcurl -lblobmsg_json -lbbfdm -lbbf_api
LIB_LDFLAGS = $(LDFLAGS) -lbbf_api
%.o: %.c
$(CC) $(PROG_CFLAGS) $(FPIC) -c -o $@ $<
all: $(PROG) $(LIB)
$(PROG): $(PROG_OBJS)
$(CC) $(PROG_CFLAGS) -o $@ $^ $(PROG_LDFLAGS)
$(LIB): $(LIB_OBJS)
$(CC) $(PROG_CFLAGS) $(LIB_LDFLAGS) -shared -o $@ $^
clean:
rm -f *.o $(PROG) $(LIB)

View File

@@ -1,265 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*
*/
#include <strings.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <unistd.h>
#include <ctype.h>
#include "buci.h"
struct uci_context *uci_ctx = NULL;
int buci_init(void)
{
uci_ctx = uci_alloc_context();
if (!uci_ctx) {
return -1;
}
return 0;
}
int buci_fini(void)
{
if (uci_ctx) {
uci_free_context(uci_ctx);
}
return 0;
}
static bool buci_validate_section(const char *str)
{
if (!*str)
return false;
for (; *str; str++) {
unsigned char c = *str;
if (isalnum(c) || c == '_')
continue;
return false;
}
return true;
}
static int buci_init_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *package, char *section, char *option, char *value)
{
memset(ptr, 0, sizeof(struct uci_ptr));
/* value */
if (value) {
ptr->value = value;
}
ptr->package = package;
if (!ptr->package)
goto error;
ptr->section = section;
if (!ptr->section) {
ptr->target = UCI_TYPE_PACKAGE;
goto lastval;
}
ptr->option = option;
if (!ptr->option) {
ptr->target = UCI_TYPE_SECTION;
goto lastval;
} else {
ptr->target = UCI_TYPE_OPTION;
}
lastval:
if (ptr->section && !buci_validate_section(ptr->section))
ptr->flags |= UCI_LOOKUP_EXTENDED;
return 0;
error:
return -1;
}
struct uci_section *buci_walk_section(char *package, char *section_type, struct uci_section *prev_section)
{
struct uci_ptr ptr;
struct uci_element *e;
struct uci_section *next_section;
if (section_type == NULL) {
if (prev_section) {
e = &prev_section->e;
if (e->list.next == &prev_section->package->sections)
return NULL;
e = container_of(e->list.next, struct uci_element, list);
next_section = uci_to_section(e);
return next_section;
}
else {
if (buci_init_ptr(uci_ctx, &ptr, package, NULL, NULL, NULL)) {
return NULL;
}
if (uci_lookup_ptr(uci_ctx, &ptr, NULL, true) != UCI_OK) {
return NULL;
}
if (ptr.p->sections.next == &ptr.p->sections)
return NULL;
e = container_of(ptr.p->sections.next, struct uci_element, list);
next_section = uci_to_section(e);
return next_section;
}
}
else {
struct uci_list *ul, *shead = NULL;
if (prev_section) {
ul = &prev_section->e.list;
shead = &prev_section->package->sections;
}
else {
if (buci_init_ptr(uci_ctx, &ptr, package, NULL, NULL, NULL)) {
return NULL;
}
if (uci_lookup_ptr(uci_ctx, &ptr, NULL, true) != UCI_OK) {
return NULL;
}
ul = &ptr.p->sections;
shead = &ptr.p->sections;
}
while (ul->next != shead) {
e = container_of(ul->next, struct uci_element, list);
next_section = uci_to_section(e);
if (strcmp(next_section->type, section_type) == 0)
return next_section;
ul = ul->next;
}
return NULL;
}
return NULL;
}
void buci_print_list(struct uci_list *uh, char **val, char *delimiter)
{
struct uci_element *e;
static char buffer[512];
char *buf = buffer;
*buf = '\0';
uci_foreach_element(uh, e) {
if (*buf) {
strcat(buf, delimiter);
strcat(buf, e->name);
}
else {
strcpy(buf, e->name);
}
}
*val = buf;
}
struct uci_element *buci_lookup_list(struct uci_list *list, const char *name)
{
struct uci_element *e;
uci_foreach_element(list, e) {
if (!strcmp(e->name, name))
return e;
}
return NULL;
}
int uci_lookup_ptr_bysection(struct uci_context *ctx, struct uci_ptr *ptr, struct uci_section *section, char *option, char *value)
{
struct uci_element *e;
memset(ptr, 0, sizeof(struct uci_ptr));
ptr->package = section->package->e.name;
ptr->section = section->e.name;
ptr->option = option;
ptr->value = value;
ptr->flags |= UCI_LOOKUP_DONE;
ptr->p = section->package;
ptr->s = section;
if (ptr->option) {
e = buci_lookup_list(&ptr->s->options, ptr->option);
if (!e)
return UCI_OK;
ptr->o = uci_to_option(e);
ptr->last = e;
ptr->target = UCI_TYPE_OPTION;
}
else {
ptr->last = &ptr->s->e;
ptr->target = UCI_TYPE_SECTION;
}
ptr->flags |= UCI_LOOKUP_COMPLETE;
return UCI_OK;
}
char *buci_get_value_bysection(struct uci_section *section, char *option)
{
struct uci_ptr ptr;
char *val = "";
if (uci_lookup_ptr_bysection(uci_ctx, &ptr, section, option, NULL) != UCI_OK) {
return val;
}
if (!ptr.o)
return val;
if(ptr.o->type == UCI_TYPE_LIST) {
buci_print_list(&ptr.o->v.list, &val, " ");
return val;
}
if (ptr.o->v.string)
return ptr.o->v.string;
else
return val;
}
char *buci_get_value(char *package, char *section, char *option)
{
struct uci_ptr ptr;
char *val = "";
if (!section || !option)
return val;
if (buci_init_ptr(uci_ctx, &ptr, package, section, option, NULL)) {
return val;
}
if (uci_lookup_ptr(uci_ctx, &ptr, NULL, true) != UCI_OK) {
return val;
}
if (!ptr.o)
return val;
if(ptr.o->type == UCI_TYPE_LIST) {
buci_print_list(&ptr.o->v.list, &val, " ");
return val;
}
if (ptr.o->v.string)
return ptr.o->v.string;
else
return val;
}

View File

@@ -1,31 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*
*/
#ifndef __BUCI_H
#define __BUCI_H
#include <uci.h>
int buci_init(void);
int buci_fini(void);
struct uci_section *buci_walk_section(char *package, char *section_type, struct uci_section *prev_section);
void buci_print_list(struct uci_list *uh, char **val, char *delimiter);
struct uci_element *buci_lookup_list(struct uci_list *list, const char *name);
int uci_lookup_ptr_bysection(struct uci_context *ctx, struct uci_ptr *ptr, struct uci_section *section, char *option, char *value);
char *buci_get_value_bysection(struct uci_section *section, char *option);
char *buci_get_value(char *package, char *section, char *option);
#define buci_foreach_section(package, section_type, section) \
for (section = buci_walk_section(package, section_type, NULL); \
section != NULL; \
section = buci_walk_section(package, section_type, section))
#endif //__BUCI_H

View File

@@ -1,144 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
* Omar Kallel <omar.kallel@pivasoftware.com>
*/
#include <stdio.h>
#include <string.h>
#include <libubox/uloop.h>
#include "http.h"
#include "config.h"
#include "log.h"
#include "common.h"
#include "report.h"
#include "times.h"
#include "bulkdata.h"
struct bulkdata bulkdata_main = {0};
int profiles_number = 0;
void bulkdata_profile_cb(struct uloop_timeout *timeout);
int get_retry_period(int min)
{
srand(time(NULL));
return rand()%min + min;
}
static void bulkdata_run_profiles(struct bulkdata *bulkdata)
{
unsigned int next_period;
int i = 0;
for (i = 0; i < profiles_number; i++) {
bulkdata->profile[i].utimer.cb = bulkdata_profile_cb;
LIST_HEAD(failedreports);
bulkdata->profile[i].failed_reports = &failedreports;
next_period = get_next_period(bulkdata->profile[i].time_reference, bulkdata->profile[i].reporting_interval);
bulkdata_log(SINFO, "The session of profile_id %d will be start in %d sec", bulkdata->profile[i].profile_id, next_period);
uloop_timeout_set(&bulkdata->profile[i].utimer, next_period * 1000);
}
}
int http_send_report(struct profile *profile, char *report)
{
char *msg_in = NULL;
int http_code;
http_client_init(profile);
bulkdata_log(SINFO, "Send the report of profile_id %d to Bulkdata Collector", profile->profile_id);
http_code = http_send_message(profile, report, strlen(report), &msg_in);
http_client_exit();
return http_code;
}
void bulkdata_profile_cb(struct uloop_timeout *timeout)
{
struct profile *profile;
unsigned int http_code, retry_period;
char *report = NULL;
profile = container_of(timeout, struct profile, utimer);
time_t now = time(NULL);
bulkdata_log(SINFO, "New session of profile_id %d started", profile->profile_id);
if(profile->retry_count == 0 || profile->next_retry > now || !profile->http_retry_enable) //Perdiodic execution
create_encoding_bulkdata_report(profile, &report);
else
create_failed_report(profile, &report);
bulkdata_log(SDEBUG, "The content of the profile_id report %d is :\n==========\n%s\n==========\n", profile->profile_id, report);
http_code= http_send_report(profile, report);
if(http_code != 200){
if(profile->retry_count == 0 || profile->next_retry > now || !profile->http_retry_enable) { //Perdiodic execution
retry_period = get_retry_period(profile->http_retry_minimum_wait_interval);
profile->next_period = now + profile->reporting_interval;
profile->next_retry = now + retry_period;
profile->retry_count = 1;
profile->min_retry = profile->http_retry_minimum_wait_interval * 2;
if((profile->next_retry < profile->next_period) && profile->http_retry_enable) {
bulkdata_log(SINFO, "Retry session of profile_id %d in %d sec", profile->profile_id, retry_period);
uloop_timeout_set(timeout, 1000 * retry_period);
}
else {
bulkdata_log(SINFO, "Start New session of profile_id %d in %d sec", profile->profile_id, profile->reporting_interval);
uloop_timeout_set(timeout, 1000 * profile->reporting_interval);
}
} else { //Retry execution
retry_period= get_retry_period(profile->min_retry);
profile->min_retry*=2;
profile->next_retry+=retry_period;
profile->retry_count++;
if(profile->next_retry < profile->next_period) {
bulkdata_log(SINFO, "Retry session of profile_id %d in %d sec", profile->profile_id, retry_period);
uloop_timeout_set(timeout, 1000 * retry_period);
}
else {
bulkdata_log(SINFO, "Retry session of profile_id %d in %d sec", profile->profile_id, (profile->next_period-profile->next_retry+retry_period));
uloop_timeout_set(timeout, 1000 * (profile->next_period-profile->next_retry+retry_period));
}
}
if(profile->new_report){
bulkdata_add_failed_report(profile, profile->new_report);
FREE(profile->new_report);
}
FREE(report);
} else {
if(profile->retry_count == 0 || profile->next_retry > now || !profile->http_retry_enable) {
bulkdata_log(SINFO, "Start New session of profile_id %d in %d sec", profile->profile_id, profile->reporting_interval);
uloop_timeout_set(timeout, 1000 * profile->reporting_interval);
}
else {
bulkdata_log(SINFO, "Retry session of profile_id %d in %d sec", profile->profile_id, (profile->next_period-profile->next_retry));
uloop_timeout_set(timeout, 1000 * (profile->next_period-profile->next_retry));
}
FREE(profile->new_report);
FREE(report);
empty_failed_reports_list(profile);
profile->retry_count= 0;
}
}
int main(void)
{
struct bulkdata *bulkdata = &bulkdata_main;
if (bulkdata_config_init(bulkdata) == -1)
return -1;
bulkdata_log(SINFO, "Start bulkdatad daemon");
uloop_init();
bulkdata_run_profiles(bulkdata);
uloop_run();
uloop_done();
bulkdata_config_fini(bulkdata);
bulkdata_log(SINFO, "Stop bulkdatad daemon");
return 0;
}

View File

@@ -1,18 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*
*/
#ifndef __BULKDATA_H
#define __BULKDATA_H
extern struct bulkdata bulkdata_main;
extern int profiles_number;
#endif /* __BULKDATA_H */

View File

@@ -1,105 +0,0 @@
# README #
bulkdatad is an implementation of The HTTP bulk data collection mechanism which is an extended feature of CPE and other agents implementing TR-069(CWMP) or TR-369(USP), defined by the Broadband Forum. It provides a means by which an Auto-Configuration Server (ACS), or USP Controller, can configure an agent to periodically send a JSON or CSV formatted set of Device information to an HTTP server running a data collection application.
## Configuration File ##
The bulkdatad UCI configuration is located in **'/etc/config/bulkdata'**, and contains 4 sections: **bulkdata**, **profile**, **profile\_parameter** and **profile\_http\_request\_uri\_parameter**.
```
config bulkdata 'bulkdata'
option enable '0'
option log_level '3'
config profile
option profile_id '1'
option enable '0'
option csv_encoding_row_time_stamp 'unix'
option json_encoding_report_time_stamp 'unix'
option http_retry_minimum_wait_interval '5'
option http_retry_interval_multiplier '2000'
config profile_parameter
option profile_id '1'
option name ''
option reference ''
config profile_http_request_uri_parameter
option profile_id '1'
option name ''
option reference ''
```
### bulkdata section ###
It defines **bulkdata configuration**: enable and log\_level.
| Name | Type | Description |
| ----------- | ------- | ----------------------------------------------------------------------------------------------- |
| `enable` | boolean | Enables the BulkData feature if set to **1**. |
| `log_level` | integer | Specifies the log type to use, by default **'INFO'**. The possible types are **'EMERG', 'ALERT', 'CRITIC' ,'ERROR', 'WARNING', 'NOTICE', 'INFO' and 'DEBUG'**. |
### profile section ###
It defines **the profile section configuration**: enable, name,... The possible options for **profile** section are listed below:
| Name | Type | Description |
| ---------------------------------- | ------- | ---------------------------------------------- |
| `profile_id` | integer | The profile id to use. |
| `enable` | boolean | If set to **1**, enables the bulkdata profile. |
| `name` | string | The name of the profile. |
| `nbre_of_retained_failed_reports` | integer | The number of failed reports to be retained and transmitted at the end of the current reporting interval. |
| `protocol` | string | The protocol used for the collection profile. |
| `encoding_type` | string | The encoding type used for the collection profile. |
| `reporting_interval` | integer | The reporting interval in seconds. |
| `time_reference` | integer | The time reference to determine when the profile will be transmitted to the ACS collector. |
| `csv_encoding_field_separator` | string | The field separator to use when encoding CSV data. |
| `csv_encoding_row_separator` | string | The row separator to use when encoding CSV data. |
| `csv_encoding_escape_character` | string | The escape character to use when encoding CSV data. |
| `csv_encoding_report_format` | string | Describes how reports will be formatted. Two possible formats are supported: **'ParameterPerRow' and 'ParameterPerColumn'**. |
| `csv_encoding_row_time_stamp` | string | The format of the timestamp to use for data inserted into the row. The row time stamp supported are **'Unix-Epoch', 'ISO-8601' and 'None'**. |
| `json_encoding_report_format` | string | Describes the report format. The supported report formats are **'ObjectHierarchy' and 'NameValuePair'**. |
| `json_encoding_report_time_stamp` | string | The format of the timestamp to use for the JSON Object named "CollectionTime". The supported timestamp are **'Unix-Epoch', 'ISO-8601' and 'None'**. |
| `http_url` | string | The URL of the collection server. |
| `http_username` | string | The username of the collection server. |
| `http_password` | string | The password of the collection server. |
| `http_compression` | string | The HTTP Compression mechanism used by the collection server. The supported compression mechanism are **'GZIP', 'Compress' and 'Deflate'**. |
| `http_method` | string | The HTTP method used by the collection server. Two methods are supported: **'POST' and 'PUT'**. |
| `http_use_date_header` | boolean | If set to **1**, the CPE encodes the HTTP Date Header. |
| `http_retry_enable` | boolean | If set to **1**, the CPE retries unsuccessful attempts to transfer data. |
| `http_retry_minimum_wait_interval` | integer | The data transfer retry wait interval. |
| `http_retry_interval_multiplier` | integer | The retry interval multiplier. |
| `http_persist_across_reboot` | boolean | If set to **1**, failed data transfers must be persisted across reboots. |
### profile_parameter section ###
It defines **the profile\_parameter section configuration**: profile\_id, name, reference.
| Name | Type | Description |
| ------------ | ------- | --------------------------------------- |
| `profile_id` | integer | The id of the used profile. |
| `name` | string | The name of the profile parameter. |
| `reference` | string | The reference of the profile parameter. |
### profile_http_request_uri_parameter section ###
It defines **the profile\_http\_request\_uri\_parameter section configuration**: profile\_id, name, reference.
| Name | Type | Description |
| ------------ | ------- | --------------------------------------- |
| `profile_id` | integer | The id of the used profile. |
| `name` | string | The name of the Request-URI parameter. |
| `reference` | string | The reference of the profile parameter. |
## Dependencies ##
To successfully build bulkdatad, the following libraries are needed:
| Dependency | Link | License |
| ----------- | ------------------------------------------- | -------------- |
| libuci | https://git.openwrt.org/project/uci.git | LGPL 2.1 |
| libubox | https://git.openwrt.org/project/libubox.git | BSD |
| libjson-c | https://s3.amazonaws.com/json-c_releases | MIT |
| libcurl | https://dl.uxnr.de/mirror/curl | MIT |
| libbbfdm | https://dev.iopsys.eu/iopsys/bbf.git | LGPL 2.1 |

View File

@@ -1,450 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
* Omar Kallel <omar.kallel@pivasoftware.com>
*/
#include "common.h"
static pathnode *head = NULL;
static pathnode *temphead = NULL;
int bulkdata_dm_ctx_init(struct dmctx *ctx)
{
struct bulkdata *bulkdata = &bulkdata_main;
dm_ctx_init(ctx, bulkdata->instance_mode);
return 0;
}
int bulkdata_dm_ctx_clean(struct dmctx *ctx)
{
dm_ctx_clean(ctx);
return 0;
}
static char **str_split(const char* str, const char* delim, size_t* numtokens)
{
char *s = strdup(str);
size_t tokens_alloc = 1;
size_t tokens_used = 0;
char **tokens = calloc(tokens_alloc, sizeof(char*));
char *token, *strtok_ctx;
for (token = strtok_r(s, delim, &strtok_ctx); token != NULL; token = strtok_r(NULL, delim, &strtok_ctx)) {
if (tokens_used == tokens_alloc) {
tokens_alloc *= 2;
tokens = realloc(tokens, tokens_alloc * sizeof(char*));
}
tokens[tokens_used++] = strdup(token);
}
// cleanup
if (tokens_used == 0) {
FREE(tokens);
} else {
tokens = realloc(tokens, tokens_used * sizeof(char*));
}
*numtokens = tokens_used;
FREE(s);
return tokens;
}
static bool bulkdata_match(const char *string, const char *pattern)
{
regex_t re;
if (regcomp(&re, pattern, REG_EXTENDED) != 0) return 0;
int status = regexec(&re, string, 0, NULL, 0);
regfree(&re);
if (status != 0) return false;
return true;
}
static bool is_res_required(char *str, int *start, int *len)
{
char temp_char[NAME_MAX] = {'\0'};
if (bulkdata_match(str, GLOB_CHAR)) {
int s_len = strlen(str);
int b_len = s_len, p_len = s_len;
char *star = strchr(str, '*');
if(star)
s_len = star - str;
*start = MIN(MIN(s_len, p_len), b_len);
if (*start == s_len)
*len = 1;
strncpy(temp_char, str+*start, *len);
if (bulkdata_match(temp_char, "[*+]+"))
return true;
}
*start = strlen(str);
return false;
}
static void insert(char *data, bool active)
{
pathnode *link = (pathnode*) calloc(1, sizeof(pathnode));
if(!link) {
return;
}
link->ref_path = data;
if(active) {
link->next = head;
head = link;
} else {
link->next = temphead;
temphead = link;
}
}
static void swap_heads(void)
{
pathnode *temp = head;
head = temphead;
temphead = temp;
}
static void deleteList(void)
{
pathnode *ptr = head, *temp;
while(ptr != NULL) {
temp = ptr;
free(ptr->ref_path);
if(ptr->next != NULL) {
ptr = ptr->next;
} else {
ptr = NULL;
}
free(temp);
}
head = NULL;
swap_heads();
}
void bulkdata_add_data_to_list(struct list_head *dup_list, char *name, char *value, char *type)
{
struct resultsnode *link;
link = calloc(1, sizeof(struct resultsnode));
list_add_tail(&link->list, dup_list);
link->name = strdup(name);
link->data = strdup(value);
link->type = strdup(type);
}
void bulkdata_delete_data_from_list(struct resultsnode *link)
{
list_del(&link->list);
FREE(link->name);
FREE(link->data);
FREE(link->type);
FREE(link);
}
void bulkdata_free_data_from_list(struct list_head *dup_list)
{
struct resultsnode *link;
while (dup_list->next != dup_list) {
link = list_entry(dup_list->next, struct resultsnode, list);
bulkdata_delete_data_from_list(link);
}
}
static bool bulkdata_get(int operation, char *path, struct dmctx *dm_ctx)
{
int fault = 0;
switch(operation) {
case CMD_GET_NAME:
fault = dm_entry_param_method(dm_ctx, CMD_GET_NAME, path, "true", NULL);
break;
case CMD_GET_VALUE:
fault = dm_entry_param_method(dm_ctx, CMD_GET_VALUE, path, NULL, NULL);
break;
default:
return false;
}
if (dm_ctx->list_fault_param.next != &dm_ctx->list_fault_param) {
return false;
}
if (fault) {
return false;
}
return true;
}
char *bulkdata_get_value_param(char *path)
{
struct dmctx ctx = {0};
struct dm_parameter *n;
char *value = NULL;
bulkdata_dm_ctx_init(&ctx);
if(bulkdata_get(CMD_GET_VALUE, path, &ctx)) {
list_for_each_entry(n, &ctx.list_parameter, list) {
value = strdup(n->data);
break;
}
}
bulkdata_dm_ctx_clean(&ctx);
return value;
}
void bulkdata_get_value(char *path, struct list_head *list)
{
struct dmctx ctx = {0};
struct dm_parameter *n;
bulkdata_dm_ctx_init(&ctx);
if(bulkdata_get(CMD_GET_VALUE, path, &ctx)) {
list_for_each_entry(n, &ctx.list_parameter, list) {
bulkdata_add_data_to_list(list, n->name, n->data, n->type);
}
}
bulkdata_dm_ctx_clean(&ctx);
}
bool bulkdata_get_name(char *path)
{
struct dmctx ctx = {0};
struct dm_parameter *n;
bool ret = false;
bulkdata_dm_ctx_init(&ctx);
if(bulkdata_get(CMD_GET_NAME, path, &ctx)) {
list_for_each_entry(n, &ctx.list_parameter, list) {
insert(strdup(n->name), false);
}
ret = true;
}
bulkdata_dm_ctx_clean(&ctx);
return ret;
}
static void fill_node_path(void)
{
pathnode *p=head;
while(p!=NULL) {
bulkdata_get_name(p->ref_path);
p=p->next;
}
deleteList();
}
static void bulkdata_filter_results(char *path, int start, int end)
{
int startpos = start, m_index = 0, m_len = 0;
char *pp = path + startpos;
char exp[NAME_MAX] = {'\0'};
if(start >= end) {
return;
}
if(!is_res_required(pp, &m_index, &m_len)) {
//append rest of the path to the final list
if(pp == path ) {
insert(strdup(pp), true);
return;
}
pathnode *p = head;
while(p != NULL) {
char name[NAME_MAX] = {'\0'};
strcpy(name, p->ref_path);
strcat(name, pp);
insert(strdup(name), false);
p = p->next;
}
deleteList();
return;
}
// Get the string before the match
char name[NAME_MAX]={'\0'};
strncpy(name, pp, m_index);
pathnode *p = head;
if(p == NULL) {
insert(strdup(name), false);
}
while(p != NULL) {
char ref_name[NAME_MAX] = {'\0'};
sprintf(ref_name, "%s%s", p->ref_path, name);
insert(strdup(ref_name), false);
p = p->next;
}
deleteList();
startpos += m_index;
strncpy(exp, pp+m_index, m_len);
pp = path + startpos;
fill_node_path();
startpos += 2;
bulkdata_filter_results(path, startpos, end);
}
static void bulkdata_parse_results(struct list_head *list)
{
pathnode *p = head;
while(p != NULL) {
bulkdata_get_value(p->ref_path, list);
p = p->next;
}
deleteList();
}
void bulkdata_get_value_results(char *path, struct list_head *list)
{
bulkdata_filter_results(path, 0, strlen(path));
bulkdata_parse_results(list);
}
char *create_request_url(struct profile *profile)
{
int i = 0, http_uri_number = profile->profile_http_request_uri_parameter_number;
char *value, *uri_param = NULL, *uri_tmp = NULL, *http_url = NULL;
for (i = 0; i < http_uri_number; i++)
{
if((profile->profile_http_uri_parameter[i].reference == NULL) || (profile->profile_http_uri_parameter[i].name == NULL))
continue;
value = bulkdata_get_value_param(profile->profile_http_uri_parameter[i].reference);
if(!uri_param) {
asprintf(&uri_param, "&%s=%s", profile->profile_http_uri_parameter[i].name, value);
free(value);
}
else {
uri_tmp = strdup(uri_param);
free(uri_param);
asprintf(&uri_param, "%s&%s=%s", uri_tmp, profile->profile_http_uri_parameter[i].name, value);
free(value);
free(uri_tmp);
}
}
if(uri_param) {
asprintf(&http_url, "%s%s", profile->http_url, uri_param);
free(uri_param);
} else {
asprintf(&http_url, "%s", profile->http_url);
}
return http_url;
}
char *get_bulkdata_profile_parameter_name(char *paramref, char *paramname, char *param)
{
char **paramarr, *idx1 = NULL, *idx2 = NULL, *res = NULL, *instance = NULL, *tmp = NULL, *retparam = NULL, *s = NULL;
int i, j = 0;
size_t length;
if(paramname == NULL || strlen(paramname) <= 0)
return strdup(param);
paramarr = str_split(paramref, "*", &length);
res = strdup(paramname);
for(i = 0; i < length; i++) {
if(i == length - 1)
break;
j++;
idx1 = strstr(param, paramarr[i]);
idx2 = strstr(param, paramarr[i+1]);
instance = (char*)calloc(idx2 - idx1 - strlen(paramarr[i]) + 1, sizeof(char));
memcpy(instance, idx1 + strlen(paramarr[i]), idx2 - idx1 - strlen(paramarr[i]));
tmp = strdup(res);
FREE(res);
asprintf(&res, "%s.%s", tmp, instance);
FREE(tmp);
FREE(instance);
}
if ((s = strstr(param,paramarr[j]) ) != NULL && strlen(s) == strlen(paramarr[j]))
asprintf(&retparam, "%s", res);
else
asprintf(&retparam, "%s.%s", res, strstr(param, paramarr[j]) + strlen(paramarr[j]));
FREE(res);
for(int k = 0; k < length; k++)
FREE(paramarr[k]);
FREE(paramarr);
return retparam;
}
void append_string_to_string(char *strappend, char **target)
{
char *tmp = NULL;
if(strappend == NULL || strlen(strappend) <= 0)
return;
if(*target == NULL || strlen(*target) <= 0) {
*target = strdup(strappend);
return;
} else {
tmp = strdup(*target);
FREE(*target);
}
asprintf(target, "%s%s", tmp, strappend);
FREE(tmp);
}
void bulkdata_add_failed_report(struct profile *profile, char *freport)
{
struct failed_reports *report, *retreport, *rtmp;
if(profile->nbre_failed_reports < profile->nbre_of_retained_failed_reports || profile->nbre_of_retained_failed_reports < 0) {
profile->nbre_failed_reports++;
} else {
list_for_each_entry_safe(retreport, rtmp, profile->failed_reports, list) {
bulkdata_delete_failed_report(retreport);
break;
}
}
report = calloc(1, sizeof(struct failed_reports));
list_add_tail(&report->list, profile->failed_reports);
report->freport= strdup(freport);
}
void bulkdata_delete_failed_report(struct failed_reports *report)
{
if(report != NULL) {
list_del(&report->list);
FREE(report->freport);
FREE(report);
}
}
struct failed_reports* empty_failed_reports_list(struct profile *profile)
{
struct failed_reports *report, *rtmp;
if(list_empty(profile->failed_reports))
return NULL;
list_for_each_entry_safe(report, rtmp, profile->failed_reports, list) {
list_del(&report->list);
FREE(report->freport);
FREE(report);
}
return NULL;
}
void add_failed_reports_to_report_csv(struct profile *profile, char **report, int isnext)
{
struct failed_reports *retreport = NULL;
int j = 0;
if(list_empty(profile->failed_reports))
return;
list_for_each_entry(retreport, profile->failed_reports, list) {
if(!j && isnext) {
j = 1;
continue;
}
append_string_to_string(retreport->freport, report);
}
}

View File

@@ -1,69 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*
*/
#ifndef __COMMON_H
#define __COMMON_H
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <regex.h>
#include <sys/param.h>
#include <libubox/blobmsg.h>
#include <libubox/blobmsg_json.h>
#include <libubox/utils.h>
#include <libubus.h>
#include <libbbfdm/dmentry.h>
#include <libbbfdm/dmbbfcommon.h>
#include "config.h"
#include "log.h"
#include "bulkdata.h"
typedef struct pathnode {
char *ref_path;
struct pathnode *next;
} pathnode;
typedef struct resultsnode {
struct list_head list;
char *name;
char *data;
char *type;
} resultsnode;
struct failed_reports {
struct list_head list;
char *freport;
};
#define GLOB_CHAR "[[+*]+"
int bulkdata_dm_ctx_init(struct dmctx *ctx);
int bulkdata_dm_ctx_clean(struct dmctx *ctx);
char *bulkdata_get_value_param(char *path);
void bulkdata_get_value(char *path, struct list_head *list);
void bulkdata_free_data_from_list(struct list_head *dup_list);
void bulkdata_get_value_results(char *path, struct list_head *list);
char *create_request_url(struct profile *profile);
char *get_bulkdata_profile_parameter_name(char *paramref, char *paramname, char *param);
void append_string_to_string(char *strappend, char **target);
void bulkdata_add_failed_report(struct profile *profile, char *freport);
void bulkdata_delete_failed_report(struct failed_reports *report);
struct failed_reports *empty_failed_reports_list(struct profile *profile);
void add_failed_reports_to_report_csv(struct profile *profile, char **report, int isnext);
#endif //__COMMON_H

View File

@@ -1,523 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
* Omar Kallel <omar.kallel@pivasoftware.com>
*/
#include <stdio.h>
#include <strings.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include "log.h"
#include "config.h"
#include "buci.h"
#include "common.h"
#include "bulkdata.h"
int get_log_level_config(struct bulkdata *bulkdata)
{
char *value = NULL;
buci_init();
value = buci_get_value("bulkdata", "bulkdata", "log_level");
if(value != NULL && *value != '\0')
bulkdata->log_level = atoi(value);
else
bulkdata->log_level = DEFAULT_LOGLEVEL;
bulkdata_log(SDEBUG,"Log Level of Bulkdata is : %d", bulkdata->log_level);
buci_fini();
return 0;
}
int get_amd_version_config(struct bulkdata *bulkdata)
{
char *value = NULL;
buci_init();
value = buci_get_value("cwmp", "cpe", "amd_version");
if(value != NULL && *value != '\0')
bulkdata->amd_version = atoi(value);
else
bulkdata->amd_version = DEFAULT_AMD_VERSION;
bulkdata_log(SDEBUG,"CWMP Amendment Version is : %d", bulkdata->amd_version);
buci_fini();
return 0;
}
int get_instance_mode_config(struct bulkdata *bulkdata)
{
char *value = NULL;
buci_init();
value = buci_get_value("cwmp", "cpe", "instance_mode");
if(value != NULL && *value != '\0') {
if(!strcmp(value, "InstanceNumber"))
bulkdata->instance_mode = INSTANCE_MODE_NUMBER;
else
bulkdata->instance_mode = INSTANCE_MODE_ALIAS;
}
else
bulkdata->instance_mode = DEFAULT_INSTANCE_MODE;
bulkdata_log(SDEBUG,"CWMP Instance Mode is : %d", bulkdata->instance_mode);
buci_fini();
return 0;
}
int get_device_id_config(struct bulkdata *bulkdata)
{
struct dmctx dmctx = {0};
bulkdata_dm_ctx_init(&dmctx);
bulkdata->device_id.manufacturer_oui = bulkdata_get_value_param("Device.DeviceInfo.ManufacturerOUI");
bulkdata->device_id.product_class = bulkdata_get_value_param("Device.DeviceInfo.ProductClass");
bulkdata->device_id.serial_number = bulkdata_get_value_param("Device.DeviceInfo.SerialNumber");
bulkdata_dm_ctx_clean(&dmctx);
return 0;
}
int load_profile_config(struct bulkdata *bulkdata, struct uci_section *s, int i)
{
char *value = NULL;
value = buci_get_value_bysection(s, "profile_id");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].profile_id = atoi(value);
value = NULL;
bulkdata_log(SDEBUG,"The profile_id of profile_id %d is : %d", i, bulkdata->profile[i].profile_id);
} else
return -1;
value = buci_get_value_bysection(s, "nbre_of_retained_failed_reports");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].nbre_of_retained_failed_reports = atoi(value);
value = NULL;
bulkdata_log(SDEBUG,"The nombre of retained failed reports of profile_id %d is : %d", bulkdata->profile[i].profile_id, bulkdata->profile[i].nbre_of_retained_failed_reports);
}
value = buci_get_value_bysection(s, "protocol");
if(value != NULL && *value != '\0' && strcasecmp(value, "http")==0) {
bulkdata->profile[i].protocol = strdup(value);
value = NULL;
bulkdata_log(SDEBUG,"The protocol of profile_id %d is : %s", bulkdata->profile[i].profile_id, bulkdata->profile[i].protocol);
} else
return -1;
value = buci_get_value_bysection(s, "encoding_type");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].encoding_type = strdup(value);
value = NULL;
bulkdata_log(SDEBUG,"The encoding type of profile_id %d is : %s", bulkdata->profile[i].profile_id, bulkdata->profile[i].encoding_type);
} else
return -1;
value = buci_get_value_bysection(s, "reporting_interval");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].reporting_interval = atoi(value);
value = NULL;
bulkdata_log(SDEBUG,"The reporting interval of profile_id %d is : %d", bulkdata->profile[i].profile_id, bulkdata->profile[i].reporting_interval);
} else
return -1;
value = buci_get_value_bysection(s, "time_reference");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].time_reference = atoi(value);
value = NULL;
bulkdata_log(SDEBUG,"The time reference of profile_id %d is : %ld", bulkdata->profile[i].profile_id, bulkdata->profile[i].time_reference);
} else
return -1;
value = buci_get_value_bysection(s, "csv_encoding_field_separator");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].csv_encoding_field_separator = strdup(value);
value = NULL;
bulkdata_log(SDEBUG,"The csv encoding field separator of profile_id %d is : %s", bulkdata->profile[i].profile_id, bulkdata->profile[i].csv_encoding_field_separator);
} else
return -1;
value = buci_get_value_bysection(s, "csv_encoding_row_separator");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].csv_encoding_row_separator = strdup(value);
value = NULL;
bulkdata_log(SDEBUG,"The csv encoding row separator of profile_id %d is : %s", bulkdata->profile[i].profile_id, bulkdata->profile[i].csv_encoding_row_separator);
} else
return -1;
value = buci_get_value_bysection(s, "csv_encoding_escape_character");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].csv_encoding_escape_character = strdup(value);
value = NULL;
bulkdata_log(SDEBUG,"The csv encoding escape character of profile_id %d is : %s", bulkdata->profile[i].profile_id, bulkdata->profile[i].csv_encoding_escape_character);
}
value = buci_get_value_bysection(s, "csv_encoding_report_format");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].csv_encoding_report_format = strdup(value);
value = NULL;
bulkdata_log(SDEBUG,"The csv encoding report format of profile_id %d is : %s", bulkdata->profile[i].profile_id, bulkdata->profile[i].csv_encoding_report_format);
} else
return -1;
value = buci_get_value_bysection(s, "csv_encoding_row_time_stamp");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].csv_encoding_row_time_stamp = strdup(value);
value = NULL;
bulkdata_log(SDEBUG,"The csv encoding row time stamp of profile_id %d is : %s", bulkdata->profile[i].profile_id, bulkdata->profile[i].csv_encoding_row_time_stamp);
} else
return -1;
value = buci_get_value_bysection(s, "json_encoding_report_format");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].json_encoding_report_format = strdup(value);
value = NULL;
bulkdata_log(SDEBUG,"The json encoding report format of profile_id %d is : %s", bulkdata->profile[i].profile_id, bulkdata->profile[i].json_encoding_report_format);
} else
return -1;
value = buci_get_value_bysection(s, "json_encoding_report_time_stamp");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].json_encoding_report_time_stamp = strdup(value);
value = NULL;
bulkdata_log(SDEBUG,"The json encoding report time stamp of profile_id %d is : %s", bulkdata->profile[i].profile_id, bulkdata->profile[i].json_encoding_report_time_stamp);
} else
return -1;
value = buci_get_value_bysection(s, "http_url");
if(value != NULL && *value != '\0') {
char *url = NULL;
asprintf(&url, "%s?oui=%s&pc=%s&sn=%s", value, bulkdata->device_id.manufacturer_oui, bulkdata->device_id.serial_number, bulkdata->device_id.serial_number);
bulkdata->profile[i].http_url = strdup(url);
free(url);
value = NULL;
bulkdata_log(SDEBUG,"The HTTP url of profile_id %d is : %s", bulkdata->profile[i].profile_id, bulkdata->profile[i].http_url);
} else
return -1;
value = buci_get_value_bysection(s, "http_username");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].http_username = strdup(value);
value = NULL;
bulkdata_log(SDEBUG,"The HTTP username of profile_id %d is : %s", bulkdata->profile[i].profile_id, bulkdata->profile[i].http_username);
} else {
bulkdata->profile[i].http_username = NULL;
}
value = buci_get_value_bysection(s, "http_password");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].http_password = strdup(value);
value = NULL;
bulkdata_log(SDEBUG,"The HTTP password of profile_id %d is : %s", bulkdata->profile[i].profile_id, bulkdata->profile[i].http_password);
} else {
bulkdata->profile[i].http_password = NULL;
}
value = buci_get_value_bysection(s, "http_compression");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].http_compression = strdup(value);
value = NULL;
bulkdata_log(SDEBUG,"The HTTP compression of profile_id %d is : %s", bulkdata->profile[i].profile_id, bulkdata->profile[i].http_compression);
} else
return -1;
value = buci_get_value_bysection(s, "http_method");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].http_method = strdup(value);
value = NULL;
bulkdata_log(SDEBUG,"The HTTP method of profile_id %d is : %s", bulkdata->profile[i].profile_id, bulkdata->profile[i].http_method);
} else
return -1;
value = buci_get_value_bysection(s, "http_use_date_header");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].http_use_date_header = atoi(value);
value = NULL;
bulkdata_log(SDEBUG,"The HTTP use date header of profile_id %d is : %d", bulkdata->profile[i].profile_id, bulkdata->profile[i].http_use_date_header);
}
value = buci_get_value_bysection(s, "http_retry_enable");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].http_retry_enable = atoi(value);
value = NULL;
bulkdata_log(SDEBUG,"The HTTP retry enable of profile_id %d is : %d", bulkdata->profile[i].profile_id, bulkdata->profile[i].http_retry_enable);
} else
return -1;
value = buci_get_value_bysection(s, "http_retry_minimum_wait_interval");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].http_retry_minimum_wait_interval = atoi(value);
value = NULL;
bulkdata_log(SDEBUG,"The HTTP retry minimum wait interval of profile_id %d is : %d", bulkdata->profile[i].profile_id, bulkdata->profile[i].http_retry_minimum_wait_interval);
}
value = buci_get_value_bysection(s, "http_retry_interval_multiplier");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].http_retry_interval_multiplier = atoi(value);
value = NULL;
bulkdata_log(SDEBUG,"The HTTP retry interval multiplier of profile_id %d is : %d", bulkdata->profile[i].profile_id, bulkdata->profile[i].http_retry_interval_multiplier);
}
value = buci_get_value_bysection(s, "http_persist_across_reboot");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].http_persist_across_reboot = atoi(value);
value = NULL;
bulkdata_log(SDEBUG,"The HTTP persist across reboot of profile_id %d is : %d", bulkdata->profile[i].profile_id, bulkdata->profile[i].http_persist_across_reboot);
} else
return -1;
value = buci_get_value_bysection(s, "http_ssl_capath");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].http_ssl_capath = strdup(value);
value = NULL;
bulkdata_log(SDEBUG,"The HTTP ssl capath of profile_id %d is : %s", bulkdata->profile[i].profile_id, bulkdata->profile[i].http_ssl_capath);
} else {
bulkdata->profile[i].http_ssl_capath = NULL;
}
value = buci_get_value_bysection(s, "http_insecure_enable");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].http_insecure_enable = atoi(value);
value = NULL;
bulkdata_log(SDEBUG,"The HTTP insecure enable of profile_id %d is : %d", bulkdata->profile[i].profile_id, bulkdata->profile[i].http_insecure_enable);
}
bulkdata->profile[i].retry_count = 0;
bulkdata->profile[i].nbre_failed_reports = 0;
return 0;
}
int get_profiles_enable(struct bulkdata *bulkdata)
{
struct uci_section *s;
char *enable;
int i = 0, nbr_profiles = 0;
buci_init();
buci_foreach_section("bulkdata", "profile", s) {
enable = buci_get_value_bysection(s, "enable");
if(strcmp(enable, "1") == 0) {
nbr_profiles++;
}
}
if(nbr_profiles != 0)
bulkdata->profile = calloc(2, sizeof(struct profile));
buci_foreach_section("bulkdata", "profile", s) {
enable = buci_get_value_bysection(s, "enable");
if(strcmp(enable, "1") == 0) {
if(load_profile_config(bulkdata, s, i) == -1) {
bulkdata_log(SCRIT,"Not able to start bulkdata: some required bulkdata configurations in profile must be set");
return -1;
}
i++;
}
}
profiles_number = nbr_profiles;
buci_fini();
return 0;
}
int load_profile_parameter_config(struct bulkdata *bulkdata, struct uci_section *s, int i, int j)
{
char *value = NULL;
value = buci_get_value_bysection(s, "name");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].profile_parameter[j].name = strdup(value);
value = NULL;
bulkdata_log(SDEBUG,"The parameter name %d of profile_id %d is : %s", j+1, bulkdata->profile[i].profile_id, bulkdata->profile[i].profile_parameter[j].name);
} else {
bulkdata->profile[i].profile_parameter[j].name = NULL;
}
value = buci_get_value_bysection(s, "reference");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].profile_parameter[j].reference = strdup(value);
value = NULL;
bulkdata_log(SDEBUG,"The parameter reference %d of profile_id %d is : %s", j+1, bulkdata->profile[i].profile_id, bulkdata->profile[i].profile_parameter[j].reference);
} else
return -1;
return 0;
}
int get_profiles_parameters(struct bulkdata *bulkdata)
{
struct uci_section *s;
char *profile_id;
int i, j, nbr_profile_parameters;
buci_init();
for (i = 0; i < profiles_number; i++) {
j = 0;
nbr_profile_parameters = 0;
buci_foreach_section("bulkdata", "profile_parameter", s) {
profile_id = buci_get_value_bysection(s, "profile_id");
if(bulkdata->profile[i].profile_id != atoi(profile_id))
continue;
nbr_profile_parameters++;
if(nbr_profile_parameters == 1) {
bulkdata->profile[i].profile_parameter = calloc(1, sizeof(struct profile_parameter));
} else {
bulkdata->profile[i].profile_parameter = realloc(bulkdata->profile[i].profile_parameter, nbr_profile_parameters * sizeof(struct profile_parameter));
}
if(load_profile_parameter_config(bulkdata, s, i, j) == -1) {
bulkdata_log(SCRIT,"Not able to start bulkdata: some required bulkdata configurations in profile_parameter must be set");
return -1;
}
j++;
}
bulkdata->profile[i].profile_parameter_number = nbr_profile_parameters;
}
buci_fini();
return 0;
}
int load_profile_http_request_uri_parameter_config(struct bulkdata *bulkdata, struct uci_section *s, int i, int j)
{
char *value = NULL;
value = buci_get_value_bysection(s, "name");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].profile_http_uri_parameter[j].name = strdup(value);
value = NULL;
bulkdata_log(SDEBUG,"The HTTP resuest URI parameter name %d of profile_id %d is : %s", j+1, bulkdata->profile[i].profile_id, bulkdata->profile[i].profile_http_uri_parameter[j].name);
} else
return -1;
value = buci_get_value_bysection(s, "reference");
if(value != NULL && *value != '\0') {
bulkdata->profile[i].profile_http_uri_parameter[j].reference = strdup(value);
value = NULL;
bulkdata_log(SDEBUG,"The HTTP resuest URI parameter reference %d of profile_id %d is : %s", j+1, bulkdata->profile[i].profile_id, bulkdata->profile[i].profile_http_uri_parameter[j].reference);
} else
return -1;
return 0;
}
int get_profile_http_request_uri_parameter(struct bulkdata *bulkdata)
{
struct uci_section *s;
char *profile_id;
int i, j, nbr_profile_http_request_uri_parameter;
buci_init();
for (i = 0; i < profiles_number; i++) {
j = 0;
nbr_profile_http_request_uri_parameter = 0;
buci_foreach_section("bulkdata", "profile_http_request_uri_parameter", s) {
profile_id = buci_get_value_bysection(s, "profile_id");
if(bulkdata->profile[i].profile_id != atoi(profile_id))
continue;
nbr_profile_http_request_uri_parameter++;
if(nbr_profile_http_request_uri_parameter == 1) {
bulkdata->profile[i].profile_http_uri_parameter = calloc(1, sizeof(struct profile_http_request_uri_parameter));
} else {
bulkdata->profile[i].profile_http_uri_parameter = realloc(bulkdata->profile[i].profile_http_uri_parameter, nbr_profile_http_request_uri_parameter * sizeof(struct profile_http_request_uri_parameter));
}
if(load_profile_http_request_uri_parameter_config(bulkdata, s, i, j)== -1) {
bulkdata_log(SCRIT,"Not able to start bulkdata: some required bulkdata configurations in profile_http_request_uri_parameter must be set");
return -1;
}
j++;
}
bulkdata->profile[i].profile_http_request_uri_parameter_number = nbr_profile_http_request_uri_parameter;
}
buci_fini();
return 0;
}
int bulkdata_config_init(struct bulkdata *bulkdata)
{
get_log_level_config(bulkdata);
get_amd_version_config(bulkdata);
get_instance_mode_config(bulkdata);
get_device_id_config(bulkdata);
if (get_profiles_enable(bulkdata) == -1)
return -1;
if (get_profiles_parameters(bulkdata) == -1)
return -1;
if (get_profile_http_request_uri_parameter(bulkdata) == -1)
return -1;
return 0;
}
int free_device_id_config(struct bulkdata *bulkdata)
{
FREE(bulkdata->device_id.manufacturer_oui);
FREE(bulkdata->device_id.product_class);
FREE(bulkdata->device_id.serial_number);
return 0;
}
int free_profiles_enable(struct bulkdata *bulkdata)
{
for(int i = 0; i < profiles_number; i++) {
FREE(bulkdata->profile[i].protocol);
FREE(bulkdata->profile[i].encoding_type);
FREE(bulkdata->profile[i].csv_encoding_field_separator);
FREE(bulkdata->profile[i].csv_encoding_row_separator);
FREE(bulkdata->profile[i].csv_encoding_escape_character);
FREE(bulkdata->profile[i].csv_encoding_report_format);
FREE(bulkdata->profile[i].csv_encoding_row_time_stamp);
FREE(bulkdata->profile[i].json_encoding_report_format);
FREE(bulkdata->profile[i].json_encoding_report_time_stamp);
FREE(bulkdata->profile[i].http_url);
FREE(bulkdata->profile[i].http_username);
FREE(bulkdata->profile[i].http_password);
FREE(bulkdata->profile[i].http_compression);
FREE(bulkdata->profile[i].http_method);
FREE(bulkdata->profile[i].http_ssl_capath);
}
FREE(bulkdata->profile);
return 0;
}
int free_profiles_parameters(struct bulkdata *bulkdata)
{
for(int i = 0; i < profiles_number; i++) {
for(int j = 0; j < bulkdata->profile[i].profile_parameter_number; j++) {
FREE(bulkdata->profile[i].profile_parameter[j].name);
FREE(bulkdata->profile[i].profile_parameter[j].reference);
}
FREE(bulkdata->profile[i].profile_parameter);
}
return 0;
}
int free_profile_http_request_uri_parameter(struct bulkdata *bulkdata)
{
for(int i = 0; i < profiles_number; i++) {
for(int j = 0; j < bulkdata->profile[i].profile_http_request_uri_parameter_number; j++) {
FREE(bulkdata->profile[i].profile_http_uri_parameter[j].name);
FREE(bulkdata->profile[i].profile_http_uri_parameter[j].reference);
}
FREE(bulkdata->profile[i].profile_http_uri_parameter);
}
return 0;
}
int bulkdata_config_fini(struct bulkdata *bulkdata)
{
free_device_id_config(bulkdata);
free_profiles_parameters(bulkdata);
free_profile_http_request_uri_parameter(bulkdata);
free_profiles_enable(bulkdata);
return 0;
}

View File

@@ -1,103 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*
*/
#ifndef __CONFIG_H
#define __CONFIG_H
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include <libubox/uloop.h>
#define DEFAULT_AMD_VERSION 2
#define DEFAULT_INSTANCE_MODE 0
typedef struct device_id {
char *manufacturer_oui;
char *product_class;
char *serial_number;
} device_id;
typedef struct profile_parameter {
int profile_id;
char *name;
char *reference;
} profile_parameter;
typedef struct profile_http_request_uri_parameter {
int profile_id;
char *name;
char *reference;
} profile_http_request_uri_parameter;
typedef struct profile {
struct uloop_timeout utimer;
int profile_id;
int nbre_of_retained_failed_reports;
int nbre_failed_reports;
int reporting_interval;
int profile_parameter_number;
int profile_http_request_uri_parameter_number;
int http_retry_minimum_wait_interval;
int http_retry_interval_multiplier;
int min_retry;
int retry_count;
char *protocol;
char *encoding_type;
char *csv_encoding_field_separator;
char *csv_encoding_row_separator;
char *csv_encoding_escape_character;
char *csv_encoding_report_format;
char *csv_encoding_row_time_stamp;
char *json_encoding_report_format;
char *json_encoding_report_time_stamp;
char *http_url;
char *http_username;
char *http_password;
char *http_compression;
char *http_method;
char *http_ssl_capath;
char *new_report;
time_t time_reference;
time_t next_retry;
time_t next_period;
bool http_persist_across_reboot;
bool http_insecure_enable;
bool enable;
bool http_use_date_header;
bool http_retry_enable;
struct profile_parameter *profile_parameter;
struct profile_http_request_uri_parameter *profile_http_uri_parameter;
struct list_head *failed_reports;
} profile;
typedef struct bulkdata {
struct device_id device_id;
struct profile *profile;
int log_level;
int amd_version;
unsigned int instance_mode;
} bulkdata;
int bulkdata_config_init(struct bulkdata *bulkdata);
int bulkdata_config_fini(struct bulkdata *bulkdata);
#ifndef FREE
#define FREE(x) do { if(x) {free(x); x = NULL;} } while (0)
#endif
#endif //__CONFIG_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,29 +0,0 @@
/*
* Copyright (C) 2020 iopsys Software Solutions AB
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation
*
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*/
#ifndef _BULKDATA_H_
#define _BULKDATA_H_
#include <libbbf_api/dmcommon.h>
extern DMOBJ tDeviceBulkDataObj[];
extern DMOBJ tBulkDataObj[];
extern DMLEAF tBulkDataParams[];
extern DMOBJ tBulkDataProfileObj[];
extern DMLEAF tBulkDataProfileParams[];
extern DMLEAF tBulkDataProfileParameterParams[];
extern DMLEAF tBulkDataProfileCSVEncodingParams[];
extern DMLEAF tBulkDataProfileJSONEncodingParams[];
extern DMOBJ tBulkDataProfileHTTPObj[];
extern DMLEAF tBulkDataProfileHTTPParams[];
extern DMLEAF tBulkDataProfileHTTPRequestURIParameterParams[];
#endif //__BULKDATA_H_

View File

@@ -1,196 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
* Omar Kallel <omar.kallel@pivasoftware.com>
*/
#include "http.h"
static struct http_client http_c;
static CURL *curl;
int http_client_init(struct profile *profile)
{
char *url = create_request_url(profile);
if(url) {
asprintf(&http_c.url, "%s", url);
free(url);
}
bulkdata_log(SINFO, "ACS url: %s", http_c.url);
curl_global_init(CURL_GLOBAL_SSL);
curl = curl_easy_init();
if (!curl) return -1;
return 0;
}
void http_client_exit(void)
{
FREE(http_c.url);
if (http_c.header_list) {
curl_slist_free_all(http_c.header_list);
http_c.header_list = NULL;
}
curl_easy_cleanup(curl);
curl_global_cleanup();
}
static size_t http_get_response(void *buffer, size_t size, size_t rxed, char **msg_in)
{
char *c;
if (asprintf(&c, "%s%.*s", *msg_in, (int) (size * rxed), (char *)buffer) == -1) {
FREE(*msg_in);
return -1;
}
free(*msg_in);
*msg_in = c;
return size * rxed;
}
int http_send_message(struct profile *profile, char *msg_out, int msg_out_len, char **msg_in)
{
CURLcode res;
long http_code = 0;
char errbuf[CURL_ERROR_SIZE];
http_c.header_list = NULL;
http_c.header_list = curl_slist_append(http_c.header_list, "User-Agent: iopsys-bulkdata");
if (!http_c.header_list) return -1;
if (profile->http_use_date_header) {
if (bulkdata_get_time() != NULL) {
http_c.header_list = curl_slist_append(http_c.header_list, bulkdata_get_time());
if (!http_c.header_list) return -1;
}
}
if (strcmp(profile->encoding_type, "json") == 0) {
http_c.header_list = curl_slist_append(http_c.header_list, "Content-Type: application/json; charset=\"utf-8\"");
if (!http_c.header_list) return -1;
if(strcmp (profile->json_encoding_report_format, "objecthierarchy") == 0) {
http_c.header_list = curl_slist_append(http_c.header_list, "BBF-Report-Format: \"ObjectHierarchy\"");
if (!http_c.header_list) return -1;
} else if(strcmp(profile->json_encoding_report_format, "namevaluepair") == 0) {
http_c.header_list = curl_slist_append(http_c.header_list, "BBF-Report-Format: \"NameValuePair\"");
if (!http_c.header_list) return -1;
}
} else if(strcmp(profile->encoding_type, "csv") == 0) {
http_c.header_list = curl_slist_append(http_c.header_list, "Content-Type: text/csv; charset=\"utf-8\"");
if (!http_c.header_list) return -1;
if(strcmp (profile->csv_encoding_report_format, "row") == 0) {
http_c.header_list = curl_slist_append(http_c.header_list, "BBF-Report-Format: \"ParameterPerRow\"");
if (!http_c.header_list) return -1;
} else if(strcmp (profile->csv_encoding_report_format, "column") == 0) {
http_c.header_list = curl_slist_append(http_c.header_list, "BBF-Report-Format: \"ParameterPerColumn\"");
if (!http_c.header_list) return -1;
}
}
curl_easy_setopt(curl, CURLOPT_URL, http_c.url);
curl_easy_setopt(curl, CURLOPT_USERNAME, profile->http_username);
curl_easy_setopt(curl, CURLOPT_PASSWORD, profile->http_password);
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC|CURLAUTH_DIGEST);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, HTTP_TIMEOUT);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, HTTP_TIMEOUT);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL);
curl_easy_setopt(curl, CURLOPT_NOBODY, 0);
if(strcasecmp(profile->http_compression, "gzip") == 0) {
curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "gzip");
http_c.header_list = curl_slist_append(http_c.header_list, "Content-Encoding: gzip");
} else if(strcasecmp(profile->http_compression, "compress") == 0) {
curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "compress");
http_c.header_list = curl_slist_append(http_c.header_list, "Content-Encoding: compress");
} else if(strcasecmp(profile->http_compression, "deflate") == 0) {
curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "deflate");
http_c.header_list = curl_slist_append(http_c.header_list, "Content-Encoding: deflate");
}
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, http_c.header_list);
if(strcasecmp(profile->http_method, "put") == 0)
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, msg_out);
if (msg_out)
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long) msg_out_len);
else
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 0);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_get_response);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, msg_in);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
if (profile->http_ssl_capath)
curl_easy_setopt(curl, CURLOPT_CAPATH, profile->http_ssl_capath);
if (profile->http_insecure_enable) {
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
}
*msg_in = (char *) calloc (1, sizeof(char));
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
size_t len = strlen(errbuf);
if(len) {
if (errbuf[len - 1] == '\n') errbuf[len - 1] = '\0';
bulkdata_log(SCRIT, "libcurl: (%d) %s", res, errbuf);
} else {
bulkdata_log(SCRIT, "libcurl: (%d) %s", res, curl_easy_strerror(res));
}
}
if (!strlen(*msg_in))
FREE(*msg_in);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
if(http_code == 200)
bulkdata_log(SINFO, "Receive HTTP 200 OK from Bulkdata Collector");
else if(http_code == 401)
bulkdata_log(SINFO, "Receive HTTP 401 Unauthorized from Bulkdata Collector");
else if(http_code == 204)
bulkdata_log(SINFO, "Receive HTTP 204 No Content from Bulkdata Collector");
else
bulkdata_log(SINFO, "Receive HTTP %d from Bulkdata Collector", http_code);
if(http_code == 415)
{
strcpy(profile->http_compression, "None");
goto error;
}
if (http_code != 200 && http_code != 204)
goto error;
curl_easy_reset(curl);
if (http_c.header_list) {
curl_slist_free_all(http_c.header_list);
http_c.header_list = NULL;
}
if (res) goto error;
return http_code;
error:
FREE(*msg_in);
if (http_c.header_list) {
curl_slist_free_all(http_c.header_list);
http_c.header_list = NULL;
}
return -1;
}

View File

@@ -1,37 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*
*/
#ifndef __HTTP_H
#define __HTTP_H
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <curl/curl.h>
#include "config.h"
#include "log.h"
#include "times.h"
#include "common.h"
#define HTTP_TIMEOUT 30
struct http_client
{
struct curl_slist *header_list;
char *url;
};
int http_client_init(struct profile *profile);
void http_client_exit(void);
int http_send_message(struct profile *profile, char *msg_out, int msg_out_len, char **msg_in);
#endif //__HTTP_H

View File

@@ -1,57 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*
*/
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <syslog.h>
#include <time.h>
#include "bulkdata.h"
#include "config.h"
#include "log.h"
static const int log_syslogmap[] = {
[SCRIT] = LOG_CRIT,
[SWARNING] = LOG_WARNING,
[SNOTICE] = LOG_NOTICE,
[SINFO] = LOG_INFO,
[SDEBUG] = LOG_DEBUG
};
static const char* log_str[] = {
[SCRIT] = "CRITICAL",
[SWARNING] = "WARNING",
[SNOTICE] = "NOTICE",
[SINFO] = "INFO",
[SDEBUG] = "DEBUG"
};
void bulkdata_log(int priority, const char *format, ...)
{
va_list vl;
if (priority <= bulkdata_main.log_level) {
time_t t = time(NULL);
struct tm tm = *localtime(&t);
va_start(vl, format);
printf("%d-%02d-%02d %02d:%02d:%02d [bulkdata] %s - ", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, log_str[priority]);
vprintf(format, vl);
va_end(vl);
printf("\n");
openlog("bulkdata", 0, LOG_DAEMON);
va_start(vl, format);
vsyslog(log_syslogmap[priority], format, vl);
va_end(vl);
closelog();
}
}

View File

@@ -1,28 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*
*/
#ifndef __LOG_H
#define __LOG_H
#define DEFAULT_LOGLEVEL SINFO
enum bulkdata_log_level_enum {
SCRIT,
SWARNING,
SNOTICE,
SINFO,
SDEBUG,
__MAX_SLOG
};
void bulkdata_log(int priority, const char *format, ...);
#endif //__LOG_H

View File

@@ -1,336 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
* Author: Omar Kallel <omar.kallel@pivasoftware.com>
*
*/
#include "report.h"
static void add_new_json_obj(json_object *json_obj, char *name, char *data, char *type)
{
json_object *jobj;
if(strstr(type, "unsignedInt") || strstr(type, "int") || strstr(type, "long"))
jobj = json_object_new_int64(atoi(data));
else if(strstr(type, "bool"))
jobj = json_object_new_boolean(atoi(data));
else
jobj = json_object_new_string(data);
json_object_object_add(json_obj, name, jobj);
}
static void create_json_bulkdata_report_object_hierarchy(struct profile *profile, char **report)
{
struct json_object *json_obj, *json_obj1, *json_obj2;
struct resultsnode *p;
int i, j, profile_param_number = profile->profile_parameter_number;
char *param_name, *result, *pch, *pchr, *collection_time = NULL;
char buf[1024] = {0};
json_obj = json_object_new_object();
get_time_stamp(profile->json_encoding_report_time_stamp, &collection_time);
if(collection_time) {
if(strcmp(profile->json_encoding_report_time_stamp, "iso8601") == 0)
json_object_object_add(json_obj, "CollectionTime", json_object_new_string(collection_time));
else
json_object_object_add(json_obj, "CollectionTime", json_object_new_int64(atoi(collection_time)));
free(collection_time);
}
json_obj2 = json_obj;
for (i = 0; i < profile_param_number; i++) {
LIST_HEAD(results_list);
bulkdata_get_value_results(profile->profile_parameter[i].reference, &results_list);
list_for_each_entry(p, &results_list, list) {
char *argv[128] = {0};
j = 0;
param_name = get_bulkdata_profile_parameter_name(profile->profile_parameter[i].reference, profile->profile_parameter[i].name, p->name);
strcpy(buf, param_name);
for (pch = strtok_r(buf, ".", &pchr); pch != NULL; pch = strtok_r(NULL, ".", &pchr)) {
argv[j] = pch;
json_obj1 = (json_object *)bbf_api_dmjson_select_obj(json_obj, argv);
if (json_obj1)
json_obj2 = json_obj1;
else {
if (pchr != NULL && *pchr != '\0') {
json_object *new_obj = json_object_new_object();
json_object_object_add(json_obj2, pch, new_obj);
json_obj2 = new_obj;
}
else
add_new_json_obj(json_obj2, pch, p->data, p->type);
}
j++;
}
}
bulkdata_free_data_from_list(&results_list);
FREE(param_name);
}
result = (char *)json_object_to_json_string_ext(json_obj, JSON_C_TO_STRING_PRETTY);
*report = strdup(result);
json_object_put(json_obj);
}
static void create_json_bulkdata_report_name_value_pair(struct profile *profile, char **report)
{
struct json_object *json_obj;
struct resultsnode *p;
char *param_name, *result, *collection_time = NULL;
int i = 0, profile_param_number = profile->profile_parameter_number;
json_obj = json_object_new_object();
get_time_stamp(profile->json_encoding_report_time_stamp, &collection_time);
if(collection_time) {
if(strcmp(profile->json_encoding_report_time_stamp, "iso8601") == 0)
json_object_object_add(json_obj, "CollectionTime", json_object_new_string(collection_time));
else
json_object_object_add(json_obj, "CollectionTime", json_object_new_int64(atoi(collection_time)));
free(collection_time);
}
for (i = 0; i < profile_param_number; i++) {
LIST_HEAD(results_list);
bulkdata_get_value_results(profile->profile_parameter[i].reference, &results_list);
list_for_each_entry(p, &results_list, list) {
param_name = get_bulkdata_profile_parameter_name(profile->profile_parameter[i].reference, profile->profile_parameter[i].name, p->name);
add_new_json_obj(json_obj, param_name, p->data, p->type);
FREE(param_name);
}
bulkdata_free_data_from_list(&results_list);
}
result = (char *)json_object_to_json_string_ext(json_obj, JSON_C_TO_STRING_PRETTY);
*report = strdup(result);
json_object_put(json_obj);
}
static void add_failed_reports_to_report_json(struct profile *profile, char *new_report, char **report, int isnext)
{
json_object *json_obj, *json_array, *json_string;
struct failed_reports *retreport = NULL;
char *msgout = NULL;
int j = 0;
json_obj = json_object_new_object();
json_array = json_object_new_array();
json_object_object_add(json_obj,"Report", json_array);
if(list_empty(profile->failed_reports))
goto new_report;
list_for_each_entry(retreport, profile->failed_reports, list) {
if(!j && isnext) {
j = 1;
continue;
}
json_string = json_tokener_parse(retreport->freport);
json_object_array_add(json_array, json_string);
}
new_report :
if(new_report) {
json_string = json_tokener_parse(new_report);
json_object_array_add(json_array, json_string);
}
msgout = (char *)json_object_to_json_string_ext(json_obj, JSON_C_TO_STRING_PRETTY);
*report = strdup(msgout);
json_object_put(json_obj);
}
static void create_report_json(char *new_report, char **report)
{
json_object *json_obj, *json_array, *json_string;
char *msgout = NULL;
json_obj = json_object_new_object();
json_array = json_object_new_array();
json_object_object_add(json_obj,"Report", json_array);
if(new_report) {
json_string = json_tokener_parse(new_report);
json_object_array_add(json_array, json_string);
}
msgout = (char *)json_object_to_json_string_ext(json_obj, JSON_C_TO_STRING_PRETTY);
*report = strdup(msgout);
json_object_put(json_obj);
}
int create_json_bulkdata_report(struct profile *profile, char **report)
{
/*
* create json msg of current report
* parse failed reports list and add it to the report
* then add new report to the report
*/
char *msgout;
profile->new_report = NULL;
if(strcmp(profile->json_encoding_report_format, "objecthierarchy") == 0) {
create_json_bulkdata_report_object_hierarchy(profile, &msgout);
} else if(strcmp(profile->json_encoding_report_format, "namevaluepair") == 0) {
create_json_bulkdata_report_name_value_pair(profile, &msgout);
}
if(profile->nbre_of_retained_failed_reports != 0) {
if(profile->nbre_failed_reports >= profile->nbre_of_retained_failed_reports && profile->nbre_of_retained_failed_reports > 0)
add_failed_reports_to_report_json(profile, msgout, report, 1);
else
add_failed_reports_to_report_json(profile, msgout, report, 0);
} else {
create_report_json(msgout, report);
}
append_string_to_string(msgout, &profile->new_report);
FREE(msgout);
return 0;
}
int create_csv_bulkdata_report(struct profile *profile, char **report)
{
/*
* create csv msg of current report
* parse failed reports list and add it to the report
*/
int i;
struct resultsnode *p;
char *str1 = NULL, *str2 = NULL, *str = NULL, *paramprofilename, *timestamp = NULL, *type = NULL, rowseparator = '\0', separator = '\0';
if(strcmp(profile->csv_encoding_row_separator, "&#10;") == 0)
rowseparator = '\n';
else if(strcmp(profile->csv_encoding_row_separator, "&#13;") == 0)
rowseparator = '\r';
if(profile->csv_encoding_field_separator)
separator = profile->csv_encoding_field_separator[0];
get_time_stamp(profile->csv_encoding_row_time_stamp, &timestamp);
/*
* Create header ReportTimestamp,ParameterName,ParameterValue,ParameterType in case of ParameterPerRow
*/
if(strcmp(profile->csv_encoding_report_format, "row") == 0) {
if(timestamp == NULL)
asprintf(&str, "ParameterName%cParameterValue%cParameterType%c", separator, separator, rowseparator);
else
asprintf(&str, "ReportTimestamp%cParameterName%cParameterValue%cParameterType%c", separator, separator, separator, rowseparator);
append_string_to_string(str, report);
FREE(str);
if(profile->nbre_of_retained_failed_reports != 0) {
if(profile->nbre_failed_reports >= profile->nbre_of_retained_failed_reports && profile->nbre_of_retained_failed_reports > 0)
add_failed_reports_to_report_csv(profile, report, 1);
else
add_failed_reports_to_report_csv(profile, report, 0);
}
}
if(strcmp(profile->csv_encoding_report_format, "column") == 0 && timestamp != NULL) {
if(profile->nbre_of_retained_failed_reports != 0) {
if(profile->nbre_failed_reports >= profile->nbre_of_retained_failed_reports && profile->nbre_of_retained_failed_reports > 0)
add_failed_reports_to_report_csv(profile, report, 1);
else
add_failed_reports_to_report_csv(profile, report, 0);
}
append_string_to_string("ReportTimestamp", &str1);
append_string_to_string(timestamp, &str2);
}
/*
* Add New reports
*/
profile->new_report = NULL;
for(i = 0; i < profile->profile_parameter_number; i++) {
LIST_HEAD(results_list);
bulkdata_get_value_results(profile->profile_parameter[i].reference, &results_list);
list_for_each_entry(p, &results_list, list) {
paramprofilename = get_bulkdata_profile_parameter_name(profile->profile_parameter[i].reference, profile->profile_parameter[i].name, p->name);
if(strcmp(profile->csv_encoding_report_format, "row") == 0) {
type = strstr(p->type, ":");
if(timestamp == NULL)
asprintf(&str, "%s%c%s%c%s%c", paramprofilename, separator, p->data, separator, type+1, rowseparator);
else
asprintf(&str, "%s%c%s%c%s%c%s%c", timestamp, separator, paramprofilename, separator, p->data, separator, type+1, rowseparator);
append_string_to_string(str, report);
append_string_to_string(str, &profile->new_report);
FREE(str);
} else if(strcmp(profile->csv_encoding_report_format, "column") == 0) {
if(str1 == NULL || strlen(str1) <= 0)
asprintf(&str, "%s", paramprofilename);
else
asprintf(&str, "%c%s", separator, paramprofilename);
append_string_to_string(str, &str1);
FREE(str);
if(str2 == NULL || strlen(str2) <= 0)
asprintf(&str, "%s", p->data);
else
asprintf(&str, "%c%s", separator, p->data);
append_string_to_string(str, &str2);
FREE(str);
}
FREE(paramprofilename);
}
bulkdata_free_data_from_list(&results_list);
}
if(strcmp(profile->csv_encoding_report_format, "column") == 0) {
asprintf(&str, "%c", rowseparator);
append_string_to_string(str, &str1);
append_string_to_string(str, &str2);
append_string_to_string(str1, report);
append_string_to_string(str2, report);
append_string_to_string(str1, &profile->new_report);
append_string_to_string(str2, &profile->new_report);
}
FREE(str);
FREE(str1);
FREE(str2);
FREE(timestamp);
return 0;
}
static void create_json_failed_report(struct profile *profile, char **report)
{
add_failed_reports_to_report_json(profile, NULL, report, 0);
}
static void create_csv_failed_report(struct profile *profile, char **report)
{
char rowseparator = '\0', separator = '\0', *timestamp = NULL;
if(strcmp(profile->csv_encoding_row_separator, "&#10;") == 0) {
rowseparator = '\n';
} else if(strcmp(profile->csv_encoding_row_separator, "&#13;") == 0) {
rowseparator = '\r';
}
if(profile->csv_encoding_field_separator)
separator = profile->csv_encoding_field_separator[0];
get_time_stamp(profile->csv_encoding_row_time_stamp, &timestamp);
if(strcmp(profile->csv_encoding_report_format, "row") == 0) {
if(timestamp == NULL)
asprintf(report, "ParameterName%cParameterValue%cParameterType%c", separator, separator, rowseparator);
else
asprintf(report, "ReportTimestamp%cParameterName%cParameterValue%cParameterType%c", separator, separator, separator, rowseparator);
}
add_failed_reports_to_report_csv(profile, report, 0);
}
void create_encoding_bulkdata_report(struct profile *profile, char **report)
{
if(strcasecmp(profile->encoding_type, "json") == 0) {
create_json_bulkdata_report(profile, report);
} else if(strcasecmp(profile->encoding_type, "csv") == 0) {
create_csv_bulkdata_report(profile, report);
}
}
void create_failed_report(struct profile *profile, char **report)
{
if(strcasecmp(profile->encoding_type, "json") == 0) {
create_json_failed_report(profile, report);
} else if(strcasecmp(profile->encoding_type, "csv") == 0) {
create_csv_failed_report(profile, report);
}
}

View File

@@ -1,24 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
* Author: Omar Kallel <omar.kallel@pivasoftware.com>
*
*/
#ifndef __REPORT_H_
#define __REPORT_H_
#include <json-c/json.h>
#include "common.h"
#include "times.h"
#include "config.h"
void create_encoding_bulkdata_report(struct profile *profile, char **report);
void create_failed_report(struct profile *profile, char **report);
#endif /* __REPORT_H_ */

View File

@@ -1,62 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*
*/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "times.h"
const char *bulkdata_get_time(void)
{
static char local_time[64];
time_t t_time = time(NULL);
struct tm *t_tm = localtime(&t_time);
if (t_tm == NULL)
return NULL;
if (strftime(local_time, sizeof(local_time),"Date: %a, %d %b %Y %X%z GMT", t_tm) == 0)
return NULL;
return local_time;
}
void get_time_stamp(const char *format, char **timestamp)
{
time_t now = time(NULL);
if (strcmp(format, "unix") == 0) {
asprintf(timestamp, "%ld", now);
} else if (strcmp(format, "iso8601") == 0) {
char buf[32] = {0};
struct tm *ts = localtime(&now);
strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%Z", ts);
asprintf(timestamp, "%s", buf);
} else
timestamp = NULL;
}
unsigned int get_next_period(time_t time_reference, int reporting_interval)
{
unsigned int next_period;
time_t now = time(NULL);
if (now > time_reference)
next_period = reporting_interval - ((now - time_reference) % reporting_interval);
else
next_period = (time_reference - now) % reporting_interval;
if (next_period == 0)
next_period = reporting_interval;
return next_period;
}

View File

@@ -1,19 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*
*/
#ifndef __TIMES_H
#define __TIMES_H
const char *bulkdata_get_time(void);
void get_time_stamp(const char *format, char **timestamp);
unsigned int get_next_period(time_t time_reference, int reporting_interval);
#endif /* __TIMES_H */

38
bulut/Makefile Normal file
View File

@@ -0,0 +1,38 @@
#
# Copyright (C) 2019 IOPSYS
#
include $(TOPDIR)/rules.mk
PKG_NAME:=bulut
PKG_VERSION:=0.2
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://dev.iopsys.eu/bulut/bulut-gw-client.git
PKG_SOURCE_VERSION:=227700c44817afa2c392fa08bf4cf70fa6177f01
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
PKG_MIRROR_HASH:=skip
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
include $(INCLUDE_DIR)/package.mk
define Package/bulut
CATEGORY:=Utilities
DEPENDS:=
TITLE:=bulut
endef
TARGET_CFLAGS += \
-I$(STAGING_DIR)/usr/include
define Package/bulut/description
obuspa keys
endef
define Package/bulut/install
$(CP) $(PKG_BUILD_DIR)/files/* $(1)/
endef
$(eval $(call BuildPackage,bulut))

View File

@@ -1,50 +1,82 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=crun
PKG_VERSION:=0.17
PKG_RELEASE:=1
PKG_VERSION:=0.18
PKG_RELEASE:=$(AUTORELEASE)
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/containers/crun.git
PKG_SOURCE_VERSION:=0e9229ae34caaebcb86f1fde18de3acaf18c6d9a
PKG_SOURCE_DATE:=2021-03-18
PKG_SOURCE_VERSION:=496e81bdd69f117f10e4477e4204e4611a94b68f
PKG_MIRROR_HASH:=26941b0d84bbeabeb5e982af48d131f55d0aa16f4a2f2ca3279a5c812cdeea8b
PKG_LICENSE:=GPL-2.0
PKG_LICENSE_FILES:=COPYING
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
PKG_INSTALL:=1
PKG_BUILD_DEPENDS:=argp-standalone
PKG_BUILD_PARALLEL:=1
PKG_FIXUP:=autoreconf
PKG_INSTALL:=1
PKG_MAINTAINER:=Oskari Rauta <oskari.rauta@gmail.com>
PKG_LICENSE:=GPL-2.0-or-later
PKG_LICENSE_FILES:=COPYING
include $(INCLUDE_DIR)/package.mk
define Package/crun
SECTION:=utils
CATEGORY:=Utilities
DEPENDS:=+yajl +argp-standalone +libcap +libseccomp
TITLE:=A fast and low-memory footprint OCI Container Runtime fully written in C
TITLE:=crun
URL:=https://github.com/containers/crun
DEPENDS:=@!arc +libseccomp +libcap
endef
define Package/crun/description
crun conforms to the OCI Container Runtime specifications
A fast and low-memory footprint OCI Container Runtime fully written in C.
endef
TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include
TARGET_LDFLAGS += -largp
CONFIGURE_ARGS+= \
--disable-systemd \
--enable-embedded-yajl \
--enable-caps \
--enable-dl \
--enable-seccomp \
--enable-bpf
define Build/Prepare
$(call Build/Prepare/Default)
$(SED) '/#include <git-version.h>/d' $(PKG_BUILD_DIR)/src/crun.c
endef
MAKE_FLAGS := \
$(TARGET_CONFIGURE_OPTS) \
CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)" \
LDFLAGS="$(TARGET_LDFLAGS)"
define Build/Configure
cd $(PKG_BUILD_DIR)/ && sh autogen.sh && ./configure
endef
$(call Build/Configure/Default)
$(SED) '/#define PACKAGE \"/d' $(PKG_BUILD_DIR)/config.h
$(SED) '/#define VERSION \"/d' $(PKG_BUILD_DIR)/config.h
$(SED) '/#define GIT_VERSION \"/d' $(PKG_BUILD_DIR)/config.h
$(SED) '/#define PACKAGE_BUGREPORT \"/d' $(PKG_BUILD_DIR)/config.h
$(SED) '/#define PACKAGE_NAME \"/d' $(PKG_BUILD_DIR)/config.h
$(SED) '/#define PACKAGE_STRING \"/d' $(PKG_BUILD_DIR)/config.h
$(SED) '/#define PACKAGE_TARNAME \"/d' $(PKG_BUILD_DIR)/config.h
$(SED) '/#define PACKAGE_VERSION \"/d' $(PKG_BUILD_DIR)/config.h
echo "#define PACKAGE \"$(PKG_NAME)\"" >> $(PKG_BUILD_DIR)/config.h
echo "#define VERSION \"$(PKG_VERSION)\"" >> $(PKG_BUILD_DIR)/config.h
echo "#define PACKAGE_NAME \"$(PKG_NAME)\"" >> $(PKG_BUILD_DIR)/config.h
echo "#define PACKAGE_VERSION \"$(PKG_VERSION)\"" >> $(PKG_BUILD_DIR)/config.h
echo "#define PACKAGE_STRING \"$(PKG_NAME) $(PKG_VERSION)\"" >> $(PKG_BUILD_DIR)/config.h
echo "#define PACKAGE_TARNAME \"$(PKG_NAME)\"" >> $(PKG_BUILD_DIR)/config.h
echo "#define PACKAGE_BUGREPORT \"bugs@openwrt.org\"" >> $(PKG_BUILD_DIR)/config.h
echo "#define GIT_VERSION \"$(PKG_SOURCE_VERSION)\"" >> $(PKG_BUILD_DIR)/config.h
endef
define Package/crun/install
$(INSTALL_DIR) $(1)/usr/bin/
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/local/bin/crun $(1)/usr/bin/
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/crun $(1)/usr/bin/
endef
define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/bin $(1)/usr/lib
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/crun $(1)/usr/bin/
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libcrun.* $(1)/usr/lib/
endef
$(eval $(call BuildPackage,crun))

View File

@@ -1,217 +0,0 @@
diff --git a/configure.ac b/configure.ac
index 5e9f2f9..5ed99bd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -52,16 +52,6 @@ AS_IF([test "x$enable_seccomp" != "xno"], [
])
])
-dnl libsystemd
-AC_ARG_ENABLE([systemd],
- AS_HELP_STRING([--disable-systemd], [Ignore systemd and disable support]))
-AS_IF([test "x$enable_systemd" != "xno"], [
- AC_CHECK_HEADERS([systemd/sd-bus.h], [], [AC_MSG_ERROR([*** Missing libsystemd headers])])
- AS_IF([test "$ac_cv_header_systemd_sd_bus_h" = "yes"], [
- AC_SEARCH_LIBS(sd_bus_match_signal_async, [systemd], [AC_DEFINE([HAVE_SYSTEMD], 1, [Define if libsystemd is available])], [AC_MSG_ERROR([*** Failed to find libsystemd])])
- ])
-])
-
dnl ebpf
AC_ARG_ENABLE([bpf],
AS_HELP_STRING([--disable-bpf], [Ignore eBPF and disable support]))
@@ -114,26 +104,6 @@ AS_IF([test "x$enable_criu" != "xno"], [
FOUND_LIBS=$LIBS
LIBS=""
-AC_MSG_CHECKING([for new mount API (fsconfig)])
-AC_COMPILE_IFELSE(
- [AC_LANG_SOURCE([[
- #include <linux/mount.h>
- int cmd = FSCONFIG_CMD_CREATE;
- ]])],
- [AC_MSG_RESULT(yes)
- AC_DEFINE([HAVE_FSCONFIG_CMD_CREATE], 1, [Define if FSCONFIG_CMD_CREATE is available])],
- [AC_MSG_RESULT(no)])
-
-AC_MSG_CHECKING([for seccomp notify API])
-AC_COMPILE_IFELSE(
- [AC_LANG_SOURCE([[
- #include <linux/seccomp.h>
- int cmd = SECCOMP_GET_NOTIF_SIZES;
- ]])],
- [AC_MSG_RESULT(yes)
- AC_DEFINE([HAVE_SECCOMP_GET_NOTIF_SIZES], 1, [Define if SECCOMP_GET_NOTIF_SIZES is available])],
- [AC_MSG_RESULT(no)])
-
AC_DEFINE([LIBCRUN_PUBLIC], [__attribute__((visibility("default"))) extern], [LIBCRUN_PUBLIC])
AC_SUBST([FOUND_LIBS])
AC_SUBST([CRUN_LDFLAGS])
diff --git a/src/libcrun/cgroup.c b/src/libcrun/cgroup.c
index 29c1f7a..77dc441 100644
--- a/src/libcrun/cgroup.c
+++ b/src/libcrun/cgroup.c
@@ -575,23 +575,6 @@ get_file_owner (const char *path, uid_t *uid, gid_t *gid)
struct stat st;
int ret;
-#ifdef HAVE_STATX
- struct statx stx;
-
- ret = statx (AT_FDCWD, path, AT_STATX_DONT_SYNC, STATX_UID | STATX_GID, &stx);
- if (UNLIKELY (ret < 0))
- {
- if (errno == ENOSYS || errno == EINVAL)
- goto fallback;
-
- return ret;
- }
- *uid = stx.stx_uid;
- *gid = stx.stx_gid;
- return ret;
-
-fallback:
-#endif
ret = stat (path, &st);
if (UNLIKELY (ret < 0))
return ret;
diff --git a/src/libcrun/error.h b/src/libcrun/error.h
index aa3f3aa..477a2fe 100644
--- a/src/libcrun/error.h
+++ b/src/libcrun/error.h
@@ -18,9 +18,6 @@
#ifndef ERROR_H
#define ERROR_H
#include <config.h>
-#ifdef HAVE_ERROR_H
-# include <error.h>
-#else
# define error(status, errno, fmt, ...) \
do \
{ \
@@ -35,7 +32,6 @@
exit (status); \
} \
while (0)
-#endif
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
diff --git a/src/libcrun/utils.c b/src/libcrun/utils.c
index cbde9b6..5ef7f5f 100644
--- a/src/libcrun/utils.c
+++ b/src/libcrun/utils.c
@@ -164,22 +164,6 @@ get_file_type_fd (int fd, mode_t *mode)
struct stat st;
int ret;
-#ifdef HAVE_STATX
- struct statx stx;
-
- ret = statx (fd, "", AT_EMPTY_PATH | AT_STATX_DONT_SYNC, STATX_TYPE, &stx);
- if (UNLIKELY (ret < 0))
- {
- if (errno == ENOSYS || errno == EINVAL)
- goto fallback;
-
- return ret;
- }
- *mode = stx.stx_mode;
- return ret;
-
-fallback:
-#endif
ret = fstat (fd, &st);
*mode = st.st_mode;
return ret;
@@ -191,22 +175,6 @@ get_file_type_at (int dirfd, mode_t *mode, bool nofollow, const char *path)
struct stat st;
int ret;
-#ifdef HAVE_STATX
- struct statx stx;
-
- ret = statx (dirfd, path, (nofollow ? AT_SYMLINK_NOFOLLOW : 0) | AT_STATX_DONT_SYNC, STATX_TYPE, &stx);
- if (UNLIKELY (ret < 0))
- {
- if (errno == ENOSYS || errno == EINVAL)
- goto fallback;
-
- return ret;
- }
- *mode = stx.stx_mode;
- return ret;
-
-fallback:
-#endif
ret = fstatat (dirfd, path, &st, nofollow ? AT_SYMLINK_NOFOLLOW : 0);
*mode = st.st_mode;
return ret;
@@ -550,22 +518,7 @@ get_file_size (int fd, off_t *size)
{
struct stat st;
int ret;
-#ifdef HAVE_STATX
- struct statx stx;
-
- ret = statx (fd, "", AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW | AT_STATX_DONT_SYNC, STATX_SIZE, &stx);
- if (UNLIKELY (ret < 0))
- {
- if (errno == ENOSYS || errno == EINVAL)
- goto fallback;
- return ret;
- }
- *size = stx.stx_size;
-
- return ret;
-fallback:
-#endif
ret = fstat (fd, &st);
*size = st.st_size;
return ret;
@@ -1060,7 +1013,6 @@ run_process (char **args, libcrun_error_t *err)
_exit (EXIT_FAILURE);
}
-#ifndef HAVE_FGETPWENT_R
static unsigned
atou (char **s)
{
@@ -1126,7 +1078,6 @@ fgetpwent_r (FILE *f, struct passwd *pw, char *line, size_t size, struct passwd
errno = rv;
return rv;
}
-#endif
int
set_home_env (uid_t id)
@@ -1690,29 +1641,6 @@ copy_rec_stat_file_at (int dfd, const char *path, mode_t *mode, off_t *size, dev
struct stat st;
int ret;
-#ifdef HAVE_STATX
- struct statx stx;
-
- ret = statx (dfd, path, AT_SYMLINK_NOFOLLOW | AT_STATX_DONT_SYNC,
- STATX_TYPE | STATX_MODE | STATX_SIZE | STATX_UID | STATX_GID, &stx);
- if (UNLIKELY (ret < 0))
- {
- if (errno == ENOSYS || errno == EINVAL)
- goto fallback;
-
- return ret;
- }
-
- *mode = stx.stx_mode;
- *size = stx.stx_size;
- *rdev = makedev (stx.stx_rdev_major, stx.stx_rdev_minor);
- *uid = stx.stx_uid;
- *gid = stx.stx_gid;
-
- return ret;
-
-fallback:
-#endif
ret = fstatat (dfd, path, &st, AT_SYMLINK_NOFOLLOW);
*mode = st.st_mode;

View File

@@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=dectmngr
PKG_RELEASE:=3
PKG_VERSION:=3.0.10
PKG_VERSION:=3.0.12
LOCAL_DEV=0
ifneq ($(LOCAL_DEV),1)
PKG_SOURCE_URL:=https://dev.iopsys.eu/iopsys/dectmngr.git
PKG_SOURCE_PROTO:=git
PKG_SOURCE_VERSION:=aba9bcef460a7c11df9096b853bf3d235e2c4a78
PKG_SOURCE_VERSION:=db155c063a9875026e573bbd292dec484fc3f103
PKG_MIRROR_HASH:=skip
endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,4 @@
#!/bin/sh /etc/rc.common
#
# Copyright (C) 2021 OpenWrt.org
#
source /lib/functions/uci-defaults.sh
@@ -25,12 +22,17 @@ stop_and_wait_dectmngr() {
}
start_service() {
local rfpi=
local opt_rfpi=
test $(db get hw.board.hasDect) = "0" && return
echo 1 > /sys/class/gpio/gpio14/value
rfpi=$(db -q get hw.board.dect_rfpi)
[ -n "$rfpi" -a ${#rfpi} -eq 14 ] && opt_rfpi="-rfpi $rfpi"
procd_open_instance
procd_set_param command $PROG -comname ttyH0 -log $LOG_PATH/dect-cmbs.log
procd_set_param command $PROG -comname ttyH0 -log $LOG_PATH/dect-cmbs.log $opt_rfpi
procd_set_param respawn 6 2 3
procd_set_param term_timeout 20
procd_set_param triggers asterisk

View File

@@ -1,27 +0,0 @@
#!/bin/sh
SOUND_BASE=/lib/modules/$(uname -r)/kernel/sound
SOUND_MODULES="$SOUND_BASE/soundcore.ko $SOUND_BASE/core/snd.ko $SOUND_BASE/core/snd-timer.ko"
SOUND_MODULES="$SOUND_MODULES $SOUND_BASE/core/snd-pcm.ko $SOUND_BASE/core/snd-hwdep.ko"
SOUND_MODULES="$SOUND_MODULES $SOUND_BASE/core/seq/snd-seq-device.ko"
SOUND_MODULES="$SOUND_MODULES $SOUND_BASE/core/seq/snd-seq.ko $SOUND_BASE/core/snd-rawmidi.ko "
SOUND_MODULES="$SOUND_MODULES $SOUND_BASE/usb/snd-usbmidi-lib.ko $SOUND_BASE/usb/snd-usb-audio.ko"
load_sound_modules() {
for mod in $SOUND_MODULES; do
insmod $mod
done
}
unload_sound_modules() {
local modules=
# reverse the order
for mod in $SOUND_MODULES; do
modules="$mod $modules"
done
for mod in $modules; do
rmmod $mod
done
}

View File

@@ -7,13 +7,13 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=easy-soc-libs
PKG_VERSION:=6.1.89
PKG_VERSION:=6.2.12
PKG_RELEASE:=1
LOCAL_DEV=0
ifneq ($(LOCAL_DEV),1)
PKG_SOURCE_PROTO:=git
PKG_SOURCE_VERSION:=509c57cdcbabcc819932e673718c1a305bf32009
PKG_SOURCE_VERSION:=48b9abce9acace69a9b270ed4438b80434fc3446
PKG_SOURCE_URL:=https://dev.iopsys.eu/iopsys/easy-soc-libs.git
PKG_MAINTAINER:=Anjan Chanda <anjan.chanda@iopsys.eu>
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)_$(PKG_SOURCE_VERSION).tar.xz
@@ -45,12 +45,6 @@ ifeq ($(CONFIG_TARGET_iopsys_brcm63xx_arm),y)
else ifeq ($(CONFIG_TARGET_iopsys_ramips),y)
TARGET_PLATFORM=MEDIATEK
TARGET_CFLAGS +=-DIOPSYS_MEDIATEK
else ifeq ($(CONFIG_TARGET_iopsys_linksys),y)
TARGET_PLATFORM=MARVELL
TARGET_CFLAGS +=-DIOPSYS_MARVELL
else ifeq ($(CONFIG_TARGET_intel_mips),y)
TARGET_PLATFORM=INTEL
TARGET_CFLAGS +=-DIOPSYS_INTEL
else ifeq ($(CONFIG_TARGET_iopsys_x86),y)
TARGET_PLATFORM=TEST
TARGET_CFLAGS +=-DIOPSYS_TEST
@@ -58,7 +52,9 @@ else ifeq ($(CONFIG_TARGET_iopsys_armvirt),y)
TARGET_PLATFORM=TEST
TARGET_CFLAGS +=-DIOPSYS_TEST
else
$(info Unexpected CONFIG_TARGET)
$(info Unexpected CONFIG_TARGET, use default MAC80211)
TARGET_PLATFORM=MAC80211
TARGET_CFLAGS +=-DIOPSYS_MAC80211
endif
export TARGET_PLATFORM

View File

@@ -1,10 +1,7 @@
define Package/libdsl
$(call Package/easy-soc-libs)
TITLE:= XDSL library (libdsl)
DEPENDS+=+TARGET_intel_mips:dsl-cpe-api-vrx \
+TARGET_intel_mips:dsl-cpe-fapi \
+TARGET_intel_mips:kmod-ppa-drv
TITLE:= xDSL library (libdsl)
endef
define Package/libdsl/config

View File

@@ -6,26 +6,17 @@
#
include $(TOPDIR)/rules.mk
PKG_RELEASE:=1
PKG_VERSION:=0.4
PKG_SOURCE_VERSION:=510b885c049b8ba06772dae59e64b370d0fded3e
PKG_LICENSE:=MIT
PKG_LICENSE_FILES:=LICENSE
ifeq ($(CONFIG_ENDPT_OPEN),y)
BRCM_KERNEL_PROFILE=$(shell echo $(CONFIG_BCM_KERNEL_PROFILE) | sed s/\"//g)
PKG_SOURCE:=endptmngr-$(BRCM_KERNEL_PROFILE)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
PKG_SOURCE_URL:=https://download.iopsys.eu/iopsys/opensdk/
PKG_NAME:=endptmngr-open
PATCH_DIR:=
PKG_HASH:=skip
else
PKG_SOURCE_URL:=https://dev.iopsys.eu/iopsys/endptmngr.git
PKG_SOURCE_PROTO:=git
PKG_NAME:=endptmngr
PKG_VERSION:=0.4
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://dev.iopsys.eu/iopsys/endptmngr.git
PKG_SOURCE_VERSION:=b94de01a4ff24bb4d31bb16b3be9e1b1859359dd
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
PKG_MIRROR_HASH:=skip
endif
PKG_LICENSE:=MIT
PKG_LICENSE_FILES:=LICENSE
export BUILD_DIR
@@ -34,14 +25,9 @@ PKG_BUILD_PARALLEL:=1
# All config variable that are passed to the make invocation, directly or
# indirectly. This ensures that the package is rebuilt on config-changes.
PKG_CONFIG_DEPENDS := \
CONFIG_TARGET_BOARD
PKG_CONFIG_DEPENDS:=CONFIG_TARGET_BOARD
export CONFIG_BRCM_SDK_VER_504001
export CONFIG_BRCM_SDK_VER_504002
export CONFIG_BRCM_SDK_VER_504003
export CONFIG_BRCM_SDK_VER_504004
export CONFIG_BRCM_SDK_VER_504005
include $(INCLUDE_DIR)/package.mk
@@ -52,7 +38,7 @@ endef
define Package/endptmngr
CATEGORY:=Utilities
TITLE:=Brcmslic
TITLE:=Broadcom Voice Endpoint Manager
URL:=
DEPENDS:= +libubox +ubus +libpicoevent +uci +bcmkernel @TARGET_HAS_VOICE @BCM_VOICE
endef
@@ -61,18 +47,9 @@ define Package/endptmngr/description
endptmngr
endef
ifeq ($(CONFIG_ENDPT_OPEN),y)
define Build/Compile
endef
endif
define Package/endptmngr/install
$(CP) ./files/* $(1)/
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_DIR) $(1)/etc/init.d/
cp $(PKG_BUILD_DIR)/files/etc/init.d/* $(1)/etc/init.d/
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/endptmngr $(1)/usr/sbin/
endef

View File

@@ -0,0 +1,25 @@
#!/bin/sh /etc/rc.common
START=68
STOP=12
USE_PROCD=1
NAME=endptmngr
start_service() {
procd_open_instance
procd_set_param env hw_board_hasDect=$(db get hw.board.hasDect)
procd_set_param command $NAME
procd_set_param respawn "5" "0" "3"
procd_set_param nice -12
procd_close_instance
}
reload_service() {
stop
start
}
service_triggers() {
procd_add_reload_trigger asterisk
}

51
fdtextract/Makefile Normal file
View File

@@ -0,0 +1,51 @@
#
# Copyright (C) 2021 IOPSYS Software Solutions AB
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=fdtextract
PKG_RELEASE:=1
PKG_VERSION:=1.0
PKG_SOURCE_URL:=https://dev.iopsys.eu/iopsys/fdtextract.git
PKG_SOURCE_PROTO:=git
PKG_SOURCE_VERSION:=485a38bc4eaf2a54d080b8529d5130b2955626d1
PKG_MIRROR_HASH:=skip
PKG_LICENSE:=GPLv2
PKG_LICENSE_FILES:=LICENSE
RSTRIP:=true
export BUILD_DIR
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
PKG_BUILD_PARALLEL:=1
include $(INCLUDE_DIR)/package.mk
define Package/$(PKG_NAME)
CATEGORY:=Utilities
TITLE:=fdtextract
DEPENDS:= +libfdt
endef
define Package/$(PKG_NAME)/description
Command to extract sub images from FIT images.
endef
MAKE_FLAGS += \
CFLAGS+="-Wall"
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/fdtextract $(1)/usr/sbin/
$(STRIP) $(1)/usr/sbin/fdtextract
endef
$(eval $(call BuildPackage,$(PKG_NAME)))

View File

@@ -1,9 +1,5 @@
if PACKAGE_icwmp
config CWMP_SCRIPTS_FULL
bool "Install all icwmp scripts"
default y
choice
prompt "Select ACS sever"
default CWMP_ACS_MULTI

View File

@@ -8,11 +8,11 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=icwmp
PKG_VERSION:=6.5.5-2021-03-25
PKG_VERSION:=7.0.1-2021-04-15
PKG_FIXUP:=autoreconf
PKG_SOURCE_URL:=https://dev.iopsys.eu/iopsys/icwmp.git
PKG_SOURCE_PROTO:=git
PKG_SOURCE_VERSION:=09a669ffa8bc94ca91bec684b5313cf309fc720e
PKG_SOURCE_VERSION:=f70cc81e5688e32aa82084faae5bc6ff710bb81b
PKG_RELEASE=$(PKG_SOURCE_VERSION)
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
PKG_MIRROR_HASH:=skip
@@ -99,14 +99,7 @@ endif
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/etc/icwmpd
$(INSTALL_DIR) $(1)/usr/sbin
$(CP) $(PKG_BUILD_DIR)/bin/icwmpd $(1)/usr/sbin
ifeq ($(CONFIG_CWMP_SCRIPTS_FULL),y)
$(INSTALL_DIR) $(1)/usr/share/icwmp
$(CP) $(PKG_BUILD_DIR)/scripts/defaults $(1)/usr/share/icwmp
$(CP) $(PKG_BUILD_DIR)/scripts/functions $(1)/usr/share/icwmp
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/scripts/icwmp.sh $(1)/usr/sbin/icwmp
endif
$(INSTALL_BIN) $(PKG_BUILD_DIR)/bin/icwmpd $(1)/usr/sbin/
$(CP) ./files/* $(1)/
endef

View File

@@ -6,7 +6,6 @@ CONFIG_DEVEL=y
CONFIG_PACKAGE_6in4=y
CONFIG_PACKAGE_6rd=y
CONFIG_PACKAGE_6to4=y
CONFIG_PACKAGE_alsa-lib=y
CONFIG_PACKAGE_at=y
CONFIG_PACKAGE_atftp=m
CONFIG_PACKAGE_atftpd=m
@@ -20,6 +19,7 @@ CONFIG_PACKAGE_ds-lite=y
CONFIG_PACKAGE_ethtool=y
CONFIG_PACKAGE_getopt=y
CONFIG_PACKAGE_glib2=y
CONFIG_PACKAGE_gre=y
CONFIG_PACKAGE_icwmp=y
CONFIG_PACKAGE_ieee1905=y
CONFIG_PACKAGE_map-1905=y
@@ -88,15 +88,14 @@ CONFIG_PACKAGE_rpcd-mod-rpcsys=y
CONFIG_PACKAGE_rulengd=y
CONFIG_PACKAGE_strace=y
CONFIG_PACKAGE_swmodd=m
CONFIG_PACKAGE_tc=y
CONFIG_PACKAGE_tcpdump=y
CONFIG_PACKAGE_terminfo=y
CONFIG_PACKAGE_traceroute6=y
CONFIG_PACKAGE_uledd=y
CONFIG_PACKAGE_umbim=y
CONFIG_PACKAGE_uqmi=y
CONFIG_PACKAGE_urlfilter=y
CONFIG_PACKAGE_usb-modeswitch=y
CONFIG_PACKAGE_usbreset=y
CONFIG_PACKAGE_uspd=y
CONFIG_PACKAGE_vsftpd-tls=m
CONFIG_PACKAGE_wwan=y
@@ -190,6 +189,7 @@ CONFIG_BUSYBOX_CONFIG_FEATURE_VOLUMEID_LINUXSWAP=y
CONFIG_BUSYBOX_CONFIG_FEATURE_VOLUMEID_SQUASHFS=y
CONFIG_BUSYBOX_CONFIG_FEATURE_VOLUMEID_UBIFS=y
CONFIG_BUSYBOX_CONFIG_TIMEOUT=y
CONFIG_BUSYBOX_CONFIG_NOHUP=y
CONFIG_LIBCURL_CRYPTO_AUTH=y
# CONFIG_LIBCURL_MBEDTLS is not set
CONFIG_LIBCURL_OPENSSL=y
@@ -225,4 +225,3 @@ CONFIG_TARGET_ROOTFS_TARGZ=y
# Disable it. Most SoCs nowadays has HW random generators anyway.
# CONFIG_PACKAGE_urandom-seed is not set
# CONFIG_PACKAGE_urngd is not set

View File

@@ -32,7 +32,7 @@ function feeds_update {
fi
# targets need to be installed explicitly
targets="iopsys-brcm63xx-arm iopsys-ramips intel_mips iopsys-x86 iopsys-armvirt iopsys-bcm27xx"
targets="iopsys-brcm63xx-arm iopsys-ramips intel_mips iopsys-x86 iopsys-armvirt iopsys-bcm27xx iopsys-mediatek"
for target in $targets
do
rm -f target/linux/$target

View File

@@ -18,6 +18,7 @@ function genconfig {
brcm63xx_arm="target/linux/iopsys-brcm63xx-arm"
ramips="target/linux/iopsys-ramips"
intel_mips="target/linux/intel_mips"
mediatek="target/linux/iopsys-mediatek"
x86="target/linux/iopsys-x86"
armvirt="target/linux/iopsys-armvirt"
@@ -113,6 +114,8 @@ function genconfig {
iopsys_brcm63xx_arm=$(cd $brcm63xx_arm; ./genconfig)
[ -e $ramips/genconfig ] &&
iopsys_ramips=$(cd $ramips; ./genconfig)
[ -e $mediatek/genconfig ] &&
iopsys_mediatek=$(cd $mediatek; ./genconfig)
[ -e $intel_mips/genconfig ] &&
iopsys_intel_mips=$(cd $intel_mips; ./genconfig)
[ -e $x86/genconfig ] &&
@@ -123,7 +126,7 @@ function genconfig {
iopsys_bcm27xx=$(cd $bcm27xx; ./genconfig)
if [ "$profile" == "LIST" ]; then
for list in iopsys_brcm63xx_arm iopsys_ramips iopsys_intel_mips iopsys_x86 iopsys_armvirt iopsys_bcm27xx; do
for list in iopsys_brcm63xx_arm iopsys_ramips iopsys_mediatek iopsys_intel_mips iopsys_x86 iopsys_armvirt iopsys_bcm27xx; do
echo "$list based boards:"
for b in ${!list}; do
echo -e "\t$b"
@@ -148,6 +151,14 @@ function genconfig {
fi
done
for p in $iopsys_mediatek; do
if [ $p == $profile ]; then
target="iopsys_mediatek"
target_config_path="$mediatek/config"
return
fi
done
for p in $iopsys_intel_mips; do
if [ $p == $profile ]; then
target="intel_mips"
@@ -358,6 +369,11 @@ function genconfig {
echo "CONFIG_TARGET_${target}=y" >> .config
echo "CONFIG_TARGET_${target}_${subtarget}=y" >> .config
echo "CONFIG_TARGET_${target}_${subtarget}_DEVICE_${BOARDTYPE}=y" >> .config
elif [ "$target" = "iopsys_mediatek" ]; then
subtarget="mt7622"
echo "CONFIG_TARGET_${target}=y" >> .config
echo "CONFIG_TARGET_${target}_${subtarget}=y" >> .config
echo "CONFIG_TARGET_${target}_${subtarget}_DEVICE_${BOARDTYPE}=y" >> .config
elif [ "$target" = "iopsys_bcm27xx" ]; then
subtarget="iopsys_bcm2711"
echo "CONFIG_TARGET_${target}=y" >> .config
@@ -429,7 +445,7 @@ function genconfig {
fi
# Force regeneration of themes
touch package/feeds/juci/juci/Makefile
touch package/feeds/iopsys/juci/Makefile
# Force regeneration of kernel Makefile
# Needed to disable kmods for iopsys-brcm targets

122
juci/Makefile Normal file
View File

@@ -0,0 +1,122 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=juci
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://dev.iopsys.eu/iopsys/juci.git
PKG_SOURCE_VERSION:=70b66bfc7f0e25e77b6920c3d44e5b05f4bfcf95
PKG_VERSION:=2020-05-27
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_SOURCE:=$(PKG_NAME)-$(PKG_SOURCE_VERSION).tar.gz
PKG_MIRROR_HASH:=skip
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_SOURCE_SUBDIR)
PKG_RELEASE=$(PKG_VERSION)-$(PKG_SOURCE_VERSION)
PKG_LICENSE:=GPLv2
PKG_LICENSE_FILES:=LICENSE
include $(INCLUDE_DIR)/package.mk
define Package/juci
$(Package/juci/default)
SECTION:=juci
CATEGORY:=JUCI
MENU=1
TITLE:=JUCI Core Package (select this to select default plugins)
DEPENDS:=+libubox +libubus +owsd +rpcd +rpcd-mod-file +questd
endef
define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/src/
ln -s $(PKG_BUILD_DIR) $(1)/usr/src/juci
endef
define Build/Compile
$(call Build/Compile/Default,THEME_PATH="$(TOPDIR)/tmp/juci-themes/")
endef
define Package/juci/description
JUCI Javascript UCI Web interface.
endef
define Package/juci/install
$(INSTALL_DIR) $(1)/
$(CP) $(PKG_BUILD_DIR)/bin/juci/* $(1)/
$(CP) ./files/* $(1)/
endef
define Package/juci/postinst
#!/bin/sh
juci-update
exit 0
endef
$(eval $(call BuildPackage,juci))
####### Extensions / Themes and Plugins
define RegisterAddonInner
define Package/$(2)
SECTION:=juci
CATEGORY:=JUCI
TITLE:=default
SUBMENU:=$(1)
TITLE:=$(if $(3),$(3),JUCI $(2) plugin)
DEPENDS:=$(4)
endef
define Package/$(2)/install
$(INSTALL_DIR) $$(1)/
$(CP) $(PKG_BUILD_DIR)/bin/$(2)/* $$(1)/
endef
endef
define RegisterAddon
$(eval $(call RegisterAddonInner,$(1),$(2),$(3),$(4),$(5)))
$(eval $(call BuildPackage,$(2)))
endef
$(eval $(call RegisterAddon,Plugins,juci-catv, CATV Module,@(PACKAGE_catv)))
$(eval $(call RegisterAddon,Plugins,juci-cgroups, CGroups Module,@(PACKAGE_icgroupd)))
$(eval $(call RegisterAddon,Plugins,juci-ddns, DDNS Configuration,@(PACKAGE_ddns-scripts)))
$(eval $(call RegisterAddon,Plugins,juci-diagnostics, Simple Diagnostics,@(PACKAGE_busybox)))
$(eval $(call RegisterAddon,Plugins,juci-ndt, NDT Speed Test client,@(PACKAGE_ndt)))
$(eval $(call RegisterAddon,Plugins,juci-dnsmasq-dhcp, DHCP/DNSMasq Configuration,@(PACKAGE_dnsmasq||PACKAGE_dnsmasq-full)))
$(eval $(call RegisterAddon,Plugins,juci-dropbear, Dropbear Configuration,@(PACKAGE_dropbear)))
$(eval $(call RegisterAddon,Plugins,juci-easyqos, Easy QoS module,@(PACKAGE_easy-qos)))
$(eval $(call RegisterAddon,Plugins,juci-event, Event Module,@(PACKAGE_owsd)))
$(eval $(call RegisterAddon,Plugins,juci-firewall-fw3, Firewall Configuration,@(PACKAGE_firewall)))
$(eval $(call RegisterAddon,Plugins,juci-icwmp, TR-069 Module,@(PACKAGE_icwmp)))
$(eval $(call RegisterAddon,Plugins,juci-config-backup, Config Backup Module))
$(eval $(call RegisterAddon,Plugins,juci-qos, QoS module,@(PACKAGE_qos-scripts)))
$(eval $(call RegisterAddon,Plugins,juci-voice-client, Asterisk Voice Client Module,@(PACKAGE_asterisk)))
$(eval $(call RegisterAddon,Plugins,juci-minidlna, MiniDLNA Configuration,@(PACKAGE_minidlna)))
$(eval $(call RegisterAddon,Plugins,juci-mcproxy, Multicast Proxy Configuration,@(PACKAGE_mcproxy)))
$(eval $(call RegisterAddon,Plugins,juci-mod-status, Status Reporting Module,@(PACKAGE_questd)))
$(eval $(call RegisterAddon,Plugins,juci-mod-system, System Administration Module))
$(eval $(call RegisterAddon,Plugins,juci-mwan3, mwan3 Configuration,@(PACKAGE_mwan3)))
$(eval $(call RegisterAddon,Plugins,juci-natalie-dect, DECT Module,@(PACKAGE_dectmngr2)))
$(eval $(call RegisterAddon,Plugins,juci-netmode, Netmode Module,@(PACKAGE_netmode)))
$(eval $(call RegisterAddon,Plugins,juci-network-device, Network Device Configuration,@(PACKAGE_netifd)))
$(eval $(call RegisterAddon,Plugins,juci-network-dsl, DSL Module))
$(eval $(call RegisterAddon,Plugins,juci-network-netifd, Network Module,@(PACKAGE_netifd)))
$(eval $(call RegisterAddon,Plugins,juci-network-port, Ethernet Port Configuration,@(PACKAGE_port-management)))
$(eval $(call RegisterAddon,Plugins,juci-openvpn, OpenVPN configuration,@(PACKAGE_openvpn)))
$(eval $(call RegisterAddon,Plugins,juci-owsd, OWSD configuration,@(PACKAGE_owsd)))
$(eval $(call RegisterAddon,Plugins,juci-printer, p910nd Printer Server Configuration,@(PACKAGE_p910nd)))
#$(eval $(call RegisterAddon,Plugins,juci-realtime-graphs, Realtime Graphs))
$(eval $(call RegisterAddon,Plugins,juci-samba, Samba Configuration,@(PACKAGE_samba3)))
$(eval $(call RegisterAddon,Plugins,juci-sfp, SFP Configuration,@(PACKAGE_peripheral_manager)))
$(eval $(call RegisterAddon,Plugins,juci-snmpd, SNMP Module,@(PACKAGE_snmpd)))
$(eval $(call RegisterAddon,Plugins,juci-sysupgrade, Sysupgrade Firmware Upgrade,@(PACKAGE_rpcd-mod-rpcsys)))
$(eval $(call RegisterAddon,Plugins,juci-uhttpd, uHTTPD Configuration,@(PACKAGE_uhttpd)))
$(eval $(call RegisterAddon,Plugins,juci-upnp, UPnP Configuration Module,@(PACKAGE_miniupnpd)))
#$(eval $(call RegisterAddon,Plugins,juci-usb, USB Module))
$(eval $(call RegisterAddon,Plugins,juci-wireless, Wireless Management Module))
$(eval $(call RegisterAddon,Plugins,juci-wifilife, WiFi Life Module,@(PACKAGE_wifilife)))
$(eval $(call RegisterAddon,Themes,juci-theme-iopsys))
####### dynamically publish themes as packages #######
$(foreach th,$(wildcard $(TOPDIR)/tmp/juci-themes/*),$(eval $(call RegisterAddon,Themes,$(notdir $(th)))))

View File

@@ -0,0 +1,66 @@
config juci 'juci'
option homepage 'overview'
option theme 'juci-theme-iopsys'
option favicon 'favicon.ico'
config login 'login'
option showusername '1'
option defaultuser 'user'
config localization 'localization'
option default_language 'en'
list languages 'en'
config wiki 'wiki'
option visible '0'
option version 'v4.2.x'
config widget
list name 'overviewWidget11WAN'
list require 'ubus:network.interface'
config widget
list name 'overviewWidget10Network'
list require 'ubus:network.interface'
list require 'ubus:router.network->hosts'
config widget
list name 'overviewWidget00WiFi'
list require 'ubus:wifi'
list require 'ubus:wifi.wps'
config menu
option path 'overview'
option page 'overview'
config menu
option path 'system'
option page 'system'
option redirect 'first'
config menu
option path 'status'
option page 'status'
option redirect 'first'
config menu
option path 'status/system'
option page 'status-system'
list require 'ubus:router.system->info'
config menu
option path 'status/network'
option page 'status-network'
list require 'ubus:network.interface'
config menu
option path 'status/dsl'
option page 'network-dsl-status'
list require 'ubus:dsl->stats'
list require 'ubus:dsl->status'
config menu
option path 'system/upgrade'
option page 'settings-upgrade'
list expose 'admin'

41
juci/files/etc/init.d/juci Executable file
View File

@@ -0,0 +1,41 @@
#!/bin/sh /etc/rc.common
. /lib/functions.sh
START=94
STOP=06
USE_PROCD=1
NAME=juci
start_service() {
mkdir -p /tmp/juci
touch /www/index.html.gz
chmod 755 /www/cgi-bin/luci
# this will simply update index.html to include any files that are for some reason not included
# a good way to make sure all plugins are properly included at each boot
config_load juci
local theme
config_get theme juci theme
if [ "$theme" ]
then
if [ -f /www/themes/theme.js.gz ]
then
rm -f /www/themes/theme.js.gz
fi
if [ -f /www/themes/*$theme.js.gz ]
then
ln -s /www/themes/*$theme.js.gz /www/themes/theme.js.gz
fi
fi
juci-update
}
stop() {
service_stop /sbin/juci
}
service_triggers()
{
procd_add_reload_trigger juci
}

View File

@@ -0,0 +1,49 @@
#!/bin/sh
. /lib/functions.sh
USER_SECTION=""
USER_EXISTS=0
find_user(){
local section="$1"
local user="$2"
config_get username $section username
if [ "$username" == "$user" ]; then
USER_SECTION="$section"
USER_EXISTS=1
fi
}
config_load rpcd
USER_EXISTS=0
config_foreach find_user login root
if [ $USER_EXISTS -eq 1 ]; then
uci delete rpcd.$USER_SECTION
fi
USER_EXISTS=0
config_foreach find_user login admin
if [ $USER_EXISTS -eq 0 ]; then
uci -q add rpcd login >/dev/null
uci -q set rpcd.@login[-1].username="admin"
uci -q set rpcd.@login[-1].password="\$p\$admin"
uci -q add_list rpcd.@login[-1].read="enduser"
uci -q add_list rpcd.@login[-1].read="administrator"
uci -q add_list rpcd.@login[-1].write="enduser"
uci -q add_list rpcd.@login[-1].write="administrator"
fi
USER_EXISTS=0
config_foreach find_user login user
if [ $USER_EXISTS -eq 0 ]; then
uci -q add rpcd login >/dev/null
uci -q set rpcd.@login[-1].username="user"
uci -q set rpcd.@login[-1].password="\$p\$user"
uci -q add_list rpcd.@login[-1].read="enduser"
uci -q add_list rpcd.@login[-1].write="enduser"
fi
uci commit rpcd

View File

@@ -0,0 +1,21 @@
{
"administrator": {
"description": "Administrator Access Rights",
"read": {
"ubus": {
"file": [
"write"
],
"rpc-sys": [
"upgrade_start",
"upgrade_test"
]
}
},
"write": {
"file": {
"/tmp/firmware.bin": ["write"]
}
}
}
}

View File

@@ -0,0 +1,217 @@
{
"enduser": {
"description": "End User Access Rights",
"read": {
"ubus": {
"dect": [
"state",
"handset",
"status",
"call"
],
"dsl": [
"status",
"stats"
],
"network.device": [
"status"
],
"network.interface*": [
"status",
"dump",
"up",
"down"
],
"router.network": [
"clients",
"hosts",
"dump"
],
"router.system": [
"info",
"memory",
"filesystem",
"process",
"processes"
],
"session": [
"access",
"list",
"destroy",
"login"
],
"system": [
"info",
"board",
"reboot"
],
"testnet": [
"status"
],
"uci": [
"*"
],
"voice.asterisk": [
"status",
"call_log",
"platform",
"supported_countries"
],
"wifi": [
"status"
],
"wifi.ap.*": [
"status",
"stats",
"assoclist",
"stations"
],
"wifi.radio.*": [
"status",
"stats",
"scan",
"scanresults",
"autochannel"
],
"wifi.wps": [
"start",
"stop",
"status",
"showpin"
]
},
"uci": [
"dhcp",
"firewall",
"juci",
"network",
"voice_client",
"wireless"
],
"owsd": [
"client",
"wifi.radio",
"wifi.sta",
"wifi.wps"
]
},
"write": {
"uci": [
"dhcp",
"firewall",
"network",
"wireless"
],
"uci_granular": {
"dhcp": [
{
"match": {
".type": "dhcp"
},
"option": [
"*"
]
},
{
"match": {
".type": "host"
},
"option": [
"*"
]
}
],
"firewall": [
{
"match": {
".type": "settings",
".name": "settings"
},
"option": [
"disabled"
]
},
{
"match": {
".type": "zone"
},
"option": [
"masq",
"name",
"network"
]
},
{
"match": {
".type": "redirect"
},
"option": [
"*"
]
},
{
"match": {
".type": "rule"
},
"option": [
"*"
]
},
{
"match": {
".type": "dmz"
},
"option": [
"enabled",
"host",
"ip6addr"
]
}
],
"network": [
{
"match": {
".type": "interface"
},
"option": [
"*"
]
}
],
"wireless": [
{
"match": {
".type": "wifi-status"
},
"option": [
"wps"
]
},
{
"match": {
".type": "wifi-iface",
"mode": "ap"
},
"option": [
"*"
]
},
{
"match": {
".type": "wifi-device"
},
"option": [
"channel"
]
}
]
},
"owsd": [
"client",
"wifi.radio",
"wifi.sta",
"wifi.wps"
]
}
}
}

View File

@@ -11,6 +11,7 @@ PKG_SOURCE_VERSION:=e4b4c5cce35a52da152776a00532aa0b80879c5b
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
PKG_MIRROR_HASH:=skip
PKG_LICENSE:=GPLv2
PKG_LICENSE_FILES:=COPYING

View File

@@ -5,9 +5,9 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=map-agent
PKG_VERSION:=3.5.14
PKG_VERSION:=3.5.20
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
PKG_SOURCE_VERSION:=cba3b22b0d02cec76a3e421302441b55f0788aea
PKG_SOURCE_VERSION:=f396b503f111461e7869f302907e1d9ec639ca3a
PKG_MAINTAINER:=Anjan Chanda <anjan.chanda@iopsys.eu>
PKG_LICENSE:=PROPRIETARY IOPSYS

View File

@@ -0,0 +1,84 @@
#!/bin/sh
diff=0
wan=$(uci -q get ports.WAN.ifname)
[ "$wan" == "" ] && exit 1 # no configuration
[ "$PORT" != "$wan" ] && exit 0
get_bridge() {
local id
local ifname="$1"
local bridge=""
id=$(cat /sys/class/net/${ifname}/brport/bridge/bridge/bridge_id)
#echo "bridge id = $id" > /dev/console
[ "$id" = "" ] && return
bridge=$(brctl show | grep $id | cut -f1)
case "$bridge" in
br-*)
bridge=$(echo $bridge | cut -c4-)
;;
esac
echo $bridge
}
disable_bstas() {
section="$1"
config_get mode "$section" mode "ap"
config_get ifname "$section" ifname
config_get device "$section" device
#echo mode=$mode ifname=$ifname > /dev/console
[ "$mode" == "sta" ] || return
uci set wireless.$section.disabled=1
bridge=$(get_bridge $ifname)
if [ "$bridge" != "" ]; then
#echo got bridge = $bridge > /dev/console
ubus call network.interface.$bridge remove_device '{"name":"$ifname"}'
fi
ifconfig "$ifname" down
diff=1
#echo disabled $ifname > /dev/console
}
enable_bstas() {
section="$1"
config_load "wireless"
config_get mode "$section" mode "ap"
config_get ifname "$section" ifname
config_get device "$section" device
#echo mode=$mode ifname=$ifname > /dev/console
[ "$mode" == "sta" ] || return
uci set wireless.$section.disabled=0
ifconfig "$ifname" up
diff=1
#echo enabled $ifname > /dev/console
}
config_load "wireless"
if [ "$LINK" == "up" ]; then
config_foreach disable_bstas wifi-iface
else
config_foreach enable_bstas wifi-iface
fi
#echo diff = $diff > /dev/console
uci -q commit wireless
[ "$diff" == "1" ] && {
#echo reloading via uci > /dev/console
ubus call uci commit '{"config":"wireless"}'
}

View File

@@ -5,9 +5,9 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=map-controller
PKG_VERSION:=2.4.9
PKG_VERSION:=2.4.12
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
PKG_SOURCE_VERSION:=4a48b471e90f11b3685829affd8cbf27604f3b38
PKG_SOURCE_VERSION:=e4d286f6348519de2613d4ba3548ec811c60ad7b
PKG_LICENSE:=PROPRIETARY IOPSYS
PKG_LICENSE_FILES:=LICENSE

View File

@@ -5,8 +5,16 @@ STOP=20
USE_PROCD=1
handle_controller_select() {
local section="$1"
config_get_bool local_ctrl "$section" local 0
return 1
}
start_service() {
local enabled
local local_ctrl=0
config_load "mapcontroller"
config_get_bool enabled controller enabled 1
@@ -14,6 +22,11 @@ start_service() {
procd_open_instance
procd_set_param command "/usr/sbin/mapcontroller" "-d"
config_load "mapagent"
config_foreach handle_controller_select controller_select
[ "$local_ctrl" -eq 0 ] && procd_append_param command "-w"
procd_set_param respawn
# procd_set_param stdout 1
# procd_set_param stderr 1
@@ -35,5 +48,11 @@ reload_service() {
return
fi
pidof "mapcontroller" > /dev/null
if [[ $? -ne 0 ]] ; then
start
return
fi
procd_send_signal "mapcontroller"
}

View File

@@ -6,11 +6,11 @@ include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=map-topology
PKG_VERSION:=1.5.20
PKG_VERSION:=1.5.22
LOCAL_DEV:=0
ifneq ($(LOCAL_DEV),1)
PKG_SOURCE_VERSION:=d542c50c81d09f553bdd36dd12fd9eb7618f4463
PKG_SOURCE_VERSION:=f10842f576fc29f6c3145a4b4b0efcb931d0e643
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://dev.iopsys.eu/iopsys/map-topology.git
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.xz

View File

@@ -16,10 +16,9 @@ start_service() {
service_triggers()
{
procd_add_reload_trigger "ieee1905"
procd_add_reload_trigger "network"
}
reload_service() {
stop
start
procd_send_signal "topologyd"
}

View File

@@ -51,6 +51,9 @@ if [ -s "/etc/config/mcast" ]; then
if uci -q get mcast.@proxy[0] >/dev/null; then
# return if there is any valid content
exit
elif uci -q get mcast.@snooping[0] >/dev/null; then
# return if there is any valid content
exit
else
rm -f /etc/config/mcast
fi

15
obuspa/Config.in Normal file
View File

@@ -0,0 +1,15 @@
if PACKAGE_obuspa
config OBUSPA_MTP_ENABLE_STOMP
bool "Enable STOMP as mtp protocol"
default y
config OBUSPA_MTP_ENABLE_MQTT
bool "Enable MQTT as mtp protocol"
default y
config OBUSPA_MTP_ENABLE_COAP
bool "Enable CoAP as mtp protocol"
default y
endif

View File

@@ -5,13 +5,14 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=obuspa
PKG_VERSION:=3.0.0.25
PKG_VERSION:=3.0.0.32
LOCAL_DEV:=0
ifneq ($(LOCAL_DEV),1)
PKG_SOURCE_PROTO:=git
PKG_SOURCE_VERSION:=617c724d409bf8d44fb2bf7b4ac47bb6dfe6c0eb
PKG_SOURCE_VERSION:=7afcb04746566f19478dfdb5dd922d57d9e60166
PKG_SOURCE_URL:=https://dev.iopsys.eu/fork/obuspa.git
PKG_MAINTAINER:=Vivek Dutta <vivek.dutta@iopsys.eu>
PKG_SOURCE:=$(PKG_NAME)-$(PKG_SOURCE_VERSION).tar.gz
PKG_MIRROR_HASH:=skip
endif
@@ -29,17 +30,46 @@ define Package/obuspa
SECTION:=utils
CATEGORY:=Utilities
TITLE:=USP agent
DEPENDS:=+libopenssl +libcurl +libsqlite3 +libubox +libubus +uspd +libmosquitto
PKG_BUILD_DEPENDS:=+openssl +ubus +sqlite3 +curl +ubox +uci
DEPENDS:=+libopenssl +libcurl +libsqlite3 +libubox +libubus +libmosquitto +uspd +libuci
endef
define Package/obuspa/description
OB-USP-AGENT is a system daemon providing a User Services Platform (USP) Agent.
endef
define Package/obuspa/config
source "$(SOURCE)/Config.in"
endef
TARGET_CFLAGS += \
-I$(STAGING_DIR)/usr/include \
-D_GNU_SOURCE
ifeq ($(CONFIG_OBUSPA_MTP_ENABLE_STOMP),y)
CONFIGURE_ARGS += \
--enable-stomp
else
CONFIGURE_ARGS += \
--disable-stomp
endif
ifeq ($(CONFIG_OBUSPA_MTP_ENABLE_MQTT),y)
CONFIGURE_ARGS += \
--enable-mqtt
else
CONFIGURE_ARGS += \
--disable-mqtt
endif
ifeq ($(CONFIG_OBUSPA_MTP_ENABLE_COAP),y)
CONFIGURE_ARGS += \
--enable-coap
else
CONFIGURE_ARGS += \
--disable-coap
endif
ifeq ($(LOCAL_DEV),1)
define Build/Prepare
$(CP) -rf ~/git/obuspa/* $(PKG_BUILD_DIR)/
@@ -55,6 +85,7 @@ define Package/obuspa/install
$(INSTALL_BIN) $(PKG_BUILD_DIR)/obuspa $(1)/usr/sbin/
$(INSTALL_BIN) ./files/etc/init.d/obuspa $(1)/etc/init.d/
$(INSTALL_DATA) ./files/etc/config/obuspa $(1)/etc/config/
$(INSTALL_DATA) ./files/etc/obuspa/roles.json $(1)/etc/obuspa/roles.json
$(INSTALL_BIN) ./files/etc/hotplug.d/iface/85-obuspa $(1)/etc/hotplug.d/iface/
endef

View File

@@ -1,16 +1,17 @@
config obuspa 'global'
option enabled 'true'
option enabled '1'
option interface 'wan'
#option ifname 'eth0.1'
option debug '0'
option log_level '1'
#option db_file '/tmp/usp.db'
#option db_file '/etc/obuspa/usp.db'
option role_file '/etc/obuspa/roles.json'
#option trust_cert '/etc/obuspa/rootCA.pem'
#option client_cert '/etc/obuspa/client.pem'
#option log_dest '/var/log/obuspa'
config localagent 'localagent'
option Enable 'true'
option Enable '1'
# Adds Device.LocalAgent.Controller.
config controller 'localcontroller'
@@ -18,6 +19,7 @@ config controller 'localcontroller'
option Protocol 'MQTT'
option Topic '/usp/controller'
option mqtt 'localmqtt'
option assigned_role_name 'Full Access'
# Adds Device.LocalAgent.MTP.
config mtp
@@ -41,3 +43,18 @@ config subscription
option Persistent 'true'
option controller 'localcontroller'
config challenge 'admin'
option Description 'Request to get Administrative access'
option role_name 'Full Access'
option Enable '1'
option Value 'admin'
option Retries 2
option LockoutPeriod 60
config challenge 'user'
option Description 'Request to get User access'
option role_name 'user'
option Enable '1'
option Value 'user'
option Retries 3
option LockoutPeriod 30

View File

@@ -5,7 +5,7 @@ USE_PROCD=1
PROG=/usr/sbin/obuspa
EXTRA_COMMANDS="remove_db"
EXTRA_HELP=" remove_db Removes obuspa persistent db before restarting"
EXTRA_HELP=" remove_db Removes obuspa persistent db before restarting, self trigger with uci change"
PARAM_FILE="/tmp/obuspa_param_reset.txt"
CONFIGURATION=obuspa
@@ -16,9 +16,20 @@ mtp_num=0
stomp_num=0
mqtt_num=0
subs_num=0
challenge_num=0
index=0
role_def_file=""
. /lib/functions/network.sh
. /usr/share/libubox/jshn.sh
cleanup() {
if [ -f "${USP_TEMP_FILE}" ]; then
rm -f "${USP_TEMP_FILE}"
fi
}
trap cleanup EXIT
log() {
echo "${@}"|logger -t obuspa -p debug
@@ -39,6 +50,37 @@ get_index() {
fi
}
get_role_index_from_json() {
local role="${@}"
# In case of role is empty or file not present
if [ -z "${role}" -o ! -f ${role_def_file} ]; then
echo 0
return 0
fi
json_init
json_load_file ${role_def_file}
if [ $? -ne 0 ]; then # In case of invalid json file
echo 0
return 0
fi
json_select roles
json_get_keys roles_obj
for k in ${roles_obj}; do
json_select $k
json_get_var name name
json_select ..
if [ "${role}" = "${name}" ]; then
echo "${k}"
return 0
fi
done
echo 0
}
get_uci_ref_index() {
local val;
@@ -62,14 +104,15 @@ validate_obuspa_section()
{
uci_validate_section ${CONFIGURATION} obuspa "${1}" \
'enabled:bool:true' \
'trust_cert:string' \
'client_cert:string' \
'trust_cert:file' \
'client_cert:file' \
'interface:string' \
'ifname:string:"br-lan"' \
'debug:bool:false' \
'log_level:uinteger' \
'log_dest:string' \
'db_file:string'
'log_dest:file' \
'db_file:file' \
'role_file:file'
}
validate_localagent_section()
@@ -85,7 +128,8 @@ validate_controller_section()
uci_validate_section ${CONFIGURATION} controller "${1}" \
'EndpointID:string' \
'Enable:bool:true' \
'AssignedRole:string:Device.LocalAgent.ControllerTrust.Role.1' \
'AssignedRole:string' \
'assigned_role_name:string' \
'PeriodicNotifInterval:uinteger:86400' \
'PeriodicNotifTime:string' \
'USPNotifRetryMinimumWaitInterval:uinteger:5' \
@@ -95,9 +139,9 @@ validate_controller_section()
'Reference:string' \
'Destination:string:controller-notify-dest' \
'Topic:string' \
'coap_host:string' \
'coap_host:host' \
'coap_path:string' \
'coap_port:uinteger' \
'coap_port:port' \
'mqtt:string' \
'stomp:string'
}
@@ -124,7 +168,7 @@ validate_mtp_section()
'PublishQoS:uinteger' \
'Destination:string' \
'coap_path:string' \
'coap_port:uinteger' \
'coap_port:port' \
'mqtt:string' \
'stomp:string'
}
@@ -132,12 +176,12 @@ validate_mtp_section()
validate_stomp_connection_section()
{
uci_validate_section ${CONFIGURATION} stomp "${1}" \
'Host:string:usp-controller.com' \
'Host:host' \
'Username:string' \
'Password:string' \
'encryption:bool:true' \
'Enable:bool:true' \
'Port:uinteger:61613' \
'Port:port:61613' \
'VirtualHost:string:/' \
'EnableHeartbeats:bool:true' \
'OutgoingHeartbeat:uinteger:30000' \
@@ -150,13 +194,13 @@ validate_stomp_connection_section()
validate_mqtt_client_section()
{
uci_validate_section ${CONFIGURATION} mqtt "${1}" \
'BrokerAddress:string' \
'BrokerPort:uinteger:1883' \
'BrokerAddress:host' \
'BrokerPort:port:1883' \
'Enable:bool:true' \
'Username:string' \
'Password:string' \
'ProtocolVersion:string:5.0' \
'TransportProtocol:string:TCP/IP' \
'ProtocolVersion:or("3.1", "3.1.1","5.0"):5.0' \
'TransportProtocol:or("TCP/IP","TLS"):TCP/IP' \
'KeepAliveTime:uinteger:60' \
'ClientID:string' \
'ConnectRetryTime:uinteger:5' \
@@ -170,7 +214,7 @@ configure_localagent() {
validate_localagent_section 'localagent' || {
log "Validation of localagent section failed"
return 1;
exit 1;
}
if [ -n "${EndpointID}" ]; then
@@ -180,7 +224,6 @@ configure_localagent() {
_num=1
while [ ${_num} -le ${controller_num} ]
do
db_set Device.LocalAgent.Controller.${_num}.BootParameter.1.Alias "cpe-1"
db_set Device.LocalAgent.Controller.${_num}.BootParameter.1.Enable "${Enable}"
db_set Device.LocalAgent.Controller.${_num}.BootParameter.1.ParameterName "${ParameterName}"
_num=$(( ${_num} + 1 ))
@@ -192,14 +235,14 @@ configure_localagent() {
configure_controller() {
local EndpointID Enable AssignedRole PeriodicNotifInterval PeriodicNotifTime USPNotifRetryMinimumWaitInterval
local USPNotifRetryIntervalMultiplier ControllerCode Protocol Destination coap_host coap_path coap_port
local Reference Topic mqtt stomp
local Reference Topic mqtt stomp assigned_role_name
validate_controller_section "${1}" || {
log "Validation of controller section failed"
return 1;
exit 1;
}
if [ -z ${EndpointID} -o -z ${Protocol} ]; then
if [ -z "${EndpointID}" -o -z "${Protocol}" ]; then
log "controller:: EndpointID id and Protocol cannot be empty"
return 1;
fi
@@ -229,10 +272,17 @@ configure_controller() {
controller_num=$(( controller_num + 1 ))
db_set Device.LocalAgent.Controller.${controller_num}.Alias "cpe-${controller_num}"
db_set Device.LocalAgent.Controller.${controller_num}.Enable "${Enable}"
db_set Device.LocalAgent.Controller.${controller_num}.EndpointID "${EndpointID}"
#db_set Device.LocalAgent.Controller.${controller_num}.AssignedRole "${AssignedRole}"
if [ -n "${AssignedRole}" ]; then
db_set Device.LocalAgent.Controller.${controller_num}.AssignedRole "${AssignedRole}"
else
if [ -n "${assigned_role_name}" ]; then
AssignedRole=$(get_role_index ${assigned_role_name})
db_set Device.LocalAgent.Controller.${controller_num}.AssignedRole "${AssignedRole}"
fi
fi
db_set Device.LocalAgent.Controller.${controller_num}.PeriodicNotifInterval "${PeriodicNotifInterval}"
if [ -n "${PeriodicNotifTime}" ]; then
db_set Device.LocalAgent.Controller.${controller_num}.PeriodicNotifTime "${PeriodicNotifTime}"
@@ -243,7 +293,6 @@ configure_controller() {
db_set Device.LocalAgent.Controller.${controller_num}.USPNotifRetryIntervalMultiplier "${USPNotifRetryIntervalMultiplier}"
db_set Device.LocalAgent.Controller.${controller_num}.ControllerCode "${ControllerCode}"
db_set Device.LocalAgent.Controller.${controller_num}.MTP.1.Alias "cpe-${controller_num}"
db_set Device.LocalAgent.Controller.${controller_num}.MTP.1.Enable "${Enable}"
db_set Device.LocalAgent.Controller.${controller_num}.MTP.1.Protocol "${Protocol}"
# only support configuration of one mtp path per controller using uci
@@ -270,7 +319,7 @@ configure_subscription(){
validate_subscription_section "${1}" || {
log "Validation of subscription section failed"
return 1;
exit 1;
}
if [ -z "${Recipient}" -a -z "${controller}" ]; then
@@ -288,7 +337,6 @@ configure_subscription(){
subs_num=$(( subs_num + 1))
db_set Device.LocalAgent.Subscription.${subs_num}.Alias "cpe-${subs_num}"
db_set Device.LocalAgent.Subscription.${subs_num}.Enable "${Enable}"
db_set Device.LocalAgent.Subscription.${subs_num}.ID "${ID}"
db_set Device.LocalAgent.Subscription.${subs_num}.NotifType "${NotifType}"
@@ -297,13 +345,81 @@ configure_subscription(){
db_set Device.LocalAgent.Subscription.${subs_num}.Recipient "${Recipient}"
}
validate_challenge_section()
{
uci_validate_section ${CONFIGURATION} challenge "${1}" \
'Enable:bool:true' \
'Alias:string' \
'Description:string' \
'role_name:string' \
'Role:string' \
'Value:string' \
'Retries:uinteger:3' \
'LockoutPeriod:uinteger:0'
}
get_role_index() {
local role="Device.LocalAgent.ControllerTrust.Role"
local index=0
local role_name="${@}"
case "${role_name}" in
'Full Access')
index=1;
;;
'Untrusted')
index=2;
;;
*)
local ji=$(get_role_index_from_json ${role_name})
index=$(( ji + 2 )) # Add predefined roles
esac
echo "${role}.${index}"
}
configure_challenges() {
local Enable Description role_name Role Value Retries LockoutPeriod Alias
validate_challenge_section "${1}" || {
log "Validation of challenge section failed"
exit 1;
}
if [ -z "${role_name}" -a -z ${Role} ]; then
log "Either role_name or Role must defined for a challenge";
return 1;
fi
challenge_num=$(( challenge_num + 1))
db_set Device.LocalAgent.ControllerTrust.Challenge.${challenge_num}.Enable "${Enable}"
if [ -n "${Description}" ]; then
db_set Device.LocalAgent.ControllerTrust.Challenge.${challenge_num}.Description "${Description}"
fi
if [ -z "${Role}" ]; then
Role=$(get_role_index ${role_name})
fi
if [ -z "${Alias}" -a -n "${role_name}" ]; then
Alias=${role_name}
fi
db_set Device.LocalAgent.ControllerTrust.Challenge.${challenge_num}.Alias "${Alias}"
db_set Device.LocalAgent.ControllerTrust.Challenge.${challenge_num}.Role "${Role}"
db_set Device.LocalAgent.ControllerTrust.Challenge.${challenge_num}.Value "${Value}"
db_set Device.LocalAgent.ControllerTrust.Challenge.${challenge_num}.Retries "${Retries}"
db_set Device.LocalAgent.ControllerTrust.Challenge.${challenge_num}.LockoutPeriod "${LockoutPeriod}"
}
configure_mtp() {
local Enable Protocol Reference ResponseTopicConfigured PublishQoS
local stomp mqtt
validate_mtp_section "${1}" || {
log "Validation of mtp section failed"
return 1;
exit 1;
}
if [ -z ${Reference} ]; then
@@ -325,7 +441,6 @@ configure_mtp() {
fi
mtp_num=$(( mtp_num + 1 ))
db_set Device.LocalAgent.MTP.${mtp_num}.Alias "cpe-${mtp_num}"
db_set Device.LocalAgent.MTP.${mtp_num}.Enable "${Enable}"
db_set Device.LocalAgent.MTP.${mtp_num}.Protocol "${Protocol}"
if [ "${Protocol}" = "MQTT" ]; then
@@ -354,7 +469,7 @@ configure_stomp_connection() {
validate_stomp_connection_section "${1}" || {
log "Validation of stomp section failed"
return 1;
exit 1;
}
stomp_num=$(( stomp_num + 1 ))
@@ -363,10 +478,9 @@ configure_stomp_connection() {
db_set Device.STOMP.Connection.${stomp_num}.Username "${Username}"
db_set Device.STOMP.Connection.${stomp_num}.Password "${Password}"
db_set Device.STOMP.Connection.${stomp_num}.Alias "cpe-${stomp_num}"
db_set Device.STOMP.Connection.${stomp_num}.Enable "${Enable}"
db_set Device.STOMP.Connection.${stomp_num}.Port "${Port}"
db_set Device.STOMP.Connection.${stomp_num}.X_ARRIS-COM_EnableEncryption "${encryption}"
db_set Device.STOMP.Connection.${stomp_num}.EnableEncryption "${encryption}"
db_set Device.STOMP.Connection.${stomp_num}.VirtualHost "${VirtualHost}"
db_set Device.STOMP.Connection.${stomp_num}.EnableHeartbeats "${EnableHeartbeats}"
db_set Device.STOMP.Connection.${stomp_num}.OutgoingHeartbeat "${OutgoingHeartbeat}"
@@ -383,7 +497,7 @@ configure_mqtt_client(){
validate_mqtt_client_section "${1}" || {
log "Validation of mqtt section failed"
return 1;
exit 1;
}
if [ -z "${BrokerAddress}" ]; then
@@ -393,7 +507,6 @@ configure_mqtt_client(){
mqtt_num=$(( mqtt_num + 1 ))
db_set Device.MQTT.Client.${mqtt_num}.Alias "cpe-${mqtt_num}"
db_set Device.MQTT.Client.${mqtt_num}.Enable "${Enable}"
db_set Device.MQTT.Client.${mqtt_num}.BrokerAddress "${BrokerAddress}"
db_set Device.MQTT.Client.${mqtt_num}.BrokerPort "${BrokerPort}"
@@ -412,13 +525,14 @@ configure_mqtt_client(){
configure_obuspa() {
local enabled trust_cert ifname interface debug log_level db_file log_dest
local enabled trust_cert ifname interface debug log_level db_file log_dest role_file
validate_obuspa_section "global" || {
log "Validation of global section failed"
return 1;
exit 1;
}
role_def_file="${role_file}"
[ ${enabled} -eq 0 ] && exit 0
if [ ${debug} -eq 1 ]; then
@@ -483,6 +597,7 @@ db_init() {
config_foreach configure_stomp_connection stomp
config_foreach configure_mqtt_client mqtt
config_foreach configure_subscription subscription
config_foreach configure_challenges challenge
db_set Internal.Reboot.Cause "LocalFactoryReset"
}

View File

@@ -0,0 +1,97 @@
{
"roles": [
{
"name": "admin",
"permission": [
{
"object": "Device.",
"perm": [
"PERMIT_NONE"
]
},
{
"object": "Device.DeviceInfo.",
"perm": [
"PERMIT_GET",
"PERMIT_GET_INST"
]
},
{
"object": "Device.WiFi.",
"perm": [
"PERMIT_GET",
"PERMIT_SET",
"PERMIT_ADD",
"PERMIT_DEL",
"PERMIT_OPER",
"PERMIT_SUBS_VAL_CHANGE",
"PERMIT_SUBS_OBJ_ADD",
"PERMIT_SUBS_OBJ_DEL",
"PERMIT_SUBS_EVT_OPER_COMP",
"PERMIT_GET_INST",
"PERMIT_OBJ_INFO",
"PERMIT_CMD_INFO"
]
},
{
"object": "Device.IP.",
"perm": [
"PERMIT_GET",
"PERMIT_GET_INST"
]
}
]
},
{
"name": "user",
"permission": [
{
"object": "Device.",
"perm": [
"PERMIT_NONE"
]
},
{
"object": "Device.DeviceInfo.",
"perm": [
"PERMIT_GET",
"PERMIT_GET_INST"
]
},
{
"object": "Device.WiFi.",
"perm": [
"PERMIT_GET",
"PERMIT_OPER",
"PERMIT_SUBS_VAL_CHANGE",
"PERMIT_SUBS_OBJ_ADD",
"PERMIT_SUBS_OBJ_DEL",
"PERMIT_SUBS_EVT_OPER_COMP",
"PERMIT_GET_INST",
"PERMIT_OBJ_INFO",
"PERMIT_CMD_INFO"
]
},
{
"object": "Device.IP.",
"perm": [
"PERMIT_GET",
"PERMIT_GET_INST"
]
}
]
},
{
"name": "undefined-1"
},
{
"name": "undefined-2"
},
{
"name": "undefined-3"
},
{
"name": "undefined-4"
}
]
}

View File

@@ -9,10 +9,10 @@ include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=peripheral_manager
PKG_VERSION:=1.0.5
PKG_VERSION:=1.0.6
PKG_RELEASE:=1
PKG_SOURCE_VERSION:=d9c22221f6cb414126978c92295fdcc0885e3285
PKG_SOURCE_VERSION:=785166a9861a119623556163179915727896156b
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://dev.iopsys.eu/iopsys/peripheral-manager
@@ -38,27 +38,15 @@ define Package/peripheral_manager
CATEGORY:=Utilities
TITLE:=Application deamon for handling of peripheral
URL:=
DEPENDS:=+libuci +libubus +libblobmsg-json @+PACKAGE_bcmkernel:bcmkernel PACKAGE_bcmkernel:bcmkernel
DEPENDS:=+libuci +libubus +libblobmsg-json
endef
define Package/peripheral_manager/description
Application handling peripheral
endef
TARGET_CFLAGS := \
-I$(STAGING_DIR)/usr/include/bcm963xx/shared/opensource/include/bcm963xx \
-I$(STAGING_DIR)/usr/include/bcm963xx/bcmdrivers/opensource/include/bcm963xx \
$(TARGET_CFLAGS)
PERIPHERAL_OPTONS:=-DSELECT_BRCM_BOARD=0
ifneq ($(CONFIG_TARGET_iopsys_brcm63xx_arm),)
PERIPHERAL_OPTONS:= -DSELECT_BRCM_BOARD=1
endif
CMAKE_OPTIONS += \
-DCMAKE_BUILD_TYPE:String="Release" \
$(PERIPHERAL_OPTONS) \
define Package/peripheral_manager/install
$(CP) ./files/* $(1)/

View File

@@ -1,16 +1,16 @@
#
# Copyright (C) 2020 Iopsys
# Copyright (C) 2021 Iopsys
#
include $(TOPDIR)/rules.mk
PKG_NAME:=prj-unish
PKG_VERSION:=0.1.0
PKG_VERSION:=0.7.0
LOCAL_DEV=0
ifneq ($(LOCAL_DEV),1)
PKG_SOURCE_PROTO:=git
PKG_SOURCE_VERSION:=3180908081492a6cfc11adbcf80845dbba12633a
PKG_SOURCE_VERSION:=595bd811428f4c1271cc8e2f61a9b6311f4672f0
PKG_SOURCE_URL:=https://dev.iopsys.eu/iopsys/prj-unish.git
PKG_MAINTAINER:=Anjan Chanda <anjan.chanda@iopsys.eu>
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)_$(PKG_SOURCE_VERSION).tar.xz
@@ -46,10 +46,26 @@ define Build/Prepare
endef
endif
define Build/InstallDev
#$(INSTALL_DIR) $(STAGING_DIR)/usr/include
#$(CP) $(PKG_BUILD_DIR)/src/cmdu.h $(STAGING_DIR)/usr/include/
$(INSTALL_DIR) $(1)/usr/include
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_BUILD_DIR)/src/cmdu.h $(1)/usr/include/
$(CP) $(PKG_BUILD_DIR)/src/lib*.so* $(1)/usr/lib/
$(CP) $(PKG_BUILD_DIR)/src/extensions/map/map2.h $(1)/usr/include/
$(CP) $(PKG_BUILD_DIR)/src/extensions/map/map_module.h $(1)/usr/include/
$(CP) $(PKG_BUILD_DIR)/src/extensions/map/lib*.so* $(1)/usr/lib/
endef
define Package/prj-unish/install
$(CP) ./files/* $(1)/
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_BUILD_DIR)/src/lib*.so* $(1)/usr/lib/
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/i1905d $(1)/usr/sbin/
$(CP) $(PKG_BUILD_DIR)/src/extensions/map/*.so* $(1)/usr/lib/
endef
$(eval $(call BuildPackage,prj-unish))

View File

@@ -2,20 +2,20 @@
config ieee1905 'ieee1905'
option enabled '1'
option extension 0
#option macaddress 'ba:c9:a6:90:6c:b0'
option macaddress 'aa:aa:aa:10:20:30'
option registrar '2 5'
config ap
option band '2'
option ssid 'TestSSID'
option ssid 'TestSSID.2'
option encryption 'psk2'
option key '1234567890'
option key '5555500000'
config ap
option band '5'
option ssid 'TestSSID'
option ssid 'TestSSID.5'
option encryption 'psk2'
option key '1234567890'
option key '2222200000'
config al-iface
option enabled 1

View File

@@ -5,14 +5,14 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=rulengd
PKG_VERSION:=1.2.1
PKG_VERSION:=1.2.2
PKG_RELEASE:=1
PKG_BUILD_PARALLEL:=1
PKG_INSTALL:=1
PKG_SOURCE_PROTO=git
PKG_SOURCE_URL:=https://dev.iopsys.eu/iopsys/rulengd.git
PKG_SOURCE_VERSION:=360b64ff1a2fe1ad578e298f63a7d6a350f99d93
PKG_SOURCE_VERSION:=e5afe7734674d416138a54526cc589c57ba28279
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
PKG_MIRROR_HASH:=skip
PKG_SOURCE_SUBDIR:=${PKG_NAME}-${PKG_VERSION}
@@ -27,7 +27,7 @@ include $(INCLUDE_DIR)/cmake.mk
define Package/rulengd
CATEGORY:=Utilities
TITLE:=RuleEngine daemon
DEPENDS:=+ubox +uci +ubus +libjson-c +libeasy
DEPENDS:=+ubox +uci +ubus +libjson-c
MENU:=1
endef

View File

@@ -16,7 +16,7 @@ PKG_SOURCE_URL:=https://github.com/kward/shflags.git
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_SOURCE_VERSION:=c12b30cebb92b49c5edb6df255c0952c65b4ddc6
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
PKG_MIRROR_HASH:=daf2a3295872237a9375ba3508105053d889a6df935f670d7d64817a833065ed
PKG_MIRROR_HASH:=skip
PKG_LICENSE:=LGPL-2.1
include $(INCLUDE_DIR)/package.mk

View File

@@ -1,42 +0,0 @@
#
# Copyright (C) 2020 iopsys Software Solutions AB
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=stun
PKG_VERSION:=1.0.0
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
include $(INCLUDE_DIR)/package.mk
define Package/$(PKG_NAME)
SECTION:=utils
CATEGORY:=Utilities
SUBMENU:=TRx69
TITLE:=BBF stun Client
DEPENDS:=+libubus +libuci +libubox +libjson-c +libopenssl +libblobmsg-json
endef
define Package/$(PKG_NAME)/description
CWMP STUN Client
endef
define Build/Prepare
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
TARGET_CFLAGS += \
-D_GNU_SOURCE
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/stund $(1)/usr/sbin/
$(CP) ./files/* $(1)/
endef
$(eval $(call BuildPackage,$(PKG_NAME)))

View File

@@ -1,36 +0,0 @@
#!/bin/sh /etc/rc.common
# STUN client software
# Copyright (C) 2020 iopsys Software Solutions AB
# Author: Omar Kallel <omar.kallel@pivasoftware.com>
START=90
USE_PROCD=1
PROG="/usr/sbin/stund"
start_service() {
local enable=`uci -q get stun.stun.enable`
if [ "$enable" == "1" ]; then
local server=`uci -q get stun.stun.server_address`
[ "$server" = "" ] && exit 0
procd_open_instance
procd_set_param command "$PROG"
procd_set_param respawn "3" "7" "0"
procd_close_instance
fi
}
boot() {
start
}
reload_service() {
logger -p crit -t "stun" "reloading service()"
stop
start
}
service_triggers()
{
procd_add_reload_trigger stun
}

View File

@@ -1,16 +0,0 @@
PROG = stund
OBJS = stun.o config.o log.o ubus.o
PROG_CFLAGS = $(CFLAGS) -Wall -Werror
PROG_LDFLAGS = $(LDFLAGS) -lubus -luci -lubox -ljson-c -lcrypto -lblobmsg_json
%.o: %.c
$(CC) $(PROG_CFLAGS) $(FPIC) -c -o $@ $<
all: $(PROG)
$(PROG): $(OBJS)
$(CC) $(PROG_CFLAGS) -o $@ $^ $(PROG_LDFLAGS)
clean:
rm -f *.o $(PROG)

View File

@@ -1,297 +0,0 @@
/*
* config.c -- contains functions that allows reading and loading of uci config parameters of stun
*
* Copyright (C) 2020 iopsys Software Solutions AB. All rights reserved.
*
* Author: Omar Kallel <omar.kallel@pivasoftware.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "config.h"
#include <strings.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <unistd.h>
#include <ctype.h>
static struct uci_context *uci_ctx = NULL;
static struct uci_context *uci_ctx_state = NULL;
struct stun_config conf;
int config_fini(void)
{
free(conf.server_address);
free(conf.password);
free(conf.username);
conf.server_address = NULL;
conf.username = NULL;
conf.password = NULL;
return 0;
}
int config_init(void)
{
char *v;
suci_init();
memset(&conf, 0, sizeof(struct stun_config));
v = suci_get_value("stun", "stun", "server_address");
if (!*v) {
stun_log(SCRIT, "Missing Server Address in the STUN config");
goto error;
}
conf.server_address = strdup(v);
v = suci_get_value("stun", "stun", "username");
if (*v)
conf.username = strdup(v);
v = suci_get_value("stun", "stun", "password");
if (*v)
conf.password = strdup(v);
v = suci_get_value("stun", "stun", "server_port");
if (*v)
conf.server_port = atoi(v);
else
conf.server_port = DEFAULT_SERVERPORT;
v = suci_get_value("stun", "stun", "log_level");
if (*v)
conf.loglevel = atoi(v);
else
conf.loglevel = DEFAULT_LOGLEVEL;
v = suci_get_value("stun", "stun", "min_keepalive");
if (*v)
conf.min_keepalive = atoi(v);
else
conf.min_keepalive = DEFAULT_MINKEEPALIVE;
v = suci_get_value("stun", "stun", "max_keepalive");
if (*v)
conf.max_keepalive = atoi(v);
else
conf.max_keepalive = DEFAULT_MAXKEEPALIVE;
v = suci_get_value("stun", "stun", "client_port");
if (*v)
conf.client_port = atoi(v);
if (conf.max_keepalive <= 0)
conf.max_keepalive = DEFAULT_MAXKEEPALIVE;
if (conf.min_keepalive <= 0)
conf.min_keepalive = DEFAULT_MINKEEPALIVE;
if (conf.server_port <= 0)
conf.server_port = DEFAULT_SERVERPORT;
if (conf.loglevel >= __MAX_SLOG || conf.loglevel < 0) {
conf.loglevel = DEFAULT_LOGLEVEL;
}
stun_log(SINFO, "STUN CONFIG - Server Address: %s", conf.server_address);
stun_log(SINFO, "STUN CONFIG - Username: %s", conf.username ? conf.username : "<not defined>");
stun_log(SINFO, "STUN CONFIG - Server port: %d", conf.server_port);
stun_log(SINFO, "STUN CONFIG - min keepalive: %d", conf.min_keepalive);
stun_log(SINFO, "STUN CONFIG - max keepalive: %d", conf.max_keepalive);
stun_log(SINFO, "STUN CONFIG - Client port: %d", (conf.client_port > 0) ? conf.client_port : -1);
stun_log(SINFO, "STUN CONFIG - LOG Level: %d (Critical=0, Warning=1, Notice=2, Info=3, Debug=4)", conf.loglevel);
suci_fini();
return 0;
error:
suci_fini();
config_fini();
exit(1);
}
int suci_init(void)
{
uci_ctx = uci_alloc_context();
if (!uci_ctx) {
return -1;
}
uci_ctx_state = uci_alloc_context();
if (!uci_ctx_state) {
return -1;
}
uci_add_delta_path(uci_ctx_state, uci_ctx_state->savedir);
uci_set_savedir(uci_ctx_state, VAR_STATE);
return 0;
}
int suci_fini(void)
{
if (uci_ctx) {
uci_free_context(uci_ctx);
}
if (uci_ctx_state) {
uci_free_context(uci_ctx_state);
}
uci_ctx = NULL;
uci_ctx_state = NULL;
return 0;
}
static bool suci_validate_section(const char *str)
{
if (!*str)
return false;
for (; *str; str++) {
unsigned char c = *str;
if (isalnum(c) || c == '_')
continue;
return false;
}
return true;
}
static int suci_init_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *package, char *section, char *option, char *value)
{
memset(ptr, 0, sizeof(struct uci_ptr));
/* value */
if (value) {
ptr->value = value;
}
ptr->package = package;
if (!ptr->package)
goto error;
ptr->section = section;
if (!ptr->section) {
ptr->target = UCI_TYPE_PACKAGE;
goto lastval;
}
ptr->option = option;
if (!ptr->option) {
ptr->target = UCI_TYPE_SECTION;
goto lastval;
} else {
ptr->target = UCI_TYPE_OPTION;
}
lastval:
if (ptr->section && !suci_validate_section(ptr->section))
ptr->flags |= UCI_LOOKUP_EXTENDED;
return 0;
error:
return -1;
}
void suci_print_list(struct uci_list *uh, char **val, char *delimiter)
{
struct uci_element *e;
static char buffer[512];
char *buf = buffer;
*buf = '\0';
uci_foreach_element(uh, e) {
if (*buf) {
strcat(buf, delimiter);
strcat(buf, e->name);
}
else {
strcpy(buf, e->name);
}
}
*val = buf;
}
char *suci_get_value(char *package, char *section, char *option)
{
struct uci_ptr ptr;
char *val = "";
if (!section || !option)
return val;
if (suci_init_ptr(uci_ctx, &ptr, package, section, option, NULL))
return val;
if (uci_lookup_ptr(uci_ctx, &ptr, NULL, true) != UCI_OK)
return val;
if (!ptr.o)
return val;
if(ptr.o->type == UCI_TYPE_LIST) {
suci_print_list(&ptr.o->v.list, &val, " ");
return val;
}
if (ptr.o->v.string)
return ptr.o->v.string;
else
return val;
}
char *suci_set_value(char *package, char *section, char *option, char *value)
{
struct uci_ptr ptr;
int ret = UCI_OK;
if (!section)
return "";
if (suci_init_ptr(uci_ctx, &ptr, package, section, option, value))
return "";
if (uci_lookup_ptr(uci_ctx, &ptr, NULL, true) != UCI_OK)
return "";
uci_set(uci_ctx, &ptr);
if (ret == UCI_OK)
ret = uci_save(uci_ctx, ptr.p);
if (ptr.o && ptr.o->v.string)
return ptr.o->v.string;
return "";
}
/*************************---/var/state--***************************/
char *suci_get_value_state(char *package, char *section, char *option)
{
char *val;
struct uci_context *save_uci_ctx = uci_ctx;
uci_ctx = uci_ctx_state;
val = suci_get_value(package, section, option);
uci_ctx = save_uci_ctx;
return val;
}
char *suci_set_value_state(char *package, char *section, char *option, char *value)
{
char *val;
struct uci_context *save_uci_ctx = uci_ctx;
uci_ctx = uci_ctx_state;
val = suci_set_value(package, section, option, value);
uci_ctx = save_uci_ctx;
return val;
}

View File

@@ -1,44 +0,0 @@
/* TR-069 STUN client software
* Copyright (C) 2020 PIVA SOFTWARE <www.pivasoftware.com> - All Rights Reserved
* Author: Omar Kallel <omar.kallel@pivasoftware.com>
*/
#ifndef __CONFIG_H
#define __CONFIG_H
#include <uci.h>
#include "log.h"
#define VAR_STATE "/var/state"
#define DEFAULT_SERVERPORT 3478
#define DEFAULT_CLIENTPORT 7547
#define DEFAULT_MINKEEPALIVE 30
#define DEFAULT_RETRYTIME 3
#define DEFAULT_MAXKEEPALIVE 3600
#define DEFAULT_LOGLEVEL SINFO
struct stun_config {
char *server_address;
char *username;
char *password;
int server_port;
int client_port;
int max_keepalive;
int min_keepalive;
int loglevel;
};
extern struct stun_config conf;
int config_init(void);
int config_fini(void);
int suci_init(void);
int suci_fini(void);
void suci_print_list(struct uci_list *uh, char **val, char *delimiter);
char *suci_get_value(char *package, char *section, char *option);
char *suci_set_value(char *package, char *section, char *option, char *value);
char *suci_get_value_state(char *package, char *section, char *option);
char *suci_set_value_state(char *package, char *section, char *option, char *value);
#endif //__CONFIG_H

View File

@@ -1,68 +0,0 @@
/*
* log.c : conatains function used log traces
*
* Copyright (C) 2020 iopsys Software Solutions AB. All rights reserved.
*
* Author: Omar Kallel <omar.kallel@pivasoftware.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <syslog.h>
#include <time.h>
#include "log.h"
#include "config.h"
static const int log_syslogmap[] = {
[SCRIT] = LOG_CRIT,
[SWARNING] = LOG_WARNING,
[SNOTICE] = LOG_NOTICE,
[SINFO] = LOG_INFO,
[SDEBUG] = LOG_DEBUG
};
static const char* log_str[] = {
[SCRIT] = "CRITICAL",
[SWARNING] = "WARNING",
[SNOTICE] = "NOTICE",
[SINFO] = "INFO",
[SDEBUG] = "DEBUG"
};
void stun_log(int priority, const char *format, ...)
{
va_list vl;
if (priority <= conf.loglevel) {
time_t t = time(NULL);
struct tm tm = *localtime(&t);
va_start(vl, format);
printf("%d-%02d-%02d %02d:%02d:%02d [stun] %s - ", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, log_str[priority]);
vprintf(format, vl);
va_end(vl);
printf("\n");
openlog("stun", 0, LOG_DAEMON);
va_start(vl, format);
vsyslog(log_syslogmap[priority], format, vl);
va_end(vl);
closelog();
}
}

View File

@@ -1,20 +0,0 @@
/* TR-069 STUN client software
* Copyright (C) 2020 PIVA SOFTWARE <www.pivasoftware.com> - All Rights Reserved
* Author: Omar Kallel <omar.kallel@pivasoftware.com>
*/
#ifndef __SLOG_H
#define __SLOG_H
enum stun_log_level_enum {
SCRIT,
SWARNING,
SNOTICE,
SINFO,
SDEBUG,
__MAX_SLOG
};
void stun_log(int priority, const char *format, ...);
#endif //__SLOG_H

View File

@@ -1,687 +0,0 @@
/*
* stun.c -- the main file of stun application
*
* Copyright (C) 2020 iopsys Software Solutions AB. All rights reserved.
*
* Author: Omar Kallel <omar.kallel@pivasoftware.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* TR-069 STUN client software
* Copyright (C) 2020 PIVA SOFTWARE <www.pivasoftware.com> - All Rights Reserved
* Author: Mohamed Kallel <mohamed.kallel@pivasoftware.com>
* Omar Kallel <omar.kallel@pivasoftware.com>
* Anis Ellouze <anis.ellouze@pivasoftware.com>
*/
#include <stdio.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/un.h>
#include <stdlib.h>
#include <libubox/uloop.h>
#include <openssl/hmac.h>
#include <string.h>
#include <ifaddrs.h>
#include "stun.h"
#include "config.h"
#include "ubus.h"
struct env_var env = {0};
int keepalive_timeout = DEFAULT_MINKEEPALIVE;
int retry_timeout = DEFAULT_RETRYTIME;
int bindcrreusaddr = 1;
int bindcrreusport = 1;
const char *BBFCR = "dslforum.org/TR-111 ";
static void stun_notify_cb(struct uloop_timeout *timeout);
static void stun_inform_cb(struct uloop_timeout *timeout);
static void listening_crport_cb(struct uloop_timeout *timeout);
static void binding_request_crport_cb(struct uloop_timeout *timeout);
static struct udp_listen listen_crport = {
.fd = -1,
.utimer = {.cb = listening_crport_cb}
};
static struct binding_request br_crport = {
.binding_cr = 1,
.udp_listen = &listen_crport,
.utimer = {.cb = binding_request_crport_cb}
};
static struct binding_request br_crport_keepalive = {
.is_keealive = 1,
.binding_cr = 1,
.udp_listen = &listen_crport,
.utimer = {.cb = binding_request_crport_cb}
};
struct uloop_timeout stun_notify_timer = {.cb = stun_notify_cb};
struct uloop_timeout stun_inform_timer = {.cb = stun_inform_cb};
void stun_notify(int afterms)
{
uloop_timeout_set(&stun_notify_timer, afterms);
}
void stun_inform(int afterms)
{
uloop_timeout_set(&stun_inform_timer, afterms);
}
static void stun_notify_cb(struct uloop_timeout *timeout)
{
stun_log(SINFO, "ubus call tr069 notify");
if (subus_call("tr069", "notify", 0, UBUS_ARGS{}) < 0) {
stun_log(SINFO, "ubus call tr069 notify failed! retry after 1s");
stun_notify(1000);
}
}
static void stun_inform_cb(struct uloop_timeout *timeout)
{
stun_log(SINFO, "ubus call tr069 inform '{\"event\": \"6 connection request\"}'");
if (subus_call("tr069", "inform", 1, UBUS_ARGS{{"event", "6 connection request"}}) < 0) {
stun_log(SINFO, "ubus call tr069 inform '{\"event\": \"6 connection request\"}' failed! retry after 1s");
stun_inform(1000);
}
}
static int stunid_cmp(stunid *left, stunid *right)
{
return memcmp(left, right, sizeof(*left));
}
static void *stunid_cpy(stunid *left, stunid *right)
{
return memcpy(left, right, sizeof(*left));
}
static void stunid_rand(stunid *id)
{
int i;
srand(time(NULL));
for (i = 0; i < 4; i++)
{
id->id[i] = rand();
}
}
ssize_t timeout_recvfrom(int sock, char *buf, int length, struct sockaddr_in *connection, int timeoutinseconds)
{
fd_set socks;
ssize_t r = 0;
struct timeval t = {0};
int clen = sizeof(*connection);
stun_log(SDEBUG, "udp revcfrom, timeout: %ds", timeoutinseconds);
FD_ZERO(&socks);
FD_SET(sock, &socks);
t.tv_sec = timeoutinseconds;
if (select(sock + 1, &socks, NULL, NULL, &t) &&
(r = recvfrom(sock, buf, length, 0, (struct sockaddr *)connection, (socklen_t *)&clen)) != -1) {
return r;
}
else {
return -1;
}
}
static int stun_send(int s, char *buf)
{
struct stun_header *sh;
struct hostent *he;
struct sockaddr_in dst = {0};
sh = (struct stun_header *)buf;
if ((he = gethostbyname(conf.server_address)) == NULL) {
return -1;
}
memcpy(&(dst.sin_addr), he->h_addr_list[0], he->h_length);
dst.sin_port = htons(conf.server_port);
dst.sin_family = AF_INET;
stun_log(SINFO, "send STUN message to %s:%u (%s:%u)", conf.server_address, conf.server_port, inet_ntoa(dst.sin_addr), ntohs(dst.sin_port));
return sendto(s, buf, ntohs(sh->len) + sizeof(*sh), 0, (struct sockaddr *)&dst, sizeof(dst));
}
static int net_socket(int srcport)
{
int sock = -1;
stun_log(SINFO, "Open UDP socket");
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock >= 0) {
if (srcport > 0) {
struct sockaddr_in bindcraddr = {0};
int i = 0;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &bindcrreusaddr, sizeof(int)) < 0) {
stun_log(SWARNING, "setsockopt(SO_REUSEADDR) failed");
}
if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &bindcrreusport, sizeof(int)) < 0) {
stun_log(SWARNING, "setsockopt(SO_REUSEPORT) failed");
}
bindcraddr.sin_family = AF_INET;
bindcraddr.sin_addr.s_addr = htonl(INADDR_ANY);
bindcraddr.sin_port = htons((unsigned short)srcport);
for(;i<9;i++)
{
if (bind(sock, (struct sockaddr *)&bindcraddr, sizeof(bindcraddr)) < 0) {
continue;
}
stun_log(SINFO, "binding socket source port to %u", srcport);
break;
}
}
fcntl(sock, F_SETFD, fcntl(sock, F_GETFD) | FD_CLOEXEC);
fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK);
}
return sock;
}
static void stun_close_socket(struct udp_listen *udp_listen)
{
uloop_timeout_cancel(&udp_listen->utimer);
if (udp_listen->fd > 0) {
stun_log(SINFO, "STUN close socket %d", udp_listen->fd);
close(udp_listen->fd);
}
udp_listen->fd = -1;
}
static void stun_socket(struct udp_listen *udp_listen)
{
if (udp_listen->fd > 0) {
stun_close_socket(udp_listen);
}
udp_listen->fd = net_socket(conf.client_port);
stun_log(SINFO, "STUN new socket %d", udp_listen->fd);
uloop_timeout_set(&udp_listen->utimer, 0);
}
static int trailing_buffer_alloc(int mp, char *buf, int len, char trail, char **bufm, int *mlen)
{
*bufm = NULL;
*mlen = len % mp;
*mlen = len + (*mlen ? (mp - *mlen) : 0);
*bufm = calloc(1, *mlen);
if (*bufm == NULL)
return -1;
memcpy(*bufm, buf, len);
if (trail) {
while(len < *mlen) {
(*bufm)[len++] = trail;
}
}
return 0;
}
static int append_attribute_buffer(unsigned char **start, char *buf, int len, unsigned short attr_type, int free)
{
if ((sizeof(struct stun_attribute) + len) > free)
return -1;
struct stun_attribute *sa = (struct stun_attribute *)*start;
sa->len = htons((unsigned short)len);
sa->type = htons(attr_type);
memcpy(sa->value, buf, len);
*start += sizeof(struct stun_attribute) + len;
return 0;
}
static int stun_hmac(int trailing_mp, unsigned char *data, int len, char *password, char *hmac)
{
char *bufmp = NULL;
int lenmp;
unsigned char* digest;
if (trailing_mp) {
if (trailing_buffer_alloc(trailing_mp, (char *)data, len, 0, &bufmp, &lenmp))
return -1;
digest = HMAC(EVP_sha1(), password, strlen(password), (unsigned char *)bufmp, lenmp, NULL, NULL);
free(bufmp);
}
else {
digest = HMAC(EVP_sha1(), password, strlen(password), data, len, NULL, NULL);
}
memcpy(hmac, digest, 20);
return 0;
}
static void hex_to_str(char *hex, int len, char *str)
{
while (len--) {
sprintf(str, "%02X", *hex++);
str += 2;
}
}
static int generate_stun_packet(struct binding_request *br, char *req_buf, int maxlen)
{
struct stun_header *req;
unsigned char *stunmsg;
req = (struct stun_header *) req_buf;
stunmsg = req->stunmsg;
stun_log(SINFO, "STUN generate BINDING-REQUEST");
req->type = htons(BINDING_REQUSET);
stunid_rand(&(req->id));
stunid_cpy(&(br->id), &(req->id));
stun_log(SINFO, "STUN request id: %d%d%d%d", req->id.id[0], req->id.id[1], req->id.id[2], req->id.id[3]);
if (conf.username) {
char *buf4;
int len4;
if (trailing_buffer_alloc(4, conf.username, strlen(conf.username), ' ', &buf4, &len4))
return -1;
append_attribute_buffer(&stunmsg, buf4, len4, ATTR_USERNAME, (maxlen - (stunmsg - (unsigned char *)req)));
stun_log(SINFO, "STUN append USERNAME: **%.*s**", len4, buf4);
free(buf4);
}
if (br->binding_cr) {
stun_log(SINFO, "STUN append CONNECTION-REQUEST-BINDING: **%s**", BBFCR);
append_attribute_buffer(&stunmsg, (char *)BBFCR, strlen(BBFCR), ATTR_CONNECTION_REQUEST_BINDING, (maxlen - (stunmsg - (unsigned char *)req)));
}
if (br->binding_change) {
stun_log(SINFO, "STUN append BINDING-CHANGE");
append_attribute_buffer(&stunmsg, "", 0, ATTR_BINDING_CHANGE, (maxlen - (stunmsg - (unsigned char *)req)));
}
if (br->msg_integrity) {
if (conf.username) {
char *password;
char hmac[20] = {0};
char hmacstr[64];
req->len = htons((stunmsg - (unsigned char *)req) - sizeof(struct stun_header) + sizeof(struct stun_attribute) + 20);
password = conf.password ? conf.password : "";
stun_hmac(64, (unsigned char *)req, stunmsg - (unsigned char *)req, password, hmac);
append_attribute_buffer(&stunmsg, hmac, sizeof(hmac), ATTR_MESSAGE_INTEGRITY, (maxlen - (stunmsg - (unsigned char *)req)));
hex_to_str(hmac, 20, hmacstr);
stun_log(SINFO, "STUN append MESSAGE-INTEGRITY: ***%s***", hmacstr);
}
else {
req->len = htons((stunmsg - (unsigned char *)req) - sizeof(struct stun_header));
br->msg_integrity = 0;
return -1;
}
}
else {
req->len = htons((stunmsg - (unsigned char *)req) - sizeof(struct stun_header));
}
stun_log(SINFO, "STUN request length: %d", ntohs(req->len));
return 0;
}
static int stun_get_mapped_address(char *buf, unsigned int *ip, unsigned short *port)
{
struct stun_header *sh = (struct stun_header *)buf;
struct stun_attribute *sa = (struct stun_attribute *)sh->stunmsg;
char *p;
while (((char *)sa - (char *)sh - sizeof(*sh)) < ntohs(sh->len)) {
if(ntohs(sa->type) == ATTR_MAPPED_ADDRESS) {
struct stun_address *ma = (struct stun_address *)sa->value;
*port = ma->port;
*ip = ma->address;
return 0;
}
p = (char *)sa;
p += sizeof(struct stun_attribute) + ntohs(sa->len);
sa = (struct stun_attribute *)p;
}
return -1;
}
static int stun_get_error_code(char *buf)
{
struct stun_header *sh = (struct stun_header *)buf;
struct stun_attribute *sa = (struct stun_attribute *)sh->stunmsg;
char *p;
while (((char *)sa - (char *)sh - sizeof(*sh)) < ntohs(sh->len)) {
if(ntohs(sa->type) == ATTR_ERROR_CODE) {
unsigned int class, number;
unsigned int ui = ntohl(*((unsigned int *)sa->value));
class = (ui >> 8) & 0x7;
number = ui & 0xff;
return (int)(class * 100 + number);
}
p = (char *)sa;
p += sizeof(struct stun_attribute) + ntohs(sa->len);
sa = (struct stun_attribute *)p;
}
return 0;
}
static void handle_udp_cr(char *resp_buf)
{
char *str;
char un[64], cn[64], sig[64], buf[256];
char *crusername;
char *crpassword;
unsigned int crid = 0, ts = 0;
int valid = 1;
stun_log(SINFO, "Handle UDP Connection Request");
if ((str = strstr(resp_buf, "ts="))) {
sscanf(str, "ts=%u", &ts);
stun_log(SINFO, "UDP CR ts = %u", ts);
}
else {
stun_log(SWARNING, "UDP CR ts not found");
return;
}
if ((str = strstr(resp_buf, "id="))) {
sscanf(str, "id=%u", &crid);
stun_log(SINFO, "UDP CR id = %u", crid);
}
else {
return;
stun_log(SWARNING, "UDP CR id not found");
}
if (crid && ts && crid != env.last_crid && ts > env.last_ts) {
stun_log(SINFO, "NEW UDP CR");
env.last_crid = crid;
env.last_ts = ts;
if ((str = strstr(resp_buf, "un="))) {
sscanf(str, "un=%63[^?& \t\n\r]", un);
stun_log(SINFO, "UDP CR un = %s", un);
}
else {
stun_log(SWARNING, "UDP CR un not found");
return;
}
if ((str = strstr(resp_buf, "cn="))) {
sscanf(str, "cn=%63[^?& \t\n\r]", cn);
stun_log(SINFO, "UDP CR cn = %s", cn);
}
else {
stun_log(SWARNING, "UDP CR cn not found");
return;
}
if ((str = strstr(resp_buf, "sig="))) {
sscanf(str, "sig=%63[^?& \t\n\r]",sig);
stun_log(SINFO, "UDP CR sig = %s", sig);
}
else {
stun_log(SWARNING, "UDP CR sig not found");
return;
}
suci_init();
crusername = suci_get_value("cwmp", "cpe", "userid");
crpassword = suci_get_value("cwmp", "cpe", "password");
if (*crusername && *crpassword) {
if (strcmp(crusername, un) != 0) {
stun_log(SINFO, "UDP CR username mismatch!");
valid = 0;
}
else {
char hmac[20], hmacstr[64];
snprintf(buf, sizeof(buf), "%u%u%s%s", ts, crid, un, cn);
stun_hmac(0, (unsigned char *)buf, strlen(buf), crpassword, hmac);
hex_to_str(hmac, 20, hmacstr);
if (strcasecmp(hmacstr, sig) != 0) {
stun_log(SINFO, "UDP CR sig mismatch!");
valid = 0;
}
}
}
suci_fini();
if (valid) {
stun_inform(0);
}
} else {
if (!ts || !crid)
stun_log(SINFO, "UDP CR ts or id not found");
else
stun_log(SINFO, "UDP CR ts is old or id is already received");
}
}
static void save_udpcr_var_state(unsigned int ip, unsigned short port)
{
struct in_addr ip_addr;
char buf[64];
ip_addr.s_addr = env.address;
snprintf(buf, sizeof(buf), "%s:%d", inet_ntoa(ip_addr), ntohs(env.port));
stun_log(SINFO, "Save New UDPConnectionRequestAddress to /var/state %s", buf);
suci_init();
suci_set_value_state("stun", "stun", "crudp_address", buf);
suci_fini();
}
static int is_udpcr_changed(unsigned int ip, unsigned short port)
{
struct in_addr ip_addr;
char buf[64];
char *v;
int changed = 0;
ip_addr.s_addr = ip;
snprintf(buf, sizeof(buf), "%s:%d", inet_ntoa(ip_addr), ntohs(port));
suci_init();
v = suci_get_value_state("stun", "stun", "crudp_address");
if (strcmp(buf, v) != 0)
changed = 1;
suci_fini();
return changed;
}
static void save_natdetected_var_state(unsigned int ip)
{
struct ifaddrs * ifaddrlist = NULL;
struct ifaddrs * ifa = NULL;
int islocal = 0;
char *nd;
getifaddrs(&ifaddrlist);
for (ifa = ifaddrlist; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa ->ifa_addr && ifa ->ifa_addr->sa_family == AF_INET) {
if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == ip) {
islocal = 1;
break;
}
}
}
if (ifaddrlist != NULL)
freeifaddrs(ifaddrlist);
suci_init();
nd = suci_get_value_state("stun", "stun", "nat_detected");
if (islocal && *nd != '\0') {
stun_log(SINFO, "Device is not behind NAT, set NATDetected to false");
suci_set_value_state("stun", "stun", "nat_detected", "");
}
else if (!islocal && *nd == '\0') {
stun_log(SINFO, "Device is behind NAT, set NATDetected to true");
suci_set_value_state("stun", "stun", "nat_detected", "1");
}
suci_fini();
}
static void binding_request_crport_cb(struct uloop_timeout *timeout)
{
struct binding_request *br;
struct udp_listen *udp_listen;
char req_buf[2048] = {0};
int r;
br = binding_request_entry(timeout);
udp_listen = br->udp_listen;
udp_listen->br = br;
stun_log(SINFO, "Binding Request cb start %s", br->is_keealive ? "(KeepAlive)" : "");
if (udp_listen->fd <= 0) {
stun_socket(udp_listen);
}
if (br->resp_success > 0)
br->resp_success = 0;
if (generate_stun_packet(br, req_buf, sizeof(req_buf) - 1)) {
br->retry_interval = (br->retry_interval) ? 2 * br->retry_interval : retry_timeout;
br->retry_interval = (br->retry_interval > 1500) ? 1500 : br->retry_interval;
uloop_timeout_set(&br->utimer, br->retry_interval * 1000);
return;
}
r = stun_send(udp_listen->fd, req_buf);
if (r < 0) {
stun_close_socket(udp_listen);
udp_listen->br = NULL;
br->retry_interval = (br->retry_interval) ? 2 * br->retry_interval : retry_timeout;
br->retry_interval = (br->retry_interval > 1500) ? 1500 : br->retry_interval;
stun_log(SINFO, "Failed send of Binding Request! retry in %ds", br->retry_interval);
uloop_timeout_set(timeout, br->retry_interval * 1000);
}
else {
br->retry_interval = 0;
stun_log(SINFO, "Success send of Binding Request.");
stun_log(SINFO, "Start KeepAlive Binding Request in %ds.", keepalive_timeout);
uloop_timeout_set(&br_crport_keepalive.utimer, keepalive_timeout * 1000);
}
}
static void listening_crport_cb(struct uloop_timeout *timeout)
{
struct udp_listen *udp_listen;
struct sockaddr_in src = {0};
char resp_buf[2048] = {0};
unsigned int ip = 0;
unsigned short port = 0;
int r;
stun_log(SDEBUG, "Binding listening CR cb start");
udp_listen = udp_listen_entry(timeout);
if (udp_listen->fd < 0) {
stun_log(SINFO, "Binding listening CR: Socket = -1");
uloop_timeout_set(timeout, 19);
return;
}
r = timeout_recvfrom(udp_listen->fd, resp_buf, sizeof(resp_buf) - 1, &src, 1);
if (r > 0) {
stun_log(SINFO, "Binding listening CR: get UDP packet");
struct stun_header *sh = (struct stun_header *)resp_buf;
if (ntohs(sh->type) == BINDING_ERROR) {
int code = stun_get_error_code(resp_buf);
stun_log(SINFO, "get BINDING-ERROR: code is %d", code);
if (udp_listen->br != NULL && stunid_cmp(&(sh->id), &(udp_listen->br->id)) == 0 && code == 401) {
udp_listen->br->msg_integrity = 1;
udp_listen->br->auth_fail++;
stun_log(SINFO, "Cancel scheduled Keepalive Binding Request");
uloop_timeout_cancel(&br_crport_keepalive.utimer);
stun_log(SINFO, "Trying new Binding Request in %ds",
(udp_listen->br->auth_fail < 3) ? 0 : (udp_listen->br->auth_fail - 2)*3);
uloop_timeout_set(&udp_listen->br->utimer,
(udp_listen->br->auth_fail < 3) ? 0 : ((udp_listen->br->auth_fail - 2) * 3000));
udp_listen->br = NULL;
}
else if (code != 401) {
stun_log(SINFO, "Unsupported error code");
}
goto end;
}
else if (ntohs(sh->type) == BINDING_RESPONSE) {
struct in_addr ip_addr;
stun_log(SINFO, "get BINDING-RESPONSE");
if (udp_listen->br != NULL && stunid_cmp(&(sh->id), &(udp_listen->br->id)) == 0) {
udp_listen->br->resp_success = 1;
udp_listen->br->msg_integrity = 0;
udp_listen->br->auth_fail = 0;
stun_get_mapped_address(resp_buf, &ip, &port);
ip_addr.s_addr = ip;
stun_log(SINFO, "Mapped Address is: %s:%u", inet_ntoa(ip_addr), ntohs(port));
save_natdetected_var_state(ip);
if (is_udpcr_changed(ip, port)) {
env.address = ip;
env.port = port;
udp_listen->br->resp_success = 0;
udp_listen->br->binding_change = 1;
uloop_timeout_set(&udp_listen->br->utimer, 0);
save_udpcr_var_state(ip, port);
stun_notify(0);
}
else {
udp_listen->br = NULL;
}
}
goto end;
}
else if (strstr(resp_buf, "http") || strstr(resp_buf, "HTTP")) {
stun_log(SINFO, "get UDP Connection Request");
handle_udp_cr(resp_buf);
}
else {
stun_log(SINFO, "get non supported STUN/UDP message");
}
}
else {
/* timed out */
if (!udp_listen->br || udp_listen->br->resp_success == 1)
goto end;
stun_log(SINFO, "Timed OUT!");
udp_listen->br->resp_success--;
if (udp_listen->br->resp_success < -2) {
int rs = -udp_listen->br->resp_success;
if ((rs % 9) == 0) {
stun_log(SINFO, "Retry sending in a new socket");
stun_close_socket(udp_listen);
uloop_timeout_set(&udp_listen->br->utimer, 0);
udp_listen->br = NULL;
}
else if ((rs % 3) == 0) {
stun_log(SINFO, "Retry sending.");
uloop_timeout_set(&udp_listen->br->utimer, 0);
}
}
}
end:
uloop_timeout_set(timeout, 1);
}
int main()
{
stun_log(SINFO, "Start stund daemon");
config_init();
keepalive_timeout = conf.min_keepalive;
uloop_init();
uloop_timeout_set(&br_crport.utimer, 100);
uloop_run();
uloop_done();
config_fini();
stun_log(SINFO, "Stop stund daemon");
return 0;
}

View File

@@ -1,106 +0,0 @@
#ifndef _STUN_H
#define _STUN_H
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <libubox/uloop.h>
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#ifndef container_of
#define container_of(ptr, type, member) \
({ \
const typeof(((type *) NULL)->member) *__mptr = (ptr); \
(type *) ((char *) __mptr - offsetof(type, member)); \
})
#endif
#define binding_request_entry(X) container_of(X, struct binding_request, utimer)
#define udp_listen_entry(X) container_of(X, struct udp_listen, utimer)
#define BINDING_REQUSET 0x0001
#define BINDING_RESPONSE 0x0101
#define BINDING_ERROR 0x0111
#define ATTR_MAPPED_ADDRESS 0x0001
#define ATTR_RESPONSE_ADDRESS 0x0002
#define ATTR_CHANGE_REQUEST 0x0003
#define ATTR_SOURCE_ADDRESS 0x0004
#define ATTR_CHANGED_ADDRESS 0x0005
#define ATTR_USERNAME 0x0006
#define ATTR_PASSWORD 0x0007
#define ATTR_MESSAGE_INTEGRITY 0x0008
#define ATTR_ERROR_CODE 0x0009
#define ATTR_UNKNOWN_ATTRIBUTES 0x000a
#define ATTR_REFLECTED_FROM 0x000b
#define ATTR_CONNECTION_REQUEST_BINDING 0xC001
#define ATTR_BINDING_CHANGE 0xC002
#define STUN_HEADER_LEN 20
struct binding_request;
typedef struct { unsigned int id[4]; } __attribute__((packed)) stunid;
struct udp_listen {
stunid expected_id;
int fd;
struct uloop_timeout utimer;
struct binding_request *br;
};
struct binding_request {
stunid id;
unsigned char is_keealive;
unsigned char msg_integrity; /* if true ==> MESSAGE-INTEGRITY should be append in the STUN msg */
unsigned char binding_change; /* if true ==> BINDING-CHANGE should be append in the STUN msg */
unsigned char binding_cr; /* if true ==> CONNECTION-REQUEST-BINDING should be append in the STUN msg */
int resp_success;
int auth_fail;
int retry_interval;
struct udp_listen *udp_listen;
struct uloop_timeout utimer;
};
struct stun_header {
unsigned short type;
unsigned short len;
stunid id;
unsigned char stunmsg[0];
} __attribute__((packed));
struct stun_attribute {
unsigned short type;
unsigned short len;
unsigned char value[0];
} __attribute__((packed));
struct stun_address {
unsigned char na;
unsigned char family;
unsigned short port;
unsigned int address;
} __attribute__((packed));
struct env_var {
unsigned short port;
unsigned int address;
unsigned int last_ts;
unsigned int last_crid;
};
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
#endif /* _STUN_H */

View File

@@ -1,49 +0,0 @@
# README #
In order to reach the devices that are connected behind NAT, the cwmp protocol introduces alternative method of executing Connection Request via NAT based on STUN. The stund is an implementation of STUN functionality that performs this feature.
## Configuration File ##
The stund UCI configuration is located in **'/etc/config/stun'** and contains only one section **stun**:
```
config stun 'stun'
option enable '0'
option username 'stun'
option password 'stun'
option server_address 'stun.l.google.com'
option server_port '19302'
option min_keepalive '30'
option max_keepalive '3600'
option client_port 7547
option log_level '1'
```
### stun section ###
It defines **the stun section configuration** (like username, password, etc...). The possible options for **stun** section are listed in the table below.
| Name | Type | Description |
| ---------------- | ------- | ------------------------------------------------- |
| `enable` | boolean | if set to **1**, the STUN client will be enabled. |
| `username` | string | The STUN username to be used in Binding Requests. |
| `password` | string | The STUN Password to be used in computing the MESSAGE-INTEGRITY. |
| `server_address` | string | The host name or IP address of the STUN server to send Binding Requests. |
| `server_port` | integer | The port number of the STUN server to send Binding Requests. |
| `min_keepalive` | integer | The minimum period that STUN Binding Requests must be sent by the CPE for the purpose of maintaining the binding in the Gateway. |
| `max_keepalive` | integer | The maximum period that STUN Binding Requests must be sent by the CPE for the purpose of maintaining the binding in the Gateway. |
| `client_port` | integer | The client source port of the STUN UDP binding. |
| `log_level` | integer | The log type to use, by default it is set to **'INFO'**. The possible types are **'EMERG', 'ALERT', 'CRITIC' ,'ERROR', 'WARNING', 'NOTICE', 'INFO' and 'DEBUG'**. |
## Dependencies ##
To successfully build stund, the following libraries are needed:
| Dependency | Link | License |
| --------------- | ------------------------------------------- | -------------- |
| libuci | https://git.openwrt.org/project/uci.git | LGPL 2.1 |
| libubox | https://git.openwrt.org/project/libubox.git | BSD |
| libubus | https://git.openwrt.org/project/ubus.git | LGPL 2.1 |
| libjson-c | https://s3.amazonaws.com/json-c_releases | MIT |
| libopenssl | http://ftp.fi.muni.cz/pub/openssl/source/ | OpenSSL |

View File

@@ -1,108 +0,0 @@
/*
* ubus.c -- This file conatains functions that allow to make ubus calls
*
*
* Copyright (C) 2020 iopsys Software Solutions AB. All rights reserved.
*
* Author: Omar Kallel <omar.kallel@pivasoftware.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include <strings.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <unistd.h>
#include <json-c/json.h>
#include <libubox/blobmsg_json.h>
#include <libubus.h>
#include "ubus.h"
static struct ubus_context *ubus_ctx = NULL;
static struct blob_buf b;
int subus_init(void)
{
ubus_ctx = ubus_connect(NULL);
if (!ubus_ctx) {
return -1;
}
return 0;
}
int subus_fini(void)
{
if (ubus_ctx) {
ubus_free(ubus_ctx);
}
ubus_ctx = NULL;
return 0;
}
void sadd_json_obj(json_object *json_obj_out, char *object, char *string)
{
json_object *json_obj_tmp = json_object_new_string(string);
json_object_object_add(json_obj_out, object, json_obj_tmp);
}
static int subus_call_req(char *path, char *method, int argc, struct sarg sarg[])
{
uint32_t id;
int i, r = 1;
char *arg;
json_object *json_obj_out = json_object_new_object();
if (json_obj_out == NULL)
return r;
blob_buf_init(&b, 0);
if (argc) {
for (i = 0; i < argc; i++) {
sadd_json_obj(json_obj_out, sarg[i].key, sarg[i].val);
}
arg = (char *)json_object_to_json_string(json_obj_out);
if (!blobmsg_add_json_from_string(&b, arg)) {
goto end;
}
}
if (ubus_lookup_id(ubus_ctx, path, &id))
goto end;
r = ubus_invoke(ubus_ctx, id, method, b.head, NULL, NULL, 1);
end:
json_object_put(json_obj_out);
blob_buf_free(&b);
return r;
}
int subus_call(char *path, char *method, int argc, struct sarg dmarg[])
{
int r = -1;
subus_init();
if (ubus_ctx) {
r = subus_call_req(path, method, argc, dmarg);
if (r > 0) r = -1;
}
subus_fini();
return r;
}

View File

@@ -1,22 +0,0 @@
/* TR-069 STUN client software
* Copyright (C) 2020 PIVA SOFTWARE <www.pivasoftware.com> - All Rights Reserved
* Author: Omar Kallel <omar.kallel@pivasoftware.com>
*/
#ifndef __SUBUS_H
#define __SUBUS_H
#include <libubox/blobmsg_json.h>
#include <json-c/json.h>
#include <libubus.h>
struct sarg {
char *key;
char *val;
};
#define UBUS_ARGS (struct sarg[])
int subus_call(char *path, char *method, int argc, struct sarg sarg[]);
#endif //__SUBUS_H

51
stunc/Makefile Executable file
View File

@@ -0,0 +1,51 @@
#
# Copyright (C) 2020 iopsys Software Solutions AB
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=stunc
PKG_VERSION:=1.0.1
PKG_SOURCE_VERSION:=cd7c5d70bc97a2f1a26d5587ccf6f4c1e9ca82c8
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://dev.iopsys.eu/iopsys/stunc.git
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
PKG_MIRROR_HASH:=skip
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
PKG_LICENSE:=GPL-2.0-only
PKG_LICENSE_FILES:=LICENSE
include $(INCLUDE_DIR)/package.mk
define Package/$(PKG_NAME)
SECTION:=utils
CATEGORY:=Utilities
SUBMENU:=TRx69
TITLE:=BBF STUN Client
DEPENDS:=+libubus +libuci +libubox +libjson-c +libopenssl +libblobmsg-json
endef
define Package/$(PKG_NAME)/description
BBF STUN Client
endef
TARGET_CFLAGS += \
-D_GNU_SOURCE
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) $(PKG_BUILD_DIR)/stunc $(1)/usr/sbin/
$(INSTALL_BIN) ./files/etc/init.d/stunc $(1)/etc/init.d/stunc
$(INSTALL_DATA) ./files/etc/config/stun $(1)/etc/config/stun
endef
$(eval $(call BuildPackage,$(PKG_NAME)))

View File

@@ -8,7 +8,5 @@ config stun 'stun'
option min_keepalive '30'
option max_keepalive '3600'
# option client_port 7547
#if client_port option is not set or < 0 then use a random port for connection request source port
#Log levels: Critical=0, Warning=1, Notice=2, Info=3, Debug=4
option log_level '3'
option log_level '0'

67
stunc/files/etc/init.d/stunc Executable file
View File

@@ -0,0 +1,67 @@
#!/bin/sh /etc/rc.common
# STUN client software
# Copyright (C) 2020 iopsys Software Solutions AB
# Author: Omar Kallel <omar.kallel@pivasoftware.com>
START=90
USE_PROCD=1
PROG="/usr/sbin/stunc"
log() {
#echo "${@}" >/dev/console
echo "${@}"|logger -t stun -p info
}
validate_stun_section()
{
uci_validate_section stun stun stun \
'enable:bool' \
'Username:string' \
'Password:string' \
'server_address:host' \
'server_port:port' \
'client_port:port' \
'log_level:uinteger:0'
}
service_running() {
ubus wait_for tr069
return $?;
}
start_service() {
local enable server_address
config_load stun
validate_stun_section || {
log "Validation failed for stun section";
exit 1;
}
if [ "$enable" -eq 0 ]; then
exit 0;
fi
if [ -z "${server_address}" ]; then
log "Stun server address not defined or invalid"
exit 0;
fi
procd_open_instance stun
procd_set_param command "$PROG"
procd_set_param respawn "3" "7" "0"
procd_close_instance
}
reload_service() {
stop
start
}
service_triggers()
{
procd_add_reload_trigger stun
}

45
sulu/Makefile Normal file
View File

@@ -0,0 +1,45 @@
#
# Copyright (C) 2021 IOPSYS
#
include $(TOPDIR)/rules.mk
PKG_NAME:=sulu
PKG_VERSION:=0.2.1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://dev.iopsys.eu/iopsys/sulu.git
PKG_SOURCE_VERSION:=a41d8edde15be3f22e358fb31e0b4786047dab53
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_SOURCE:=$(PKG_NAME)-$(PKG_SOURCE_VERSION).tar.gz
PKG_MIRROR_HASH:=skip
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_SOURCE_SUBDIR)
PKG_RELEASE=$(PKG_VERSION)-$(PKG_SOURCE_VERSION)
PKG_LICENSE:=GPLv2
PKG_LICENSE_FILES:=LICENSE
include $(INCLUDE_DIR)/package.mk
define Package/sulu
# $(Package/sulu/default)
SECTION:=sulu
CATEGORY:=Utilities
MENU=1
TITLE:=SULU-CE ReactJS based Web UI Package
endef
define Package/sulu/description
SULU-CE ReactJS based Web UI.
endef
define Package/sulu/install
$(INSTALL_DIR) $(1)/www
$(CP) $(PKG_BUILD_DIR)/out/* $(1)/www
# $(CP) ./files/* $(1)/
endef
$(eval $(call BuildPackage,sulu))

View File

@@ -10,8 +10,18 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=twamp
PKG_VERSION:=1.0.0
PKG_SOURCE_VERSION:=f6e914508aa1f7458f87bd68026f56262595d9a5
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://dev.iopsys.eu/iopsys/twamp.git
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
PKG_MIRROR_HASH:=skip
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
PKG_LICENSE:=GPL-2.0-only
PKG_LICENSE_FILES:=LICENSE
include $(INCLUDE_DIR)/package.mk
define Package/$(PKG_NAME)
@@ -26,10 +36,6 @@ define Package/$(PKG_NAME)/description
BBF twamp feature
endef
define Build/Prepare
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
TARGET_CFLAGS += \
-D_GNU_SOURCE
@@ -41,4 +47,4 @@ define Package/$(PKG_NAME)/install
$(CP) ./files/* $(1)/
endef
$(eval $(call BuildPackage,$(PKG_NAME)))
$(eval $(call BuildPackage,$(PKG_NAME)))

View File

@@ -1,23 +0,0 @@
PROG = twampd
LIB = libtwamp.so
PROG_OBJS = twamp.o twamplog.o twampuci.o twamptimestamp.o
LIB_OBJS = datamodel.o
PROG_CFLAGS = $(CFLAGS) -Wall -Werror -fPIC
PROG_LDFLAGS = $(LDFLAGS) -luci
LIB_LDFLAGS = $(LDFLAGS) -lbbf_api
%.o: %.c
$(CC) $(PROG_CFLAGS) $(FPIC) -c -o $@ $<
all: $(PROG) $(LIB)
$(PROG): $(PROG_OBJS)
$(CC) $(PROG_CFLAGS) -o $@ $^ $(PROG_LDFLAGS)
$(LIB): $(LIB_OBJS)
$(CC) $(PROG_CFLAGS) $(LIB_LDFLAGS) -shared -o $@ $^
clean:
rm -f *.o $(PROG) $(LIB)

View File

@@ -1,302 +0,0 @@
/*
* Copyright (C) 2020 iopsys Software Solutions AB
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation
*
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*/
#include <libbbf_api/dmbbf.h>
#include <libbbf_api/dmcommon.h>
#include <libbbf_api/dmuci.h>
#include <libbbf_api/dmubus.h>
#include <libbbf_api/dmjson.h>
#include "datamodel.h"
/* ********** DynamicObj ********** */
DM_MAP_OBJ tDynamicObj[] = {
/* parentobj, nextobject, parameter */
{"Device.IP.Interface.{i}.", tDeviceTWAMPReflectorObj, NULL},
{0}
};
static char *get_last_instance_with_option(char *package, char *section, char *option, char *val, char *opt_inst)
{
struct uci_section *s;
char *inst = NULL;
uci_foreach_option_eq(package, section, option, val, s) {
inst = update_instance(inst, 2, s, opt_inst);
}
return inst;
}
static char *get_last_id(char *package, char *section)
{
struct uci_section *s;
char *id;
int cnt = 0;
uci_foreach_sections(package, section, s) {
cnt++;
}
dmasprintf(&id, "%d", cnt+1);
return id;
}
static int addObjIPInterfaceTWAMPReflector(char *refparam, struct dmctx *ctx, void *data, char **instance)
{
struct uci_section *connection = NULL;
char *last_inst = get_last_instance_with_option("twamp", "twamp_reflector", "interface", section_name((struct uci_section *)data), "twamp_inst");
char *id = get_last_id("twamp", "twamp_reflector");
dmuci_add_section("twamp", "twamp_reflector", &connection);
dmasprintf(instance, "%d", last_inst ? atoi(last_inst)+1 : 1);
dmuci_set_value_by_section(connection, "twamp_inst", *instance);
dmuci_set_value_by_section(connection, "id", id);
dmuci_set_value_by_section(connection, "enable", "0");
dmuci_set_value_by_section(connection, "interface", section_name((struct uci_section *)data));
dmuci_set_value_by_section(connection, "port", "862");
dmuci_set_value_by_section(connection, "max_ttl", "1");
return 0;
}
static int delObjIPInterfaceTWAMPReflector(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
{
int found = 0;
struct uci_section *s, *ss = NULL;
char *interface;
switch (del_action) {
case DEL_INST:
dmuci_delete_by_section((struct uci_section *)data, NULL, NULL);
return 0;
case DEL_ALL:
uci_foreach_sections("twamp", "twamp_reflector", s) {
dmuci_get_value_by_section_string(s, "interface", &interface);
if (strcmp(interface, section_name((struct uci_section *)data)) != 0)
continue;
if (found != 0) {
dmuci_delete_by_section(ss, NULL, NULL);
}
ss = s;
found++;
}
if (ss != NULL) {
dmuci_delete_by_section(ss, NULL, NULL);
}
return 0;
}
return 0;
}
static int get_IPInterfaceTWAMPReflector_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = dmuci_get_value_by_section_fallback_def((struct uci_section *)data, "enable", "1");
return 0;
}
static int set_IPInterfaceTWAMPReflector_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
bool b;
struct uci_section *s;
char *interface, *device, *id, *ipv4addr = "";
json_object *res, *jobj;
switch (action) {
case VALUECHECK:
if (dm_validate_boolean(value))
return FAULT_9007;
break;
case VALUESET:
string_to_bool(value, &b);
if(b) {
dmuci_get_value_by_section_string((struct uci_section *)data, "interface", &interface);
dmuci_get_value_by_section_string((struct uci_section *)data, "id", &id);
dmuci_set_value_by_section((struct uci_section *)data, "enable", "1");
dmuci_set_value("twamp", "twamp", "id", id);
uci_foreach_sections("network", "interface", s) {
if(strcmp(section_name(s), interface) != 0)
continue;
dmuci_get_value_by_section_string(s, "ipaddr", &ipv4addr);
break;
}
if (ipv4addr[0] == '\0') {
dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", interface, String}}, 1, &res);
if (res) {
jobj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv4-address");
ipv4addr = dmjson_get_value(jobj, 1, "address");
if (ipv4addr[0] == '\0')
dmuci_set_value_by_section((struct uci_section *)data, "ip_version", "6");
else
dmuci_set_value_by_section((struct uci_section *)data, "ip_version", "4");
}
} else
dmuci_set_value_by_section((struct uci_section *)data, "ip_version", "4");
dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", interface, String}}, 1, &res);
if (res) {
device = dmjson_get_value(res, 1, "device");
dmuci_set_value_by_section((struct uci_section *)data, "device", device);
}
dmuci_set_value_by_section((struct uci_section *)data, "device", get_device(interface));
} else {
dmuci_set_value_by_section((struct uci_section *)data, "enable", "0");
}
break;
}
return 0;
}
static int get_IPInterfaceTWAMPReflector_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
char *enable;
dmuci_get_value_by_section_string((struct uci_section *)data, "enable", &enable);
if (strcmp(enable, "1") == 0)
*value = "Active";
else
*value = "Disabled";
return 0;
}
static int get_IPInterfaceTWAMPReflector_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
dmuci_get_value_by_section_string((struct uci_section *)data, "twamp_alias", value);
if ((*value)[0] == '\0')
dmasprintf(value, "cpe-%s", instance);
return 0;
}
static int set_IPInterfaceTWAMPReflector_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
switch (action) {
case VALUECHECK:
if (dm_validate_string(value, -1, 64, NULL, NULL))
return FAULT_9007;
break;
case VALUESET:
dmuci_set_value_by_section((struct uci_section *)data, "twamp_alias", value);
break;
}
return 0;
}
static int get_IPInterfaceTWAMPReflector_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = dmuci_get_value_by_section_fallback_def((struct uci_section *)data, "port", "862");
return 0;
}
static int set_IPInterfaceTWAMPReflector_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
switch (action) {
case VALUECHECK:
if (dm_validate_unsignedInt(value, RANGE_ARGS{{NULL,"65535"}}, 1))
return FAULT_9007;
break;
case VALUESET:
dmuci_set_value_by_section((struct uci_section *)data, "port", value);
break;
}
return 0;
}
static int get_IPInterfaceTWAMPReflector_MaximumTTL(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = dmuci_get_value_by_section_fallback_def((struct uci_section *)data, "max_ttl", "1");
return 0;
}
static int set_IPInterfaceTWAMPReflector_MaximumTTL(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
switch (action) {
case VALUECHECK:
if (dm_validate_unsignedInt(value, RANGE_ARGS{{"1","255"}}, 1))
return FAULT_9007;
break;
case VALUESET:
dmuci_set_value_by_section((struct uci_section *)data, "max_ttl", value);
break;
}
return 0;
}
static int get_IPInterfaceTWAMPReflector_IPAllowedList(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
dmuci_get_value_by_section_string((struct uci_section *)data, "ip_list", value);
return 0;
}
static int set_IPInterfaceTWAMPReflector_IPAllowedList(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
switch (action) {
case VALUECHECK:
if (dm_validate_string_list(value, -1, -1, 255, -1, -1, NULL, NULL))
return FAULT_9007;
break;
case VALUESET:
dmuci_set_value_by_section((struct uci_section *)data, "ip_list", value);
break;
}
return 0;
}
static int get_IPInterfaceTWAMPReflector_PortAllowedList(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
dmuci_get_value_by_section_string((struct uci_section *)data, "port_list", value);
return 0;
}
static int set_IPInterfaceTWAMPReflector_PortAllowedList(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
switch (action) {
case VALUECHECK:
if (dm_validate_string_list(value, -1, -1, 255, -1, -1, NULL, NULL))
return FAULT_9007;
break;
case VALUESET:
dmuci_set_value_by_section((struct uci_section *)data, "port_list", value);
break;
}
return 0;
}
static int browseIPInterfaceTWAMPReflectorInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
struct uci_section *s = NULL;
char *inst = NULL, *max_inst = NULL;
uci_foreach_option_eq("twamp", "twamp_reflector", "interface", section_name((struct uci_section *)prev_data), s) {
inst = handle_update_instance(2, dmctx, &max_inst, update_instance_alias, 3,
s, "twamp_inst", "twamp_alias");
if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)s, inst) == DM_STOP)
break;
}
return 0;
}
/* *** Device.IP.Interface.{i}. *** */
DMOBJ tDeviceTWAMPReflectorObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys*/
{"TWAMPReflector", &DMWRITE, addObjIPInterfaceTWAMPReflector, delObjIPInterfaceTWAMPReflector, NULL, browseIPInterfaceTWAMPReflectorInst, NULL, NULL, NULL, tIPInterfaceTWAMPReflectorParams, NULL, BBFDM_BOTH, LIST_KEY{"Alias", "Port", NULL}},
{0}
};
/* *** Device.IP.Interface.{i}.TWAMPReflector.{i}. *** */
DMLEAF tIPInterfaceTWAMPReflectorParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/
{"Enable", &DMWRITE, DMT_BOOL, get_IPInterfaceTWAMPReflector_Enable, set_IPInterfaceTWAMPReflector_Enable, BBFDM_BOTH},
{"Status", &DMREAD, DMT_STRING, get_IPInterfaceTWAMPReflector_Status, NULL, BBFDM_BOTH},
{"Alias", &DMWRITE, DMT_STRING, get_IPInterfaceTWAMPReflector_Alias, set_IPInterfaceTWAMPReflector_Alias, BBFDM_BOTH},
{"Port", &DMWRITE, DMT_UNINT, get_IPInterfaceTWAMPReflector_Port, set_IPInterfaceTWAMPReflector_Port, BBFDM_BOTH},
{"MaximumTTL", &DMWRITE, DMT_UNINT, get_IPInterfaceTWAMPReflector_MaximumTTL, set_IPInterfaceTWAMPReflector_MaximumTTL, BBFDM_BOTH},
{"IPAllowedList", &DMWRITE, DMT_STRING, get_IPInterfaceTWAMPReflector_IPAllowedList, set_IPInterfaceTWAMPReflector_IPAllowedList, BBFDM_BOTH},
{"PortAllowedList", &DMWRITE, DMT_STRING, get_IPInterfaceTWAMPReflector_PortAllowedList, set_IPInterfaceTWAMPReflector_PortAllowedList, BBFDM_BOTH},
{0}
};

View File

@@ -1,17 +0,0 @@
/*
* Copyright (C) 2020 iopsys Software Solutions AB
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation
*
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*/
#ifndef _TWAMP_H_
#define _TWAMP_H_
extern DMOBJ tDeviceTWAMPReflectorObj[];
extern DMLEAF tIPInterfaceTWAMPReflectorParams[];
#endif //_TWAMP_H_

View File

@@ -1,858 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*
* Name: Emma Mirică
* Project: TWAMP Protocol
* Class: OSS
* Email: emma.mirica@cti.pub.ro
* Contributions: stephanDB
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <time.h>
#include "twamp.h"
#include "twamplog.h"
#include "twampuci.h"
struct twamp_config cur_twamp_conf = {0};
TWAMPTimestamp ZeroT = { 0, 0 };
struct active_session {
int socket;
RequestSession req;
uint16_t server_oct;
uint32_t sid_addr;
TWAMPTimestamp sid_time;
uint32_t sid_rand;
uint32_t seq_nb;
uint32_t snd_nb;
uint32_t fw_msg;
uint32_t fw_lst_msg;
};
struct client_info {
ClientStatus status;
int socket;
struct sockaddr_in addr;
struct sockaddr_in6 addr6;
int mode;
int sess_no;
struct timeval shutdown_time;
struct active_session sessions[MAX_SESSIONS_PER_CLIENT];
};
static int fd_max = 0;
static enum Mode authmode = kModeUnauthenticated;
static int used_sockets = 0;
static fd_set read_fds;
static int socket_family = AF_INET;
static int check_ipv4_address(char *ip, char *maskstr, char *address)
{
struct sockaddr_in sa = {0};
unsigned long netaddress, maxaddress;
unsigned long mask = ~((1 << (32 - atoi(maskstr))) - 1);
inet_pton(AF_INET, address, &(sa.sin_addr));
netaddress = (ntohl(sa.sin_addr.s_addr) & mask);
sa.sin_addr.s_addr = 0;
inet_pton(AF_INET, ip, &(sa.sin_addr));
maxaddress = (ntohl(sa.sin_addr.s_addr) & mask);
if (maxaddress == netaddress)
return 1;
return 0;
}
static char *check_ipv6_address_active(char *ip)
{
unsigned char buf[sizeof(struct in6_addr)];
char str[INET6_ADDRSTRLEN], *res;
int s;
s = inet_pton(AF_INET6, ip, buf);
if (s <= 0) {
if (s == 0)
twamp_log(SCRIT, "Not in presentation format");
else
twamp_log(SCRIT, "inet_pton");
return "";
}
if (inet_ntop(AF_INET6, buf, str, INET6_ADDRSTRLEN) == NULL) {
twamp_log(SCRIT, "inet_ntop");
return "";
}
res = strdup(str);
return res;
}
static int check_ipv6_address(char *ip, char *maskstr, char *address)
{
struct sockaddr_in6 sa = {0};
unsigned long netaddress, maxaddress;
unsigned long mask = ~((1 << (128 - atoi(maskstr))) - 1);
inet_pton(AF_INET6, address, &(sa.sin6_addr));
netaddress = (ntohl((uint32_t)sa.sin6_addr.s6_addr) & mask);
inet_pton(AF_INET6, ip, &(sa.sin6_addr));
maxaddress = (ntohl((uint32_t)sa.sin6_addr.s6_addr) & mask);
if (maxaddress == netaddress)
return 1;
return 0;
}
static int check_ip_address_allowed(char *address)
{
char *pch, *spch, *ip, *mask, *str, *addr;
for (pch = strtok_r(cur_twamp_conf.ip_list, ",", &spch); pch != NULL; pch = strtok_r(NULL, ",", &spch))
{
if(strstr(pch, ".")) {
if(strstr(pch, "/")) {
ip = strtok_r(pch, "/", &str);
mask = strtok_r(NULL, "", &str);
if(check_ipv4_address(ip, mask, address))
return 1;
continue;
}
if (strcmp(pch, address) == 0)
return 1;
} else {
addr = check_ipv6_address_active(address);
if(strstr(pch, "/")) {
ip = strtok_r(pch, "/", &str);
mask = strtok_r(NULL, "", &str);
ip = check_ipv6_address_active(ip);
if(check_ipv6_address(ip, mask, addr))
return 1;
continue;
}
pch = check_ipv6_address_active(pch);
if (strcmp(pch, addr) == 0)
return 1;
}
}
return 0;
}
static int check_port_allowed(int port)
{
char *pch, *spch, *min, *max, *str;
for (pch = strtok_r(cur_twamp_conf.port_list, ",", &spch); pch != NULL; pch = strtok_r(NULL, ",", &spch))
{
if(strstr(pch, "-")) {
min = strtok_r(pch, "-", &str);
max = strtok_r(NULL, "", &str);
if(port >= atoi(min) && port <= atoi(max))
return 1;
continue;
}
if (port == atoi(pch))
return 1;
}
return 0;
}
/* The cleanup_client function will close every connection (TWAMP-Control ot TWAMP-Test that this server has with the client defined by the client_infor
* structure received as a parameter.
*/
static void cleanup_client(struct client_info *client)
{
char str_client[INET6_ADDRSTRLEN];
inet_ntop(socket_family, (socket_family == AF_INET6) ? (void*) &(client->addr6.sin6_addr) : (void*) &(client->addr.sin_addr), str_client, sizeof(str_client));
twamp_log(SINFO, "Cleanup client %s", str_client);
FD_CLR(client->socket, &read_fds);
close(client->socket);
used_sockets--;
int i;
for (i = 0; i < client->sess_no; i++)
/* If socket is -1 the session has already been closed */
if (client->sessions[i].socket > 0) {
FD_CLR(client->sessions[i].socket, &read_fds);
close(client->sessions[i].socket);
client->sessions[i].socket = -1;
used_sockets--;
}
memset(client, 0, sizeof(struct client_info));
client->status = kOffline;
}
/* The TWAMP server can only accept max_clients and it will recycle the positions for the available clients. */
static int find_empty_client(struct client_info *clients, int max_clients)
{
int i;
for (i = 0; i < max_clients; i++)
if (clients[i].status == kOffline)
return i;
return -1;
}
/* Sends a ServerGreeting message to the Control-Client after the TCP connection has been established. */
static int send_greeting(uint16_t mode_mask, struct client_info *client)
{
int socket = client->socket;
char str_client[INET6_ADDRSTRLEN]; /* String for Client IP address */
inet_ntop(socket_family, (socket_family == AF_INET6) ? (void*) &(client->addr6.sin6_addr) : (void*) &(client->addr.sin_addr), str_client, sizeof(str_client));
int i;
ServerGreeting greet;
memset(&greet, 0, sizeof(greet));
greet.Modes = htonl(client->mode & mode_mask);
for (i = 0; i < 16; i++)
greet.Challenge[i] = rand() % 16;
for (i = 0; i < 16; i++)
greet.Salt[i] = rand() % 16;
greet.Count = htonl(1 << 10);
int rv = send(socket, &greet, sizeof(greet), 0);
if (rv < 0) {
twamp_log(SCRIT,"Failed to send ServerGreeting message");
cleanup_client(client);
} else if ((authmode & 0x000F) == 0) {
twamp_log(SCRIT,"Sent ServerGreeting message with Mode 0! Abort");
cleanup_client(client);
} else {
twamp_log(SINFO,"Sent ServerGreeting message to %s", str_client);
}
return rv;
}
/* After a ServerGreeting the Control-Client should respond with a SetUpResponse. This function treats this message */
static int receive_greet_response(struct client_info *client)
{
int socket = client->socket;
char str_client[INET6_ADDRSTRLEN]; /* String for Client IP address */
inet_ntop(socket_family, (socket_family == AF_INET6)? (void*) &(client->addr6.sin6_addr) : (void*) &(client->addr.sin_addr), str_client, sizeof(str_client));
SetUpResponse resp;
memset(&resp, 0, sizeof(resp));
int rv = recv(socket, &resp, sizeof(resp), 0);
if (rv <= 32) {
twamp_log(SCRIT,"Failed to receive SetUpResponse");
cleanup_client(client);
} else {
twamp_log(SINFO, "Received SetUpResponse message from %s with mode %d", str_client, ntohl(resp.Mode));
if ((ntohl(resp.Mode) & client->mode & 0x000F) == 0) {
twamp_log(SCRIT,"The client does not support any usable Mode");
rv = 0;
}
client->mode = ntohl(resp.Mode);
}
return rv;
}
/* Sent a ServerStart message to the Control-Client to endthe TWAMP-Control session establishment phase */
static int send_start_serv(struct client_info *client, TWAMPTimestamp StartTime)
{
int socket = client->socket;
char str_client[INET6_ADDRSTRLEN];
inet_ntop(socket_family, (socket_family == AF_INET6)? (void*) &(client->addr6.sin6_addr) : (void*) &(client->addr.sin_addr), str_client, sizeof(str_client));
ServerStart msg;
memset(&msg, 0, sizeof(msg));
if ((StartTime.integer == 0) && (StartTime.fractional == 0)) {
msg.Accept = kAspectNotSupported;
} else {
msg.Accept = kOK;
}
msg.StartTime = StartTime;
int rv = send(socket, &msg, sizeof(msg), 0);
if (rv <= 0) {
twamp_log(SCRIT,"Failed to send ServerStart message");
cleanup_client(client);
} else {
client->status = kConfigured;
twamp_log(SINFO, "ServerStart message sent to %s", str_client);
if (msg.Accept == kAspectNotSupported) {
cleanup_client(client);
}
}
return rv;
}
/* Sends a StartACK for the StartSessions message */
static int send_start_ack(struct client_info *client)
{
char str_client[INET6_ADDRSTRLEN];
inet_ntop(socket_family, (socket_family == AF_INET6)? (void*) &(client->addr6.sin6_addr) : (void*) &(client->addr.sin_addr), str_client, sizeof(str_client));
StartACK ack;
memset(&ack, 0, sizeof(ack));
ack.Accept = kOK;
int rv = send(client->socket, &ack, sizeof(ack), 0);
if (rv <= 0) {
twamp_log(SCRIT,"Failed to send StartACK message");
} else
twamp_log(SINFO,"StartACK message sent to %s", str_client);
return rv;
}
/* This function treats the case when a StartSessions is received from the Control-Client to start a number of TWAMP-Test sessions */
static int receive_start_sessions(struct client_info *client)
{
int i;
int rv = send_start_ack(client);
if (rv <= 0)
return rv;
/* Now it can receive packets on the TWAMP-Test sockets */
for (i = 0; i < client->sess_no; i++) {
FD_SET(client->sessions[i].socket, &read_fds);
if (fd_max < client->sessions[i].socket)
fd_max = client->sessions[i].socket;
}
client->status = kTesting;
return rv;
}
/* This functions treats the case when a StopSessions is received from the Control-Client to end all the Test sessions. */
static int receive_stop_sessions(struct client_info *client)
{
/* If a StopSessions message was received, it can still receive Test packets until the timeout has expired */
gettimeofday(&client->shutdown_time, NULL);
return 0;
}
/* Computes the response to a RequestTWSession message */
static int send_accept_session(struct client_info *client, RequestSession * req)
{
char str_client[INET6_ADDRSTRLEN]; /* String for Client IP address */
AcceptSession acc;
memset(&acc, 0, sizeof(acc));
inet_ntop(socket_family, (socket_family == AF_INET6)? (void*) &(client->addr6.sin6_addr) : (void*) &(client->addr.sin_addr), str_client, sizeof(str_client));
/* Check if there are any slots available */
if ((used_sockets < 64) && (client->sess_no < MAX_SESSIONS_PER_CLIENT)) {
int testfd = socket(socket_family, SOCK_DGRAM, 0);
if (testfd < 0) {
twamp_log(SCRIT,"Error opening socket");
return -1;
}
int check_time = CHECK_TIMES;
if(socket_family == AF_INET6) {
struct sockaddr_in6 local_addr;
memset(&local_addr, 0, sizeof(local_addr));
local_addr.sin6_family = AF_INET6;
local_addr.sin6_addr = in6addr_any;
local_addr.sin6_port = req->ReceiverPort;
while (check_time-- && bind(testfd, (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0)
local_addr.sin6_port = htons(20000 + rand() % 1000);
if (check_time > 0) {
req->ReceiverPort = local_addr.sin6_port;
}
} else {
struct sockaddr_in local_addr;
memset(&local_addr, 0, sizeof(local_addr));
local_addr.sin_family = AF_INET;
local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
local_addr.sin_port = req->ReceiverPort;
while (check_time-- && bind(testfd, (struct sockaddr *)&local_addr, sizeof(struct sockaddr)) < 0)
local_addr.sin_port = htons(20000 + rand() % 1000);
if (check_time > 0) {
req->ReceiverPort = local_addr.sin_port;
}
}
if (check_time > 0) {
acc.Accept = kOK;
acc.Port = req->ReceiverPort;
client->sessions[client->sess_no].socket = testfd;
client->sessions[client->sess_no].req = *req;
/* SID construction */
memcpy(acc.SID, &req->ReceiverAddress, 4);
TWAMPTimestamp sidtime = get_timestamp();
memcpy(&acc.SID[4], &sidtime, 8);
int k;
for (k = 0; k < 4; k++)
acc.SID[12 + k] = rand() % 256;
memcpy(&client->sessions[client->sess_no].sid_addr, &acc.SID, 4);
client->sessions[client->sess_no].sid_time = sidtime;
memcpy(&client->sessions[client->sess_no].sid_rand, &acc.SID[12], 4);
twamp_log(SINFO, "SID: 0x%04X.%04X.%04X.%04X",
ntohl(client->sessions[client->sess_no].sid_addr),
ntohl(client->sessions[client->sess_no].sid_time.integer),
ntohl(client->sessions[client->sess_no].sid_time.fractional),
ntohl(client->sessions[client->sess_no].sid_rand));
/* Set socket options */
set_socket_option(testfd, cur_twamp_conf.max_ttl);
set_socket_tos(testfd, (client->sessions[client->sess_no].req.TypePDescriptor << 2));
client->sess_no++;
} else {
twamp_log(SINFO, "kTemporaryResourceLimitation: check_time [%d]", check_time);
acc.Accept = kTemporaryResourceLimitation;
acc.Port = 0;
}
} else {
twamp_log(SINFO, "kTemporaryResourceLimitation: used_sockets [%d], sess_no [%d]", used_sockets, client->sess_no);
acc.Accept = kTemporaryResourceLimitation;
acc.Port = 0;
}
int rv = send(client->socket, &acc, sizeof(acc), 0);
return rv;
}
/* This function treats the case when a RequestTWSession is received */
static int receive_request_session(struct client_info *client, RequestSession * req)
{
char str_client[INET6_ADDRSTRLEN]; /* String for Client IP address */
if(socket_family == AF_INET6) {
inet_ntop(AF_INET6, &(client->addr6.sin6_addr), str_client, sizeof(str_client));
twamp_log(SINFO, "Server received RequestTWSession message");
} else {
char str_server[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(client->addr.sin_addr), str_client, INET_ADDRSTRLEN);
struct in_addr se_addr;
se_addr.s_addr = req->ReceiverAddress;
inet_ntop(AF_INET, &(se_addr), str_server, INET_ADDRSTRLEN);
twamp_log(SINFO, "Server %s received RequestTWSession message with port %d", str_server, ntohs(req->ReceiverPort));
}
/* Check port test packets if its allowed by PortAllowedList parameter */
if(cur_twamp_conf.port_list[0] != '\0') {
if(!check_port_allowed(ntohs(req->ReceiverPort))) {
twamp_log(SINFO, "Port %d is not allowed", ntohs(req->ReceiverPort));
return -1;
}
}
int rv = send_accept_session(client, req);
if (rv <= 0) {
twamp_log(SCRIT,"Failed to send the Accept-Session message");
}
return rv;
}
/* This function will receive a TWAMP-Test packet and will send a response. In TWAMP the Session-Sender (in our case the Control-Client, meaning the
* TWAMP-Client) is always sending TWAMP-Test packets and the Session-Reflector (Server) is receiving TWAMP-Test packets.
*/
static int receive_test_message(struct client_info *client, int session_index)
{
struct sockaddr_in addr;
struct sockaddr_in6 addr6;
socklen_t len = sizeof(addr);
char str_client[INET6_ADDRSTRLEN];
inet_ntop(socket_family, (socket_family == AF_INET6)? (void*) &(client->addr6.sin6_addr) : (void*) &(client->addr.sin_addr), str_client, sizeof(str_client));
ReflectorUPacket pack_reflect;
memset(&pack_reflect, 0, sizeof(pack_reflect));
SenderUPacket pack;
memset(&pack, 0, sizeof(pack));
/* New for recvmsg */
struct msghdr *message = malloc(sizeof(struct msghdr));
struct cmsghdr *c_msg;
char *control_buffer = malloc(TST_PKT_SIZE);
uint16_t control_length = TST_PKT_SIZE;
memset(message, 0, sizeof(*message));
message->msg_name = (socket_family == AF_INET6)? (void*)&addr6: (void*)&addr;
message->msg_namelen = len;
message->msg_iov = malloc(sizeof(struct iovec));
message->msg_iov->iov_base = &pack;
message->msg_iov->iov_len = TST_PKT_SIZE;
message->msg_iovlen = 1;
message->msg_control = control_buffer;
message->msg_controllen = control_length;
int rv = recvmsg(client->sessions[session_index].socket, message, 0);
pack_reflect.receive_time = get_timestamp();
char str_server[INET6_ADDRSTRLEN]; /* String for Client IP address */
inet_ntop(socket_family, (socket_family == AF_INET6)? (void*) &(addr6.sin6_addr) : (void*) &(addr.sin_addr), str_server, sizeof(str_server));
if (rv <= 0) {
twamp_log(SCRIT,"Failed to receive TWAMP-Test packet");
return rv;
} else if (rv < 14) {
twamp_log(SCRIT,"Short TWAMP-Test packet");
return rv;
}
/* Get TTL/TOS values from IP header */
uint8_t fw_ttl = 0;
uint8_t fw_tos = 0;
for (c_msg = CMSG_FIRSTHDR(message); c_msg; c_msg = (CMSG_NXTHDR(message, c_msg))) {
if ((c_msg->cmsg_level == IPPROTO_IP && c_msg->cmsg_type == IP_TTL) || (c_msg->cmsg_level == IPPROTO_IPV6 && c_msg->cmsg_type == IPV6_HOPLIMIT)) {
fw_ttl = *(int *)CMSG_DATA(c_msg);
} else if (c_msg->cmsg_level == IPPROTO_IP && c_msg->cmsg_type == IP_TOS) {
fw_tos = *(int *)CMSG_DATA(c_msg);
} else {
twamp_log(SINFO, "Warning, unexpected data of level %i and type %i", c_msg->cmsg_level, c_msg->cmsg_type);
}
}
twamp_log(SINFO, "Received TWAMP-Test message from %s", inet_ntoa(addr.sin_addr));
pack_reflect.seq_number = htonl(client->sessions[session_index].seq_nb++);
pack_reflect.error_estimate = htons(0x8001); // Sync = 1, Multiplier = 1
pack_reflect.sender_seq_number = pack.seq_number;
pack_reflect.sender_time = pack.time;
pack_reflect.sender_error_estimate = pack.error_estimate;
pack_reflect.sender_ttl = fw_ttl; // Copy from the IP header packet from Sender
if ((client->mode & kModeDSCPECN) == kModeDSCPECN) {
pack_reflect.sender_tos = fw_tos; // Copy from the IP header packet from Sender
}
if(socket_family == AF_INET6) {
addr.sin_port = client->sessions[session_index].req.SenderPort;
} else {
addr6.sin6_port = client->sessions[session_index].req.SenderPort;
}
/* FW Loss Calculation */
if (client->sessions[session_index].fw_msg == 0) {
client->sessions[session_index].fw_msg = 1;
/* Response packet for TOS with ECN */
if ((fw_tos & 0x03) > 0) {
uint8_t ecn_tos = (fw_tos & 0x03) - (((fw_tos & 0x2) >> 1) & (fw_tos & 0x1));
set_socket_tos(client->sessions[session_index].socket, (client->sessions[session_index].req.TypePDescriptor << 2) + ecn_tos);
}
} else {
client->sessions[session_index].fw_msg = client->sessions[session_index].fw_msg + ntohl(pack.seq_number) - client->sessions[session_index].snd_nb;
client->sessions[session_index].fw_lst_msg = client->sessions[session_index].fw_lst_msg + ntohl(pack.seq_number) - client->sessions[session_index].snd_nb - 1;
}
client->sessions[session_index].snd_nb = ntohl(pack.seq_number);
/* Response packet */
pack_reflect.time = get_timestamp();
if(socket_family == AF_INET6) {
if (rv < 41) {
rv = sendto(client->sessions[session_index].socket, &pack_reflect, 41, 0, (struct sockaddr *)&addr6, sizeof(addr6));
} else {
rv = sendto(client->sessions[session_index].socket, &pack_reflect, rv, 0, (struct sockaddr *)&addr6, sizeof(addr6));
}
} else {
if (rv < 41) {
rv = sendto(client->sessions[session_index].socket, &pack_reflect, 41, 0, (struct sockaddr *)&addr, sizeof(addr));
} else {
rv = sendto(client->sessions[session_index].socket, &pack_reflect, rv, 0, (struct sockaddr *)&addr, sizeof(addr));
}
}
if (rv <= 0) {
twamp_log(SCRIT,"Failed to send TWAMP-Test packet");
}
/* Print the FW metrics */
print_metrics_server(str_client, socket_family == AF_INET6 ? ntohs(addr6.sin6_port): ntohs(addr.sin_port), ntohs(client->sessions[session_index].req.ReceiverPort), (client->sessions[session_index].req.TypePDescriptor << 2), fw_tos, &pack_reflect);
if ((client->sessions[session_index].fw_msg % 10) == 0) {
twamp_log(SINFO,"FW Lost packets: %u/%u", client->sessions[session_index].fw_lst_msg, client->sessions[session_index].fw_msg);
twamp_log(SINFO,"FW Loss Ratio: %3.2f%%", (float)100 * client->sessions[session_index].fw_lst_msg / client->sessions[session_index].fw_msg);
//printf("FW Lost packets: %u/%u, FW Loss Ratio: %3.2f%%\n", client->sessions[session_index].fw_lst_msg, client->sessions[session_index].fw_msg, (float)100 * client->sessions[session_index].fw_lst_msg / client->sessions[session_index].fw_msg);
}
return rv;
}
int twamp_connect(void)
{
int listenfd, newsockfd;
struct client_info clients[MAX_CLIENTS];
struct sockaddr_in client_addr;
struct sockaddr_in6 client_addr6;
int rv;
/* Obtain start server time in TWAMP format */
TWAMPTimestamp StartTime = get_timestamp();
if(cur_twamp_conf.ip_version == 4)
socket_family = AF_INET;
else
socket_family = AF_INET6;
listenfd = socket(socket_family, SOCK_STREAM, 0);
if (listenfd < 0) {
twamp_log(SCRIT,"Error opening socket");
return -1;
}
int ret = setsockopt(listenfd, SOL_SOCKET, SO_BINDTODEVICE, cur_twamp_conf.device, strlen(cur_twamp_conf.device)+1);
if(ret) {
twamp_log(SCRIT,"Error on setsockopt with ret %d", ret);
return -1;
}
if(socket_family == AF_INET6) {
/* Set Server address and bind on the TWAMP port */
struct sockaddr_in6 serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin6_family = AF_INET6;
serv_addr.sin6_addr = in6addr_any;
serv_addr.sin6_port = htons(cur_twamp_conf.port);
if (bind(listenfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
twamp_log(SCRIT,"Error on binding");
return -1;
}
} else {
/* Set Server address and bind on the TWAMP port */
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(cur_twamp_conf.port);
if (bind(listenfd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr)) < 0) {
twamp_log(SCRIT,"Error on binding");
return -1;
}
}
used_sockets++;
/* Start listening on the TWAMP port for new TWAMP-Control connections */
if (listen(listenfd, MAX_CLIENTS)) {
twamp_log(SCRIT,"Error on listen");
return -1;
}
FD_ZERO(&read_fds);
FD_SET(listenfd, &read_fds);
fd_max = listenfd;
memset(clients, 0, MAX_CLIENTS * sizeof(struct client_info));
fd_set tmp_fds;
FD_ZERO(&tmp_fds);
while (1) {
tmp_fds = read_fds;
if (select(fd_max + 1, &tmp_fds, NULL, NULL, NULL) < 0) {
twamp_log(SCRIT,"Error in select");
close(listenfd);
return -1;
}
/* If an event happened on the listenfd, then a new TWAMP-Control connection is received */
if (FD_ISSET(listenfd, &tmp_fds)) {
uint32_t client_len = (socket_family == AF_INET6)? sizeof(client_addr6) : sizeof(client_addr);
if ((newsockfd = accept(listenfd, (socket_family == AF_INET6) ? (struct sockaddr *)&client_addr6 : (struct sockaddr *)&client_addr, &client_len)) < 0) {
twamp_log(SCRIT,"Error in accept");
} else {
/* Add a new client if there are any slots available */
int pos = find_empty_client(clients, MAX_CLIENTS);
uint16_t mode_mask = 0;
if (pos != -1) {
clients[pos].status = kConnected;
clients[pos].socket = newsockfd;
clients[pos].addr = client_addr;
clients[pos].addr6 = client_addr6;
clients[pos].mode = authmode;
clients[pos].sess_no = 0;
used_sockets++;
FD_SET(newsockfd, &read_fds);
if (newsockfd > fd_max)
fd_max = newsockfd;
mode_mask = 0x01FF;
}
char str_client[INET6_ADDRSTRLEN]; /* String for Client IP address */
inet_ntop(socket_family, (socket_family == AF_INET6) ? (void*) &(clients[pos].addr6.sin6_addr) : (void*) &(clients[pos].addr.sin_addr), str_client, sizeof(str_client));
twamp_log(SINFO,"Receive a TCP connection from %s", str_client);
/* Check ip test packets if its allowed by IPAllowedList parameter */
if(cur_twamp_conf.ip_list[0] != '\0') {
if(!check_ip_address_allowed(str_client)) {
twamp_log(SINFO, "IP Address %d is not allowed", str_client);
close(listenfd);
return -1;
}
}
rv = send_greeting(mode_mask, &clients[pos]);
}
}
/* Receives other packets from the established TWAMP-Control sessions */
uint8_t buffer[4096];
int i, j;
for (i = 0; i < MAX_CLIENTS; i++)
/* It can only receive TWAMP-Control messages from Online clients */
if (clients[i].status != kOffline)
if (FD_ISSET(clients[i].socket, &tmp_fds)) {
switch (clients[i].status) {
case kConnected:
/* If a TCP session has been established and a ServerGreeting has been sent, wait for the SetUpResponse and finish the TWAMP-Control setup */
rv = receive_greet_response(&clients[i]);
if (rv > 32) {
rv = send_start_serv(&clients[i], StartTime);
} else {
rv = send_start_serv(&clients[i], ZeroT);
}
break;
case kConfigured:
/* Reset the buffer to receive a new message */
memset(buffer, 0, 4096);
rv = recv(clients[i].socket, buffer, 4096, 0);
if (rv <= 0) {
cleanup_client(&clients[i]);
break;
}
/* Check the message received: It can only be StartSessions or RequestTWSession */
switch (buffer[0]) {
case kStartSessions:
rv = receive_start_sessions(&clients[i]);
break;
case kRequestTWSession:
rv = receive_request_session(&clients[i], (RequestSession *) buffer);
break;
default:
break;
}
if (rv <= 0)
cleanup_client(&clients[i]);
break;
case kTesting:
/* In this state can only receive a StopSessions msg */
memset(buffer, 0, 4096);
rv = recv(clients[i].socket, buffer, 4096, 0);
if (rv <= 0) {
cleanup_client(&clients[i]);
break;
}
if (buffer[0] == kStopSessions) {
rv = receive_stop_sessions(&clients[i]);
}
break;
default:
break;
}
}
/* Check for TWAMP-Test packets */
for (i = 0; i < MAX_CLIENTS; i++) {
struct timeval current;
gettimeofday(&current, NULL);
if (clients[i].status == kTesting) {
uint8_t has_active_test_sessions = 0;
for (j = 0; j < clients[i].sess_no; j++) {
rv = get_actual_shutdown(&current, &clients[i].shutdown_time, &clients[i].sessions[j].req.Timeout);
if (rv > 0) {
has_active_test_sessions = 1;
if (FD_ISSET(clients[i].sessions[j].socket, &tmp_fds)) {
rv = receive_test_message(&clients[i], j);
}
} else {
FD_CLR(clients[i].sessions[j].socket, &read_fds);
close(clients[i].sessions[j].socket);
used_sockets--;
clients[i].sessions[j].socket = -1;
/* print loss result */
twamp_log(SINFO, "Session: %u, FW Lost packets: %u/%u, FW Loss Ratio: %3.2f%%", j, clients[i].sessions[j].fw_lst_msg, clients[i].sessions[j].fw_msg, (float)100 * clients[i].sessions[j].fw_lst_msg / clients[i].sessions[j].fw_msg);
}
}
if (!has_active_test_sessions) {
memset(&clients[i].shutdown_time, 0, sizeof(clients[i].shutdown_time));
clients[i].sess_no = 0;
clients[i].status = kConfigured;
}
}
}
}
return 0;
}
char *get_twamp_reflector_option(char *instance, char *option)
{
struct uci_section *s;
char *v, *twamp_id;
dmuci_foreach_section("twamp", "twamp_reflector", s) {
twamp_id = dmuci_get_value_bysection(s, "id");
if(strcmp(twamp_id, instance) == 0)
{
v = dmuci_get_value_bysection(s, option);
return v;
}
}
v = "";
return v;
}
int twamp_init(void)
{
char *id, *value = NULL;
int a;
value = dmuci_get_value("twamp", "twamp", "log_level");
if(value != NULL && *value != '\0') {
a = atoi(value);
cur_twamp_conf.loglevel = a;
}
else
cur_twamp_conf.loglevel = DEFAULT_LOGLEVEL;
twamp_log(SDEBUG,"TWAMP Reflector Log Level:%d", cur_twamp_conf.loglevel);
id = dmuci_get_value("twamp", "twamp", "id");
cur_twamp_conf.enable = atoi(get_twamp_reflector_option(id, "enable"));
cur_twamp_conf.interface = strdup(get_twamp_reflector_option(id, "interface"));
cur_twamp_conf.device = strdup(get_twamp_reflector_option(id, "device"));
cur_twamp_conf.ip_version = atoi(get_twamp_reflector_option(id, "ip_version"));
cur_twamp_conf.port = atoi(get_twamp_reflector_option(id, "port"));
cur_twamp_conf.max_ttl = atoi(get_twamp_reflector_option(id, "max_ttl"));
cur_twamp_conf.ip_list = strdup(get_twamp_reflector_option(id, "ip_list"));
cur_twamp_conf.port_list = strdup(get_twamp_reflector_option(id, "port_list"));
twamp_log(SDEBUG,"TWAMP Reflector Enable: %d", cur_twamp_conf.enable);
twamp_log(SDEBUG,"TWAMP Reflector Interface: %s", cur_twamp_conf.interface);
twamp_log(SDEBUG,"TWAMP Reflector Device: %s", cur_twamp_conf.device);
twamp_log(SDEBUG,"TWAMP Reflector Port: %d", cur_twamp_conf.port);
twamp_log(SDEBUG,"TWAMP Reflector MaximumTTL: %d", cur_twamp_conf.max_ttl);
twamp_log(SDEBUG,"TWAMP Reflector IPAllowedList: %s", cur_twamp_conf.ip_list);
twamp_log(SDEBUG,"TWAMP Reflector PortAllowedList: %s", cur_twamp_conf.port_list);
return 0;
}
void twamp_exit(void)
{
free(cur_twamp_conf.interface);
free(cur_twamp_conf.device);
free(cur_twamp_conf.ip_list);
free(cur_twamp_conf.port_list);
}
int main(int argc, char *argv[])
{
dmuci_init();
twamp_init();
dmuci_fini();
twamp_log(SINFO,"START TWAMP Reflector");
twamp_connect();
twamp_exit();
twamp_log(SINFO,"EXIT TWAMP Reflector");
return 0;
}

View File

@@ -1,237 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*
* Name: Emma Mirică
* Project: TWAMP Protocol
* Class: OSS
* Email: emma.mirica@cti.pub.ro
* Contributions: stephanDB
*
*/
/*
* The following logical-model will be implemented:
*
* +----------------+ +-------------------+
* | Control-Client |<--TWAMP-Control-->| Server |
* | | | |
* | Session-Sender |<--TWAMP-Test----->| Session-Reflector |
* +----------------+ +-------------------+
*
*/
#ifndef _TWAMP_H__
#define _TWAMP_H__
#include <stdlib.h>
#include <stdbool.h>
#include <inttypes.h>
#include <sys/time.h>
#define CHECK_TIMES 100
#define LOSTTIME 2 /* SECONDS - Timeout for TWAMP test packet */
#define MAX_CLIENTS 10
#define MAX_SESSIONS_PER_CLIENT 10
enum CommandNumber {
kReserved,
kForbidden,
kStartSessions,
kStopSessions,
kReserved4,
kRequestTWSession,
kExperimentation
};
enum Mode {
kModeReserved = 0,
kModeUnauthenticated = 1,
kModeAuthenticated = 2,
kModeEncrypted = 4,
kModeHybrid = 8, /* Unauthenticated test, encrypted control */
kModeIndividual = 16,
kModeReflectOctets = 32,
KModeSymmetrical = 64,
KModeIKEv2Derived = 128,
kModeDSCPECN = 256
};
enum AcceptCode {
kOK,
kFailure,
kInternalError,
kAspectNotSupported,
kPermanentResourceLimitation,
kTemporaryResourceLimitation
};
typedef enum {
kOffline = 0,
kConnected,
kConfigured,
kTesting
} ClientStatus;
typedef struct twamp_timestamp {
uint32_t integer;
uint32_t fractional;
} TWAMPTimestamp;
/*****************************************/
/* */
/* TWAMP-Control specific messages */
/* */
/*****************************************/
/* First messsage sent by the Server to the Control-Client to establish a connection */
typedef struct server_greeting {
uint8_t Unused[12];
/* Modes = bit-wise OR between Mode values
* First 23 bits MUST be zero in TWAMP (29 in first version)*/
uint32_t Modes;
uint8_t Challenge[16]; /* Random sequence of bytes generated by the server */
uint8_t Salt[16];
uint32_t Count; /* MUST be a power of 2. Minimum 1024 */
uint8_t MBZ[12];
} ServerGreeting;
/* The Control-Client's response to the Server's greeting */
typedef struct control_client_greeting_response {
uint32_t Mode; /* if 0 -> the Server does not wish to communicate */
uint8_t KeyID[80];
uint8_t Token[64];
uint8_t ClientIV[16];
} SetUpResponse;
/* The Server sends a start message to conclude the TWAMP-Control session */
typedef struct server_start {
uint8_t MBZ1[15];
uint8_t Accept; /* 0 means Continue. See 3.3 of RFC 4656 */
uint8_t ServerIV[16];
TWAMPTimestamp StartTime; /* TWAMPTimestamp; 0 if Accept is NonZero. */
uint8_t MBZ2[8];
} ServerStart;
/* The Control-Client sends a RequestSession packet for each TWAMP-Test session */
typedef struct request_session {
uint8_t Type; /* 5 / CommandNumber */
uint8_t IPVN; /* MBZ | IPVN */
uint8_t ConfSender; /* 0 */
uint8_t ConfReceiver; /* 0 */
uint32_t SlotsNo; /* 0 */
uint32_t PacketsNo; /* 0 */
uint16_t SenderPort;
uint16_t ReceiverPort;
uint32_t SenderAddress;
uint8_t MBZ1[12]; /* Sender Address Cont */
uint32_t ReceiverAddress;
uint8_t MBZ2[12]; /* Receiver Address Cont */
uint8_t SID[16]; /* 0 */
uint32_t PaddingLength;
TWAMPTimestamp StartTime;
TWAMPTimestamp Timeout;
uint32_t TypePDescriptor;
uint16_t OctetsToBeReflected;
uint16_t PadLenghtToReflect;
uint8_t MBZ3[4];
uint8_t HMAC[16];
} RequestSession;
/* The Server's response to the RequestSession packet */
typedef struct accept_session_packet {
uint8_t Accept; /* 3 if not supported */
uint8_t MBZ1;
uint16_t Port;
uint8_t SID[16]; /* Generated by server */
//uint16_t ReflectedOctets;
//uint16_t ServerOctets;
uint8_t MBZ2[8];
uint8_t HMAC[16];
} AcceptSession;
/* The Control-Client sends a StartSessions message to start all accepted TWAMP-Test sessions */
typedef struct start_message1 {
uint8_t Type; /* 2 */
uint8_t MBZ[15];
uint8_t HMAC[16];
} StartSessions;
/* When it receives a StartSessions, the Server responds with a StartACK */
typedef struct start_ack {
uint8_t Accept;
uint8_t MBZ[15];
uint8_t HMAC[16];
} StartACK;
/* The Control-Client sends a StopSessions message to stop all active TWAMP-Test sessions */
typedef struct twamp_stop {
uint8_t Type; /* 3 */
uint8_t Accept;
uint8_t MBZ1[2];
uint32_t SessionsNo;
uint8_t MBZ2[8];
uint8_t HMAC[16];
} StopSessions;
/*****************************************/
/* */
/* TWAMP-Test specific messages */
/* */
/*****************************************/
#define TST_PKT_SIZE 1472 //1472 (MTU 1514)
/* Session-Sender TWAMP-Test packet for Unauthenticated mode */
typedef struct test_packet {
uint32_t seq_number;
TWAMPTimestamp time;
uint16_t error_estimate;
uint8_t padding[TST_PKT_SIZE - 14];
} SenderUPacket;
/* Session-Reflector TWAMP-Test packet for Unauthenticated mode */
typedef struct reflector_unauth_packet {
uint32_t seq_number;
TWAMPTimestamp time;
uint16_t error_estimate;
uint8_t mbz1[2];
TWAMPTimestamp receive_time;
uint32_t sender_seq_number;
TWAMPTimestamp sender_time;
uint16_t sender_error_estimate;
uint8_t mbz2[2];
uint8_t sender_ttl;
uint8_t sender_tos;
uint8_t padding[TST_PKT_SIZE - 42];
} ReflectorUPacket;
struct twamp_config
{
bool enable;
char *interface;
char *device;
int ip_version;
int port;
int max_ttl;
char *ip_list;
char *port_list;
int loglevel;
};
extern struct twamp_config cur_twamp_conf;
void timeval_to_timestamp(const struct timeval *tv, TWAMPTimestamp * ts);
void timestamp_to_timeval(const TWAMPTimestamp * ts, struct timeval *tv);
uint64_t get_usec(const TWAMPTimestamp * ts);
TWAMPTimestamp get_timestamp();
int get_actual_shutdown(const struct timeval *tv, const struct timeval *ts, const TWAMPTimestamp * t);
void print_metrics_server(char *addr_cl, uint16_t snd_port, uint16_t rcv_port, uint8_t snd_tos, uint8_t fw_tos, const ReflectorUPacket * pack);
void set_socket_option(int socket, uint8_t ip_ttl);
void set_socket_tos(int socket, uint8_t ip_tos);
#endif /* _TWAMP_H__ */

View File

@@ -1,57 +0,0 @@
# README #
twampd is an implementation of the Two-Way Active Measurement Protocol (TWAMP) reflector.
## Configuration File ##
The twampd UCI configuration is located in **'/etc/config/twamp'**, and contains 2 sections the **twamp** and the **twamp\_reflector**.
```
config twamp 'twamp'
option id '1'
option log_level '3'
config twamp_reflector
option id '1'
option enable ''
option interface ''
option device ''
option ip_version ''
option port ''
option max_ttl ''
option ip_list ''
option port_list ''
```
### twamp section ###
It defines **the twamp configuration**: id, log_level. The possible options for **twamp** section are:
| Name | Type | Description |
| --------- | ------- | ------------------------------------------- |
| `id` | integer | Specifies the id of TWAMP reflector to use. |
| `log_level` | integer | Specifies the log type to use, by default **'INFO'**. The possible types are **'EMERG', 'ALERT', 'CRITIC' ,'ERROR', 'WARNING', 'NOTICE', 'INFO' and 'DEBUG'**. |
### twamp_reflector section ###
It describes **the twamp reflector configuration**: id, ip\_version, etc... The possible options for **twamp_reflector** section are:
| Name | Type | Description |
| ---------- | ------- | ------------------------------ |
| `id` | integer | Specifies the TWAMP id to use. |
| `enable` | boolean | If set to **1**, it enables the TWAMP reflector. |
| `ip_version` | integer | Specifies the IP version to use, **4** by default. The possible versions are **4** and **6**. |
| `port` | integer | Specifies the port to listen on. |
| `max_ttl` | integer | Specifies the maximum TTL of a received packet, that the TWAMP reflector will reflect to the TWAMP controller. |
| `ip_list` | string | Specifies the allowed source IP addresses and subnets to handle test packets. |
| `port_list` | string | Specifies the range of source ports allowed to use for twamp\_reflector tests. |
## Dependencies ##
To successfully build twampd, the following libraries are needed:
| Dependency | Link | License |
| ----------- | ------------------------------------------- | -------------- |
| libuci | https://git.openwrt.org/project/uci.git | LGPL 2.1 |

View File

@@ -1,55 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*/
#include <stdio.h>
#include <time.h>
#include <syslog.h>
#include <stdarg.h>
#include "twamplog.h"
#include "twamp.h"
#define DEBUG
static const int log_syslogmap[] = {
[SCRIT] = LOG_CRIT,
[SWARNING] = LOG_WARNING,
[SNOTICE] = LOG_NOTICE,
[SINFO] = LOG_INFO,
[SDEBUG] = LOG_DEBUG
};
static const char* log_str[] = {
[SCRIT] = "CRITICAL",
[SWARNING] = "WARNING",
[SNOTICE] = "NOTICE",
[SINFO] = "INFO",
[SDEBUG] = "DEBUG"
};
void twamp_log(int priority, const char *format, ...)
{
va_list vl;
if (priority <= cur_twamp_conf.loglevel) {
#ifdef DEBUG
time_t t = time(NULL);
struct tm tm = *localtime(&t);
va_start(vl, format);
printf("%d-%02d-%02d %02d:%02d:%02d [twamp] %s - ", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, log_str[priority]);
vprintf(format, vl);
va_end(vl);
printf("\n");
#endif
openlog("twamp", 0, LOG_DAEMON);
va_start(vl, format);
vsyslog(log_syslogmap[priority], format, vl);
va_end(vl);
closelog();
}
}

View File

@@ -1,27 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*/
#ifndef _TWAMPLOG_H_
#define _TWAMPLOG_H_
#define DEFAULT_LOGLEVEL SINFO
enum udpechoserver_log_level_enum {
SCRIT,
SWARNING,
SNOTICE,
SINFO,
SDEBUG,
__MAX_SLOG
};
void twamp_log(int priority, const char *format, ...);
#endif /* _TWAMPLOG_H_ */

View File

@@ -1,195 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*
* Name: Emma Mirică
* Project: TWAMP Protocol
* Class: OSS
* Email: emma.mirica@cti.pub.ro
* Contributions: stephanDB
*
*/
#include <inttypes.h>
#include <sys/time.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <stdio.h>
#include "twamp.h"
#include "twamplog.h"
void timeval_to_timestamp(const struct timeval *tv, TWAMPTimestamp * ts)
{
if (!tv || !ts)
return;
/* Unix time to NTP */
ts->integer = tv->tv_sec + 2208988800uL;
ts->fractional = (uint32_t) ((double)tv->tv_usec * ((double)(1uLL << 32)
/ (double)1e6));
ts->integer = htonl(ts->integer);
ts->fractional = htonl(ts->fractional);
}
void timestamp_to_timeval(const TWAMPTimestamp * ts, struct timeval *tv)
{
if (!tv || !ts)
return;
TWAMPTimestamp ts_host_ord;
ts_host_ord.integer = ntohl(ts->integer);
ts_host_ord.fractional = ntohl(ts->fractional);
/* NTP to Unix time */
tv->tv_sec = ts_host_ord.integer - 2208988800uL;
tv->tv_usec = (uint32_t) (double)ts_host_ord.fractional * (double)1e6 / (double)(1uLL << 32);
}
TWAMPTimestamp get_timestamp()
{
struct timeval tv;
gettimeofday(&tv, NULL);
TWAMPTimestamp ts;
timeval_to_timestamp(&tv, &ts);
return ts;
}
uint64_t get_usec(const TWAMPTimestamp * ts)
{
struct timeval tv;
timestamp_to_timeval(ts, &tv);
return tv.tv_sec * 1000000 + tv.tv_usec;
}
int get_actual_shutdown(const struct timeval *tv, const struct timeval *ts,
const TWAMPTimestamp * t)
{
/* If ts is 0 then no StopSessions message was received */
if ((ts->tv_sec * 1000000 + ts->tv_usec) == 0)
return 1;
/* Else compute time difference */
uint64_t current = tv->tv_sec * 1000000 + tv->tv_usec;
uint64_t shutdown = ts->tv_sec * 1000000 + ts->tv_usec;
uint64_t timeout = get_usec(t);
/* This should be ok, as no difference is computed */
if (current > shutdown + timeout)
return 1;
return 0;
}
void print_metrics_server(char *addr_cl, uint16_t snd_port, uint16_t rcv_port,
uint8_t snd_tos, uint8_t fw_tos,
const ReflectorUPacket * pack)
{
/* Compute timestamps in usec */
uint64_t t_sender_usec1 = get_usec(&pack->sender_time);
uint64_t t_receive_usec1 = get_usec(&pack->receive_time);
uint64_t t_reflsender_usec1 = get_usec(&pack->time);
/* Compute delays */
int64_t fwd1 = t_receive_usec1 - t_sender_usec1;
int64_t intd1 = t_reflsender_usec1 - t_receive_usec1;
char sync1 = 'Y';
if (fwd1 < 0) {
sync1 = 'N';
}
/* Sequence number */
uint32_t snd_nb = ntohl(pack->sender_seq_number);
uint32_t rcv_nb = ntohl(pack->seq_number);
/* Sender TOS with ECN from FW TOS */
snd_tos = snd_tos + (fw_tos & 0x3) - (((fw_tos & 0x2) >> 1) & (fw_tos & 0x1));
/* Print different metrics */
twamp_log(SINFO,"Snd@: %s", addr_cl);
twamp_log(SINFO,"Time: %.0f", (double)t_sender_usec1 * 1e-3);
twamp_log(SINFO,"Snd#: %d", snd_nb);
twamp_log(SINFO,"Rcv#: %d", rcv_nb);
twamp_log(SINFO,"SndPt: %d", snd_port);
twamp_log(SINFO,"RcvPt: %d", rcv_port);
twamp_log(SINFO,"Sync: %c", sync1);
twamp_log(SINFO,"TTL: %d", pack->sender_ttl);
twamp_log(SINFO,"SndTOS: %d", snd_tos);
twamp_log(SINFO,"FW_TOS: %d", fw_tos);
twamp_log(SINFO,"Int D: %.3f", (double)intd1 * 1e-3);
}
void set_socket_option(int socket, uint8_t ip_ttl)
{
/* Set socket options : timeout, IPTTL, IP_RECVTTL, IP_RECVTOS */
uint8_t One = 1;
int result;
/* Set Timeout */
struct timeval timeout = { LOSTTIME, 0 }; //set timeout for 2 seconds
/* Set receive UDP message timeout value */
#ifdef SO_RCVTIMEO
result = setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO,
(char *)&timeout, sizeof(struct timeval));
if (result != 0) {
twamp_log(SDEBUG, "[PROBLEM] Cannot set the timeout value for reception.\n");
}
#else
twamp_log(SDEBUG, "No way to set the timeout value for incoming packets on that platform.\n");
#endif
/* Set IPTTL value to twamp standard: 255 */
#ifdef IP_TTL
result = setsockopt(socket, IPPROTO_IP, IP_TTL, &ip_ttl, sizeof(ip_ttl));
if (result != 0) {
twamp_log(SDEBUG, "[PROBLEM] Cannot set the TTL value for emission.\n");
}
#else
twamp_log(SDEBUG, "No way to set the TTL value for leaving packets on that platform.\n");
#endif
/* Set receive IP_TTL option */
#ifdef IP_RECVTTL
result = setsockopt(socket, IPPROTO_IP, IP_RECVTTL, &One, sizeof(One));
if (result != 0) {
twamp_log(SDEBUG, "[PROBLEM] Cannot set the socket option for TTL reception.\n");
}
#else
twamp_log(SDEBUG, "No way to ask for the TTL of incoming packets on that platform.\n");
#endif
/* Set receive IP_TOS option */
#ifdef IP_RECVTOS
result = setsockopt(socket, IPPROTO_IP, IP_RECVTOS, &One, sizeof(One));
if (result != 0) {
twamp_log(SDEBUG, "[PROBLEM] Cannot set the socket option for TOS reception.\n");
}
#else
twamp_log(SDEBUG, "No way to ask for the TOS of incoming packets on that platform.\n");
#endif
}
void set_socket_tos(int socket, uint8_t ip_tos)
{
/* Set socket options : IP_TOS */
int result;
/* Set IP TOS value */
#ifdef IP_TOS
result = setsockopt(socket, IPPROTO_IP, IP_TOS, &ip_tos, sizeof(ip_tos));
if (result != 0) {
twamp_log(SDEBUG, "[PROBLEM] Cannot set the TOS value for emission.\n");
}
#else
twamp_log(SDEBUG, "No way to set the TOS value for leaving packets on that platform.\n");
#endif
}

View File

@@ -1,266 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*/
#include <strings.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdarg.h>
#include <errno.h>
#include <unistd.h>
#include <ctype.h>
#include <uci.h>
#include "twampuci.h"
struct uci_context *uci_ctx;
int dmuci_init(void)
{
uci_ctx = uci_alloc_context();
if (!uci_ctx) {
return -1;
}
return 0;
}
int dmuci_fini(void)
{
if (uci_ctx) {
uci_free_context(uci_ctx);
}
return 0;
}
static bool dmuci_validate_section(const char *str)
{
if (!*str)
return false;
for (; *str; str++) {
unsigned char c = *str;
if (isalnum(c) || c == '_')
continue;
return false;
}
return true;
}
static int dmuci_init_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *package, char *section, char *option, char *value)
{
memset(ptr, 0, sizeof(struct uci_ptr));
/* value */
if (value) {
ptr->value = value;
}
ptr->package = package;
if (!ptr->package)
goto error;
ptr->section = section;
if (!ptr->section) {
ptr->target = UCI_TYPE_PACKAGE;
goto lastval;
}
ptr->option = option;
if (!ptr->option) {
ptr->target = UCI_TYPE_SECTION;
goto lastval;
} else {
ptr->target = UCI_TYPE_OPTION;
}
lastval:
if (ptr->section && !dmuci_validate_section(ptr->section))
ptr->flags |= UCI_LOOKUP_EXTENDED;
return 0;
error:
return -1;
}
struct uci_section *dmuci_walk_section(char *package, char *section_type, struct uci_section *prev_section)
{
struct uci_ptr ptr;
struct uci_element *e;
struct uci_section *next_section;
if (section_type == NULL) {
if (prev_section) {
e = &prev_section->e;
if (e->list.next == &prev_section->package->sections)
return NULL;
e = container_of(e->list.next, struct uci_element, list);
next_section = uci_to_section(e);
return next_section;
}
else {
if (dmuci_init_ptr(uci_ctx, &ptr, package, NULL, NULL, NULL)) {
return NULL;
}
if (uci_lookup_ptr(uci_ctx, &ptr, NULL, true) != UCI_OK) {
return NULL;
}
if (ptr.p->sections.next == &ptr.p->sections)
return NULL;
e = container_of(ptr.p->sections.next, struct uci_element, list);
next_section = uci_to_section(e);
return next_section;
}
}
else {
struct uci_list *ul;
struct uci_list *shead = NULL;
if (prev_section) {
ul = &prev_section->e.list;
shead = &prev_section->package->sections;
}
else {
if (dmuci_init_ptr(uci_ctx, &ptr, package, NULL, NULL, NULL)) {
return NULL;
}
if (uci_lookup_ptr(uci_ctx, &ptr, NULL, true) != UCI_OK) {
return NULL;
}
ul = &ptr.p->sections;
shead = &ptr.p->sections;
}
while (ul->next != shead) {
e = container_of(ul->next, struct uci_element, list);
next_section = uci_to_section(e);
if (strcmp(next_section->type, section_type) == 0)
return next_section;
ul = ul->next;
}
return NULL;
}
return NULL;
}
void dmuci_print_list(struct uci_list *uh, char **val, char *delimiter)
{
struct uci_element *e;
static char buffer[512];
char *buf = buffer;
*buf = '\0';
uci_foreach_element(uh, e) {
if (*buf) {
strcat(buf, delimiter);
strcat(buf, e->name);
}
else {
strcpy(buf, e->name);
}
}
*val = buf;
}
struct uci_element *dmuci_lookup_list(struct uci_list *list, const char *name)
{
struct uci_element *e;
uci_foreach_element(list, e) {
if (!strcmp(e->name, name))
return e;
}
return NULL;
}
int uci_lookup_ptr_bysection(struct uci_context *ctx, struct uci_ptr *ptr, struct uci_section *section, char *option, char *value)
{
struct uci_element *e;
memset(ptr, 0, sizeof(struct uci_ptr));
ptr->package = section->package->e.name;
ptr->section = section->e.name;
ptr->option = option;
ptr->value = value;
ptr->flags |= UCI_LOOKUP_DONE;
ptr->p = section->package;
ptr->s = section;
if (ptr->option) {
e = dmuci_lookup_list(&ptr->s->options, ptr->option);
if (!e)
return UCI_OK;
ptr->o = uci_to_option(e);
ptr->last = e;
ptr->target = UCI_TYPE_OPTION;
}
else {
ptr->last = &ptr->s->e;
ptr->target = UCI_TYPE_SECTION;
}
ptr->flags |= UCI_LOOKUP_COMPLETE;
return UCI_OK;
}
char *dmuci_get_value_bysection(struct uci_section *section, char *option)
{
struct uci_ptr ptr;
char *val = "";
if (uci_lookup_ptr_bysection(uci_ctx, &ptr, section, option, NULL) != UCI_OK) {
return val;
}
if (!ptr.o)
return val;
if(ptr.o->type == UCI_TYPE_LIST) {
dmuci_print_list(&ptr.o->v.list, &val, " ");
return val;
}
if (ptr.o->v.string)
return ptr.o->v.string;
else
return val;
}
char *dmuci_get_value(char *package, char *section, char *option)
{
struct uci_ptr ptr;
char *val = "";
if (!section || !option)
return val;
if (dmuci_init_ptr(uci_ctx, &ptr, package, section, option, NULL)) {
return val;
}
if (uci_lookup_ptr(uci_ctx, &ptr, NULL, true) != UCI_OK) {
return val;
}
if (!ptr.o)
return val;
if(ptr.o->type == UCI_TYPE_LIST) {
dmuci_print_list(&ptr.o->v.list, &val, " ");
return val;
}
if (ptr.o->v.string)
return ptr.o->v.string;
else
return val;
}

View File

@@ -1,34 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*/
#ifndef _TWAMPUCI_H__
#define _TWAMPUCI_H__
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <uci.h>
int dmuci_init(void);
int dmuci_fini(void);
struct uci_section *dmuci_walk_section(char *package, char *section_type, struct uci_section *prev_section);
void dmuci_print_list(struct uci_list *uh, char **val, char *delimiter);
struct uci_element *dmuci_lookup_list(struct uci_list *list, const char *name);
int uci_lookup_ptr_bysection(struct uci_context *ctx, struct uci_ptr *ptr, struct uci_section *section, char *option, char *value);
char *dmuci_get_value_bysection(struct uci_section *section, char *option);
char *dmuci_get_value(char *package, char *section, char *option);
#define dmuci_foreach_section(package, section_type, section) \
for (section = dmuci_walk_section(package, section_type, NULL); \
section != NULL; \
section = dmuci_walk_section(package, section_type, section))
#endif /* _TWAMPUCI_H__ */

View File

@@ -10,24 +10,30 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=udpechoserver
PKG_VERSION:=1.0.0
PKG_SOURCE_VERSION:=a3f0860f4268482f9ec9dad0c67745f615293fca
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://dev.iopsys.eu/iopsys/udpechoserver.git
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
PKG_MIRROR_HASH:=skip
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
PKG_LICENSE:=GPL-2.0-only
PKG_LICENSE_FILES:=LICENSE
include $(INCLUDE_DIR)/package.mk
define Package/$(PKG_NAME)
SECTION:=utils
CATEGORY:=Utilities
SUBMENU:=TRx69
TITLE:=BBF udp echo server
TITLE:=BBF UDP Echo Server
DEPENDS:=+libuci +libbbf_api
endef
define Package/$(PKG_NAME)/description
BBF UDP_echo_server
endef
define Build/Prepare
$(CP) ./src/* $(PKG_BUILD_DIR)/
BBF UDP Echo Server
endef
TARGET_CFLAGS += \
@@ -41,4 +47,4 @@ define Package/$(PKG_NAME)/install
$(CP) ./files/* $(1)/
endef
$(eval $(call BuildPackage,$(PKG_NAME)))
$(eval $(call BuildPackage,$(PKG_NAME)))

View File

@@ -1,23 +0,0 @@
PROG = udpechoserverd
LIB = libudpechoserver.so
PROG_OBJS = udpechoserver.o udpechoserverlog.o udpechoserveruci.o
LIB_OBJS = datamodel.o
PROG_CFLAGS = $(CFLAGS) -Wall -Werror -fPIC
PROG_LDFLAGS = $(LDFLAGS) -luci
LIB_LDFLAGS = $(LDFLAGS) -lbbf_api
%.o: %.c
$(CC) $(PROG_CFLAGS) $(FPIC) -c -o $@ $<
all: $(PROG) $(LIB)
$(PROG): $(PROG_OBJS)
$(CC) $(PROG_CFLAGS) -o $@ $^ $(PROG_LDFLAGS)
$(LIB): $(LIB_OBJS)
$(CC) $(PROG_CFLAGS) $(LIB_LDFLAGS) -shared -o $@ $^
clean:
rm -f *.o $(PROG) $(LIB)

View File

@@ -1,213 +0,0 @@
/*
* Copyright (C) 2020 iopsys Software Solutions AB
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation
*
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*/
#include <libbbf_api/dmbbf.h>
#include <libbbf_api/dmcommon.h>
#include <libbbf_api/dmuci.h>
#include <libbbf_api/dmubus.h>
#include <libbbf_api/dmjson.h>
#include "datamodel.h"
/* ********** DynamicObj ********** */
DM_MAP_OBJ tDynamicObj[] = {
/* parentobj, nextobject, parameter */
{"Device.IP.Diagnostics.", tDeviceUDPEchoConfigObj, NULL},
{0}
};
static int get_IPDiagnosticsUDPEchoConfig_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = dmuci_get_option_value_fallback_def("udpechoserver", "udpechoserver", "enable", "1");
return 0;
}
static int set_IPDiagnosticsUDPEchoConfig_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
bool b;
char file[32] = "/var/state/udpechoserver";
switch (action) {
case VALUECHECK:
if (dm_validate_boolean(value))
return FAULT_9007;
return 0;
case VALUESET:
string_to_bool(value, &b);
if (b) {
if( access( file, F_OK ) != -1 )
dmcmd("/bin/rm", 1, file);
dmuci_set_value("udpechoserver", "udpechoserver", "enable", "1");
} else
dmuci_set_value("udpechoserver", "udpechoserver", "enable", "0");
return 0;
}
return 0;
}
static int get_IPDiagnosticsUDPEchoConfig_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
dmuci_get_option_value_string("udpechoserver", "udpechoserver", "interface", value);
return 0;
}
static int set_IPDiagnosticsUDPEchoConfig_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
switch (action) {
case VALUECHECK:
if (dm_validate_string(value, -1, 256, NULL, NULL))
return FAULT_9007;
return 0;
case VALUESET:
dmuci_set_value("udpechoserver", "udpechoserver", "interface", value);
return 0;
}
return 0;
}
static int get_IPDiagnosticsUDPEchoConfig_SourceIPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
dmuci_get_option_value_string("udpechoserver", "udpechoserver", "address", value);
return 0;
}
static int set_IPDiagnosticsUDPEchoConfig_SourceIPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
switch (action) {
case VALUECHECK:
if (dm_validate_string(value, -1, 45, NULL, IPAddress))
return FAULT_9007;
return 0;
case VALUESET:
dmuci_set_value("udpechoserver", "udpechoserver", "address", value);
return 0;
}
return 0;
}
static int get_IPDiagnosticsUDPEchoConfig_UDPPort(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = dmuci_get_option_value_fallback_def("udpechoserver", "udpechoserver", "server_port", "0");
return 0;
}
static int set_IPDiagnosticsUDPEchoConfig_UDPPort(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
switch (action) {
case VALUECHECK:
if (dm_validate_unsignedInt(value, RANGE_ARGS{{NULL,NULL}}, 1))
return FAULT_9007;
return 0;
case VALUESET:
dmuci_set_value("udpechoserver", "udpechoserver", "server_port", value);
return 0;
}
return 0;
}
static int get_IPDiagnosticsUDPEchoConfig_EchoPlusEnabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = dmuci_get_option_value_fallback_def("udpechoserver", "udpechoserver", "plus", "1");
return 0;
}
static int set_IPDiagnosticsUDPEchoConfig_EchoPlusEnabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
bool b;
switch (action) {
case VALUECHECK:
if (dm_validate_boolean(value))
return FAULT_9007;
return 0;
case VALUESET:
string_to_bool(value, &b);
dmuci_set_value("udpechoserver", "udpechoserver", "plus", b ? "1" : "0");
return 0;
}
return 0;
}
static int get_IPDiagnosticsUDPEchoConfig_EchoPlusSupported(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = "true";
return 0;
}
static inline char *udpechoconfig_get(char *option, char *def)
{
char *tmp;
varstate_get_value_string("udpechoserver", "udpechoserver", option, &tmp);
if(tmp && tmp[0] == '\0')
return dmstrdup(def);
else
return tmp;
}
static int get_IPDiagnosticsUDPEchoConfig_PacketsReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = udpechoconfig_get("PacketsReceived", "0");
return 0;
}
static int get_IPDiagnosticsUDPEchoConfig_PacketsResponded(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = udpechoconfig_get("PacketsResponded", "0");
return 0;
}
static int get_IPDiagnosticsUDPEchoConfig_BytesReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = udpechoconfig_get("BytesReceived", "0");
return 0;
}
static int get_IPDiagnosticsUDPEchoConfig_BytesResponded(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = udpechoconfig_get("BytesResponded", "0");
return 0;
}
static int get_IPDiagnosticsUDPEchoConfig_TimeFirstPacketReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = udpechoconfig_get("TimeFirstPacketReceived", "0001-01-01T00:00:00.000000Z");
return 0;
}
static int get_IPDiagnosticsUDPEchoConfig_TimeLastPacketReceived(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = udpechoconfig_get("TimeLastPacketReceived", "0001-01-01T00:00:00.000000Z");
return 0;
}
/* *** Device.IP.Diagnostics. *** */
DMOBJ tDeviceUDPEchoConfigObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys*/
{"UDPEchoConfig", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tIPDiagnosticsUDPEchoConfigParams, NULL, BBFDM_BOTH},
{0}
};
/* *** Device.IP.Diagnostics.UDPEchoConfig. *** */
DMLEAF tIPDiagnosticsUDPEchoConfigParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/
{"Enable", &DMWRITE, DMT_BOOL, get_IPDiagnosticsUDPEchoConfig_Enable, set_IPDiagnosticsUDPEchoConfig_Enable, BBFDM_BOTH},
{"Interface", &DMWRITE, DMT_STRING, get_IPDiagnosticsUDPEchoConfig_Interface, set_IPDiagnosticsUDPEchoConfig_Interface, BBFDM_BOTH},
{"SourceIPAddress", &DMWRITE, DMT_STRING, get_IPDiagnosticsUDPEchoConfig_SourceIPAddress, set_IPDiagnosticsUDPEchoConfig_SourceIPAddress, BBFDM_BOTH},
{"UDPPort", &DMWRITE, DMT_UNINT, get_IPDiagnosticsUDPEchoConfig_UDPPort, set_IPDiagnosticsUDPEchoConfig_UDPPort, BBFDM_BOTH},
{"EchoPlusEnabled", &DMWRITE, DMT_BOOL, get_IPDiagnosticsUDPEchoConfig_EchoPlusEnabled, set_IPDiagnosticsUDPEchoConfig_EchoPlusEnabled, BBFDM_BOTH},
{"EchoPlusSupported", &DMREAD, DMT_BOOL, get_IPDiagnosticsUDPEchoConfig_EchoPlusSupported, NULL, BBFDM_BOTH},
{"PacketsReceived", &DMREAD, DMT_UNINT, get_IPDiagnosticsUDPEchoConfig_PacketsReceived, NULL, BBFDM_BOTH},
{"PacketsResponded", &DMREAD, DMT_UNINT, get_IPDiagnosticsUDPEchoConfig_PacketsResponded, NULL, BBFDM_BOTH},
{"BytesReceived", &DMREAD, DMT_UNINT, get_IPDiagnosticsUDPEchoConfig_BytesReceived, NULL, BBFDM_BOTH},
{"BytesResponded", &DMREAD, DMT_UNINT, get_IPDiagnosticsUDPEchoConfig_BytesResponded, NULL, BBFDM_BOTH},
{"TimeFirstPacketReceived", &DMREAD, DMT_TIME, get_IPDiagnosticsUDPEchoConfig_TimeFirstPacketReceived, NULL, BBFDM_BOTH},
{"TimeLastPacketReceived", &DMREAD, DMT_TIME, get_IPDiagnosticsUDPEchoConfig_TimeLastPacketReceived, NULL, BBFDM_BOTH},
{0}
};

View File

@@ -1,17 +0,0 @@
/*
* Copyright (C) 2020 iopsys Software Solutions AB
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation
*
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*/
#ifndef _UDPECHOSERVER_H_
#define _UDPECHOSERVER_H_
extern DMOBJ tDeviceUDPEchoConfigObj[];
extern DMLEAF tIPDiagnosticsUDPEchoConfigParams[];
#endif //_UDPECHOSERVER_H_

View File

@@ -1,230 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*/
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <netdb.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include "udpechoserver.h"
#include "udpechoserverlog.h"
#include "udpechoserveruci.h"
struct udpechoserver_config cur_udpechoserver_conf = {0};
struct udpechoserver_result cur_udpechoserver_result={0};
static void set_udpechoserver_stats(void)
{
char PacketsReceived[8], PacketsResponded[8], BytesReceived[8], BytesResponded[8];
sprintf(PacketsReceived, "%d", cur_udpechoserver_result.PacketsReceived);
sprintf(PacketsResponded, "%d", cur_udpechoserver_result.PacketsResponded);
sprintf(BytesReceived, "%d", cur_udpechoserver_result.BytesReceived);
sprintf(BytesResponded, "%d", cur_udpechoserver_result.BytesResponded);
dmuci_init();
dmuci_set_value_state("udpechoserver", "udpechoserver", "PacketsReceived", PacketsReceived);
dmuci_set_value_state("udpechoserver", "udpechoserver", "PacketsResponded", PacketsResponded);
dmuci_set_value_state("udpechoserver", "udpechoserver", "BytesReceived", BytesReceived);
dmuci_set_value_state("udpechoserver", "udpechoserver", "BytesResponded", BytesResponded);
dmuci_set_value_state("udpechoserver", "udpechoserver", "TimeFirstPacketReceived", cur_udpechoserver_result.TimeFirstPacket);
dmuci_set_value_state("udpechoserver", "udpechoserver", "TimeLastPacketReceived", cur_udpechoserver_result.TimeLastPacket);
dmuci_fini();
}
int udpechoserver_connect(void)
{
int sock, fromlen, n, ret;
struct sockaddr_in server, from;
struct timeval tv_recv, tv_reply;
struct tm lt;
char buf[1024];
char str[INET_ADDRSTRLEN];
char s_now[default_date_size];
struct udpechoserver_plus *plus;
memset(&cur_udpechoserver_result, 0, sizeof(cur_udpechoserver_result));
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
udpechoserver_log(SCRIT,"Socket error = %d", sock);
return -1;
}
bzero(&server, sizeof(server));
server.sin_family=AF_INET;
server.sin_addr.s_addr=INADDR_ANY;
server.sin_port=htons(cur_udpechoserver_conf.server_port);
if (bind(sock, (struct sockaddr *)&server, sizeof(server)) > 0) {
udpechoserver_log(SCRIT,"Error in bind function");
return -1;
}
udpechoserver_log(SINFO,"CONNECT UDPECHOSERVER");
while(true)
{
fromlen = sizeof(from);
n = recvfrom(sock, buf, 1024, 0, (struct sockaddr *)&from, (socklen_t *)&fromlen);
if (n < 0)
udpechoserver_log(SCRIT,"Error in receive message");
inet_ntop(AF_INET, &(from.sin_addr.s_addr), str, INET_ADDRSTRLEN);
udpechoserver_log(SINFO,"UDPECHOSERVER receive massage from %s with data size is %d Bytes", str, n);
if(cur_udpechoserver_conf.address && cur_udpechoserver_conf.address[0] != '\0') {
if(strcmp(cur_udpechoserver_conf.address, str) != 0) {
udpechoserver_log(SINFO,"UDPECHOSERVER can not respond to a UDP echo from this source IP address %s", str);
continue;
}
}
gettimeofday(&tv_recv, NULL);
if(cur_udpechoserver_result.TimeFirstPacketReceived.tv_sec == 0 && cur_udpechoserver_result.TimeFirstPacketReceived.tv_usec == 0)
cur_udpechoserver_result.TimeFirstPacketReceived = tv_recv;
cur_udpechoserver_result.TimeLastPacketReceived = tv_recv;
cur_udpechoserver_result.PacketsReceived++;
cur_udpechoserver_result.BytesReceived+=n;
(void) localtime_r(&(cur_udpechoserver_result.TimeFirstPacketReceived.tv_sec), &lt);
strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", &lt);
sprintf(cur_udpechoserver_result.TimeFirstPacket,"%s.%06ld", s_now, (long) cur_udpechoserver_result.TimeFirstPacketReceived.tv_usec);
(void) localtime_r(&(cur_udpechoserver_result.TimeLastPacketReceived.tv_sec), &lt);
strftime(s_now, sizeof s_now, "%Y-%m-%dT%H:%M:%S", &lt);
sprintf(cur_udpechoserver_result.TimeLastPacket,"%s.%06ld", s_now, (long) cur_udpechoserver_result.TimeLastPacketReceived.tv_usec);
if(cur_udpechoserver_conf.plus) {
if(n >= sizeof(struct udpechoserver_plus)) {
plus = (struct udpechoserver_plus *)buf;
plus->TestRespSN = htonl(cur_udpechoserver_result.TestRespSN);
plus->TestRespRecvTimeStamp = htonl(tv_recv.tv_sec*1000000+tv_recv.tv_usec);
plus->TestRespReplyFailureCount = htonl(cur_udpechoserver_result.TestRespReplyFailureCount);
gettimeofday(&tv_reply, NULL);
plus->TestRespReplyTimeStamp = htonl(tv_reply.tv_sec*1000000+tv_reply.tv_usec);
}
}
ret = sendto(sock, buf, n, 0, (struct sockaddr *)&from, fromlen);
if (n != ret) {
cur_udpechoserver_result.TestRespReplyFailureCount++;
udpechoserver_log(SCRIT,"Error in send massage");
}
else {
cur_udpechoserver_result.TestRespSN++;
cur_udpechoserver_result.PacketsResponded++;
cur_udpechoserver_result.BytesResponded+=ret;
}
udpechoserver_log(SINFO,"UDPECHOSERVER sent massage to %s with data size is %d Bytes", str, ret);
set_udpechoserver_stats();
udpechoserver_log(SDEBUG,"UDPECHOSERVER Stats : PacketsReceived = %d", cur_udpechoserver_result.PacketsReceived);
udpechoserver_log(SDEBUG,"UDPECHOSERVER Stats : PacketsResponded = %d", cur_udpechoserver_result.PacketsResponded);
udpechoserver_log(SDEBUG,"UDPECHOSERVER Stats : BytesReceived = %d", cur_udpechoserver_result.BytesReceived);
udpechoserver_log(SDEBUG,"UDPECHOSERVER Stats : BytesResponded = %d", cur_udpechoserver_result.BytesResponded);
udpechoserver_log(SDEBUG,"UDPECHOSERVER Stats : TestRespReplyFailureCount = %d", cur_udpechoserver_result.TestRespReplyFailureCount);
udpechoserver_log(SDEBUG,"UDPECHOSERVER Stats : TimeFirstPacketReceived = %s", cur_udpechoserver_result.TimeFirstPacket);
udpechoserver_log(SDEBUG,"UDPECHOSERVER Stats : TimeLastPacketReceived = %s", cur_udpechoserver_result.TimeLastPacket);
}
}
int udpechoserver_init(void)
{
char *value = NULL;
int a;
value = dmuci_get_value("udpechoserver", "udpechoserver", "log_level");
if(value != NULL && *value != '\0') {
a = atoi(value);
cur_udpechoserver_conf.loglevel = a;
}
else
cur_udpechoserver_conf.loglevel = DEFAULT_LOGLEVEL;
udpechoserver_log(SDEBUG,"Log Level of UDP ECHO SERVER is :%d", cur_udpechoserver_conf.loglevel);
value = dmuci_get_value("udpechoserver", "udpechoserver", "enable");
if(value != NULL && *value != '\0') {
if ((strcasecmp(value,"true")==0) || (strcmp(value,"1")==0)) {
cur_udpechoserver_conf.enable = true;
udpechoserver_log(SDEBUG,"UDP echo server is Enabled");
}
}
value = dmuci_get_value("udpechoserver", "udpechoserver", "interface");
if(value != NULL && *value != '\0') {
if (cur_udpechoserver_conf.interface != NULL)
free(cur_udpechoserver_conf.interface);
cur_udpechoserver_conf.interface = strdup(value);
udpechoserver_log(SDEBUG,"UDP echo server interface is :%s", cur_udpechoserver_conf.interface);
}
else {
cur_udpechoserver_conf.interface = strdup("");
udpechoserver_log(SDEBUG,"UDP echo server interface is empty");
}
value = dmuci_get_value("udpechoserver", "udpechoserver", "address");
if(value != NULL && *value != '\0') {
if (cur_udpechoserver_conf.address != NULL)
free(cur_udpechoserver_conf.address);
cur_udpechoserver_conf.address = strdup(value);
udpechoserver_log(SDEBUG,"UDP echo server address is :%s", cur_udpechoserver_conf.address);
}
else {
cur_udpechoserver_conf.address = strdup("");
udpechoserver_log(SDEBUG,"UDP echo server address is empty");
}
value = dmuci_get_value("udpechoserver", "udpechoserver", "server_port");
if(value != NULL && *value != '\0') {
a = atoi(value);
cur_udpechoserver_conf.server_port = a;
udpechoserver_log(SDEBUG,"UDP echo server port is :%d", cur_udpechoserver_conf.server_port);
}
value = dmuci_get_value("udpechoserver", "udpechoserver", "plus");
if(value != NULL && *value != '\0') {
if ((strcasecmp(value,"true")==0) || (strcmp(value,"1")==0)) {
cur_udpechoserver_conf.plus = true;
udpechoserver_log(SDEBUG,"UDP echo server plus is Enabled");
}
else {
cur_udpechoserver_conf.plus = false;
udpechoserver_log(SDEBUG,"UDP echo server plus is Disabled");
}
}
return 0;
}
void udpechoserver_exit(void)
{
free(cur_udpechoserver_conf.address);
free(cur_udpechoserver_conf.interface);
}
int main(void)
{
dmuci_init();
udpechoserver_init();
dmuci_fini();
udpechoserver_log(SINFO,"START UDPECHOSERVER");
udpechoserver_connect();
udpechoserver_exit();
udpechoserver_log(SINFO,"EXIT UDPECHOSERVER");
return 0;
}

View File

@@ -1,56 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*/
#ifndef _UDPECHOSERVER_H__
#define _UDPECHOSERVER_H__
#include <stdbool.h>
#include <sys/time.h>
#define default_date_format "AAAA-MM-JJTHH:MM:SS.000000Z"
#define default_date_size sizeof(default_date_format) + 1
struct udpechoserver_config
{
bool enable;
char *interface;
char *address;
int server_port;
bool plus;
int loglevel;
};
struct udpechoserver_plus
{
unsigned int TestGenSN;
unsigned int TestRespSN;
unsigned int TestRespRecvTimeStamp;
unsigned int TestRespReplyTimeStamp;
unsigned int TestRespReplyFailureCount;
};
struct udpechoserver_result
{
unsigned int TestRespSN;
unsigned int TestRespReplyFailureCount;
unsigned int PacketsReceived;
unsigned int PacketsResponded;
unsigned int BytesReceived;
unsigned int BytesResponded;
struct timeval TimeFirstPacketReceived;
struct timeval TimeLastPacketReceived;
char TimeFirstPacket[default_date_size];
char TimeLastPacket[default_date_size];
};
extern struct udpechoserver_config cur_udpechoserver_conf;
extern struct udpechoserver_result cur_udpechoserver_result;
#endif /* _UDPECHOSERVER_H__ */

View File

@@ -1,40 +0,0 @@
# README #
udpechoserverd is an implementation of udp echo server to perform the UDP Echo Service and UDP Echo Plus Service.
## Configuration File ##
The udpechoserverd UCI configuration is located in **'/etc/config/udpechoserver'** and contains only one section: **udpechoserver**.
```
config udpechoserver 'udpechoserver'
option enable '0'
option interface ''
option address ''
option server_port ''
option plus '0'
option log_level '3'
```
### udpechoserver section ###
It defines **the udpechoserver configuration** such as enable, interface, address, etc... Possible options to be used in **the udpechoserver** section are listed in the table below.
| Name | Type | Description |
| ------------- | ------- | ------------------------------------------------- |
| `enable` | boolean | If set to **1**, UDP Echo Server will be enabled. |
| `interface` | string | Specifies the interface on which the CPE MUST listen and receive UDP echo requests. |
| `address` | string | Specifies the source IP address which can make an UDP echo requests. |
| `server_port` | integer | The UDP port on which the UDP Echo server MUST listen and respond to UDP echo requests. |
| `plus` | boolean | If set to **1**, the CPE will perform necessary packet processing for UDP Echo Plus packets. |
| `log_level` | integer | Specifies the log type to use, by default it is set to **'INFO'**. The possible types are **'EMERG', 'ALERT', 'CRITIC' ,'ERROR', 'WARNING', 'NOTICE', 'INFO' and 'DEBUG'**. |
## Dependencies ##
To successfully build udpechoserverd, the following libraries are needed:
| Dependency | Link | License |
| ----------- | ------------------------------------------- | -------------- |
| libuci | https://git.openwrt.org/project/uci.git | LGPL 2.1 |

View File

@@ -1,55 +0,0 @@
/*
* This program 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, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2020 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*/
#include <stdio.h>
#include <time.h>
#include <syslog.h>
#include <stdarg.h>
#include "udpechoserverlog.h"
#include "udpechoserver.h"
#define DEBUG
static const int log_syslogmap[] = {
[SCRIT] = LOG_CRIT,
[SWARNING] = LOG_WARNING,
[SNOTICE] = LOG_NOTICE,
[SINFO] = LOG_INFO,
[SDEBUG] = LOG_DEBUG
};
static const char* log_str[] = {
[SCRIT] = "CRITICAL",
[SWARNING] = "WARNING",
[SNOTICE] = "NOTICE",
[SINFO] = "INFO",
[SDEBUG] = "DEBUG"
};
void udpechoserver_log(int priority, const char *format, ...)
{
va_list vl;
if (priority <= cur_udpechoserver_conf.loglevel) {
#ifdef DEBUG
time_t t = time(NULL);
struct tm tm = *localtime(&t);
va_start(vl, format);
printf("%d-%02d-%02d %02d:%02d:%02d [udpechoserver] %s - ", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, log_str[priority]);
vprintf(format, vl);
va_end(vl);
printf("\n");
#endif
openlog("udpechoserver", 0, LOG_DAEMON);
va_start(vl, format);
vsyslog(log_syslogmap[priority], format, vl);
va_end(vl);
closelog();
}
}

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