summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cesar/bsu/inc/context.h4
-rw-r--r--cesar/bsu/ntb/ntb.h11
-rw-r--r--cesar/bsu/ntb/ntb_sync.h8
-rw-r--r--cesar/bsu/ntb/src/ntb.c32
-rw-r--r--cesar/bsu/ntb/test/utest/src/ntb_compute.c32
-rw-r--r--cesar/bsu/src/bsu.c26
-rw-r--r--cesar/bsu/test/utest/src/bsut.c96
-rw-r--r--cesar/ce/rx/bitloading/inc/ber.h6
-rw-r--r--cesar/ce/rx/bitloading/inc/poly.h2
-rw-r--r--cesar/ce/rx/bitloading/nsr.h24
-rw-r--r--cesar/ce/rx/bitloading/src/nsr.c3
-rw-r--r--cesar/ce/rx/bitloading/test/src/test_bl.c3
-rw-r--r--cesar/ce/rx/test/src/test_rx.c1
-rw-r--r--cesar/cl/inc/context.h4
-rw-r--r--cesar/cl/inc/trace.h1
-rw-r--r--cesar/cl/src/bridge_table.c14
-rw-r--r--cesar/cl/src/cl.c27
-rw-r--r--cesar/cl/src/trace.c2
-rw-r--r--cesar/common/make/config.mk4
-rw-r--r--cesar/common/tests/tests19
-rw-r--r--cesar/cp/beacon/test/src/beacon.c987
-rw-r--r--cesar/cp/cco/action/test/src/action_gen_nek.c22
-rw-r--r--cesar/cp/secu/test/sparc-Makefile6
-rw-r--r--cesar/cp/src/cp.c6
-rw-r--r--cesar/cp/sta/action/src/vs.c5
-rw-r--r--cesar/cp/sta/action/test/utest/src/vs.c2
-rw-r--r--cesar/cp/sta/mgr/test/src/sta_mgr.c2
-rw-r--r--cesar/cp/test/mme/Makefile2
-rw-r--r--cesar/hal/arch/Config1
-rw-r--r--cesar/hal/arch/arch.h10
-rw-r--r--cesar/hal/arch/inc/sparc.h26
-rw-r--r--cesar/hal/phy/Module2
-rw-r--r--cesar/hal/phy/inc/context.h4
-rw-r--r--cesar/hal/phy/maximus/src/maximus_phy_ctrl.c8
-rw-r--r--cesar/hal/phy/maximus/test/src/test_phy_ctrl.c4
-rw-r--r--cesar/hal/phy/src/phy.c8
-rw-r--r--cesar/hle/inc/context.h6
-rw-r--r--cesar/hle/inc/trace.h4
-rw-r--r--cesar/hle/src/hle.c53
-rw-r--r--cesar/hle/src/trace.c4
-rw-r--r--cesar/lib/Config2
-rw-r--r--cesar/lib/Module5
-rw-r--r--cesar/lib/seq_check.h170
-rw-r--r--cesar/lib/src/seq_check.c154
-rw-r--r--cesar/lib/src/utils.c42
-rw-r--r--cesar/lib/test/fixed/src/test_fixed.c12
-rw-r--r--cesar/lib/test/heap/src/test_heap.c2
-rw-r--r--cesar/lib/test/mbox/src/mbox.c2
-rw-r--r--cesar/lib/test/seq_check/Config2
-rw-r--r--cesar/lib/test/seq_check/Makefile8
-rw-r--r--cesar/lib/test/seq_check/src/seq_check.c250
-rw-r--r--cesar/lib/test/utils/src/test_utils.c50
-rw-r--r--cesar/lib/utils.h12
-rw-r--r--cesar/mac/design/test/mfs_tx2/src/test_mfs.c7
-rw-r--r--cesar/mac/pbproc/src/fsm_rx_sound.c6
-rw-r--r--cesar/mac/pbproc/src/fsm_tx_sound.c6
-rw-r--r--cesar/mac/pbproc/src/prep_mpdu.c2
-rw-r--r--cesar/mac/pbproc/test/int/sparc-Config1
-rw-r--r--cesar/mac/sar/inc/sar_context.h4
-rw-r--r--cesar/mac/sar/inc/trace.h1
-rw-r--r--cesar/mac/sar/src/sar.c28
-rw-r--r--cesar/mac/sar/src/trace.c2
-rw-r--r--cesar/maximus/channel/src/ChannelComputerTest.cpp38
-rw-r--r--cesar/maximus/coreengine/src/Maximus.cpp1
-rw-r--r--cesar/maximus/ethernet/src/EthernetProcessor.cpp6
-rw-r--r--cesar/maximus/prototest/fcall/src/test_fcall.c11
-rw-r--r--cesar/maximus/python/maximus/ethernet/scapy.py1
-rw-r--r--cesar/maximus/python/maximus/station/sta.py94
-rw-r--r--cesar/maximus/python/src/interface_module.cpp2
-rw-r--r--cesar/maximus/python/test/test_lib_cesar.py5
-rw-r--r--cesar/maximus/python/tools/csi/csicore.py4
-rw-r--r--cesar/maximus/stationtest/src/test_send.c7
-rw-r--r--cesar/maximus/stationtest/src/test_tx_rx.c7
-rw-r--r--cesar/projects/plc/Config.traces10
-rw-r--r--cesar/station/src/station.c4
-rw-r--r--cesar/test_general/maximus/integration/interface-dp/src/station.c7
-rw-r--r--cesar/test_general/maximus/integration/sar-pbproc/src/station.c8
-rw-r--r--cesar/test_general/station/cco0/s1/py/sc12_five_stations.py2
-rw-r--r--cesar/test_general/station/cco0/s1/py/sc13_10stations.py2
-rw-r--r--cesar/test_general/station/cco0/s1/py/sc9_cco_leaving.py4
-rw-r--r--cesar/test_general/station/maximus/Makefile2
-rw-r--r--cesar/test_general/station/maximus/py/sc01_long_simu.py2
-rw-r--r--cesar/test_general/station/maximus/py/sc02_long_simu_data.py2
-rw-r--r--cesar/test_general/station/tonemap/py/sc01_bl_initial.py9
-rw-r--r--cesar/test_general/station/tonemap/py/sc02_vs_get_tonemap.py11
-rw-r--r--cleopatre/Makefile19
-rw-r--r--cleopatre/application/upnpd/Makefile40
-rw-r--r--cleopatre/application/upnpd/README22
-rwxr-xr-xcleopatre/application/upnpd/S98upnpd43
-rw-r--r--cleopatre/application/upnpd/inc/config.h56
-rw-r--r--cleopatre/application/upnpd/inc/daemonize.h57
-rw-r--r--cleopatre/application/upnpd/inc/getifaddr.h62
-rw-r--r--cleopatre/application/upnpd/inc/minissdp.h59
-rw-r--r--cleopatre/application/upnpd/inc/minixml.h68
-rw-r--r--cleopatre/application/upnpd/inc/options.h79
-rw-r--r--cleopatre/application/upnpd/inc/upnpdescgen.h110
-rw-r--r--cleopatre/application/upnpd/inc/upnpdescstrings.h50
-rw-r--r--cleopatre/application/upnpd/inc/upnpdpath.h63
-rw-r--r--cleopatre/application/upnpd/inc/upnpdtypes.h56
-rw-r--r--cleopatre/application/upnpd/inc/upnpevents.h65
-rw-r--r--cleopatre/application/upnpd/inc/upnpglobalvars.h88
-rw-r--r--cleopatre/application/upnpd/inc/upnphttp.h153
-rw-r--r--cleopatre/application/upnpd/inc/upnpreplyparse.h84
-rw-r--r--cleopatre/application/upnpd/inc/upnpsoap.h69
-rw-r--r--cleopatre/application/upnpd/inc/uuid.h42
-rw-r--r--cleopatre/application/upnpd/src/.upnpd.c.swpbin0 -> 16384 bytes
-rw-r--r--cleopatre/application/upnpd/src/daemonize.c156
-rw-r--r--cleopatre/application/upnpd/src/getifaddr.c211
-rw-r--r--cleopatre/application/upnpd/src/minissdp.c604
-rw-r--r--cleopatre/application/upnpd/src/minixml.c214
-rw-r--r--cleopatre/application/upnpd/src/options.c193
-rw-r--r--cleopatre/application/upnpd/src/upnpd.c809
-rw-r--r--cleopatre/application/upnpd/src/upnpdescgen.c1192
-rw-r--r--cleopatre/application/upnpd/src/upnpevents.c571
-rw-r--r--cleopatre/application/upnpd/src/upnpglobalvars.c80
-rw-r--r--cleopatre/application/upnpd/src/upnphttp.c756
-rw-r--r--cleopatre/application/upnpd/src/upnpreplyparse.c137
-rw-r--r--cleopatre/application/upnpd/src/upnpsoap.c1590
-rw-r--r--cleopatre/application/upnpd/src/uuid.c247
-rw-r--r--cleopatre/application/upnpd/upnpd.conf29
-rwxr-xr-xcleopatre/application/upnpd/zcip.script39
-rw-r--r--cleopatre/buildroot/target/device/Spidcom/arizona/linux26.config1
-rw-r--r--cleopatre/buildroot/target/device/Spidcom/scr310/linux26.config1
-rw-r--r--cleopatre/buildroot/target/device/Spidcom/spk300/linux26.config1
-rw-r--r--cleopatre/buildroot/target/device/Spidcom/spk300g/linux26.config1
-rw-r--r--cleopatre/buildroot/target/device/Spidcom/spk310/linux26.config1
-rw-r--r--cleopatre/buildroot/target/device/Spidcom/spr300/linux26.config1
-rw-r--r--cleopatre/buildroot/target/device/Spidcom/spr310/linux26.config1
-rw-r--r--cleopatre/devkit/plcdrv/arm/Makefile5
-rw-r--r--cleopatre/devkit/plcdrv/arm/inc/linux_drv.h4
-rw-r--r--cleopatre/devkit/plcdrv/arm/src/linux_drv.c10
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/Makefile9
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504.c11
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/include/net/seq_check.h89
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/net/Kconfig9
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/net/Makefile2
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/net/seq_check.c298
137 files changed, 10174 insertions, 871 deletions
diff --git a/cesar/bsu/inc/context.h b/cesar/bsu/inc/context.h
index 4447509c7d..ec25ae908a 100644
--- a/cesar/bsu/inc/context.h
+++ b/cesar/bsu/inc/context.h
@@ -121,7 +121,9 @@ struct bsu_t
/** Station's discover info updated by CP. */
bsu_beacon_bmi_discover_info_t discover_info;
/** NTB clock synchronization weight configuration. k is for 1/2^k. */
- uint bsu_ntb_clk_sync_weight_k;
+ uint ntb_clk_sync_weight_k;
+ /** Number of NTB clock synchronizations for stable error measure. */
+ uint ntb_clk_sync_nb_stable;
#if CONFIG_TRACE
/** Trace system. */
trace_buffer_t trace;
diff --git a/cesar/bsu/ntb/ntb.h b/cesar/bsu/ntb/ntb.h
index ce01f409da..b18c487126 100644
--- a/cesar/bsu/ntb/ntb.h
+++ b/cesar/bsu/ntb/ntb.h
@@ -16,22 +16,23 @@
#include "mac/common/config.h"
#include "hal/phy/phy.h"
-#define BSU_NTB_CLK_SYNC_WEIGHT_K_DEFAULT 2
+#define BSU_NTB_CLK_SYNC_WEIGHT_K_DEFAULT 6
+
+#define BSU_NTB_CLK_SYNC_NB_STABLE_DEFAULT 64
BEGIN_DECLS
-/*
+/**
* Synchronize local clock to be as close as possible to estimated value
* of the NTB clock reference.
* \param ctx the module context data.
- * \param phy the phy context.
* \param beacon_bts beacon time stamp
* \param beacon_sta_ltmr STA local time captured when receiving beacon
* \param weight_k the coefficient weight to use to smooth the NTB clock
*/
void
-bsu_ntb_clk_sync (bsu_ntb_sync_t * ctx, phy_t *phy, u32 beacon_bts,
- u32 beacon_sys_ltmr, u32 beacon_sta_ltmr, uint weight_k);
+bsu_ntb_clk_sync (bsu_ntb_sync_t * ctx, u32 beacon_bts, u32 beacon_sys_ltmr,
+ u32 beacon_sta_ltmr, uint weight_k);
/**
* Configure the clock frequency.
diff --git a/cesar/bsu/ntb/ntb_sync.h b/cesar/bsu/ntb/ntb_sync.h
index e515ab3897..4eafa76268 100644
--- a/cesar/bsu/ntb/ntb_sync.h
+++ b/cesar/bsu/ntb/ntb_sync.h
@@ -20,10 +20,8 @@ struct bsu_ntb_sync_t
{
/** Initialised ? */
bool init;
- /** First time it computes the Frequency error. This bool is useful
- * because the first computation of the frequency error is not equal to
- * the others. */
- bool second_shoot;
+ /** Number of clock synchronisations, will saturate at UINT_MAX. */
+ uint sync_nb;
/** Frequency error. */
double fe;
/** beacon time stamp. */
@@ -36,8 +34,6 @@ struct bsu_ntb_sync_t
u32 sta_numerator;
/** NTB clock tick offset. */
u32 ntb_offset_tck;
- /** Delay before processing the beacon. */
- u32 delay_systck;
};
typedef struct bsu_ntb_sync_t bsu_ntb_sync_t;
diff --git a/cesar/bsu/ntb/src/ntb.c b/cesar/bsu/ntb/src/ntb.c
index fe4a49a7f0..e5fe84bd28 100644
--- a/cesar/bsu/ntb/src/ntb.c
+++ b/cesar/bsu/ntb/src/ntb.c
@@ -14,6 +14,7 @@
#include "lib/fixed.h"
#include "bsu/ntb/ntb.h"
#include "mac/common/timings.h"
+#include "limits.h"
/** Define a security level for frequency error.
* If frequency error is greater then re-initialise freq error. */
@@ -46,22 +47,22 @@ bsu_ntb_frequency_error (bsu_ntb_sync_t *ctx, double freq_err, u32 bts,
{
double num = bts - ctx->bts;
double denum = preamble_sysdate - ctx->preamble_sysdate;
- if (!ctx->second_shoot)
+ if (!ctx->sync_nb)
{
ctx->fe = num / denum - 1;
- ctx->second_shoot = true;
}
else
{
double part2 = num / denum - 1 - freq_err;
ctx->fe = freq_err + bsu_ntb_wf * part2;
}
+ if (ctx->sync_nb < UINT_MAX)
+ ctx->sync_nb++;
}
}
/** Compute the current offset from the NTB clock and the phy clock.
* \param ctx module context.
- * \param phy the phy context.
* \param freq_error last frequency error computed.
* \param bts the last beacon time stamp received in the last beacon.
* \param preamble_stadata the sta date preamble corresponding to the last
@@ -70,19 +71,18 @@ bsu_ntb_frequency_error (bsu_ntb_sync_t *ctx, double freq_err, u32 bts,
* last beacon received.
*/
PRIVATE u32
-bsu_ntb_offset (bsu_ntb_sync_t *ctx, phy_t *phy, double freq_error,
- u32 bts, u32 preamble_stadate, u32 preamble_sysdate)
+bsu_ntb_offset (bsu_ntb_sync_t *ctx, double freq_error, u32 bts,
+ u32 preamble_stadate, u32 preamble_sysdate)
{
u32 offset;
dbg_assert (ctx);
offset = bts - preamble_stadate;
if (ctx->init)
{
- /* Get the delay in system ticks. */
- ctx->delay_systck = phy_sysdate () - preamble_sysdate;
- dbg_assert ((s32) ctx->delay_systck >= 0);
- offset += ((ctx->fe * ctx->delay_systck)
- - (freq_error * ctx->delay_systck));
+ /* Add offset for the update delay. */
+ int delay_systck = phy_sysdate () - preamble_sysdate;
+ dbg_assert (delay_systck >= 0);
+ offset += ctx->fe * delay_systck - freq_error * delay_systck;
}
return offset;
}
@@ -92,14 +92,13 @@ bsu_ntb_init (bsu_ntb_sync_t *ctx)
{
dbg_assert (ctx);
ctx->init = false;
- ctx->second_shoot = false;
+ ctx->sync_nb = 0;
ctx->fe = 0.0;
ctx->bts = 0;
ctx->preamble_sysdate = 0;
ctx->preamble_stadate = 0;
ctx->sta_numerator = 0;
ctx->ntb_offset_tck = 0;
- ctx->delay_systck = 0;
}
void
@@ -109,12 +108,11 @@ bsu_ntb_uninit (bsu_ntb_sync_t *ctx)
}
void
-bsu_ntb_clk_sync (bsu_ntb_sync_t * ctx, phy_t *phy, u32 beacon_bts,
- u32 beacon_sys_ltmr, u32 beacon_sta_ltmr, uint weight_k)
+bsu_ntb_clk_sync (bsu_ntb_sync_t * ctx, u32 beacon_bts, u32 beacon_sys_ltmr,
+ u32 beacon_sta_ltmr, uint weight_k)
{
double freq_error;
dbg_assert (ctx);
- dbg_assert (phy);
freq_error = ctx->fe;
/**
* Check the beacon received is not received N MS after the previous one,
@@ -132,10 +130,10 @@ bsu_ntb_clk_sync (bsu_ntb_sync_t * ctx, phy_t *phy, u32 beacon_bts,
freq_error = 0;
ctx->fe = 0;
ctx->init = false;
- ctx->second_shoot = false;
+ ctx->sync_nb = 0;
}
}
- ctx->ntb_offset_tck= bsu_ntb_offset (ctx, phy, freq_error, beacon_bts,
+ ctx->ntb_offset_tck= bsu_ntb_offset (ctx, freq_error, beacon_bts,
beacon_sta_ltmr, beacon_sys_ltmr);
ctx->preamble_sysdate = beacon_sys_ltmr;
ctx->preamble_stadate = beacon_sta_ltmr;
diff --git a/cesar/bsu/ntb/test/utest/src/ntb_compute.c b/cesar/bsu/ntb/test/utest/src/ntb_compute.c
index 19745c4c65..1612ddbae4 100644
--- a/cesar/bsu/ntb/test/utest/src/ntb_compute.c
+++ b/cesar/bsu/ntb/test/utest/src/ntb_compute.c
@@ -65,21 +65,21 @@ test_case_ntb_ntb_sync (test_t test, bsu_ntb_test_type_t type)
bsu_ntb_test_init (&t);
bsu_ntb_init (&sync);
/* Initialise the values. */
- sync.second_shoot = sync.init = true;
+ sync.init = true;
+ sync.sync_nb = 1;
sync.fe = freqerr [0];
sync.ntb_offset_tck = offset[0];
sync.bts = bts[0];
sync.preamble_sysdate = preamble_sysdate[0];
sync.preamble_stadate = preamble_stadate[0];
- sync.delay_systck = delay_systck [0];
for (i = 1; i < bts_nb; i++)
{
t.phy.preamble_sysdate = preamble_sysdate[i];
t.phy.sys_date = t.phy.preamble_sysdate + delay_systck[i];
/* In this test the sys_date_preamble is the same as the station
* date preamble. */
- bsu_ntb_clk_sync (&sync, (phy_t*) &t.phy, bts[i],
- preamble_sysdate[i], preamble_stadate[i], 2);
+ bsu_ntb_clk_sync (&sync, bts[i], preamble_sysdate[i],
+ preamble_stadate[i], 2);
test_fail_unless (ABS(sync.fe - freqerr[i]) < 1.0e-12,
"Freq different in loop %d", i);
test_fail_unless (sync.ntb_offset_tck == offset[i],
@@ -112,33 +112,32 @@ test_case_freq_error (test_t test)
bsu_ntb_init (&sync);
/* Configure with real data. */
sync.init = true;
- sync.second_shoot = true;
+ sync.sync_nb = 1;
sync.fe = -1.074e-05;
sync.bts = 0x8a1ad69;
sync.preamble_sysdate = 0x6f04181;
sync.preamble_stadate = 0x6f04181;
/* Compute new Frequency error. */
- bsu_ntb_clk_sync (&sync, (phy_t*) &t.phy, 0x21e04ad,
- 0x1ddf30d3, 0x1ddf30d3, 2);
+ bsu_ntb_clk_sync (&sync, 0x21e04ad, 0x1ddf30d3, 0x1ddf30d3, 2);
test_fail_unless (sync.fe == 0);
test_fail_unless (sync.init == true);
- test_fail_unless (sync.second_shoot == false);
+ test_fail_unless (sync.sync_nb == 0);
test_fail_unless (
sync.ntb_offset_tck == sync.bts - sync.preamble_stadate);
/* Negative one. */
bsu_ntb_init (&sync);
sync.init = true;
- sync.second_shoot = true;
+ sync.sync_nb = 1;
sync.fe = -2.04;
sync.bts = 0x8a1ad69;
sync.preamble_sysdate = 0x6f04181;
sync.preamble_stadate = 0x6f04181;
/* Compute new Frequency error. */
- bsu_ntb_clk_sync (&sync, (phy_t*) &t.phy, sync.bts + 1,
- sync.preamble_sysdate + 1, 0x1ddf30d3, 2);
+ bsu_ntb_clk_sync (&sync, sync.bts + 1, sync.preamble_sysdate + 1,
+ 0x1ddf30d3, 2);
test_fail_unless (sync.fe == 0);
test_fail_unless (sync.init == true);
- test_fail_unless (sync.second_shoot == false);
+ test_fail_unless (sync.sync_nb == 0);
test_fail_unless (
sync.ntb_offset_tck == sync.bts - sync.preamble_stadate);
}
@@ -149,7 +148,7 @@ test_case_freq_error (test_t test)
bsu_ntb_init (&sync);
/* Configure with real data. */
sync.init = true;
- sync.second_shoot = true;
+ sync.sync_nb = 1;
sync.fe = -1.074e-05;
sync.bts = 0x8a1ad69;
sync.preamble_sysdate = 0x6f04181;
@@ -159,15 +158,14 @@ test_case_freq_error (test_t test)
scmp.preamble_sysdate = sync.preamble_sysdate + MAC_MS_TO_TCK (500);
scmp.preamble_stadate = sync.preamble_stadate + MAC_MS_TO_TCK (500);
/* Compute new Frequency error. */
- bsu_ntb_clk_sync (
- &sync, (phy_t*) &t.phy, scmp.bts, scmp.preamble_sysdate,
- scmp.preamble_stadate, 2);
+ bsu_ntb_clk_sync (&sync, scmp.bts, scmp.preamble_sysdate,
+ scmp.preamble_stadate, 2);
test_fail_unless (sync.fe == scmp.fe);
test_fail_unless (scmp.bts == sync.bts);
test_fail_unless (scmp.preamble_sysdate == sync.preamble_sysdate);
test_fail_unless (scmp.preamble_stadate == sync.preamble_stadate);
test_fail_unless (sync.init == true);
- test_fail_unless (sync.second_shoot == true);
+ test_fail_unless (sync.sync_nb == 1);
}
test_end;
}
diff --git a/cesar/bsu/src/bsu.c b/cesar/bsu/src/bsu.c
index cfea17ce50..77cdaf9936 100644
--- a/cesar/bsu/src/bsu.c
+++ b/cesar/bsu/src/bsu.c
@@ -69,7 +69,7 @@ bsu_stats_store (bsu_t *ctx)
{
#if CONFIG_STATS
ctx->stats.ntb_offset_tck = ctx->sta_avln->sync.ntb_offset_tck;
- if (ctx->sta_avln->sync.second_shoot)
+ if (ctx->sta_avln->sync.sync_nb >= ctx->ntb_clk_sync_nb_stable)
ctx->stats.frequency_error_q30 =
FIXED (ctx->sta_avln->sync.fe, BSU_NTB_FIXED_POINT);
else
@@ -889,7 +889,11 @@ bsu_stats_init (bsu_t *ctx)
LIB_STATS_ACCESS_READ_ONLY,
LIB_STATS_USER);
lib_stats_set_stat_value_notype ("CLK_SYNC_WEIGHT_K",
- &ctx->bsu_ntb_clk_sync_weight_k,
+ &ctx->ntb_clk_sync_weight_k,
+ LIB_STATS_ACCESS_WRITE_ONLY,
+ LIB_STATS_USER);
+ lib_stats_set_stat_value_notype ("CLK_SYNC_NB_STABLE",
+ &ctx->ntb_clk_sync_nb_stable,
LIB_STATS_ACCESS_WRITE_ONLY,
LIB_STATS_USER);
#endif
@@ -945,7 +949,8 @@ bsu_init (bsu_aclf_t *aclf, mac_config_t *mac_config, phy_t *phy,
ctx->beacon_nb_sent[i] = 0;
for (i = 0; i < COUNT (ctx->ca_schedules_in_use); i++)
ctx->ca_schedules_in_use[i] = CA_SCHEDULE_NB;
- ctx->bsu_ntb_clk_sync_weight_k = BSU_NTB_CLK_SYNC_WEIGHT_K_DEFAULT;
+ ctx->ntb_clk_sync_weight_k = BSU_NTB_CLK_SYNC_WEIGHT_K_DEFAULT;
+ ctx->ntb_clk_sync_nb_stable = BSU_NTB_CLK_SYNC_NB_STABLE_DEFAULT;
/* Trace. */
bsu_trace_init (ctx);
bsu_stats_init (ctx);
@@ -990,10 +995,9 @@ bsu_beacon_process__avln_tracked (bsu_t *ctx, bsu_beacon_t *beacon,
+ bsu_aclf_beacon_period_tck (ctx->aclf));
memcpy (&ctx->sta_avln->beacon, beacon, sizeof (bsu_beacon_t));
/* NTB synchronisation. */
- bsu_ntb_clk_sync (&ctx->sta_avln->sync, ctx->phy,
- params->bts, params->preamble_sysdate,
- params->preamble_date,
- ctx->bsu_ntb_clk_sync_weight_k);
+ bsu_ntb_clk_sync (&ctx->sta_avln->sync, params->bts,
+ params->preamble_sysdate, params->preamble_date,
+ ctx->ntb_clk_sync_weight_k);
/* Configure the clock frequency. */
bsu_ntb_clock_configure (
&ctx->sta_avln->sync, ctx->mac_config, ctx->phy);
@@ -1055,10 +1059,8 @@ bsu_beacon_process__avln_not_tracked (bsu_t *ctx, bsu_beacon_t *beacon,
avln->bto[i] = params->bto[i];
memcpy (&avln->beacon, beacon, sizeof (bsu_beacon_t));
/* NTB synchronisation. */
- bsu_ntb_clk_sync (&avln->sync, ctx->phy,
- params->bts, params->preamble_sysdate,
- params->preamble_date,
- ctx->bsu_ntb_clk_sync_weight_k);
+ bsu_ntb_clk_sync (&avln->sync, params->bts, params->preamble_sysdate,
+ params->preamble_date, ctx->ntb_clk_sync_weight_k);
avln->beacon.beacon_period_start_date = params->bts -
avln->sync.ntb_offset_tck;
BSU_TRACE (BEACON_PROCESS, phy_date (), params->snid, beacon->vf.stei,
@@ -1106,7 +1108,7 @@ bsu_beacon_process (bsu_t *ctx, pb_beacon_t *beacon,
FIXED (avln->sync.fe, BSU_NTB_FIXED_POINT);
bsu_beacon->params.ntb_offset_tck = avln->sync.ntb_offset_tck;
bsu_beacon->params.frequency_error_valid =
- avln->sync.second_shoot;
+ avln->sync.sync_nb >= ctx->ntb_clk_sync_nb_stable;
}
}
else
diff --git a/cesar/bsu/test/utest/src/bsut.c b/cesar/bsu/test/utest/src/bsut.c
index b25a9cbd60..8dfe19384b 100644
--- a/cesar/bsu/test/utest/src/bsut.c
+++ b/cesar/bsu/test/utest/src/bsut.c
@@ -20,6 +20,7 @@
#include "bsu/inc/bsu.h"
#include "bsu/inc/context.h"
#include "bsu/inc/interface.h"
+#include "bsu/ntb/ntb.h"
bsu_avln_t*
bsu_avln_add (bsu_t *ctx, u64 nid, u8 snid, mac_t mac, bool *added);
@@ -36,6 +37,8 @@ bsu_update__persistent_schedules (bsu_t *ctx, bsu_beacon_t *beacon);
void
test_case_bsu_process (test_t test)
{
+ uint i;
+ uint central_beacon_nb_recv = 0;
bsu_test_t t;
bsu_test_init (&t);
bsu_activate (t.bsu, true);
@@ -51,10 +54,11 @@ test_case_bsu_process (test_t test)
pbproc_tx_beacon_params_t bp_tx;
pbproc_rx_beacon_params_t bpneighbour_rx;
pbproc_rx_beacon_params_t bp_rx;
- bsu_test_create_beacon (&t, &beacon_neighbour);
memset (&bp_rx, 0, sizeof (pbproc_rx_beacon_params_t));
memset (&bpneighbour_rx, 0, sizeof (pbproc_rx_beacon_params_t));
t.mac_config.tei = 4;
+ /* => Neighbour beacon with bad CRC. */
+ bsu_test_create_beacon (&t, &beacon_neighbour);
bpneighbour_rx.snid = 0x4;
bpneighbour_rx.bts = 0;
bneighbour = bsu_beacon_write (&beacon_neighbour,
@@ -64,80 +68,101 @@ test_case_bsu_process (test_t test)
bneighbour->phy_pb.pb_rx.pb_measurement.crc_error = true;
bprocessed = bsu_beacon_process (t.bsu, bneighbour, &bpneighbour_rx);
blk_release_desc ((blk_t*) bneighbour);
- /* Central beacon processed ? */
+ /* Central beacon processed? */
test_fail_unless (!bprocessed);
test_fail_unless (t.bsu->avlns[0].snid == 0);
test_fail_unless (t.bsu->avlns[0].beacon.vf.nid == 0);
test_fail_unless (t.bsu->beacon_nb_sent [BSU_BEACON_TYPE_CENTRAL]
== 0);
- /* NTB called ? */
+ /* NTB called? */
test_fail_unless (t.bsu->avlns[0].sync.init == false);
+ test_fail_unless (t.bsu->avlns[0].sync.sync_nb == 0);
+ /* => First neighbour beacon reception. */
bneighbour = bsu_beacon_write (&beacon_neighbour,
BSU_BEACON_TYPE_CENTRAL,
&t.mac_config,
&bpneighbour_tx);
bneighbour->phy_pb.pb_rx.pb_measurement.crc_error = false;
bprocessed = bsu_beacon_process (t.bsu, bneighbour, &bpneighbour_rx);
- /* Central beacon processed ? */
+ /* Central beacon processed? */
test_fail_unless (bprocessed);
- test_fail_unless (!bprocessed->params.frequency_error_valid);
test_fail_unless (t.bsu->avlns[0].snid == bpneighbour_rx.snid);
test_fail_unless (t.bsu->avlns[0].beacon.vf.nid
== beacon_neighbour.vf.nid);
+ central_beacon_nb_recv++;
test_fail_unless (t.bsu->beacon_nb_recv [BSU_BEACON_TYPE_CENTRAL]
- == 1);
- blk_release (bprocessed);
- /* NTB called ? */
- test_fail_unless (t.bsu->avlns[0].sync.init == true);
- /* Second shoot... */
- bprocessed = bsu_beacon_process (t.bsu, bneighbour, &bpneighbour_rx);
- /* Central beacon processed ? */
- test_fail_unless (bprocessed);
- test_fail_unless (t.bsu->avlns[0].snid == bpneighbour_rx.snid);
- test_fail_unless (t.bsu->avlns[0].beacon.vf.nid
- == beacon_neighbour.vf.nid);
- /* NTB called ? */
+ == central_beacon_nb_recv);
+ /* NTB called? */
test_fail_unless (t.bsu->avlns[0].sync.init == true);
- test_fail_unless (bprocessed->params.frequency_error_valid);
- blk_release_desc ((blk_t*) bneighbour);
- test_fail_unless (t.bsu->beacon_nb_recv [BSU_BEACON_TYPE_CENTRAL]
- == 2);
+ test_fail_unless (t.bsu->avlns[0].sync.sync_nb == 0);
+ test_fail_unless (!bprocessed->params.frequency_error_valid);
+ /* Cleanup. */
blk_release (bprocessed);
- /* Our AVLN. */
+ /* => Next neighbour beacon receptions. */
+ for (i = 1; i <= BSU_NTB_CLK_SYNC_NB_STABLE_DEFAULT; i++)
+ {
+ bprocessed = bsu_beacon_process (t.bsu, bneighbour,
+ &bpneighbour_rx);
+ /* Central beacon processed? */
+ test_fail_unless (bprocessed);
+ test_fail_unless (t.bsu->avlns[0].snid == bpneighbour_rx.snid);
+ test_fail_unless (t.bsu->avlns[0].beacon.vf.nid
+ == beacon_neighbour.vf.nid);
+ central_beacon_nb_recv++;
+ test_fail_unless (t.bsu->beacon_nb_recv [BSU_BEACON_TYPE_CENTRAL]
+ == central_beacon_nb_recv);
+ /* NTB called? */
+ test_fail_unless (t.bsu->avlns[0].sync.init == true);
+ test_fail_unless (t.bsu->avlns[0].sync.sync_nb == i);
+ if (i == BSU_NTB_CLK_SYNC_NB_STABLE_DEFAULT)
+ test_fail_unless (bprocessed->params.frequency_error_valid);
+ else
+ test_fail_unless (!bprocessed->params.frequency_error_valid);
+ /* Cleanup. */
+ blk_release (bprocessed);
+ }
+ /* Cleanup. */
+ blk_release_desc ((blk_t*) bneighbour);
+ /* => Our AVLN. */
bsu_track_avln (t.bsu,
beacon_neighbour.vf.nid, 0x4, beacon_neighbour.vf.stei,
beacon_neighbour.bmis.mac_address.mac_address);
- t.bsu->sta_avln->sync.init = false;
+ /* Reset synchronisation. */
+ bsu_ntb_init (&t.bsu->sta_avln->sync);
+ /* => Beacon with bad CRC. */
bsu_test_create_beacon (&t, &beacon);
+ bp_rx.snid = 0x4;
+ bp_rx.bts = 0;
b = bsu_beacon_write (&beacon, BSU_BEACON_TYPE_CENTRAL,
&t.mac_config, &bp_tx);
b->phy_pb.pb_rx.pb_measurement.crc_error = true;
bprocessed = bsu_beacon_process (t.bsu, b, &bp_rx);
- /* Central beacon processed ? */
+ blk_release_desc ((blk_t*) b);
+ /* Central beacon processed? */
test_fail_unless (!bprocessed);
test_fail_unless (t.bsu->sta_avln->snid == t.bsu->snid_track);
test_fail_unless (t.bsu->sta_avln->beacon.vf.nid == t.bsu->nid_track);
test_fail_unless (t.bsu->beacon_nb_recv [BSU_BEACON_TYPE_CENTRAL]
- == 2);
- blk_release_desc ((blk_t*) b);
- /* NTB called ? */
+ == central_beacon_nb_recv);
+ /* NTB called? */
test_fail_unless (t.bsu->sta_avln->sync.init == false);
- bp_rx.snid = 0x4;
- bp_rx.bts = 0;
+ /* => First beacon reception. */
b = bsu_beacon_write (&beacon, BSU_BEACON_TYPE_CENTRAL,
&t.mac_config, &bp_tx);
b->phy_pb.pb_rx.pb_measurement.crc_error = false;
bprocessed = bsu_beacon_process (t.bsu, b, &bp_rx);
- /* Central beacon processed ? */
+ /* Central beacon processed? */
test_fail_unless (bprocessed);
test_fail_unless (t.bsu->sta_avln->snid == bp_rx.snid);
test_fail_unless (t.bsu->sta_avln->beacon.vf.nid == beacon.vf.nid);
+ central_beacon_nb_recv++;
test_fail_unless (t.bsu->beacon_nb_recv [BSU_BEACON_TYPE_CENTRAL]
- == 3);
- /* NTB called ? */
+ == central_beacon_nb_recv);
+ /* NTB called? */
test_fail_unless (t.bsu->sta_avln->sync.init == true);
- test_fail_unless (t.bsu->sta_avln->sync.second_shoot);
- test_fail_unless (bprocessed->params.frequency_error_valid);
+ test_fail_unless (t.bsu->sta_avln->sync.sync_nb == 0);
+ test_fail_unless (!bprocessed->params.frequency_error_valid);
+ /* Cleanup. */
blk_release_desc ((blk_t*) b);
blk_release (bprocessed);
}
@@ -171,8 +196,9 @@ test_case_bsu_process (test_t test)
test_fail_unless (t.sar.mfs->common.lid == MAC_LID_DISCOVER);
test_fail_unless (t.bsu->beacon_nb_sent [BSU_BEACON_TYPE_DISCOVER]
== 1);
+ central_beacon_nb_recv += 2;
test_fail_unless (t.bsu->beacon_nb_recv [BSU_BEACON_TYPE_CENTRAL]
- == 5);
+ == central_beacon_nb_recv);
/* Upper layer receives it ? */
test_fail_unless (t.ul.beacon);
test_fail_unless (t.ul.beacon->next);
diff --git a/cesar/ce/rx/bitloading/inc/ber.h b/cesar/ce/rx/bitloading/inc/ber.h
index d1182233f9..3184bbac4c 100644
--- a/cesar/ce/rx/bitloading/inc/ber.h
+++ b/cesar/ce/rx/bitloading/inc/ber.h
@@ -51,12 +51,6 @@
#define CE_RX_BL_BPT_QUANT_FACTOR (1ull << 8)
/**
- * NSR must be rescaled before used by BER vs polynomials.
- * Rescaling is not the same if NSR is based on sound or data.
- */
-#define CE_RX_BL_BER_NSR_SOUND_RESCALE (2)
-
-/**
* Polynomials for each modulation to compute BER.
*/
struct ce_rx_bl_ber_poly_coef_t
diff --git a/cesar/ce/rx/bitloading/inc/poly.h b/cesar/ce/rx/bitloading/inc/poly.h
index 5b56bc8c85..ae35acbea9 100644
--- a/cesar/ce/rx/bitloading/inc/poly.h
+++ b/cesar/ce/rx/bitloading/inc/poly.h
@@ -36,7 +36,7 @@ BEGIN_DECLS
* Therefore, implementation uses the second forms of the polynomial.
*/
extern inline s64
-ce_rx_bl_poly (const u8 degree, const s64 const *coef, const u32 x)
+ce_rx_bl_poly (const u8 degree, const s64 * const coef, const u32 x)
{
/* Check parameter. */
dbg_assert (coef);
diff --git a/cesar/ce/rx/bitloading/nsr.h b/cesar/ce/rx/bitloading/nsr.h
new file mode 100644
index 0000000000..6d4a9a824c
--- /dev/null
+++ b/cesar/ce/rx/bitloading/nsr.h
@@ -0,0 +1,24 @@
+#ifndef ce_rx_bitloading_nsr_h
+#define ce_rx_bitloading_nsr_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2011 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file ce/rx/bitloading/nsr.h
+ * \brief Public data
+ * \ingroup ce_rx_bl
+ *
+ * This file contains the information related to NSR.
+ */
+
+/**
+ * NSR must be rescaled before used by BER vs polynomials.
+ * Rescaling is not the same if NSR is based on sound or data.
+ */
+#define CE_RX_BL_NSR_SOUND_RESCALE (2)
+
+#endif /* ce_rx_bitloading_nsr_h */
diff --git a/cesar/ce/rx/bitloading/src/nsr.c b/cesar/ce/rx/bitloading/src/nsr.c
index d3499c2494..4da8168e0f 100644
--- a/cesar/ce/rx/bitloading/src/nsr.c
+++ b/cesar/ce/rx/bitloading/src/nsr.c
@@ -13,6 +13,7 @@
#include "common/std.h"
#include "ce/rx/bitloading/inc/nsr.h"
+#include "ce/rx/bitloading/nsr.h"
#include "ce/rx/bitloading/inc/ber.h"
#include "hal/phy/defs.h"
@@ -171,7 +172,7 @@ ce_rx_bl_nsr_compute_mean (ce_rx_bitloading_t *bl)
/* Compute mean and rescale (for NSR dynamics). */
cur_sum_nsr[j] = ce_rx_bl_nsr_mean (cur_sum_nsr[j],
bl->mean_count)
- * CE_RX_BL_BER_NSR_SOUND_RESCALE
+ * CE_RX_BL_NSR_SOUND_RESCALE
* ce_rx_bl_nsr_margin_ / CE_RX_BL_NSR_MARGIN_QUANT_FACTOR;
}
/* Next block. */
diff --git a/cesar/ce/rx/bitloading/test/src/test_bl.c b/cesar/ce/rx/bitloading/test/src/test_bl.c
index 5a1e410d5d..0fabe28917 100644
--- a/cesar/ce/rx/bitloading/test/src/test_bl.c
+++ b/cesar/ce/rx/bitloading/test/src/test_bl.c
@@ -22,6 +22,7 @@
#include "ce/rx/bitloading/inc/bitloading.h"
#include "ce/rx/bitloading/bitloading.h"
#include "ce/rx/bitloading/inc/common.h"
+#include "ce/rx/bitloading/nsr.h"
#include "lib/rnd.h"
/* Test vectors. */
@@ -1936,7 +1937,7 @@ main (int argc, char **argv)
uint i;
for (i = 0; i < mean_on_sound_nsr_height;
i++)
- mean_on_sound_nsr[i][0] *= CE_RX_BL_BER_NSR_SOUND_RESCALE;
+ mean_on_sound_nsr[i][0] *= CE_RX_BL_NSR_SOUND_RESCALE;
/* BER target margin. */
test_suite_ce_rx_bl_ber_target_margin (t);
diff --git a/cesar/ce/rx/test/src/test_rx.c b/cesar/ce/rx/test/src/test_rx.c
index 9bc9d3162c..f01deb8e65 100644
--- a/cesar/ce/rx/test/src/test_rx.c
+++ b/cesar/ce/rx/test/src/test_rx.c
@@ -143,6 +143,7 @@ test_ce_rx_measure_suite (test_t t)
{
pbproc_rx_params_t rx_params;
rx_params.tei = 1;
+ rx_params.multi_net_bcast = false;
rx_params.preamble_ntb = 0;
rx_params.beacon_period_start_ntb = 42;
mac_store_t *mac_store = mac_store_init ();
diff --git a/cesar/cl/inc/context.h b/cesar/cl/inc/context.h
index 662e56118f..965a190ccd 100644
--- a/cesar/cl/inc/context.h
+++ b/cesar/cl/inc/context.h
@@ -17,6 +17,7 @@
#include "common/defs/ethernet.h"
#include "lib/slab.h"
+#include "lib/seq_check.h"
#include "mac/common/mfs.h"
#include "mac/common/store.h"
#include "mac/common/config.h"
@@ -171,6 +172,9 @@ struct cl_t
/** cl Trace */
trace_buffer_t trace;
#endif /* !CONFIG_TRACE */
+#if CONFIG_SEQ_CHECK
+ lib_seq_check_t seq_check_rx_ctx;
+#endif
};
#endif /* CL_INC_CONTEXT_H_ */
diff --git a/cesar/cl/inc/trace.h b/cesar/cl/inc/trace.h
index e312a292f6..7192677e7c 100644
--- a/cesar/cl/inc/trace.h
+++ b/cesar/cl/inc/trace.h
@@ -47,6 +47,7 @@ enum
CL_TRACE_DATA_RECV,
CL_TRACE_DATA_BUFFER_ADD,
CL_TRACE_BRIDGE_ADD,
+ CL_TRACE_SEQ_CHECK,
};
BEGIN_DECLS
diff --git a/cesar/cl/src/bridge_table.c b/cesar/cl/src/bridge_table.c
index 94d96f0cc2..c5bd352e6b 100644
--- a/cesar/cl/src/bridge_table.c
+++ b/cesar/cl/src/bridge_table.c
@@ -146,12 +146,11 @@ bridge_table_update (cl_t *ctx)
/* The temporary local bridge is now empty. */
ctx->bridge_table.table_tmp_entry_count = 0;
- /* Remove old table. */
- if (ctx->bridge_table.table)
- mac_lookup_table_release (ctx->bridge_table.table);
-
- /* Affect new local bridge table. */
+ /* Atomically replace local bridge table. */
+ mac_lookup_table_t *old_table = ctx->bridge_table.table;
ctx->bridge_table.table = mac_lookup_table_convert (new_bridge_table);
+ if (old_table)
+ mac_lookup_table_release (old_table);
/* Bridge table has been modified. */
return true;
@@ -173,12 +172,11 @@ bridge_table_update (cl_t *ctx)
0xFFFF,
ctx->bridge_table.cycle_counter);
- /* Remove old table. */
- mac_lookup_table_release (ctx->bridge_table.table);
-
/* Affect new local bridge table. */
+ mac_lookup_table_t *old_table = ctx->bridge_table.table;
ctx->bridge_table.table
= mac_lookup_table_convert (new_bridge_table);
+ mac_lookup_table_release (old_table);
/* Bridge table has been modified. */
return true;
diff --git a/cesar/cl/src/cl.c b/cesar/cl/src/cl.c
index fc6b7d22bb..11d721149f 100644
--- a/cesar/cl/src/cl.c
+++ b/cesar/cl/src/cl.c
@@ -15,6 +15,7 @@
#include "common/std.h"
#include "common/defs/ethernet.h"
#include "lib/bitstream.h"
+#include "lib/seq_check.h"
#include "config/cl.h"
#include "cl/cl.h"
@@ -42,6 +43,26 @@
static struct cl_t cl_global;
/**
+ * Callback when the lib sequencer detect a wrong sequencing.
+ * \param user user data
+ * \param vlan the VLAN id
+ * \param seq_expected the sequence number expected
+ * \param seq_actual the actual sequence number found in the packet
+ */
+void
+cl_lib_seq_check_cb (void *user, uint vlan, uint seq_expected,
+ uint seq_actual);
+
+void
+cl_lib_seq_check_cb (void *user, uint vlan, uint seq_expected,
+ uint seq_actual)
+{
+ dbg_assert (user);
+ trace_do (cl_t *ctx = (cl_t *) user);
+ CL_TRACE (SEQ_CHECK, vlan, seq_expected, seq_actual);
+}
+
+/**
* Search for the lid in the classifier
*
* \param ctx CL context
@@ -324,6 +345,9 @@ cl_init (mac_store_t *mac_store, sar_t *sar, mac_config_t *mac_config)
CL_TRACE (INIT, phy_date ());
+ /* Initialise packet sequence check. */
+ lib_seq_check_init (&ctx->seq_check_rx_ctx, cl_lib_seq_check_cb, ctx);
+
/* Debug leds. */
GPIO_SETUP (LED_CL_RX, GPIO_DIRECTION_OUT);
GPIO_SET (LED_CL_RX, 0);
@@ -985,6 +1009,9 @@ void cl_data_recv (cl_t *ctx, u8 *buffer, uint length, mfs_rx_t *mfs)
&& (length <= ETH_PACKET_MAX_SIZE));
dbg_assert (mfs);
+ /* Check sequence number of throughput. */
+ lib_seq_check_packet (&ctx->seq_check_rx_ctx, buffer, length);
+
dbg_assert (ctx->data_rx.cb);
mac_t smac, dmac;
bitstream_direct_read_macs (buffer, &dmac, &smac);
diff --git a/cesar/cl/src/trace.c b/cesar/cl/src/trace.c
index 9ad0392a54..758caa7561 100644
--- a/cesar/cl/src/trace.c
+++ b/cesar/cl/src/trace.c
@@ -52,6 +52,8 @@ cl_trace_init (cl_t *ctx)
TRACE_EVENT (CL_TRACE_DATA_RECV, "CL_DATA_RECV buffer @ : %x, destination : %m, source : %m, length : %d", TIMESTAMP),
TRACE_EVENT (CL_TRACE_DATA_BUFFER_ADD, "CL_DATA_BUFFER_ADD buffer @ : %x", TIMESTAMP),
TRACE_EVENT (CL_TRACE_BRIDGE_ADD, "Bridging MAC %m"),
+ TRACE_EVENT (CL_TRACE_SEQ_CHECK, "[SeqCheck] input from PLC: "
+ "[%02d] expected=%04X, actual=%04X"),
};
dbg_assert (ctx);
trace_namespace_init (&namespace, event_ids, COUNT (event_ids));
diff --git a/cesar/common/make/config.mk b/cesar/common/make/config.mk
index ac46989db0..c5dbc829ff 100644
--- a/cesar/common/make/config.mk
+++ b/cesar/common/make/config.mk
@@ -64,6 +64,10 @@ $$($2_OBJ_INC_DIR)/build_info.h: $$($2_OBJ_INC_DIR_STAMP) BUILD_INFO_FORCE
endef
$(call foreach_type,CONFIG_RULES_template)
+# Check for old build system leftovers.
+$(if $(wildcard $(OBJ_INC_DIR)/build_info.h),\
+$(error old build system leftovers detected, please rm -r obj))
+
$(DEFAULT_PROJECT_CONFIG): $(OBJ_DIR_STAMP)
touch $@
diff --git a/cesar/common/tests/tests b/cesar/common/tests/tests
index 589b7a068f..b5c46c5b5f 100644
--- a/cesar/common/tests/tests
+++ b/cesar/common/tests/tests
@@ -80,8 +80,8 @@ cov test_mac_lookup_table: ./obj/test_mac_lookup_table
lib/test/mbox:
make: make COV=y
-cov test_mbox_host: ./obj/host
-cov test_mbox_ecos: ./obj/mbox.elf
+cov test_mbox_host: ./obj/mbox_host
+cov-target test_mbox_ecos: ./obj/mbox.elf
lib/test/perf:
make: make
@@ -134,6 +134,10 @@ lib/scenario/test:
make: make COV=y
cov test_scenario: ./obj/test_scenario
+lib/test/seq_check:
+make: make COV=y
+cov test_seq_check: ./obj/test_seq_check
+
maximus/stationtest:
make
@@ -480,7 +484,8 @@ sc01_long_simu: python py/sc01_long_simu.py -d false -t 25000000000
sc02_long_simu_data: python py/sc02_long_simu_data.py -d false -t 25000000000
test_general/station/tonemap:
-make
+make -f host-Makefile
+sc01_bl_initial: python py/sc01_bl_initial.py --maximus
sc02_vs_get_tonemap: python py/sc02_vs_get_tonemap.py --maximus
cp/cco/bw/test:
@@ -527,10 +532,6 @@ test_general/station/compliance:
make
6.2.1-dut_as_a_cco: python py/sc01_dut_as_a_cco.py --maximus
-test_general/station/tonemap:
-make -f host-Makefile
-tone_map_exchange_no_snr: python py/sc01_bl_initial.py --maximus
-
bsu/beacon/test/utest:
make
beacon: ./obj/beacon
@@ -546,3 +547,7 @@ bsu/ntb: ./obj/ntb
bsu/aclf/test/utest:
make
bsu/aclf: ./obj/aclf
+
+projects/plc:
+make
+make traces: make PROJECT_CONFIG=Config.traces
diff --git a/cesar/cp/beacon/test/src/beacon.c b/cesar/cp/beacon/test/src/beacon.c
index 1716547d1d..0e4b83c116 100644
--- a/cesar/cp/beacon/test/src/beacon.c
+++ b/cesar/cp/beacon/test/src/beacon.c
@@ -35,7 +35,47 @@ cp_beacon_receive (cp_t *ctx, bsu_beacon_t *beacon);
void
cp_beacon_sta_compute_schedules (cp_t *ctx, bsu_beacon_t *beacon_data);
-static cp_t cp;
+struct test_beacon_t
+{
+ cp_t cp;
+ mac_config_t mac_config;
+ cl_t cl;
+ sar_t sar;
+ bsu_aclf_t aclf;
+ uint ca;
+};
+typedef struct test_beacon_t test_beacon_t;
+
+void
+test_beacon_init (test_beacon_t *ctx)
+{
+ memset (ctx, 0, sizeof (test_beacon_t));
+ lib_rnd_init (&ctx->cp.rnd, 0x1234);
+ ctx->cp.mac_config = &ctx->mac_config;
+ ctx->cp.sar = &ctx->sar;
+ ctx->cp.cl = &ctx->cl;
+ ctx->cp.bsu_aclf = &ctx->aclf;
+ *((bsu_aclf_frequency_t*) &ctx->aclf.frequency) = BSU_ACLF_FREQ_50HZ;
+ *((bsu_aclf_bp_t*) &ctx->aclf.beacon_period_theo_tck) =
+ BSU_ACLF_BP_50HZ_TCK;
+ ctx->aclf.beacon_period_tck = ctx->aclf.beacon_period_theo_tck;
+ ctx->cp.mac_store = mac_store_init();
+ ctx->cp.ca = (ca_t*) &ctx->ca;
+ cp_sta_mgr_init (&ctx->cp);
+ cp_cco_bw_init (&ctx->cp);
+ cp_cco_region_init (&ctx->cp);
+ cp_beacon_init (&ctx->cp);
+}
+
+void
+test_beacon_uninit (test_beacon_t *ctx)
+{
+ cp_beacon_uninit (&ctx->cp);
+ cp_cco_bw_uninit (&ctx->cp);
+ cp_cco_region_uninit (&ctx->cp);
+ cp_sta_mgr_uninit (&ctx->cp);
+ mac_store_uninit (ctx->cp.mac_store);
+}
bsu_beacon_t*
test_new_beacon (void)
@@ -75,21 +115,6 @@ test_new_beacon (void)
return beacon;
}
-
-/** Initialise
- *
- * At the end of this test, all the variables present in the beacon context
- * shall be equal to zero or null for the pointers.
- */
-void
-test_case_beacon_init (test_t test)
-{
-
- cp_beacon_init (&cp);
-
- test_case_begin (test, "beacon init");
-}
-
/** Uninitialise
* \param test the test object.
*
@@ -118,8 +143,8 @@ test_case_beacon_uninit (test_t test)
test_case_begin (test, "Beacon uninit");
test_begin (test, "remove beacons received")
{
- cp_beacon_init (&cp);
- cp.mac_store = mac_store_init ();
+ test_beacon_t ctx;
+ test_beacon_init (&ctx);
bsu_beacon_t *b;
uint i;
for (i = 0; i < 2; i++)
@@ -127,10 +152,10 @@ test_case_beacon_uninit (test_t test)
b = blk_alloc ();
b->next = NULL;
b->params.direction = BSU_BEACON_DIRECTION_FROM_PLC;
- cp_beacon_receive (&cp, b);
+ cp_beacon_receive (&ctx.cp, b);
}
- cp_beacon_uninit (&cp);
- test_fail_unless (slist_empty (cp.beacon.list., bare));
+ test_beacon_uninit (&ctx);
+ test_fail_unless (slist_empty (ctx.cp.beacon.list., bare));
}
test_end;
}
@@ -139,35 +164,25 @@ void
test_case_beacon__deactivate (test_t test)
{
test_case_begin (test, "Deactivate");
-
test_begin (test, "Deactivate beacon module")
{
+ test_beacon_t ctx;
uint nb_beacons = 2;
- mac_store_t *mac_store = mac_store_init();
- uint ca;
-
- /* Configure the test. */
- memset (&cp, 0, sizeof (cp_t));
- cp.mac_store = mac_store;
- cp.ca = (ca_t *) &ca;
-
- cp_beacon_init (&cp);
-
+ test_beacon_init (&ctx);
/* Still configuring the test... */
- cp.beacon.leon_timer.status = true;
-
+ ctx.cp.beacon.leon_timer.status = true;
/* Allocate some beacons. */
uint i;
for (i = 0; i < nb_beacons; i++)
{
bsu_beacon_t *beacon = blk_alloc ();
beacon->next = NULL;
- slist_push_back (cp.beacon.list., beacon, bare);
+ slist_push_back (ctx.cp.beacon.list., beacon, bare);
}
/* test. */
- cp_beacon_deactivate (&cp);
- test_fail_unless (slist_empty (cp.beacon.list., bare));
- mac_store_uninit (mac_store);
+ cp_beacon_deactivate (&ctx.cp);
+ test_fail_unless (slist_empty (ctx.cp.beacon.list., bare));
+ test_beacon_uninit (&ctx);
test_fail_if (blk_check_memory () != true, "Memory leaks");
}
test_end;
@@ -287,30 +302,9 @@ test_beacon_bentries (test_t test, bsu_beacon_t *beacon,
void
test_suite_beacon__beacon_generation (test_t test)
{
+ test_beacon_t ctx;
bsu_beacon_t beacon;
-
- mac_config_t mac_config;
- cl_t cl;
- sar_t sar;
- bsu_aclf_t aclf;
-
- /* Configure the context. */
- memset (&mac_config, 0, sizeof (mac_config_t));
- memset (&cl, 0, sizeof (cl_t));
- memset (&sar, 0, sizeof (sar_t));
- memset (&aclf, 0, sizeof (bsu_aclf_t));
-
- cp.mac_config = &mac_config;
- cp.cl = &cl;
- cp.sar = &sar;
- cp.bsu_aclf = &aclf;
- aclf.beacon_period_tck = BSU_ACLF_BP_50HZ_TCK;
-
- cp_sta_mgr_init (&cp);
- cp_beacon_init (&cp);
- cp_cco_bw_init (&cp);
- cp_cco_region_init (&cp);
- cp.mac_store = mac_store_init();
+ test_beacon_init (&ctx);
/* Data set one */
const cp_nid_t nid_1 = 0x001456789ABCDEF0ull;
@@ -331,39 +325,39 @@ test_suite_beacon__beacon_generation (test_t test)
const u8 snid_cd = 0xA;
const cp_snid_t new_snid = 0xF;
- cp_net_t *net_1 = cp_sta_mgr_add_avln (&cp, snid_1, nid_1);
- cp_sta_own_data_set_tei (&cp, tei_1);
- cp_net_set_slot_id_and_usage (&cp, net_1, slot_id_1, 0);
- cp_sta_mgr_set_our_avln (&cp, net_1);
- cp_beacon_handover_hoipflag (&cp, hoip_flag_1);
- cp_sta_own_data_set_cco_status (&cp, cco_flag_1);
- cp_sta_own_data_set_pco_status (&cp, pco_flag_1);
- cp_sta_own_data_set_authenticated_status (&cp, authen_1);
- cp.beacon.discover.discover_interval_bp = 10;
- ((cp_sta_own_data_t *)&cp.sta_mgr.sta_own_data)->hybrid_mode = hm_1;
-
- cp_beacon_change_hm (&cp, new_hm);
- cp.beacon.eks.kccd = kc_cd;
- cp.beacon.eks.kbc = kbc;
- cp.beacon.eks.new_eks = eks;
- cp.beacon.hoip.hoipcd = hoip_cd;
- cp.beacon.hoip.cco = hoip_tei;
- cp.beacon.snids.snidcd = snid_cd;
- cp.beacon.snids.snid = new_snid;
- cp.beacon.discover.countdown_bp = 0; // so that the flag is true
+ cp_net_t *net_1 = cp_sta_mgr_add_avln (&ctx.cp, snid_1, nid_1);
+ cp_sta_own_data_set_tei (&ctx.cp, tei_1);
+ cp_net_set_slot_id_and_usage (&ctx.cp, net_1, slot_id_1, 0);
+ cp_sta_mgr_set_our_avln (&ctx.cp, net_1);
+ cp_beacon_handover_hoipflag (&ctx.cp, hoip_flag_1);
+ cp_sta_own_data_set_cco_status (&ctx.cp, cco_flag_1);
+ cp_sta_own_data_set_pco_status (&ctx.cp, pco_flag_1);
+ cp_sta_own_data_set_authenticated_status (&ctx.cp, authen_1);
+ ctx.cp.beacon.discover.discover_interval_bp = 10;
+ ((cp_sta_own_data_t *)&ctx.cp.sta_mgr.sta_own_data)->hybrid_mode = hm_1;
+
+ cp_beacon_change_hm (&ctx.cp, new_hm);
+ ctx.cp.beacon.eks.kccd = kc_cd;
+ ctx.cp.beacon.eks.kbc = kbc;
+ ctx.cp.beacon.eks.new_eks = eks;
+ ctx.cp.beacon.hoip.hoipcd = hoip_cd;
+ ctx.cp.beacon.hoip.cco = hoip_tei;
+ ctx.cp.beacon.snids.snidcd = snid_cd;
+ ctx.cp.beacon.snids.snid = new_snid;
+ ctx.cp.beacon.discover.countdown_bp = 0; // so that the flag is true
/* Regions. */
cp_cco_region_alloc_t *region;
uint end_time_atu = 3907;
- region = cp_cco_region_alloc_init (&cp);
+ region = cp_cco_region_alloc_init (&ctx.cp);
region->type = CP_BEACON_REGION_TYPE_SHARED_CSMA;
region->end_time_atu = end_time_atu;
- cp_cco_region_alloc_add (&cp, &cp.region.region_list, region);
+ cp_cco_region_alloc_add (&ctx.cp, &ctx.cp.region.region_list, region);
slab_release (region);
/* Fill the beacon data share memory */
- cp_beacon_fill (&cp, &beacon);
+ cp_beacon_fill (&ctx.cp, &beacon);
test_suite_begin (test, "Beacon generation");
test_case_begin (test, "fill share memory");
@@ -412,32 +406,32 @@ test_suite_beacon__beacon_generation (test_t test)
const bool authen_2 = false;
const mac_coexistence_mode_t hm_2 = MAC_COEXISTENCE_NB - 1;
- cp_net_t *net_2 = cp_sta_mgr_add_avln (&cp, snid_2, nid_2);
- cp_sta_own_data_set_tei (&cp, tei_2);
- cp_net_set_slot_id_and_usage (&cp, net_2, slot_id_2, 0);
- cp_sta_mgr_set_our_avln (&cp, net_2);
- cp_beacon_handover_hoipflag (&cp, hoip_flag_2);
- cp_sta_own_data_set_cco_status (&cp, cco_flag_2);
- cp_sta_own_data_set_pco_status (&cp, pco_flag_2);
- cp_sta_own_data_set_authenticated_status (&cp, authen_2);
- ((cp_sta_own_data_t *)&cp.sta_mgr.sta_own_data)->hybrid_mode = hm_2;
-
- cp.beacon.eks.kccd = 0;
- cp.beacon.hoip.hoipcd = 0;
- cp.beacon.snids.snidcd = 0;
- cp.beacon.hm.hmcd = 0;
+ cp_net_t *net_2 = cp_sta_mgr_add_avln (&ctx.cp, snid_2, nid_2);
+ cp_sta_own_data_set_tei (&ctx.cp, tei_2);
+ cp_net_set_slot_id_and_usage (&ctx.cp, net_2, slot_id_2, 0);
+ cp_sta_mgr_set_our_avln (&ctx.cp, net_2);
+ cp_beacon_handover_hoipflag (&ctx.cp, hoip_flag_2);
+ cp_sta_own_data_set_cco_status (&ctx.cp, cco_flag_2);
+ cp_sta_own_data_set_pco_status (&ctx.cp, pco_flag_2);
+ cp_sta_own_data_set_authenticated_status (&ctx.cp, authen_2);
+ ((cp_sta_own_data_t *)&ctx.cp.sta_mgr.sta_own_data)->hybrid_mode = hm_2;
+
+ ctx.cp.beacon.eks.kccd = 0;
+ ctx.cp.beacon.hoip.hoipcd = 0;
+ ctx.cp.beacon.snids.snidcd = 0;
+ ctx.cp.beacon.hm.hmcd = 0;
/* Regions. */
- region = cp_cco_region_alloc_init (&cp);
+ region = cp_cco_region_alloc_init (&ctx.cp);
region->type = CP_BEACON_REGION_TYPE_BEACON;
region->end_time_atu = end_time_atu - 10;
- cp_cco_region_alloc_add (&cp, &cp.region.region_list, region);
+ cp_cco_region_alloc_add (&ctx.cp, &ctx.cp.region.region_list, region);
slab_release (region);
- region = cp_cco_region_alloc_init (&cp);
+ region = cp_cco_region_alloc_init (&ctx.cp);
region->type = CP_BEACON_REGION_TYPE_STAYOUT;
region->end_time_atu = end_time_atu + 10;
- cp_cco_region_alloc_add (&cp, &cp.region.region_list, region);
+ cp_cco_region_alloc_add (&ctx.cp, &ctx.cp.region.region_list, region);
slab_release (region);
/* Schedules. */
@@ -449,7 +443,7 @@ test_suite_beacon__beacon_generation (test_t test)
{
for (ns=0; ns < 2; ns++)
{
- sched = cp_cco_bw_alloc_init (&cp);
+ sched = cp_cco_bw_alloc_init (&ctx.cp);
sched->persistence = CP_CCO_BW_ALLOC_PERSISTENCE_PERSISTENT;
sched->pscd = i;
sched->cscd = i;
@@ -457,14 +451,14 @@ test_suite_beacon__beacon_generation (test_t test)
sched->glid = 0x55 + nb;
sched->end_time_atu = end_time_atu + nb * 10 + ns * 5;
sched->start_time_atu = end_time_atu + nb * 10 + ns * 5 -4;
- cp_cco_bw_alloc_add (&cp, &cp.bw.alloc_list, sched);
+ cp_cco_bw_alloc_add (&ctx.cp, &ctx.cp.bw.alloc_list, sched);
slab_release (sched);
}
}
for (ns = 0; ns < BSU_BEACON_BMIS_SCHEDULES_SAI_MAX; ns++)
{
- sched = cp_cco_bw_alloc_init (&cp);
+ sched = cp_cco_bw_alloc_init (&ctx.cp);
sched->persistence = CP_CCO_BW_ALLOC_PERSISTENCE_NOT_PERSISTENT;
sched->pscd = ns;
sched->cscd = ns;
@@ -472,12 +466,12 @@ test_suite_beacon__beacon_generation (test_t test)
sched->glid = 0x45 + ns;
sched->start_time_atu = end_time_atu - 10 * (ns + 1) -9;
sched->end_time_atu = end_time_atu - 10 * (ns + 1);
- cp_cco_bw_alloc_add (&cp, &cp.bw.alloc_list, sched);
+ cp_cco_bw_alloc_add (&ctx.cp, &ctx.cp.bw.alloc_list, sched);
slab_release (sched);
}
/* Fill the beacon data share memory */
- cp_beacon_fill (&cp, &beacon);
+ cp_beacon_fill (&ctx.cp, &beacon);
test_suite_begin (test, "Beacon generation 2");
test_case_begin (test, "fill share memory 2");
@@ -554,9 +548,7 @@ test_suite_beacon__beacon_generation (test_t test)
test_fail_unless (beacon.bmis.nps.ns == ns);
}
test_end;
-
- cp_cco_bw_uninit (&cp);
- cp_cco_region_uninit (&cp);
+ test_beacon_uninit (&ctx);
}
void
@@ -564,53 +556,32 @@ test_case_beacon_snid_change_cco (test_t test)
{
uint snid;
cp_net_t *net;
- mac_config_t mac_config;
- cl_t cl;
- sar_t sar;
- bsu_aclf_t aclf;
+ test_beacon_t ctx;
test_case_begin (test, "CCo");
+ test_beacon_init (&ctx);
+ ctx.cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
+ ctx.cp.beacon.last_countdown_date = 0;
- /* Configure the test. */
- memset (&cp, 0, sizeof (cp_t));
- memset (&mac_config, 0, sizeof (mac_config_t));
- memset (&cl, 0, sizeof (cl_t));
- memset (&sar, 0, sizeof (sar_t));
-
- *((bsu_aclf_frequency_t*) &aclf.frequency) = BSU_ACLF_FREQ_50HZ;
- *((bsu_aclf_bp_t*) &aclf.beacon_period_theo_tck) = BSU_ACLF_BP_50HZ_TCK;
- aclf.beacon_period_tck = aclf.beacon_period_theo_tck;
- cp.bsu_aclf = &aclf;
-
- cp_sta_mgr_init (&cp);
- cp_beacon_init (&cp);
-
- cp.mac_config = &mac_config;
- cp.cl = &cl;
- cp.sar = &sar;
- cp.mac_store = mac_store_init();
- cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
- cp.beacon.last_countdown_date = 0;
-
- net = cp_sta_mgr_add_avln (&cp, 0xA, 1);
- cp_sta_own_data_set_snid (&cp, 0xA);
- cp_sta_own_data_set_tei (&cp, 1);
- cp_sta_mgr_set_our_avln (&cp, net);
- cp_sta_own_data_set_cco_status (&cp, true);
- cp_sta_own_data_set_mac_address (&cp, 0x123456789ABCull);
+ net = cp_sta_mgr_add_avln (&ctx.cp, 0xA, 1);
+ cp_sta_own_data_set_snid (&ctx.cp, 0xA);
+ cp_sta_own_data_set_tei (&ctx.cp, 1);
+ cp_sta_mgr_set_our_avln (&ctx.cp, net);
+ cp_sta_own_data_set_cco_status (&ctx.cp, true);
+ cp_sta_own_data_set_mac_address (&ctx.cp, 0x123456789ABCull);
test_begin (test, "Change SNID")
{
/* Process the test. */
- test_fail_unless (cp.beacon.snids.snid == 0);
- test_fail_unless (cp.beacon.snids.snidcd == 0);
+ test_fail_unless (ctx.cp.beacon.snids.snid == 0);
+ test_fail_unless (ctx.cp.beacon.snids.snidcd == 0);
snid = 1;
- cp_beacon_change_snid (&cp, snid);
+ cp_beacon_change_snid (&ctx.cp, snid);
- test_fail_unless (cp.beacon.snids.snid == snid);
- test_fail_unless (cp.beacon.snids.snidcd == CP_BEACON_COUNTDOWN_SNID);
+ test_fail_unless (ctx.cp.beacon.snids.snid == snid);
+ test_fail_unless (ctx.cp.beacon.snids.snidcd == CP_BEACON_COUNTDOWN_SNID);
}
test_end;
@@ -624,53 +595,51 @@ test_case_beacon_snid_change_cco (test_t test)
set_init (&set_schedules, cp_cco_bw_alloc_less);
set_init (&set_regions, cp_cco_region_alloc_less);
- cp_cco_region_init (&cp);
- cp_cco_bw_init (&cp);
+ cp_cco_region_init (&ctx.cp);
+ cp_cco_bw_init (&ctx.cp);
/* Regions. */
- region = cp_cco_region_alloc_init (&cp);
+ region = cp_cco_region_alloc_init (&ctx.cp);
region->type = CP_BEACON_REGION_TYPE_SHARED_CSMA;
region->end_time_atu = 3907;
- cp_cco_region_alloc_add (&cp, &cp.region.region_list, region);
+ cp_cco_region_alloc_add (&ctx.cp, &ctx.cp.region.region_list, region);
slab_release (region);
/* Schedules. */
- alloc = cp_cco_bw_alloc_init (&cp);
+ alloc = cp_cco_bw_alloc_init (&ctx.cp);
alloc->pscd = 7;
alloc->cscd = 7;
alloc->stpf = false;
alloc->glid = 0x45;
alloc->end_time_atu = 3907;
alloc->persistence = CP_CCO_BW_ALLOC_PERSISTENCE_PERSISTENT;
- cp_cco_bw_alloc_add (&cp, &cp.bw.alloc_list, alloc);
+ cp_cco_bw_alloc_add (&ctx.cp, &ctx.cp.bw.alloc_list, alloc);
slab_release (alloc);
- cp_beacon_fill (&cp, &beacon);
+ cp_beacon_fill (&ctx.cp, &beacon);
test_fail_unless (beacon.bmis.change_snid.present == true);
- test_fail_unless (beacon.bmis.change_snid.snidccd == cp.beacon.snids.snidcd);
- test_fail_unless (beacon.bmis.change_snid.new_snid == cp.beacon.snids.snid);
+ test_fail_unless (beacon.bmis.change_snid.snidccd == ctx.cp.beacon.snids.snidcd);
+ test_fail_unless (beacon.bmis.change_snid.new_snid == ctx.cp.beacon.snids.snid);
- cp_cco_bw_alloc_clean (&cp, &set_schedules);
- cp_cco_region_alloc_clean (&cp, &set_regions);
+ cp_cco_bw_alloc_clean (&ctx.cp, &set_schedules);
+ cp_cco_region_alloc_clean (&ctx.cp, &set_regions);
- cp_beacon_sta_compute_schedules (&cp, &beacon);
- alloc = cp_cco_bw_alloc_get_first (&cp, &cp.bw.alloc_list);
+ cp_beacon_sta_compute_schedules (&ctx.cp, &beacon);
+ alloc = cp_cco_bw_alloc_get_first (&ctx.cp, &ctx.cp.bw.alloc_list);
test_fail_unless (alloc->persistence ==
CP_CCO_BW_ALLOC_PERSISTENCE_PERSISTENT);
- alloc = cp_cco_bw_alloc_get_next (&cp, &cp.bw.alloc_list, alloc);
+ alloc = cp_cco_bw_alloc_get_next (&ctx.cp, &ctx.cp.bw.alloc_list, alloc);
test_fail_unless (!alloc);
- cp_cco_region_alloc_clean (&cp, &set_regions);
- cp_cco_bw_alloc_clean (&cp, &set_schedules);
- cp_cco_bw_uninit (&cp);
- cp_cco_region_uninit (&cp);
+ cp_cco_region_alloc_clean (&ctx.cp, &set_regions);
+ cp_cco_bw_alloc_clean (&ctx.cp, &set_schedules);
+ cp_cco_bw_uninit (&ctx.cp);
+ cp_cco_region_uninit (&ctx.cp);
}
test_end;
/* Uninit all the data. */
- cp_beacon_uninit (&cp);
- cp_sta_mgr_uninit (&cp);
- mac_store_uninit (cp.mac_store);
+ test_beacon_uninit (&ctx);
}
@@ -682,172 +651,137 @@ test_case_beacon_snid_change_sta (test_t test)
test_begin (test, "Beacon reception")
{
bsu_beacon_t *beacon;
- mac_config_t mac_config;
- cl_t cl;
- sar_t sar;
cp_net_t *net;
- bsu_aclf_t aclf;
cp_sta_own_data_t *own;
- uint phy = 0;
+ test_beacon_t ctx;
+ test_beacon_init (&ctx);
/** Init the context. */
- memset (&mac_config, 0, sizeof (mac_config_t));
- memset (&cl, 0, sizeof (cl_t));
- memset (&sar, 0, sizeof (sar_t));
- cp.mac_config = &mac_config;
- cp.cl = &cl;
- cp.sar = &sar;
- cp.phy = (phy_t *) &phy;
- cp.bsu_aclf = &aclf;
- cp.mac_store = mac_store_init ();
- cp_sta_mgr_init (&cp);
- cp_beacon_init (&cp);
- cp_cco_bw_init (&cp);
- cp_cco_region_init (&cp);
- cp.bsu_aclf->beacon_period_tck = BSU_ACLF_BP_60HZ_TCK;
- cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
- cp.beacon.last_countdown_date = 0;
+ ctx.cp.bsu_aclf->beacon_period_tck = BSU_ACLF_BP_60HZ_TCK;
+ ctx.cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
+ ctx.cp.beacon.last_countdown_date = 0;
/* Configure station own data. */
- net = cp_sta_mgr_add_avln (&cp, 0, 1);
- cp_sta_own_data_set_tei (&cp, 2);
- cp_sta_own_data_set_mac_address (&cp, 0x23456789abcull);
- cp_sta_mgr_set_our_avln (&cp, net);
- own = cp_sta_mgr_get_sta_own_data (&cp);
+ net = cp_sta_mgr_add_avln (&ctx.cp, 0, 1);
+ cp_sta_own_data_set_tei (&ctx.cp, 2);
+ cp_sta_own_data_set_mac_address (&ctx.cp, 0x23456789abcull);
+ cp_sta_mgr_set_our_avln (&ctx.cp, net);
+ own = cp_sta_mgr_get_sta_own_data (&ctx.cp);
own->nid_track = 1;
own->tei_track = 1;
/** Check snid default values. */
- test_fail_unless (cp.beacon.snids.snid == 0);
- test_fail_unless (cp.beacon.snids.snidcd == 0);
- test_fail_unless (cp_net_get_snid (&cp, net) == 0x0);
- test_fail_unless (cp_sta_own_data_get_snid (&cp) == 0x0);
+ test_fail_unless (ctx.cp.beacon.snids.snid == 0);
+ test_fail_unless (ctx.cp.beacon.snids.snidcd == 0);
+ test_fail_unless (cp_net_get_snid (&ctx.cp, net) == 0x0);
+ test_fail_unless (cp_sta_own_data_get_snid (&ctx.cp) == 0x0);
/** Create a central beacon. */
beacon = test_new_beacon ();
beacon->bmis.change_snid.present = true;
beacon->bmis.change_snid.new_snid = 0xC;
beacon->bmis.change_snid.snidccd = 3;
- cp_beacon_receive (&cp, beacon);
- cp_beacon_get_and_process_beacon (&cp);
+ cp_beacon_receive (&ctx.cp, beacon);
+ cp_beacon_get_and_process_beacon (&ctx.cp);
/** Check snid values are taken. */
- test_fail_unless (cp.beacon.snids.snid == 0xC);
- test_fail_unless (cp.beacon.snids.snidcd == 3);
- test_fail_unless (cp_net_get_snid (&cp, net) == 0x0);
- test_fail_unless (cp_sta_own_data_get_snid (&cp) == 0x0);
+ test_fail_unless (ctx.cp.beacon.snids.snid == 0xC);
+ test_fail_unless (ctx.cp.beacon.snids.snidcd == 3);
+ test_fail_unless (cp_net_get_snid (&ctx.cp, net) == 0x0);
+ test_fail_unless (cp_sta_own_data_get_snid (&ctx.cp) == 0x0);
/** Create the next beacon (countdown decreased). */
beacon = test_new_beacon ();
beacon->bmis.change_snid.snidccd = 2;
- cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
- cp.beacon.last_countdown_date = 0;
+ ctx.cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
+ ctx.cp.beacon.last_countdown_date = 0;
/** launch the test. */
- cp_beacon_receive (&cp, beacon);
- cp_beacon_get_and_process_beacon (&cp);
+ cp_beacon_receive (&ctx.cp, beacon);
+ cp_beacon_get_and_process_beacon (&ctx.cp);
/** Check countdown. */
- test_fail_unless (cp.beacon.snids.snid == 0xC);
- test_fail_unless (cp.beacon.snids.snidcd == 2);
- test_fail_unless (cp_net_get_snid (&cp, net) == 0x0);
- test_fail_unless (cp_sta_own_data_get_snid (&cp) == 0x0);
+ test_fail_unless (ctx.cp.beacon.snids.snid == 0xC);
+ test_fail_unless (ctx.cp.beacon.snids.snidcd == 2);
+ test_fail_unless (cp_net_get_snid (&ctx.cp, net) == 0x0);
+ test_fail_unless (cp_sta_own_data_get_snid (&ctx.cp) == 0x0);
/** Create the next beacon (countdown decreased). */
beacon = test_new_beacon ();
beacon->bmis.change_snid.snidccd = 1;
- cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
- cp.beacon.last_countdown_date = 0;
+ ctx.cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
+ ctx.cp.beacon.last_countdown_date = 0;
/** launch the test. */
- cp_beacon_receive (&cp, beacon);
- cp_beacon_get_and_process_beacon (&cp);
+ cp_beacon_receive (&ctx.cp, beacon);
+ cp_beacon_get_and_process_beacon (&ctx.cp);
/** Check countdown. */
- test_fail_unless (cp.beacon.snids.snid == 0xC);
- test_fail_unless (cp.beacon.snids.snidcd == 1);
- test_fail_unless (cp_net_get_snid (&cp, net) == 0x0);
- test_fail_unless (cp_sta_own_data_get_snid (&cp) == 0x0);
+ test_fail_unless (ctx.cp.beacon.snids.snid == 0xC);
+ test_fail_unless (ctx.cp.beacon.snids.snidcd == 1);
+ test_fail_unless (cp_net_get_snid (&ctx.cp, net) == 0x0);
+ test_fail_unless (cp_sta_own_data_get_snid (&ctx.cp) == 0x0);
/* Create the beacon. */
beacon = test_new_beacon ();
beacon->bmis.change_snid.present = false;
beacon->bmis.nbe--;
beacon->params.rx_parameters.snid = 0xC;
- cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
- cp.beacon.last_countdown_date = 0;
+ ctx.cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
+ ctx.cp.beacon.last_countdown_date = 0;
/* launch the test. */
- cp_beacon_receive (&cp, beacon);
- cp_beacon_get_and_process_beacon (&cp);
+ cp_beacon_receive (&ctx.cp, beacon);
+ cp_beacon_get_and_process_beacon (&ctx.cp);
/** Check new snid is 0xC. */
- test_fail_unless (cp.beacon.snids.snid == 0xC);
- test_fail_unless (cp.beacon.snids.snidcd == 0);
- test_fail_unless (cp_net_get_snid (&cp, net) == 0xC);
- test_fail_unless (cp_sta_own_data_get_snid (&cp) == 0xC);
+ test_fail_unless (ctx.cp.beacon.snids.snid == 0xC);
+ test_fail_unless (ctx.cp.beacon.snids.snidcd == 0);
+ test_fail_unless (cp_net_get_snid (&ctx.cp, net) == 0xC);
+ test_fail_unless (cp_sta_own_data_get_snid (&ctx.cp) == 0xC);
- cp_beacon_uninit (&cp);
- cp_sta_mgr_uninit (&cp);
- cp_cco_bw_uninit (&cp);
- cp_cco_region_uninit (&cp);
- dbg_check (mac_store_sta_remove (cp.mac_store, 1));
- mac_store_uninit (cp.mac_store);
+ dbg_check (mac_store_sta_remove (ctx.cp.mac_store, 1));
+ test_beacon_uninit (&ctx);
}
test_end;
test_begin (test, "Beacon missed")
{
- mac_config_t mac_config;
- cl_t cl;
- sar_t sar;
+ test_beacon_t ctx;
cp_net_t *net;
cp_cco_region_alloc_t *region;
cp_cco_bw_alloc_t *alloc;
-
- memset (&mac_config, 0, sizeof (mac_config_t));
- memset (&cl, 0, sizeof (cl_t));
- memset (&sar, 0, sizeof (sar_t));
-
- cp_cco_region_init (&cp);
- cp_cco_bw_init (&cp);
-
+ test_beacon_init (&ctx);
/* Regions. */
- region = cp_cco_region_alloc_init (&cp);
+ region = cp_cco_region_alloc_init (&ctx.cp);
region->type = CP_BEACON_REGION_TYPE_SHARED_CSMA;
region->end_time_atu = 3907;
- cp_cco_region_alloc_add (&cp, &cp.region.region_list, region);
+ cp_cco_region_alloc_add (&ctx.cp, &ctx.cp.region.region_list, region);
slab_release (region);
/* Schedules. */
- alloc = cp_cco_bw_alloc_init (&cp);
+ alloc = cp_cco_bw_alloc_init (&ctx.cp);
alloc->stpf = false;
alloc->glid = 0x45;
alloc->end_time_atu = 3907;
alloc->persistence = CP_CCO_BW_ALLOC_PERSISTENCE_NOT_PERSISTENT;
- cp_cco_bw_alloc_add (&cp, &cp.bw.alloc_list, alloc);
+ cp_cco_bw_alloc_add (&ctx.cp, &ctx.cp.bw.alloc_list, alloc);
slab_release (alloc);
- cp_sta_mgr_init (&cp);
- cp_beacon_init (&cp);
-
/* Configure station own data. */
- net = cp_sta_mgr_add_avln (&cp, 1, 1);
- cp_sta_own_data_set_tei (&cp, 2);
- cp_sta_own_data_set_mac_address (&cp, 0x23456789abcull);
- cp_sta_mgr_set_our_avln (&cp, net);
- cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
- cp.beacon.last_countdown_date = 0;
+ net = cp_sta_mgr_add_avln (&ctx.cp, 1, 1);
+ cp_sta_own_data_set_tei (&ctx.cp, 2);
+ cp_sta_own_data_set_mac_address (&ctx.cp, 0x23456789abcull);
+ cp_sta_mgr_set_our_avln (&ctx.cp, net);
+ ctx.cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
+ ctx.cp.beacon.last_countdown_date = 0;
/* Configure the test. */
- cp.beacon.snids.snidcd = 2;
- cp.beacon.snids.snid = 0xc;
+ ctx.cp.beacon.snids.snidcd = 2;
+ ctx.cp.beacon.snids.snid = 0xc;
- cp_beacon_beacon_not_received (&cp);
+ cp_beacon_beacon_not_received (&ctx.cp);
- test_fail_unless (cp.beacon.snids.snidcd == 1);
- test_fail_unless (cp.beacon.snids.snid == 0xc);
+ test_fail_unless (ctx.cp.beacon.snids.snidcd == 1);
+ test_fail_unless (ctx.cp.beacon.snids.snid == 0xc);
- cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
- cp.beacon.last_countdown_date = 0;
+ ctx.cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
+ ctx.cp.beacon.last_countdown_date = 0;
- cp_beacon_beacon_not_received (&cp);
+ cp_beacon_beacon_not_received (&ctx.cp);
- test_fail_unless (cp.beacon.snids.snidcd == 0);
- test_fail_unless (cp.beacon.snids.snid == 0xc);
- test_fail_unless (cp_net_get_snid (&cp, net) == 0xC);
- test_fail_unless (cp_sta_own_data_get_snid (&cp) == 0xC);
+ test_fail_unless (ctx.cp.beacon.snids.snidcd == 0);
+ test_fail_unless (ctx.cp.beacon.snids.snid == 0xc);
+ test_fail_unless (cp_net_get_snid (&ctx.cp, net) == 0xC);
+ test_fail_unless (cp_sta_own_data_get_snid (&ctx.cp) == 0xC);
- cp_beacon_uninit (&cp);
- cp_sta_mgr_uninit (&cp);
- cp_cco_region_uninit (&cp);
- cp_cco_bw_uninit (&cp);
+ test_beacon_uninit (&ctx);
}
test_end;
}
@@ -868,38 +802,22 @@ test_case_beacon_hm_change_sta (test_t test)
test_begin (test, "Beacon reception")
{
+ test_beacon_t ctx;
bsu_beacon_t *beacon;
- mac_config_t mac_config;
- cl_t cl;
- sar_t sar;
cp_net_t *net;
- uint phy = 0;
- bsu_aclf_t aclf;
cp_sta_own_data_t *own;
/** Init the context. */
- memset (&mac_config, 0, sizeof (mac_config_t));
- memset (&cl, 0, sizeof (cl_t));
- memset (&sar, 0, sizeof (sar_t));
- cp.mac_config = &mac_config;
- cp.cl = &cl;
- cp.sar = &sar;
- cp.phy = (phy_t *) &phy;
- cp.mac_store = mac_store_init ();
- cp.bsu_aclf = &aclf;
- cp_sta_mgr_init (&cp);
- cp_beacon_init (&cp);
- cp_cco_bw_init (&cp);
- cp_cco_region_init (&cp);
- cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
- cp.bsu_aclf->beacon_period_tck = BSU_ACLF_BP_60HZ_TCK;
- cp.beacon.last_countdown_date = 0;
+ test_beacon_init (&ctx);
+ ctx.cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
+ ctx.cp.bsu_aclf->beacon_period_tck = BSU_ACLF_BP_60HZ_TCK;
+ ctx.cp.beacon.last_countdown_date = 0;
/** Configure station own data. */
- own = cp_sta_mgr_get_sta_own_data (&cp);
- net = cp_sta_mgr_add_avln (&cp, 0, 1);
- cp_sta_own_data_set_tei (&cp, 2);
- cp_sta_own_data_set_mac_address (&cp, 0x23456789abcull);
- cp_sta_mgr_set_our_avln (&cp, net);
- own = cp_sta_mgr_get_sta_own_data (&cp);
+ own = cp_sta_mgr_get_sta_own_data (&ctx.cp);
+ net = cp_sta_mgr_add_avln (&ctx.cp, 0, 1);
+ cp_sta_own_data_set_tei (&ctx.cp, 2);
+ cp_sta_own_data_set_mac_address (&ctx.cp, 0x23456789abcull);
+ cp_sta_mgr_set_our_avln (&ctx.cp, net);
+ own = cp_sta_mgr_get_sta_own_data (&ctx.cp);
own->nid_track = 1;
own->tei_track = 1;
own->hybrid_mode = 0;
@@ -910,126 +828,110 @@ test_case_beacon_hm_change_sta (test_t test)
beacon->bmis.change_hm.hmccd = 3;
beacon->bmis.nbe = 4;
/** Check default values. */
- test_fail_unless (cp.beacon.hm.hm == 0);
- test_fail_unless (cp.beacon.hm.hmcd == 0);
+ test_fail_unless (ctx.cp.beacon.hm.hm == 0);
+ test_fail_unless (ctx.cp.beacon.hm.hmcd == 0);
test_fail_unless (own->hybrid_mode == 0);
/* launch the test. */
- cp_beacon_receive (&cp, beacon);
- cp_beacon_get_and_process_beacon (&cp);
+ cp_beacon_receive (&ctx.cp, beacon);
+ cp_beacon_get_and_process_beacon (&ctx.cp);
/** Check values are taken. */
- test_fail_unless (cp.beacon.hm.hm == 0x1);
- test_fail_unless (cp.beacon.hm.hmcd == 3);
+ test_fail_unless (ctx.cp.beacon.hm.hm == 0x1);
+ test_fail_unless (ctx.cp.beacon.hm.hmcd == 3);
test_fail_unless (own->hybrid_mode == 0);
/** Create the new beacon. */
beacon = test_new_beacon ();
beacon->bmis.change_hm.hmccd = 2;
- cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
- cp.beacon.last_countdown_date = 0;
+ ctx.cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
+ ctx.cp.beacon.last_countdown_date = 0;
/** launch the test. */
- cp_beacon_receive (&cp, beacon);
- cp_beacon_get_and_process_beacon (&cp);
+ cp_beacon_receive (&ctx.cp, beacon);
+ cp_beacon_get_and_process_beacon (&ctx.cp);
/** Check values are taken. */
- test_fail_unless (cp.beacon.hm.hm == 0x1);
- test_fail_unless (cp.beacon.hm.hmcd == 2);
+ test_fail_unless (ctx.cp.beacon.hm.hm == 0x1);
+ test_fail_unless (ctx.cp.beacon.hm.hmcd == 2);
test_fail_unless (own->hybrid_mode == 0);
/** Create the new beacon. */
beacon = test_new_beacon ();
beacon->bmis.change_hm.hmccd = 1;
- cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
- cp.beacon.last_countdown_date = 0;
+ ctx.cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
+ ctx.cp.beacon.last_countdown_date = 0;
/* launch the test. */
- cp_beacon_receive (&cp, beacon);
- cp_beacon_get_and_process_beacon (&cp);
- test_fail_unless (cp.beacon.hm.hm == 0x1);
- test_fail_unless (cp.beacon.hm.hmcd == 1);
+ cp_beacon_receive (&ctx.cp, beacon);
+ cp_beacon_get_and_process_beacon (&ctx.cp);
+ test_fail_unless (ctx.cp.beacon.hm.hm == 0x1);
+ test_fail_unless (ctx.cp.beacon.hm.hmcd == 1);
test_fail_unless (own->hybrid_mode == 0);
/* Create the beacon. */
beacon = test_new_beacon ();
beacon->bmis.change_hm.present = false;
beacon->bmis.nbe = 3;
- cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
- cp.beacon.last_countdown_date = 0;
+ ctx.cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
+ ctx.cp.beacon.last_countdown_date = 0;
/* launch the test. */
- cp_beacon_receive (&cp, beacon);
- cp_beacon_get_and_process_beacon (&cp);
- test_fail_unless (cp.beacon.hm.hm == 0x1);
- test_fail_unless (cp.beacon.hm.hmcd == 0);
+ cp_beacon_receive (&ctx.cp, beacon);
+ cp_beacon_get_and_process_beacon (&ctx.cp);
+ test_fail_unless (ctx.cp.beacon.hm.hm == 0x1);
+ test_fail_unless (ctx.cp.beacon.hm.hmcd == 0);
test_fail_unless (own->hybrid_mode == 0x1);
- cp_beacon_uninit (&cp);
- cp_sta_mgr_uninit (&cp);
- cp_cco_bw_uninit (&cp);
- cp_cco_region_uninit (&cp);
- dbg_check (mac_store_sta_remove (cp.mac_store, 1));
- mac_store_uninit (cp.mac_store);
+ dbg_check (mac_store_sta_remove (ctx.cp.mac_store, 1));
+ test_beacon_uninit (&ctx);
}
test_end;
test_begin (test, "Beacon missed")
{
- mac_config_t mac_config;
- cl_t cl;
- sar_t sar;
+ test_beacon_t ctx;
cp_net_t *net;
cp_cco_region_alloc_t *region;
cp_cco_bw_alloc_t *alloc;
cp_sta_own_data_t *own;
-
- memset (&mac_config, 0, sizeof (mac_config_t));
- memset (&cl, 0, sizeof (cl_t));
- memset (&sar, 0, sizeof (sar_t));
-
- cp_cco_region_init (&cp);
- cp_cco_bw_init (&cp);
-
+ test_beacon_init (&ctx);
/* Regions. */
- region = cp_cco_region_alloc_init (&cp);
+ region = cp_cco_region_alloc_init (&ctx.cp);
region->type = CP_BEACON_REGION_TYPE_SHARED_CSMA;
region->end_time_atu = 3907;
- cp_cco_region_alloc_add (&cp, &cp.region.region_list, region);
+ cp_cco_region_alloc_add (&ctx.cp, &ctx.cp.region.region_list, region);
slab_release (region);
/* Schedules. */
- alloc = cp_cco_bw_alloc_init (&cp);
+ alloc = cp_cco_bw_alloc_init (&ctx.cp);
alloc->stpf = false;
alloc->glid = 0x45;
alloc->end_time_atu = 3907;
alloc->persistence = CP_CCO_BW_ALLOC_PERSISTENCE_NOT_PERSISTENT;
- cp_cco_bw_alloc_add (&cp, &cp.bw.alloc_list, alloc);
+ cp_cco_bw_alloc_add (&ctx.cp, &ctx.cp.bw.alloc_list, alloc);
slab_release (alloc);
- cp_sta_mgr_init (&cp);
- cp_beacon_init (&cp);
+ cp_sta_mgr_init (&ctx.cp);
+ cp_beacon_init (&ctx.cp);
/* Configure station own data. */
- own = cp_sta_mgr_get_sta_own_data (&cp);
- net = cp_sta_mgr_add_avln (&cp, 0, 1);
- cp_sta_own_data_set_tei (&cp, 2);
- cp_sta_own_data_set_mac_address (&cp, 0x23456789abcull);
- cp_sta_mgr_set_our_avln (&cp, net);
- cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
- cp.beacon.last_countdown_date = 0;
+ own = cp_sta_mgr_get_sta_own_data (&ctx.cp);
+ net = cp_sta_mgr_add_avln (&ctx.cp, 0, 1);
+ cp_sta_own_data_set_tei (&ctx.cp, 2);
+ cp_sta_own_data_set_mac_address (&ctx.cp, 0x23456789abcull);
+ cp_sta_mgr_set_our_avln (&ctx.cp, net);
+ ctx.cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
+ ctx.cp.beacon.last_countdown_date = 0;
/* Configure the test. */
- cp.beacon.hm.hmcd = 2;
- cp.beacon.hm.hm = 0x1;
+ ctx.cp.beacon.hm.hmcd = 2;
+ ctx.cp.beacon.hm.hm = 0x1;
- cp_beacon_beacon_not_received (&cp);
+ cp_beacon_beacon_not_received (&ctx.cp);
- test_fail_unless (cp.beacon.hm.hmcd == 1);
- test_fail_unless (cp.beacon.hm.hm == 0x1);
- cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
- cp.beacon.last_countdown_date = 0;
+ test_fail_unless (ctx.cp.beacon.hm.hmcd == 1);
+ test_fail_unless (ctx.cp.beacon.hm.hm == 0x1);
+ ctx.cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
+ ctx.cp.beacon.last_countdown_date = 0;
- cp_beacon_beacon_not_received (&cp);
+ cp_beacon_beacon_not_received (&ctx.cp);
- test_fail_unless (cp.beacon.hm.hmcd == 0);
- test_fail_unless (cp.beacon.hm.hm == 0x1);
+ test_fail_unless (ctx.cp.beacon.hm.hmcd == 0);
+ test_fail_unless (ctx.cp.beacon.hm.hm == 0x1);
test_fail_unless (own->hybrid_mode == 0x1);
- cp_beacon_uninit (&cp);
- cp_sta_mgr_uninit (&cp);
- cp_cco_region_uninit (&cp);
- cp_cco_bw_uninit (&cp);
+ test_beacon_uninit (&ctx);
}
test_end;
}
@@ -1047,58 +949,43 @@ test_case_beacon_eks_change_cco (test_t test)
{
cp_key_t nek;
cp_net_t *net;
- mac_config_t mac_config;
- cl_t cl;
- sar_t sar;
-
+ test_beacon_t ctx;
test_case_begin (test, "CCo");
/** Configure the context. */
- memset (&mac_config, 0, sizeof (mac_config_t));
- memset (&cl, 0, sizeof (cl_t));
- memset (&sar, 0, sizeof (sar_t));
-
- cp_sta_mgr_init (&cp);
- cp_beacon_init (&cp);
-
- cp.mac_config = &mac_config;
- cp.cl = &cl;
- cp.sar = &sar;
- cp.mac_store = mac_store_init();
- cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
- cp.beacon.last_countdown_date = 0;
+ test_beacon_init (&ctx);
+ ctx.cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
+ ctx.cp.beacon.last_countdown_date = 0;
/** Configure our station. */
- net = cp_sta_mgr_add_avln (&cp, 0xA, 1);
- cp_sta_own_data_set_tei (&cp, 1);
- cp_sta_mgr_set_our_avln (&cp, net);
- cp_sta_own_data_set_cco_status (&cp, true);
- cp_sta_own_data_set_mac_address (&cp, 0x123456789ABCull);
+ net = cp_sta_mgr_add_avln (&ctx.cp, 0xA, 1);
+ cp_sta_own_data_set_tei (&ctx.cp, 1);
+ cp_sta_mgr_set_our_avln (&ctx.cp, net);
+ cp_sta_own_data_set_cco_status (&ctx.cp, true);
+ cp_sta_own_data_set_mac_address (&ctx.cp, 0x123456789ABCull);
test_begin (test, "Change EKS")
{
uint i;
/** Check default values. */
- test_fail_unless (cp.beacon.eks.kccd == 0);
- test_fail_unless (cp.beacon.eks.kbc == BSU_BEACON_EKS_KBC_NEK);
- test_fail_unless (cp.beacon.eks.new_eks == 0);
+ test_fail_unless (ctx.cp.beacon.eks.kccd == 0);
+ test_fail_unless (ctx.cp.beacon.eks.kbc == BSU_BEACON_EKS_KBC_NEK);
+ test_fail_unless (ctx.cp.beacon.eks.new_eks == 0);
/** Change nek. */
for (i = 0; i < COUNT (nek.key); i++)
nek.key[i] = i;
- cp_beacon_change_nek (&cp, MAC_EKS_MIN, nek, false /* not now*/);
+ cp_beacon_change_nek (&ctx.cp, MAC_EKS_MIN, nek, false /* not now*/);
/** Check new values. */
- test_fail_unless (cp.beacon.eks.new_eks == MAC_EKS_MIN);
- test_fail_unless (cp.beacon.eks.kbc == BSU_BEACON_EKS_KBC_NEK);
- test_fail_unless (cp.beacon.eks.kccd == CP_BEACON_COUNTDOWN_EKS);
+ test_fail_unless (ctx.cp.beacon.eks.new_eks == MAC_EKS_MIN);
+ test_fail_unless (ctx.cp.beacon.eks.kbc == BSU_BEACON_EKS_KBC_NEK);
+ test_fail_unless (ctx.cp.beacon.eks.kccd == CP_BEACON_COUNTDOWN_EKS);
}
test_end;
/* Uninit all the data. */
- cp_beacon_uninit (&cp);
- cp_sta_mgr_uninit (&cp);
- mac_store_uninit (cp.mac_store);
+ test_beacon_uninit (&ctx);
}
void
@@ -1109,37 +996,18 @@ test_case_beacon_eks_change_sta (test_t test)
test_begin (test, "Beacon reception")
{
bsu_beacon_t *beacon;
- mac_config_t mac_config;
- cl_t cl;
- sar_t sar;
cp_net_t *net;
- uint phy = 0;
- bsu_aclf_t aclf;
cp_sta_own_data_t *own;
+ test_beacon_t ctx;
/** Init the context. */
- memset (&mac_config, 0, sizeof (mac_config_t));
- memset (&cl, 0, sizeof (cl_t));
- memset (&sar, 0, sizeof (sar_t));
- cp.mac_config = &mac_config;
- cp.cl = &cl;
- cp.sar = &sar;
- cp.phy = (phy_t *) &phy;
- cp.bsu_aclf = &aclf;
- cp.mac_store = mac_store_init ();
- cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
- cp.bsu_aclf->beacon_period_tck = BSU_ACLF_BP_60HZ_TCK;
- cp.beacon.last_countdown_date = 0;
- cp_sta_mgr_init (&cp);
- cp_beacon_init (&cp);
- cp_cco_bw_init (&cp);
- cp_cco_region_init (&cp);
+ test_beacon_init (&ctx);
/** Configure station own data. */
- own = cp_sta_mgr_get_sta_own_data (&cp);
- net = cp_sta_mgr_add_avln (&cp, 0, 1);
- cp_sta_own_data_set_tei (&cp, 2);
- cp_sta_own_data_set_mac_address (&cp, 0x23456789abcull);
- cp_sta_mgr_set_our_avln (&cp, net);
- own = cp_sta_mgr_get_sta_own_data (&cp);
+ own = cp_sta_mgr_get_sta_own_data (&ctx.cp);
+ net = cp_sta_mgr_add_avln (&ctx.cp, 0, 1);
+ cp_sta_own_data_set_tei (&ctx.cp, 2);
+ cp_sta_own_data_set_mac_address (&ctx.cp, 0x23456789abcull);
+ cp_sta_mgr_set_our_avln (&ctx.cp, net);
+ own = cp_sta_mgr_get_sta_own_data (&ctx.cp);
own->nid_track = 1;
own->tei_track = 1;
/** Create a central beacon. */
@@ -1150,134 +1018,118 @@ test_case_beacon_eks_change_sta (test_t test)
beacon->bmis.eks.new_eks = MAC_EKS_MIN + 1;
mac_eks_t ref_eks_current = MAC_EKS_MIN + 2;
mac_eks_t ref_eks_next = MAC_EKS_MIN + 3;
- mac_config.nek[bsu_nek_index_current (INVALID_PTR)].eks =
+ ctx.mac_config.nek[bsu_nek_index_current (INVALID_PTR)].eks =
ref_eks_current;
- mac_config.nek[bsu_nek_index_next (INVALID_PTR)].eks = ref_eks_next;
+ ctx.mac_config.nek[bsu_nek_index_next (INVALID_PTR)].eks = ref_eks_next;
/** Check default values. */
- test_fail_unless (cp.beacon.eks.kccd == 0);
- test_fail_unless (cp.beacon.eks.kbc == BSU_BEACON_EKS_KBC_NEK);
- test_fail_unless (cp.beacon.eks.new_eks == MAC_EKS_MIN);
+ test_fail_unless (ctx.cp.beacon.eks.kccd == 0);
+ test_fail_unless (ctx.cp.beacon.eks.kbc == BSU_BEACON_EKS_KBC_NEK);
+ test_fail_unless (ctx.cp.beacon.eks.new_eks == MAC_EKS_MIN);
/* launch the test. */
- cp_beacon_receive (&cp, beacon);
- cp_beacon_get_and_process_beacon (&cp);
- test_fail_unless (cp.beacon.eks.kccd == 2);
- test_fail_unless (cp.beacon.eks.kbc == BSU_BEACON_EKS_KBC_NEK);
- test_fail_unless (cp.beacon.eks.new_eks == MAC_EKS_MIN + 1);
+ cp_beacon_receive (&ctx.cp, beacon);
+ cp_beacon_get_and_process_beacon (&ctx.cp);
+ test_fail_unless (ctx.cp.beacon.eks.kccd == 2);
+ test_fail_unless (ctx.cp.beacon.eks.kbc == BSU_BEACON_EKS_KBC_NEK);
+ test_fail_unless (ctx.cp.beacon.eks.new_eks == MAC_EKS_MIN + 1);
test_fail_unless (
- mac_config.nek[bsu_nek_index_current (INVALID_PTR)].eks ==
+ ctx.mac_config.nek[bsu_nek_index_current (INVALID_PTR)].eks ==
ref_eks_current);
- test_fail_unless (mac_config.nek[bsu_nek_index_next (INVALID_PTR)].eks ==
+ test_fail_unless (ctx.mac_config.nek[bsu_nek_index_next (INVALID_PTR)].eks ==
ref_eks_next);
/* Create the beacon. */
beacon = test_new_beacon ();
beacon->bmis.eks.kccd = 1;
- cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
- cp.beacon.last_countdown_date = 0;
+ ctx.cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
+ ctx.cp.beacon.last_countdown_date = 0;
/* launch the test. */
- cp_beacon_receive (&cp, beacon);
- cp_beacon_get_and_process_beacon (&cp);
- test_fail_unless (cp.beacon.eks.kccd == 1);
- test_fail_unless (cp.beacon.eks.kbc == BSU_BEACON_EKS_KBC_NEK);
- test_fail_unless (cp.beacon.eks.new_eks == MAC_EKS_MIN + 1);
+ cp_beacon_receive (&ctx.cp, beacon);
+ cp_beacon_get_and_process_beacon (&ctx.cp);
+ test_fail_unless (ctx.cp.beacon.eks.kccd == 1);
+ test_fail_unless (ctx.cp.beacon.eks.kbc == BSU_BEACON_EKS_KBC_NEK);
+ test_fail_unless (ctx.cp.beacon.eks.new_eks == MAC_EKS_MIN + 1);
test_fail_unless (
- mac_config.nek[bsu_nek_index_current (INVALID_PTR)].eks ==
+ ctx.mac_config.nek[bsu_nek_index_current (INVALID_PTR)].eks ==
ref_eks_current);
- test_fail_unless (mac_config.nek[bsu_nek_index_next (INVALID_PTR)].eks ==
+ test_fail_unless (ctx.mac_config.nek[bsu_nek_index_next (INVALID_PTR)].eks ==
ref_eks_next);
/* Create the beacon. */
beacon = test_new_beacon ();
beacon->bmis.eks.present = false;
beacon->bmis.nbe--;
- cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
- cp.beacon.last_countdown_date = 0;
+ ctx.cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
+ ctx.cp.beacon.last_countdown_date = 0;
/* launch the test. */
- cp_beacon_receive (&cp, beacon);
- cp_beacon_get_and_process_beacon (&cp);
- test_fail_unless (cp.beacon.eks.kccd == 0);
- test_fail_unless (cp.beacon.eks.kbc == BSU_BEACON_EKS_KBC_NB);
- test_fail_unless (cp.beacon.eks.new_eks == MAC_EKS_MIN + 1);
+ cp_beacon_receive (&ctx.cp, beacon);
+ cp_beacon_get_and_process_beacon (&ctx.cp);
+ test_fail_unless (ctx.cp.beacon.eks.kccd == 0);
+ test_fail_unless (ctx.cp.beacon.eks.kbc == BSU_BEACON_EKS_KBC_NB);
+ test_fail_unless (ctx.cp.beacon.eks.new_eks == MAC_EKS_MIN + 1);
test_fail_unless (
- mac_config.nek[bsu_nek_index_current (INVALID_PTR)].eks ==
+ ctx.mac_config.nek[bsu_nek_index_current (INVALID_PTR)].eks ==
ref_eks_current);
- test_fail_unless (mac_config.nek[bsu_nek_index_next (INVALID_PTR)].eks ==
+ test_fail_unless (ctx.mac_config.nek[bsu_nek_index_next (INVALID_PTR)].eks ==
MAC_EKS_CLEAR);
- cp_beacon_uninit (&cp);
- cp_sta_mgr_uninit (&cp);
- dbg_check (mac_store_sta_remove (cp.mac_store, 1));
- mac_store_uninit (cp.mac_store);
- cp_cco_region_uninit (&cp);
- cp_cco_bw_uninit (&cp);
+ dbg_check (mac_store_sta_remove (ctx.cp.mac_store, 1));
+ test_beacon_uninit (&ctx);
}
test_end;
test_begin (test, "Beacon missed")
{
- mac_config_t mac_config;
- cl_t cl;
- sar_t sar;
cp_net_t *net;
cp_cco_region_alloc_t *region;
cp_cco_bw_alloc_t *alloc;
cp_sta_own_data_t *own;
-
- memset (&mac_config, 0, sizeof (mac_config_t));
- memset (&cl, 0, sizeof (cl_t));
- memset (&sar, 0, sizeof (sar_t));
-
- cp_cco_region_init (&cp);
- cp_cco_bw_init (&cp);
-
+ test_beacon_t ctx;
+ test_beacon_init (&ctx);
/* Regions. */
- region = cp_cco_region_alloc_init (&cp);
+ region = cp_cco_region_alloc_init (&ctx.cp);
region->type = CP_BEACON_REGION_TYPE_SHARED_CSMA;
region->end_time_atu = 3907;
- cp_cco_region_alloc_add (&cp, &cp.region.region_list, region);
+ cp_cco_region_alloc_add (&ctx.cp, &ctx.cp.region.region_list, region);
slab_release (region);
/* Schedules. */
- alloc = cp_cco_bw_alloc_init (&cp);
+ alloc = cp_cco_bw_alloc_init (&ctx.cp);
alloc->stpf = false;
alloc->glid = 0x45;
alloc->end_time_atu = 3907;
alloc->persistence = CP_CCO_BW_ALLOC_PERSISTENCE_NOT_PERSISTENT;
- cp_cco_bw_alloc_add (&cp, &cp.bw.alloc_list, alloc);
+ cp_cco_bw_alloc_add (&ctx.cp, &ctx.cp.bw.alloc_list, alloc);
slab_release (alloc);
- cp_sta_mgr_init (&cp);
- cp_beacon_init (&cp);
+ cp_sta_mgr_init (&ctx.cp);
+ cp_beacon_init (&ctx.cp);
/* Configure station own data. */
- own = cp_sta_mgr_get_sta_own_data (&cp);
- net = cp_sta_mgr_add_avln (&cp, 0, 1);
- cp_sta_own_data_set_tei (&cp, 2);
- cp_sta_own_data_set_mac_address (&cp, 0x23456789abcull);
- cp_sta_mgr_set_our_avln (&cp, net);
- cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
- cp.beacon.last_countdown_date = 0;
+ own = cp_sta_mgr_get_sta_own_data (&ctx.cp);
+ net = cp_sta_mgr_add_avln (&ctx.cp, 0, 1);
+ cp_sta_own_data_set_tei (&ctx.cp, 2);
+ cp_sta_own_data_set_mac_address (&ctx.cp, 0x23456789abcull);
+ cp_sta_mgr_set_our_avln (&ctx.cp, net);
+ ctx.cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
+ ctx.cp.beacon.last_countdown_date = 0;
/* Configure the test. */
- cp.beacon.eks.kccd = 2;
- cp.beacon.eks.kbc = BSU_BEACON_EKS_KBC_NEK;
- cp.beacon.eks.new_eks = MAC_EKS_MIN + 1;
+ ctx.cp.beacon.eks.kccd = 2;
+ ctx.cp.beacon.eks.kbc = BSU_BEACON_EKS_KBC_NEK;
+ ctx.cp.beacon.eks.new_eks = MAC_EKS_MIN + 1;
- cp_beacon_beacon_not_received (&cp);
+ cp_beacon_beacon_not_received (&ctx.cp);
- test_fail_unless (cp.beacon.eks.kccd == 1);
- test_fail_unless (cp.beacon.eks.kbc == BSU_BEACON_EKS_KBC_NEK);
- test_fail_unless (cp.beacon.eks.new_eks == MAC_EKS_MIN + 1);
- cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
- cp.beacon.last_countdown_date = 0;
+ test_fail_unless (ctx.cp.beacon.eks.kccd == 1);
+ test_fail_unless (ctx.cp.beacon.eks.kbc == BSU_BEACON_EKS_KBC_NEK);
+ test_fail_unless (ctx.cp.beacon.eks.new_eks == MAC_EKS_MIN + 1);
+ ctx.cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
+ ctx.cp.beacon.last_countdown_date = 0;
- cp_beacon_beacon_not_received (&cp);
+ cp_beacon_beacon_not_received (&ctx.cp);
- test_fail_unless (cp.beacon.eks.kccd == 0);
- test_fail_unless (cp.beacon.eks.kbc == BSU_BEACON_EKS_KBC_NB);
- test_fail_unless (cp.beacon.eks.new_eks == MAC_EKS_MIN + 1);
+ test_fail_unless (ctx.cp.beacon.eks.kccd == 0);
+ test_fail_unless (ctx.cp.beacon.eks.kbc == BSU_BEACON_EKS_KBC_NB);
+ test_fail_unless (ctx.cp.beacon.eks.new_eks == MAC_EKS_MIN + 1);
- cp_beacon_uninit (&cp);
- cp_sta_mgr_uninit (&cp);
- cp_cco_region_uninit (&cp);
- cp_cco_bw_uninit (&cp);
+ test_beacon_uninit (&ctx);
}
test_end;
}
@@ -1300,38 +1152,17 @@ test_suite_beacon_mac_address_bentry (test_t test)
test_begin (test, "Beacon reception")
{
bsu_beacon_t *beacon;
- mac_config_t mac_config;
- cl_t cl;
- sar_t sar;
cp_net_t *net;
- uint phy = 0;
- bsu_aclf_t aclf;
cp_sta_own_data_t *own;
+ test_beacon_t ctx;
/** Init the context. */
- memset (&mac_config, 0, sizeof (mac_config_t));
- memset (&cl, 0, sizeof (cl_t));
- memset (&sar, 0, sizeof (sar_t));
-
- cp.mac_config = &mac_config;
- cp.cl = &cl;
- cp.sar = &sar;
- cp.phy = (phy_t *) &phy;
- cp.bsu_aclf = &aclf;
- cp.mac_store = mac_store_init ();
- cp.beacon.countdown_limit_date = BSU_ACLF_BP_60HZ_TCK;
- cp.bsu_aclf->beacon_period_tck = BSU_ACLF_BP_60HZ_TCK;
- cp.beacon.last_countdown_date = 0;
- cp_sta_mgr_init (&cp);
- cp_beacon_init (&cp);
- cp_cco_bw_init (&cp);
- cp_cco_region_init (&cp);
-
+ test_beacon_init (&ctx);
/** Configure station own data. */
- own = cp_sta_mgr_get_sta_own_data (&cp);
- net = cp_sta_mgr_add_avln (&cp, 0, 1);
- cp_sta_own_data_set_tei (&cp, 2);
- cp_sta_own_data_set_mac_address (&cp, 0x23456789abcull);
- cp_sta_mgr_set_our_avln (&cp, net);
+ own = cp_sta_mgr_get_sta_own_data (&ctx.cp);
+ net = cp_sta_mgr_add_avln (&ctx.cp, 0, 1);
+ cp_sta_own_data_set_tei (&ctx.cp, 2);
+ cp_sta_own_data_set_mac_address (&ctx.cp, 0x23456789abcull);
+ cp_sta_mgr_set_our_avln (&ctx.cp, net);
own->nid_track = 1;
own->tei_track = 1;
own->cco_mac_addr_track = MAC_ZERO;
@@ -1339,9 +1170,9 @@ test_suite_beacon_mac_address_bentry (test_t test)
beacon = test_new_beacon ();
beacon->bmis.mac_address.present = false;
/* launch the test. */
- cp_beacon_receive (&cp, beacon);
- cp_beacon_get_and_process_beacon (&cp);
- cp_sta_t *cco = cp_net_get_cco (&cp, net);
+ cp_beacon_receive (&ctx.cp, beacon);
+ cp_beacon_get_and_process_beacon (&ctx.cp);
+ cp_sta_t *cco = cp_net_get_cco (&ctx.cp, net);
test_fail_unless (cco);
test_fail_unless (cp_sta_get_mac_address (cco) == MAC_BROADCAST);
test_fail_unless (cp_sta_get_cco_status (cco) == true);
@@ -1351,9 +1182,9 @@ test_suite_beacon_mac_address_bentry (test_t test)
beacon = test_new_beacon ();
beacon->bmis.mac_address.present = true;
beacon->bmis.mac_address.mac_address = 0x12345678abcull;
- cp_beacon_receive (&cp, beacon);
- cp_beacon_get_and_process_beacon (&cp);
- cco = cp_net_get_cco (&cp, net);
+ cp_beacon_receive (&ctx.cp, beacon);
+ cp_beacon_get_and_process_beacon (&ctx.cp);
+ cco = cp_net_get_cco (&ctx.cp, net);
test_fail_unless (cco);
/* The beacon is not processed. */
test_fail_unless (cp_sta_get_mac_address (cco)
@@ -1364,9 +1195,9 @@ test_suite_beacon_mac_address_bentry (test_t test)
beacon = test_new_beacon ();
beacon->bmis.mac_address.present = true;
beacon->bmis.mac_address.mac_address = 0x0013d7000001ull;
- cp_beacon_receive (&cp, beacon);
- cp_beacon_get_and_process_beacon (&cp);
- cco = cp_net_get_cco (&cp, net);
+ cp_beacon_receive (&ctx.cp, beacon);
+ cp_beacon_get_and_process_beacon (&ctx.cp);
+ cco = cp_net_get_cco (&ctx.cp, net);
test_fail_unless (cco);
test_fail_unless (cp_sta_get_mac_address (cco)
!= beacon->bmis.mac_address.mac_address);
@@ -1378,9 +1209,9 @@ test_suite_beacon_mac_address_bentry (test_t test)
beacon = test_new_beacon ();
beacon->bmis.mac_address.present = true;
beacon->bmis.mac_address.mac_address = 0x0013d7000001ull;
- cp_beacon_receive (&cp, beacon);
- cp_beacon_get_and_process_beacon (&cp);
- cco = cp_net_get_cco (&cp, net);
+ cp_beacon_receive (&ctx.cp, beacon);
+ cp_beacon_get_and_process_beacon (&ctx.cp);
+ cco = cp_net_get_cco (&ctx.cp, net);
test_fail_unless (cco);
test_fail_unless (cp_sta_get_mac_address (cco)
== beacon->bmis.mac_address.mac_address);
@@ -1391,23 +1222,17 @@ test_suite_beacon_mac_address_bentry (test_t test)
beacon = test_new_beacon ();
beacon->bmis.mac_address.present = true;
beacon->bmis.mac_address.mac_address = 0x12345678abcull;
- cp_beacon_receive (&cp, beacon);
- cp_beacon_get_and_process_beacon (&cp);
- cco = cp_net_get_cco (&cp, net);
+ cp_beacon_receive (&ctx.cp, beacon);
+ cp_beacon_get_and_process_beacon (&ctx.cp);
+ cco = cp_net_get_cco (&ctx.cp, net);
test_fail_unless (cco);
test_fail_unless (cp_sta_get_mac_address (cco) == 0x0013d7000001ull);
test_fail_unless (cp_sta_get_cco_status (cco) == true);
slab_release (cco);
- cp_beacon_uninit (&cp);
- cp_sta_mgr_uninit (&cp);
- dbg_check (mac_store_sta_remove (cp.mac_store, 1));
- mac_store_uninit (cp.mac_store);
-
- cp_cco_region_uninit (&cp);
- cp_cco_bw_uninit (&cp);
+ dbg_check (mac_store_sta_remove (ctx.cp.mac_store, 1));
+ test_beacon_uninit (&ctx);
}
test_end;
-
}
void
@@ -1466,53 +1291,48 @@ test_suite_beacon_no_net (test_t t)
void
test_suite_beacon_spoc_update (test_t test)
{
- cp_t cp;
- mac_config_t mc;
- cp.mac_config = &mc;
- mac_config_init (cp.mac_config);
- cp_beacon_init (&cp);
- cp_sta_mgr_init (&cp);
- cp_cco_region_init (&cp);
- cp_cco_bw_init (&cp);
+ test_beacon_t ctx;
+ test_beacon_init (&ctx);
test_suite_begin (test, "SPOC update");
test_case_begin (test, "Frequency error invalid and valid");
test_begin (test, "SPOC only updated if F.E. is valid")
{
- cp_sta_own_data_t *own = cp_sta_mgr_get_sta_own_data (&cp);
- cp.beacon.spoc_update_interval_ms = 1;
+ cp_sta_own_data_t *own = cp_sta_mgr_get_sta_own_data (&ctx.cp);
+ ctx.cp.beacon.spoc_update_interval_ms = 1;
bsu_beacon_t *beacon = test_new_beacon ();
- cp_sta_mgr_add_avln (&cp, beacon->params.rx_parameters.snid,
+ cp_sta_mgr_add_avln (&ctx.cp, beacon->params.rx_parameters.snid,
beacon->vf.nid);
- cp.beacon.spoc_update_date = phy_date () - 1;
- cp_sta_own_data_set_nid (&cp, beacon->vf.nid);
+ ctx.cp.beacon.spoc_update_date = phy_date () - 1;
+ cp_sta_own_data_set_nid (&ctx.cp, beacon->vf.nid);
own->nid_track = beacon->vf.nid;
own->tei_track = beacon->vf.stei;
+ beacon->params.rx_parameters.snid =
+ cp_sta_own_data_get_snid (&ctx.cp);
/* Process a received beacon with a frequency error invalid. */
- cp_beacon_receive (&cp, beacon);
- cp_beacon_get_and_process_beacon (&cp);
- test_fail_unless (!cp.beacon.spoc_updated);
+ cp_beacon_receive (&ctx.cp, beacon);
+ cp_beacon_get_and_process_beacon (&ctx.cp);
+ test_fail_unless (!ctx.cp.beacon.spoc_updated);
/* This received beacon has a valid frequency error, SPOC should be
* updated. */
beacon = test_new_beacon ();
beacon->params.frequency_error_valid = true;
- cp.beacon.spoc_update_date = phy_date () - 1;
- cp_beacon_receive (&cp, beacon);
- cp_beacon_get_and_process_beacon (&cp);
- test_fail_unless (cp.beacon.spoc_updated);
+ beacon->params.rx_parameters.snid =
+ cp_sta_own_data_get_snid (&ctx.cp);
+ ctx.cp.beacon.spoc_update_date = phy_date () - 1;
+ cp_beacon_receive (&ctx.cp, beacon);
+ cp_beacon_get_and_process_beacon (&ctx.cp);
+ test_fail_unless (ctx.cp.beacon.spoc_updated);
/* This received beacon has a invalid frequency error. SPOC updated
* flag stay at true. */
beacon = test_new_beacon ();
beacon->params.frequency_error_valid = false;
- cp.beacon.spoc_update_date = phy_date () - 1;
- cp_beacon_receive (&cp, beacon);
- cp_beacon_get_and_process_beacon (&cp);
- test_fail_unless (cp.beacon.spoc_updated);
+ ctx.cp.beacon.spoc_update_date = phy_date () - 1;
+ cp_beacon_receive (&ctx.cp, beacon);
+ cp_beacon_get_and_process_beacon (&ctx.cp);
+ test_fail_unless (ctx.cp.beacon.spoc_updated);
}
test_end;
- cp_cco_region_uninit (&cp);
- cp_cco_bw_uninit (&cp);
- cp_sta_mgr_uninit (&cp);
- cp_beacon_uninit (&cp);
+ test_beacon_uninit (&ctx);
}
int
@@ -1521,7 +1341,6 @@ main (void)
test_t test;
test_init (test, 0, NULL);
- test_case_beacon_init (test);
test_case_beacon_uninit (test);
test_case_beacon__deactivate (test);
test_suite_beacon__beacon_generation (test);
diff --git a/cesar/cp/cco/action/test/src/action_gen_nek.c b/cesar/cp/cco/action/test/src/action_gen_nek.c
index 513d4f50a6..ea2f334c10 100644
--- a/cesar/cp/cco/action/test/src/action_gen_nek.c
+++ b/cesar/cp/cco/action/test/src/action_gen_nek.c
@@ -48,23 +48,21 @@ test_case_gen_nek (test_t test)
/* Initialise the seed of the random generator. */
cp_cco_action_init (&cp);
- lib_rnd_init (&cp.rnd, 0x12345678);
test_begin (test, "Verify first shot")
{
uint i;
- uint computed_keys [4] = {0xf48aa84f, 0xb3b084cb, 0xdf36c134,
- 0xaa4010d2};
+ cp_key_t computed_keys;
+ lib_rnd_init (&cp.rnd, 0x12345678);
+ cp_secu_generate_key(&cp, lib_rnd32 (&cp.rnd),
+ 5, &computed_keys);
+ lib_rnd_init (&cp.rnd, 0x12345678);
cp_cco_action_cco__cco_nek_change (&cp);
-
- for (i = 0; i < 4; i++)
- printf ("Keys : %x, computed : %x\n", cp.cco_action.nek_new.key[i],
- computed_keys[i]);
-
- test_fail_unless (cp.cco_action.nek_new.key[0] == computed_keys[0]);
- test_fail_unless (cp.cco_action.nek_new.key[1] == computed_keys[1]);
- test_fail_unless (cp.cco_action.nek_new.key[2] == computed_keys[2]);
- test_fail_unless (cp.cco_action.nek_new.key[3] == computed_keys[3]);
+ for (i = 0; i < COUNT (cp.cco_action.nek_new.key); i++)
+ {
+ test_fail_unless (cp.cco_action.nek_new.key[i]
+ == computed_keys.key[i]);
+ }
}
test_end;
}
diff --git a/cesar/cp/secu/test/sparc-Makefile b/cesar/cp/secu/test/sparc-Makefile
index e53439ca02..b9c0e85845 100644
--- a/cesar/cp/secu/test/sparc-Makefile
+++ b/cesar/cp/secu/test/sparc-Makefile
@@ -8,13 +8,13 @@ INCLUDES = cp/secu/test/override
TARGET_PROGRAMS = test-sha2 test-aes test-nmk
test-sha2_SOURCES = test-sha2.c
-test-sha2_MODULES = lib cp/secu cp/sta/core/stub
+test-sha2_MODULES = lib cp/secu cp/sta/core/stub hal/arch
test-aes_SOURCES = test-aes.c
-test-aes_MODULES = lib cp/secu cp/sta/core/stub
+test-aes_MODULES = lib cp/secu cp/sta/core/stub hal/arch
test-nmk_SOURCES = test-nmk.c
-test-nmk_MODULES = lib cp/secu cp/sta/core/stub
+test-nmk_MODULES = lib cp/secu cp/sta/core/stub hal/arch
VARIANT = sparc
include $(BASE)/common/make/top.mk
diff --git a/cesar/cp/src/cp.c b/cesar/cp/src/cp.c
index dd1cc868ee..3396c61d94 100644
--- a/cesar/cp/src/cp.c
+++ b/cesar/cp/src/cp.c
@@ -62,6 +62,9 @@ cp_init (bsu_t *bsu, bsu_aclf_t* aclf, mac_config_t * mac_config,
cp_global.bsu = bsu;
cp_global.bsu_aclf = aclf;
+ /* Init the random generator. */
+ lib_rnd_init (&cp_global.rnd, seed ^ 0x87543571);
+
/* Initialise traces. */
cp_trace_init (&cp_global);
@@ -98,9 +101,6 @@ cp_init (bsu_t *bsu, bsu_aclf_t* aclf, mac_config_t * mac_config,
/* Initialise the FSM. */
cp_fsm_init (&cp_global);
- /* Init the random generator. */
- lib_rnd_init (&cp_global.rnd, seed ^ 0x87543571);
-
/* Init CE in TX. */
ce_tx_init (&cp_global);
#if CONFIG_CP_EOC_SCHEDULER && CONFIG_CP_STA_MGR_EOC
diff --git a/cesar/cp/sta/action/src/vs.c b/cesar/cp/sta/action/src/vs.c
index 1daf2482af..29c5216e82 100644
--- a/cesar/cp/sta/action/src/vs.c
+++ b/cesar/cp/sta/action/src/vs.c
@@ -19,6 +19,7 @@
#include "cp/inc/context.h"
#include "mac/common/tonemap.h"
#include "cp/sta/action/misc.h"
+#include "ce/rx/bitloading/nsr.h"
/**
* Handle STARTED => VS_GET_TONEMAP.REQ.
@@ -229,8 +230,8 @@ cp_sta_action_vs__started__vs_get_snr_req (cp_t *ctx, cp_mme_rx_t *mme)
carrier_gr)
{
data_to_send.snr[grp_snr_index] =
- data[(all_snr_index - PHY_CARRIER_OFFSET) %
- (BLK_SIZE/4)];
+ (data[(all_snr_index - PHY_CARRIER_OFFSET) %
+ (BLK_SIZE/4)]) / CE_RX_BL_NSR_SOUND_RESCALE;
grp_snr_index++;
}
}
diff --git a/cesar/cp/sta/action/test/utest/src/vs.c b/cesar/cp/sta/action/test/utest/src/vs.c
index 279d0e8205..a1b2f4dc0f 100644
--- a/cesar/cp/sta/action/test/utest/src/vs.c
+++ b/cesar/cp/sta/action/test/utest/src/vs.c
@@ -13,6 +13,7 @@
#include "common/std.h"
#include "lib/scenario/scenario.h"
#include "inc/test_sta_action.h"
+#include "ce/rx/bitloading/nsr.h"
blk_t* nsr_block;
@@ -171,6 +172,7 @@ vs_get_snr_test_case (test_t t)
{
snr[i] = -(i * CP_MSG_VS_GET_SNR_REQ_CARRIER_GR_NB + group -
PHY_CARRIER_OFFSET);
+ snr[i] /= CE_RX_BL_NSR_SOUND_RESCALE;
}
else
snr[i] = 0;
diff --git a/cesar/cp/sta/mgr/test/src/sta_mgr.c b/cesar/cp/sta/mgr/test/src/sta_mgr.c
index 67adcd4e3a..73bbf7f97b 100644
--- a/cesar/cp/sta/mgr/test/src/sta_mgr.c
+++ b/cesar/cp/sta/mgr/test/src/sta_mgr.c
@@ -1315,7 +1315,7 @@ test_case__cp_sta_mgr_partial_ack (test_t test)
}
test_fail_unless (teis[0] == false);
for (i = 1; i < COUNT (teis); i++)
- test_fail_unless (teis[i] == true);
+ test_fail_unless (teis[i] == true);
slab_release (sta);
}
test_end;
diff --git a/cesar/cp/test/mme/Makefile b/cesar/cp/test/mme/Makefile
index 8876e7cfd3..798dd377e6 100644
--- a/cesar/cp/test/mme/Makefile
+++ b/cesar/cp/test/mme/Makefile
@@ -9,6 +9,6 @@ test_mme_SOURCES = test_mme.c
test_mme_MODULES = lib
test_mme_target_SOURCES = test_mme.c
-test_mme_target_MODULES = lib
+test_mme_target_MODULES = lib hal/arch
include $(BASE)/common/make/top.mk
diff --git a/cesar/hal/arch/Config b/cesar/hal/arch/Config
new file mode 100644
index 0000000000..5d46bd1570
--- /dev/null
+++ b/cesar/hal/arch/Config
@@ -0,0 +1 @@
+CONFIG_ARCH_ILRAM_PRIO = 5
diff --git a/cesar/hal/arch/arch.h b/cesar/hal/arch/arch.h
index 81aae83a8e..a1ad0d96fa 100644
--- a/cesar/hal/arch/arch.h
+++ b/cesar/hal/arch/arch.h
@@ -21,6 +21,16 @@
#define ARCH_ILRAM
/**
+ * Put in the instruction local ram section, with lower priority.
+ * \param prio function priority
+ *
+ * Should be put between function return type and function name. Function
+ * will be included in local ram only if priority is lower than or equal to
+ * configured limit.
+ */
+#define ARCH_ILRAM_PRIO(prio)
+
+/**
* Put in the data local ram section.
*/
#define ARCH_DLRAM_DATA
diff --git a/cesar/hal/arch/inc/sparc.h b/cesar/hal/arch/inc/sparc.h
index 03f8dcab86..beafd42c3b 100644
--- a/cesar/hal/arch/inc/sparc.h
+++ b/cesar/hal/arch/inc/sparc.h
@@ -17,9 +17,35 @@
#if defined (ECOS) && ECOS
+# include "config/arch/ilram.h"
+
# undef ARCH_ILRAM
# define ARCH_ILRAM __attribute__ ((section (".ilram")))
+# undef ARCH_ILRAM_PRIO
+# define ARCH_ILRAM_PRIO(prio) PASTE (ARCH_ILRAM_PRIO_, prio)
+
+# if CONFIG_ARCH_ILRAM_PRIO >= 3
+# define ARCH_ILRAM_PRIO_3 ARCH_ILRAM
+# else
+# define ARCH_ILRAM_PRIO_3
+# endif
+# if CONFIG_ARCH_ILRAM_PRIO >= 2
+# define ARCH_ILRAM_PRIO_2 ARCH_ILRAM
+# else
+# define ARCH_ILRAM_PRIO_2
+# endif
+# if CONFIG_ARCH_ILRAM_PRIO >= 1
+# define ARCH_ILRAM_PRIO_1 ARCH_ILRAM
+# else
+# define ARCH_ILRAM_PRIO_1
+# endif
+# if CONFIG_ARCH_ILRAM_PRIO >= 0
+# define ARCH_ILRAM_PRIO_0 ARCH_ILRAM
+# else
+# define ARCH_ILRAM_PRIO_0
+# endif
+
# undef ARCH_DLRAM_DATA
# define ARCH_DLRAM_DATA __attribute__ ((section (".dlram_data")))
diff --git a/cesar/hal/phy/Module b/cesar/hal/phy/Module
index a363c5f9d3..20e833f76f 100644
--- a/cesar/hal/phy/Module
+++ b/cesar/hal/phy/Module
@@ -99,4 +99,4 @@ $(hal_phy_params_h): $(call src2src,phy_params.pl,hal/phy/src) \
endif
$(call src2obj,hal/phy/src/resys.c,$(BUILD_TYPE)): $(hal_phy_resys_prog_h) \
-$(hal_phy_resys_offsettable_h)
+$(hal_phy_resys_prog_patch_h) $(hal_phy_resys_offsettable_h)
diff --git a/cesar/hal/phy/inc/context.h b/cesar/hal/phy/inc/context.h
index df64f4a6ea..0a21e76b77 100644
--- a/cesar/hal/phy/inc/context.h
+++ b/cesar/hal/phy/inc/context.h
@@ -70,10 +70,10 @@ struct phy_t
uint resys_gil_table[PHY_GIL_NB];
/** Start PBDMA on RESYS interrupt. */
bool pbdma_start_on_resys_it;
- /** CAP activation mask. */
- u8 cap_mask;
/** Whether frequency error is synchronised. */
bool freq_error_sync;
+ /** CAP activation mask. */
+ u8 cap_mask;
/** Phy stats. */
phy_stats_t stats;
};
diff --git a/cesar/hal/phy/maximus/src/maximus_phy_ctrl.c b/cesar/hal/phy/maximus/src/maximus_phy_ctrl.c
index 5aeec9e9d9..cafe769610 100644
--- a/cesar/hal/phy/maximus/src/maximus_phy_ctrl.c
+++ b/cesar/hal/phy/maximus/src/maximus_phy_ctrl.c
@@ -2315,6 +2315,14 @@ phy_clock_get_zero_cross_captured_sysdate (phy_t *ctx)
}
+void
+phy_freq_error_set (phy_t *ctx, bool sync, s32 rho_q30)
+{
+ dbg_assert_ptr (ctx);
+ /* Ignored. */
+}
+
+
/**
* set errno to:
* - EINVAL if ctx is null
diff --git a/cesar/hal/phy/maximus/test/src/test_phy_ctrl.c b/cesar/hal/phy/maximus/test/src/test_phy_ctrl.c
index 626ad6f86f..96b1382faf 100644
--- a/cesar/hal/phy/maximus/test/src/test_phy_ctrl.c
+++ b/cesar/hal/phy/maximus/test/src/test_phy_ctrl.c
@@ -2090,10 +2090,10 @@ void phy_tx_frame_test_case(test_t t)
} test_end;
// test the fourth callback
+ phy_pb_t pb[PHY_PB_MAX_NB];
+ u8 pb_data[PHY_PB_MAX_NB][MAC_PB520_BYTES];
test_begin(t, "maximus phy tx mpdu cb")
{
- phy_pb_t pb[PHY_PB_MAX_NB];
- u8 pb_data[PHY_PB_MAX_NB][MAC_PB520_BYTES];
int i = 0;
char c = 'a';
diff --git a/cesar/hal/phy/src/phy.c b/cesar/hal/phy/src/phy.c
index 804a06f774..254bb07664 100644
--- a/cesar/hal/phy/src/phy.c
+++ b/cesar/hal/phy/src/phy.c
@@ -463,6 +463,14 @@ phy_init_tunable_param (phy_t *ctx)
&phy_tunable.spoc_rho_initial_q30,
LIB_STATS_ACCESS_WRITE_ONLY,
LIB_STATS_DEBUG);
+ lib_stats_set_stat_value_notype ("DELTA_RES_COEF_INTERNAL",
+ &phy_tunable.delta_res_coef_internal,
+ LIB_STATS_ACCESS_WRITE_ONLY,
+ LIB_STATS_DEBUG);
+ lib_stats_set_stat_value_notype ("DELTA_RES_COEF_EXTERNAL",
+ &phy_tunable.delta_res_coef_external,
+ LIB_STATS_ACCESS_WRITE_ONLY,
+ LIB_STATS_DEBUG);
lib_stats_set_stat_value_notype ("CAP_MASK",
&ctx->cap_mask,
LIB_STATS_ACCESS_WRITE_ONLY,
diff --git a/cesar/hle/inc/context.h b/cesar/hle/inc/context.h
index 9c8fb18893..8681744177 100644
--- a/cesar/hle/inc/context.h
+++ b/cesar/hle/inc/context.h
@@ -15,6 +15,7 @@
*/
#include "lib/trace.h"
+#include "lib/seq_check.h"
#include "cl/cl.h"
@@ -51,6 +52,11 @@ struct hle_t
/** HLE Trace */
trace_buffer_t trace;
#endif /* !CONFIG_TRACE */
+#if CONFIG_SEQ_CHECK
+ /** Sequence check. */
+ lib_seq_check_t seq_in;
+ lib_seq_check_t seq_out;
+#endif
};
#endif /* hle_inc_context_h */
diff --git a/cesar/hle/inc/trace.h b/cesar/hle/inc/trace.h
index 29ba7ec8c1..185b9be4d9 100644
--- a/cesar/hle/inc/trace.h
+++ b/cesar/hle/inc/trace.h
@@ -34,7 +34,9 @@ enum
HLE_TRACE_MME_SEND,
HLE_TRACE_MME_RECV,
HLE_TRACE_IPMBOX,
- HLE_TRACE_DROPPED
+ HLE_TRACE_DROPPED,
+ HLE_TRACE_SEQ_CHECK_IN,
+ HLE_TRACE_SEQ_CHECK_OUT,
};
BEGIN_DECLS
diff --git a/cesar/hle/src/hle.c b/cesar/hle/src/hle.c
index 71e2eb48a8..60080f0acd 100644
--- a/cesar/hle/src/hle.c
+++ b/cesar/hle/src/hle.c
@@ -20,6 +20,7 @@
#include "hle/inc/context.h"
#include "hle/inc/trace.h"
#include "mac/common/ntb.h"
+#include "lib/seq_check.h"
#include "common/module.h"
@@ -27,6 +28,48 @@
static hle_t hle_global;
/**
+ * Callback when the lib sequencer detect a wrong sequencing, input from
+ * Linux.
+ * \param user user data
+ * \param vlan the VLAN id
+ * \param seq_expected the sequence number expected
+ * \param seq_actual the actual sequence number found in the packet
+ */
+void
+hle_lib_seq_check_cb_in (void *user, uint vlan, uint seq_expected,
+ uint seq_actual);
+
+/**
+ * Callback when the lib sequencer detect a wrong sequencing, output to
+ * Linux.
+ * \param user user data
+ * \param vlan the VLAN id
+ * \param seq_expected the sequence number expected
+ * \param seq_actual the actual sequence number found in the packet
+ */
+void
+hle_lib_seq_check_cb_out (void *user, uint vlan, uint seq_expected,
+ uint seq_actual);
+
+void
+hle_lib_seq_check_cb_in (void *user, uint vlan, uint seq_expected,
+ uint seq_actual)
+{
+ dbg_assert (user);
+ trace_do (hle_t *ctx = (hle_t *) user);
+ HLE_TRACE (SEQ_CHECK_IN, vlan, seq_expected, seq_actual);
+}
+
+void
+hle_lib_seq_check_cb_out (void *user, uint vlan, uint seq_expected,
+ uint seq_actual)
+{
+ dbg_assert (user);
+ trace_do (hle_t *ctx = (hle_t *) user);
+ HLE_TRACE (SEQ_CHECK_OUT, vlan, seq_expected, seq_actual);
+}
+
+/**
* Send a data to the Convergence Layer to be sent over the PWL.
* \param hle the hle context.
* \param buffer the buffer containing the data to send.
@@ -40,6 +83,10 @@ hle_data_send (hle_t *ctx, u8 *buffer, uint length, uint tag,
{
dbg_assert (buffer);
dbg_assert (length <= ETH_PACKET_MAX_SIZE);
+
+ /* Check sequence. */
+ lib_seq_check_packet (&ctx->seq_in, buffer, length);
+
if (length < ETH_PACKET_MIN_SIZE_ALLOWED)
{
hle_send_done (ctx, buffer);
@@ -69,6 +116,9 @@ hle_data_recv (hle_t *ctx, u8 *buffer, uint length)
/* Tracing data. */
HLE_TRACE (DATA_RECV, phy_date (), length, buffer);
+ /* Check sequence. */
+ lib_seq_check_packet (&ctx->seq_out, buffer, length);
+
word[0] = BF_FILL (IPMBOX_REG, (MSG_TYPE, HLE_MSG_TYPE_DATA),
(MSG_LENGTH, 1), (PARAM_MSG_TYPE, 0),
(PARAM_MSG_LENGTH, length));
@@ -250,6 +300,9 @@ hle_init (cl_t *cl)
#endif
/* Tracing */
HLE_TRACE (INIT, phy_date ());
+ /* Sequence check initialization. */
+ lib_seq_check_init (&ctx->seq_in, hle_lib_seq_check_cb_in, &hle_global);
+ lib_seq_check_init (&ctx->seq_out, hle_lib_seq_check_cb_out, &hle_global);
return &hle_global;
}
diff --git a/cesar/hle/src/trace.c b/cesar/hle/src/trace.c
index 0945e876b4..630d4500e2 100644
--- a/cesar/hle/src/trace.c
+++ b/cesar/hle/src/trace.c
@@ -38,6 +38,10 @@ hle_trace_init (hle_t *ctx)
TRACE_EVENT (HLE_TRACE_MME_RECV, "HLE_MME_RECV length : %d, buffer @ : %x", TIMESTAMP),
TRACE_EVENT (HLE_TRACE_IPMBOX, "HLE_IPMBOX_ACTIVATE avctive : %d", TIMESTAMP),
TRACE_EVENT (HLE_TRACE_DROPPED, "HLE_MSG DROPPED data: %d, length: %d, buffer: %x", TIMESTAMP),
+ TRACE_EVENT (HLE_TRACE_SEQ_CHECK_IN, "[SeqCheck] input from linux: "
+ "[%02d] expected=%04X, actual=%04X"),
+ TRACE_EVENT (HLE_TRACE_SEQ_CHECK_OUT, "[SeqCheck] output to linux: "
+ "[%02d] expected=%04X, actual=%04X"),
};
dbg_assert (ctx);
trace_namespace_init (&namespace, event_ids, COUNT (event_ids));
diff --git a/cesar/lib/Config b/cesar/lib/Config
index bf0afe4a15..cb6dd037a9 100644
--- a/cesar/lib/Config
+++ b/cesar/lib/Config
@@ -27,3 +27,5 @@ CONFIG_GPIO_FATAL_BLINK_DELAY = 10000000
CONFIG_SLAB_ALLOC_SCRAMBLE = n
CONFIG_RND_MT19937 = n
CONFIG_RND_TT800 = y
+CONFIG_SEQ_CHECK = n
+CONFIG_SEQ_CHECK_VLAN_MAX = 64
diff --git a/cesar/lib/Module b/cesar/lib/Module
index 0c9d1aa51b..e57586f636 100644
--- a/cesar/lib/Module
+++ b/cesar/lib/Module
@@ -1,7 +1,7 @@
SOURCES := crc.c dbg.c heap.c test.c blk.c slab.c list.c \
aatree.c try.c fixed.c blk_table.c \
swap.c read_word.c bitstream.c circular_buffer.c mbox.c \
- mac_lookup_table.c init.c rnd.c
+ mac_lookup_table.c init.c rnd.c utils.c
ifeq ($(CONFIG_HEAP_SKEW),y)
SOURCES += skewheap.c
endif
@@ -26,3 +26,6 @@ endif
ifeq ($(CONFIG_RND_TT800),y)
SOURCES += tt800.c
endif
+ifeq ($(CONFIG_SEQ_CHECK),y)
+SOURCES += seq_check.c
+endif
diff --git a/cesar/lib/seq_check.h b/cesar/lib/seq_check.h
new file mode 100644
index 0000000000..5e0916ce29
--- /dev/null
+++ b/cesar/lib/seq_check.h
@@ -0,0 +1,170 @@
+#ifndef lib_seq_check_h
+#define lib_seq_check_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2011 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/seq_check.h
+ * \brief Check sequence number in data packets
+ * \ingroup lib
+ *
+ * This lib is used to check sequence number in data packets generated by
+ * IPerf or Ixia. It supports VLAN if packets are tagged.
+ *
+ * De-sequence is stored in traces (no assert is done).
+ *
+ * You can configure:
+ * - position of the sequence number in the packet,
+ * - Ethernet type to inspect.
+ *
+ * This lib has some limitations:
+ * - you can not ignore some packets: for example during an IPerf traffic, if
+ * they are some pings, they will be inspected. If there is video traffic, it
+ * will be inspected too,
+ * - having different kind of throughput at the same time is not possible: an
+ * IPerf, an Ixia and video. You can only configure for one throughput,
+ * - you can not specify the first sequence number value,
+ * - you can not specify the size/length of the sequence number,
+ * - it can not support VLAN and non VLAN traffic at the same time (sequence
+ * position is the same for both).
+ *
+ * This lib should only be enabled when needed as it will probably impact
+ * performance (it needs to inspect packets).
+ */
+
+#include "config/seq/check.h"
+
+#if CONFIG_SEQ_CHECK
+
+/**
+ * Callback used when there is a de-sequencing in the packets.
+ * \param user an user pointer
+ * \param vlan the VLAN id which in the packet or 0 if there is none
+ * \param seq_expected the sequence number expected
+ * \param seq_actual the sequence actually in the packet
+ *
+ * This function is called by lib_seq_check_packet when there the sequence
+ * number is not the one expected.
+ */
+typedef void
+(*lib_seq_check_error_cb_t) (void *user, uint vlan, uint seq_expected,
+ uint seq_actual);
+
+/**
+ * Ethernet type IP.
+ */
+#define SEQ_CHECK_ET_IP 0x8000
+
+/**
+ * Sequence counters.
+ * This structure is used to store states of the sequence counter. There is
+ * one for each VLAN.
+ */
+typedef struct lib_seq_check_t
+{
+ /**
+ * Sequence counters, for each VLAN id.
+ * \note if no VLAN is present on frames, first index of the table is
+ * used. There should be no problem, as VLAN 0 is for management.
+ */
+ uint seq[CONFIG_SEQ_CHECK_VLAN_MAX];
+ /**
+ * Callback when sequence is wrong.
+ */
+ lib_seq_check_error_cb_t cb;
+ /**
+ * The user pointer used when calling the callback.
+ */
+ void *cb_user;
+} lib_seq_check_t;
+
+/**
+ * Configuration structure.
+ */
+typedef struct lib_seq_check_config_t
+{
+ /**
+ * Sequence number size.
+ * It only support 16 for the moment.
+ */
+ u8 seq_size;
+ /**
+ * Position of the sequence number in the packet.
+ * The position start at first bit of the Ethernet frame.
+ * This counter is expressed in byte.
+ */
+ uint seq_pos;
+ /**
+ * Ethernet type the packet has to have.
+ */
+ uint ethertype;
+} lib_seq_check_config_t;
+
+BEGIN_DECLS
+
+/**
+ * Configure lib sequencer check.
+ * \param config the new configuration structure to use.
+ *
+ * All fields are copied to the configuration. If you only want to setup one
+ * field, you need to use lib_seq_check_config_get before.
+ */
+void
+lib_seq_check_config_set (lib_seq_check_config_t *config);
+
+/**
+ * Get current configuration.
+ * \param config a configuration which will be set to the current one of the
+ * sequencer check of the lib.
+ */
+void
+lib_seq_check_config_get (lib_seq_check_config_t *config);
+
+/**
+ * Initialize lib sequencer check configuration.
+ * You need to do this only one time in the life of the station.
+ */
+void
+lib_seq_check_config_init (void);
+
+/**
+ * Initialize lib sequencer check.
+ * \param ctx the context to initialize
+ * \param cb the callback to use when there is an problem of sequence in the
+ * packet
+ * \param user an user pointer used when calling the callback
+ *
+ * This need to be done for each entry point to inspect.
+ */
+void
+lib_seq_check_init (lib_seq_check_t *ctx, lib_seq_check_error_cb_t cb,
+ void *user);
+
+/**
+ * Data packet to inspect.
+ * \param ctx the context of lib seq check
+ * \param buffer the packet buffer
+ * \param len the packet length (in byte)
+ * \return true if there is a de-sequencing in the packet and callback was
+ * called, false otherwise (this include packets which can not be inspected).
+ */
+bool
+lib_seq_check_packet (lib_seq_check_t *ctx, u8 *buffer, uint len);
+
+END_DECLS
+
+#else /* !CONFIG_SEQ_CHECK */
+
+# define lib_seq_check_config_get() ((void) 0)
+# define lib_seq_check_config_set() ((void) 0)
+# define lib_seq_check_config_init() ((void) 0)
+# define lib_seq_check_init(args...) ((void) 0)
+# define lib_seq_check_packet(args...) ((void) 0)
+
+#endif /* !CONFIG_SEQ_CHECK */
+
+#endif /* lib_seq_check_h */
diff --git a/cesar/lib/src/seq_check.c b/cesar/lib/src/seq_check.c
new file mode 100644
index 0000000000..5b7d0a1e01
--- /dev/null
+++ b/cesar/lib/src/seq_check.c
@@ -0,0 +1,154 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2011 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/src/seq_check.c
+ * \brief Check sequence number in data packets
+ * \ingroup lib
+ *
+ *
+ */
+#include "common/std.h"
+#include "lib/bitstream.h"
+#include "lib/swap.h"
+#include "lib/stats.h"
+
+#include "config/seq/check/vlan/max.h"
+
+#include "lib/seq_check.h"
+
+/**
+ * Ethernet type VLAN ID.
+ */
+#define SEQ_CHECK_ET_VLAN 0x8100
+
+lib_seq_check_config_t lib_seq_check_config;
+
+void
+lib_seq_check_config_set (lib_seq_check_config_t *config)
+{
+ dbg_assert (config);
+ /* Set configuration. */
+ lib_seq_check_config = *config;
+}
+
+void
+lib_seq_check_config_get (lib_seq_check_config_t *config)
+{
+ dbg_assert (config);
+ /* Get configuration. */
+ *config = lib_seq_check_config;
+}
+
+void
+lib_seq_check_config_init (void)
+{
+ /* Set default configuration. */
+ lib_seq_check_config_t config =
+ {
+ .seq_size = 16,
+ .seq_pos = 44, /* For IPerf. */
+ .ethertype = SEQ_CHECK_ET_IP, /* No check for Ethernet type. */
+ };
+ lib_seq_check_config_set (&config);
+
+ /* Register our configuration item. */
+ lib_stats_set_stat_value_notype ("SEQ_CHECK_SEQ_POS",
+ &lib_seq_check_config.seq_pos,
+ LIB_STATS_ACCESS_READ_WRITE,
+ LIB_STATS_DEBUG);
+ lib_stats_set_stat_value_notype ("SEQ_CHECK_ETHERTYPE",
+ &lib_seq_check_config.ethertype,
+ LIB_STATS_ACCESS_READ_WRITE,
+ LIB_STATS_DEBUG);
+}
+
+void
+lib_seq_check_init (lib_seq_check_t *ctx, lib_seq_check_error_cb_t cb,
+ void *user)
+{
+ /* Check parameters. */
+ dbg_assert (ctx);
+ dbg_assert (cb);
+
+ uint i;
+ /* Initialize sequence number to 0. */
+ for (i = 0; i < CONFIG_SEQ_CHECK_VLAN_MAX; i++)
+ {
+ ctx->seq[i] = 0;
+ }
+ ctx->cb = cb;
+ ctx->cb_user = user;
+}
+
+bool
+lib_seq_check_packet (lib_seq_check_t *ctx, u8 *buffer, uint len)
+{
+ /* Check parameter. */
+ dbg_assert (ctx);
+
+ bool result = false;
+
+ /* Get Ethernet type (after SRC & DST MAC (6 bytes each)). */
+ uint ethertype = swap16 (bitstream_direct_read (buffer, 6 * 8 * 2, 2 *
+ 8));
+
+ /* Position of sequence counter index in the table. */
+ uint seq_index = 0;
+
+ /* VLAN in used? */
+ if (ethertype == SEQ_CHECK_ET_VLAN)
+ {
+ /* VLAN id on 12 bits. VLAN id is located after SRC & DST (6 bytes
+ * each) & VLAN/IEEE_802.1Q fields (TPID + PCP + CFI = 20 bits). But
+ * we can only get on 2 bytes. We need to get TCI field (PCP, CFI &
+ * VID). */
+ seq_index = swap16 (bitstream_direct_read (buffer, (6 * 2 + 2) * 8,
+ 16));
+ /* Remove PCP & CFI. */
+ seq_index &= (0xFFFF >> 4);
+ dbg_assert (seq_index < CONFIG_SEQ_CHECK_VLAN_MAX);
+
+ /* Get real Ethernet type, located after SRC & DST (6 bytes each) and
+ * VLAN/IEEE_802.1Q fields (4 bytes). */
+ ethertype = swap16 (bitstream_direct_read (buffer, (6 + 6 + 4) * 8,
+ 2 * 8));
+ }
+
+ /* If this is the expected ethertype. */
+ if (lib_seq_check_config.ethertype
+ && ethertype == lib_seq_check_config.ethertype)
+ {
+
+ /* Get sequence value. */
+ dbg_assert (lib_seq_check_config.seq_size == 16);
+ uint received_seq = swap16 (
+ bitstream_direct_read (buffer, lib_seq_check_config.seq_pos * 8,
+ lib_seq_check_config.seq_size));
+
+ /* Handle overflow. */
+ ctx->seq[seq_index] &= BITS_ONES (lib_seq_check_config.seq_size);
+
+ /* Check. */
+ if (ctx->seq[seq_index] != received_seq)
+ {
+ /* Call callback. */
+ dbg_assert (ctx->cb);
+ (*ctx->cb) (ctx->cb_user, seq_index, ctx->seq[seq_index],
+ received_seq);
+ /* Reset. */
+ ctx->seq[seq_index] = received_seq;
+ result = true;
+ }
+
+ /* Increment. */
+ ctx->seq[seq_index]++;
+ }
+
+ /* Return result. */
+ return result;
+}
diff --git a/cesar/lib/src/utils.c b/cesar/lib/src/utils.c
new file mode 100644
index 0000000000..4ca7b39654
--- /dev/null
+++ b/cesar/lib/src/utils.c
@@ -0,0 +1,42 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2011 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/src/utils.c
+ * \brief Common utilities.
+ * \ingroup lib
+ */
+#include "common/std.h"
+
+/* See
+ * http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
+ */
+bool
+almost_eqf (float a, float b, int max_ulps)
+{
+ union
+ {
+ float f;
+ s32 i;
+ } aInt, bInt;
+ /* Make sure max_ulps is non-negative and small enough that the default
+ * NAN won't compare as equal to anything. */
+ dbg_assert (max_ulps > 0 && max_ulps < 4 * 1024 * 1024);
+ aInt.f = a;
+ /* Make aInt lexicographically ordered as a twos-complement int. */
+ if (aInt.i < 0)
+ aInt.i = 0x80000000 - aInt.i;
+ /* Make bInt lexicographically ordered as a twos-complement int. */
+ bInt.f = b;
+ if (bInt.i < 0)
+ bInt.i = 0x80000000 - bInt.i;
+ s32 intDiff = ABS (aInt.i - bInt.i);
+ if (intDiff <= max_ulps)
+ return true;
+ return false;
+}
+
diff --git a/cesar/lib/test/fixed/src/test_fixed.c b/cesar/lib/test/fixed/src/test_fixed.c
index 9b3ff3a8c8..15fe7ca3e0 100644
--- a/cesar/lib/test/fixed/src/test_fixed.c
+++ b/cesar/lib/test/fixed/src/test_fixed.c
@@ -36,30 +36,30 @@
void
asm_fixed_mul (void)
{
- volatile s32 a, b, r;
- volatile uint shift;
+ volatile s32 a = 0, b = 0, r;
+ volatile uint shift = 0;
r = fixed_mul (a, b, shift);
}
void
asm_fixed_mul_2 (void)
{
- volatile s32 a, b, r;
+ volatile s32 a = 0, b = 0, r;
r = fixed_mul (a, b, 24);
}
void
asm_fixed_div (void)
{
- volatile s32 a, b, r;
- volatile uint shift;
+ volatile s32 a = 0, b = 0, r;
+ volatile uint shift = 0;
r = fixed_div (a, b, shift);
}
void
asm_fixed_div_2 (void)
{
- volatile s32 a, b, r;
+ volatile s32 a = 0, b = 0, r;
r = fixed_div (a, b, 24);
}
diff --git a/cesar/lib/test/heap/src/test_heap.c b/cesar/lib/test/heap/src/test_heap.c
index 20e0d9ac14..b9be79feff 100644
--- a/cesar/lib/test/heap/src/test_heap.c
+++ b/cesar/lib/test/heap/src/test_heap.c
@@ -94,7 +94,9 @@ heap_check (test_t t, heap_t *heap)
static void
heap_stats (test_t t, heap_t *heap, uint *min, uint *max, unsigned long long *sum)
{
+#if CONFIG_HEAP_LEFTIST
test_within (t);
+#endif
heap_node_t *n;
uint path_length;
#if CONFIG_HEAP_LEFTIST
diff --git a/cesar/lib/test/mbox/src/mbox.c b/cesar/lib/test/mbox/src/mbox.c
index eea3155bd5..84fb090f1b 100644
--- a/cesar/lib/test/mbox/src/mbox.c
+++ b/cesar/lib/test/mbox/src/mbox.c
@@ -87,11 +87,11 @@ thread2_entry_function(cyg_addrword_t data)
mbox_nb = mbox_peek (&mbox);
mbox_uninit (&mbox);
- blk_print_memory ();
test_init (test, 0, NULL);
test_begin (test, "Mailbox")
{
+ test_fail_if (blk_check_memory() == false, "Memory not freed");
test_fail_unless (nb_msg == 10);
test_fail_unless (mbox_nb == 0);
}
diff --git a/cesar/lib/test/seq_check/Config b/cesar/lib/test/seq_check/Config
new file mode 100644
index 0000000000..aab2ba7dab
--- /dev/null
+++ b/cesar/lib/test/seq_check/Config
@@ -0,0 +1,2 @@
+CONFIG_SEQ_CHECK = y
+CONFIG_STATS = n
diff --git a/cesar/lib/test/seq_check/Makefile b/cesar/lib/test/seq_check/Makefile
new file mode 100644
index 0000000000..a74fa304d6
--- /dev/null
+++ b/cesar/lib/test/seq_check/Makefile
@@ -0,0 +1,8 @@
+BASE = ../../..
+
+HOST_PROGRAMS = test_seq_check
+
+test_seq_check_SOURCES = seq_check.c
+test_seq_check_MODULES = lib
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/lib/test/seq_check/src/seq_check.c b/cesar/lib/test/seq_check/src/seq_check.c
new file mode 100644
index 0000000000..574f98f017
--- /dev/null
+++ b/cesar/lib/test/seq_check/src/seq_check.c
@@ -0,0 +1,250 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2011 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/test/seq_check/src/seq_check.c
+ * \brief Sequence check test
+ * \ingroup test
+ *
+ * Test sequencer check.
+ */
+#include "common/std.h"
+
+#include "lib/test.h"
+#include "lib/seq_check.h"
+#include "common/defs/ethernet.h"
+#include "lib/rnd.h"
+#include "lib/bitstream.h"
+#include "lib/swap.h"
+
+/* Test structure to use with the callback. */
+typedef struct test_seq_check_callback_t
+{
+ struct test_t *test;
+ bool cb_called;
+ uint vlan;
+ uint seq_expected;
+ uint seq_actual;
+} test_seq_check_callback_t;
+
+void
+test_seq_check_write_ethertype (u8 *p, u16 ethertype, bool vlan)
+{
+ /* Store ethertype. */
+ uint pos = 6 * 2 * 8;
+ if (vlan)
+ {
+ bitstream_direct_write (p, pos, swap16 (0x8100), 16);
+ pos += 4 * 8;
+ }
+ bitstream_direct_write (p, pos, swap16 (ethertype), 16);
+}
+
+void
+test_seq_check_cb (void *user, uint vlan, uint seq_expected, uint seq_actual)
+{
+ dbg_assert (user);
+ test_seq_check_callback_t *test_seq_check_callback_values
+ = (test_seq_check_callback_t *) user;
+
+ test_within (test_seq_check_callback_values->test);
+ test_fail_if (test_seq_check_callback_values->vlan != vlan);
+ test_fail_if (test_seq_check_callback_values->seq_expected !=
+ seq_expected);
+ test_fail_if (test_seq_check_callback_values->seq_actual != seq_actual);
+ test_seq_check_callback_values->cb_called = true;
+}
+
+void
+test_seq_check_packet (test_t t, lib_rnd_t *rnd, uint pos, u16 ethertype)
+{
+ lib_seq_check_t s;
+ uint i;
+ u32 p[ETH_PACKET_MAX_SIZE];
+ bool res;
+ test_seq_check_callback_t test_seq_check_callback_values;
+ test_seq_check_callback_values.test = t;
+
+ /* Set configuration. */
+ lib_seq_check_config_t conf;
+ lib_seq_check_config_get (&conf);
+ conf.seq_pos = pos;
+ conf.ethertype = ethertype;
+ lib_seq_check_config_set (&conf);
+
+ test_begin (t, "config")
+ {
+ lib_seq_check_config_get (&conf);
+ test_fail_if (conf.seq_pos != pos);
+ test_fail_if (conf.ethertype != ethertype);
+ } test_end;
+
+ test_begin (t, "init")
+ {
+ lib_seq_check_init (&s, test_seq_check_cb,
+ &test_seq_check_callback_values);
+
+ for (i = 0; i < CONFIG_SEQ_CHECK_VLAN_MAX; i++)
+ {
+ test_fail_if (s.seq[i] != 0);
+ }
+ } test_end;
+
+ test_begin (t, "good sequence")
+ {
+ /* Store ethertype. */
+ test_seq_check_write_ethertype ((u8 *) p, ethertype, false);
+ for (i = 0; i < 1 << 16; i++)
+ {
+ bitstream_direct_write (p, pos * 8, swap16 (i), 16);
+ test_seq_check_callback_values.cb_called = false;
+ lib_seq_check_packet (&s, (u8 *) p, ETH_PACKET_MAX_SIZE);
+ test_fail_if (test_seq_check_callback_values.cb_called == true);
+ }
+ } test_end;
+
+ test_begin (t, "good and bad sequence")
+ {
+ u16 seq, prev;
+
+ /* Re-init. */
+ lib_seq_check_init (&s, test_seq_check_cb,
+ &test_seq_check_callback_values);
+ /* Store ethertype. */
+ test_seq_check_write_ethertype ((u8 *) p, ethertype, false);
+ for (seq = 0, i = 0; i < 1 << 16; i++, seq++)
+ {
+ if (lib_rnd_uniform (rnd, 2))
+ res = true;
+ else
+ {
+ prev = seq;
+ seq = lib_rnd_uniform (rnd, 1 << 16);
+ if (seq == prev)
+ seq++;
+ test_seq_check_callback_values.vlan = 0;
+ test_seq_check_callback_values.seq_expected = prev;
+ test_seq_check_callback_values.seq_actual = seq;
+ res = false;
+ }
+ test_seq_check_callback_values.cb_called = false;
+ bitstream_direct_write (p, pos * 8, swap16 (seq), 16);
+ lib_seq_check_packet (&s, (u8 *) p, ETH_PACKET_MAX_SIZE);
+ test_fail_if (test_seq_check_callback_values.cb_called == res);
+ }
+ } test_end;
+
+ test_begin (t, "good sequence with VLAN")
+ {
+ u16 seq[CONFIG_SEQ_CHECK_VLAN_MAX];
+
+ /* Re-init. */
+ lib_seq_check_init (&s, test_seq_check_cb,
+ &test_seq_check_callback_values);
+ /* Store ethertype. */
+ test_seq_check_write_ethertype ((u8 *) p, ethertype, true);
+
+ for (i = 0; i < CONFIG_SEQ_CHECK_VLAN_MAX; i ++)
+ {
+ seq[i] = 0;
+ }
+
+ for (i = 0; i < (1 << 16) * CONFIG_SEQ_CHECK_VLAN_MAX ; i++)
+ {
+ /* Get a random VLAN. */
+ uint vlan = lib_rnd_uniform (rnd, CONFIG_SEQ_CHECK_VLAN_MAX);
+ /* Write VLAN. */
+ bitstream_direct_write ((u8 *) p, 6 * 2 * 8 + 16, swap16 (vlan),
+ 16);
+
+ test_seq_check_callback_values.cb_called = false;
+ bitstream_direct_write (p, pos * 8, swap16 (seq[vlan]), 16);
+ lib_seq_check_packet (&s, (u8 *) p, ETH_PACKET_MAX_SIZE);
+ test_fail_if (test_seq_check_callback_values.cb_called == true);
+ seq[vlan]++;
+ }
+ } test_end;
+
+ test_begin (t, "good and bad sequence with VLAN")
+ {
+ u16 seq[CONFIG_SEQ_CHECK_VLAN_MAX], prev;
+
+ /* Re-init. */
+ lib_seq_check_init (&s, test_seq_check_cb,
+ &test_seq_check_callback_values);
+ /* Store ethertype. */
+ test_seq_check_write_ethertype ((u8 *) p, ethertype, true);
+
+ for (i = 0; i < CONFIG_SEQ_CHECK_VLAN_MAX; i ++)
+ {
+ seq[i] = 0;
+ }
+
+ for (i = 0; i < (1 << 16) * CONFIG_SEQ_CHECK_VLAN_MAX ; i++)
+ {
+ /* Get a random VLAN. */
+ uint vlan = lib_rnd_uniform (rnd, CONFIG_SEQ_CHECK_VLAN_MAX);
+ /* Write VLAN. */
+ bitstream_direct_write ((u8 *) p, 6 * 2 * 8 + 16, swap16 (vlan),
+ 16);
+
+ if (lib_rnd_uniform (rnd, 2))
+ res = true;
+ else
+ {
+ prev = seq[vlan];
+ seq[vlan] = lib_rnd_uniform (rnd, 1 << 16);
+ if (seq[vlan] == prev)
+ seq[vlan]++;
+ test_seq_check_callback_values.vlan = vlan;
+ test_seq_check_callback_values.seq_expected = prev;
+ test_seq_check_callback_values.seq_actual = seq[vlan];
+ res = false;
+ }
+ test_seq_check_callback_values.cb_called = false;
+ bitstream_direct_write (p, pos * 8, swap16 (seq[vlan]), 16);
+ lib_seq_check_packet (&s, (u8 *) p, ETH_PACKET_MAX_SIZE);
+ test_fail_if (test_seq_check_callback_values.cb_called == res);
+ seq[vlan]++;
+ }
+ } test_end;
+}
+
+int
+main (int argc, char **argv)
+{
+ lib_rnd_t rnd;
+ test_t test;
+
+ lib_rnd_init (&rnd, 0x42);
+ test_init (test, argc, argv);
+
+ test_suite_begin (test, "sequence check");
+
+ lib_seq_check_config_init ();
+
+ test_begin (test, "default config")
+ {
+ lib_seq_check_config_t conf;
+ lib_seq_check_config_get (&conf);
+ test_fail_if (conf.seq_size != 16);
+ test_fail_if (conf.seq_pos != 44);
+ test_fail_if (conf.ethertype != 0x8000);
+ } test_end;
+
+ test_case_begin (test, "IPerf");
+ /* Iperf position is at 44 and we check only IP packet. */
+ test_seq_check_packet (test, &rnd, 44, 0x8000);
+
+ test_case_begin (test, "Other");
+ /* Iperf position is at 44 and we check only IP packet. */
+ test_seq_check_packet (test, &rnd, 50, 0x8042);
+
+ test_result (test);
+ return test_nb_failed (test);
+}
+
diff --git a/cesar/lib/test/utils/src/test_utils.c b/cesar/lib/test/utils/src/test_utils.c
index 8b7beab993..751a518b65 100644
--- a/cesar/lib/test/utils/src/test_utils.c
+++ b/cesar/lib/test/utils/src/test_utils.c
@@ -13,6 +13,55 @@
#include "common/std.h"
#include "lib/test.h"
+#include "float.h"
+#include "math.h"
+
+void
+eq_test_case (test_t t)
+{
+ test_case_begin (t, "eq");
+ test_begin (t, "almost_eqf basic")
+ {
+ test_fail_unless (almost_eqf (1.0f, 1.0f, 1));
+ test_fail_unless (!almost_eqf (1.0f, 2.0f, 1));
+ test_fail_unless (!almost_eqf (1000.0f, 2000.0f, 1));
+ /* FLT_EPSILON is the smallest number for which:
+ * 1.0f != 1.0f + FLT_EPSILON. */
+ test_fail_unless (almost_eqf (1.0f, 1.0f + FLT_EPSILON, 1));
+ test_fail_unless (!almost_eqf (1.0f, 1.0f + FLT_EPSILON * 2, 1));
+ test_fail_unless (almost_eqf (1.0f, 1.0f + FLT_EPSILON * 2, 2));
+ test_fail_unless (almost_eqf (512.f, 512.f + 512 * FLT_EPSILON, 1));
+ test_fail_unless (!almost_eqf (512.f, 512.f + 1024 * FLT_EPSILON, 1));
+ test_fail_unless (almost_eqf (512.f, 512.f + 1024 * FLT_EPSILON, 2));
+ } test_end;
+ test_begin (t, "almost_eqf zeroes")
+ {
+ /* IEEE floats are ordered. Compute the smallest non-zero positive and
+ * negative number. Those are subnormals. */
+ float ep = 0.0f;
+ s32 epb = *(s32 *)&ep + 1;
+ ep = *(float *) &epb;
+ float em = -0.0f;
+ s32 emb = *(s32 *)&em + 1;
+ em = *(float *) &emb;
+ /* Test around zero. */
+ test_fail_unless (almost_eqf (0.0f, -0.0f, 1));
+ test_fail_unless (almost_eqf (ep, em, 2));
+ test_fail_unless (!almost_eqf (ep, em, 1));
+ } test_end;
+ test_begin (t, "almost_eqf infinity")
+ {
+ /* Accepted complication. */
+ test_fail_unless (almost_eqf (INFINITY, FLT_MAX, 1));
+ test_fail_unless (almost_eqf (-INFINITY, -FLT_MAX, 1));
+ } test_end;
+ test_begin (t, "almost_eqf NaN")
+ {
+ test_fail_unless (!almost_eqf (NAN, 1.0f, 1));
+ /* Accepted complication. */
+ test_fail_unless (almost_eqf (NAN, NAN, 1));
+ } test_end;
+}
void
bits_test_case (test_t t)
@@ -229,6 +278,7 @@ void
utils_test_suite (test_t t)
{
test_suite_begin (t, "utils");
+ eq_test_case (t);
bits_test_case (t);
bf_test_case (t);
rot_test_case (t);
diff --git a/cesar/lib/utils.h b/cesar/lib/utils.h
index 5d0c237c37..c3229f27ce 100644
--- a/cesar/lib/utils.h
+++ b/cesar/lib/utils.h
@@ -341,4 +341,16 @@ distance_mod2p16 (u16 a, u16 b)
index = a_; \
} while (0)
+BEGIN_DECLS
+
+/** Compare floating point numbers, return true if they are almost equal.
+ * \param a first number to compare
+ * \param b second number to compare
+ * \param max_ulps maximum error as unit in the last place
+ */
+bool
+almost_eqf (float a, float b, int max_ulps);
+
+END_DECLS
+
#endif /* lib_utils_h */
diff --git a/cesar/mac/design/test/mfs_tx2/src/test_mfs.c b/cesar/mac/design/test/mfs_tx2/src/test_mfs.c
index 7336db2b9b..6031799420 100644
--- a/cesar/mac/design/test/mfs_tx2/src/test_mfs.c
+++ b/cesar/mac/design/test/mfs_tx2/src/test_mfs.c
@@ -72,7 +72,7 @@ void random_test()
test.when_to_free=lib_rnd_uniform(&rnd,0x2000);
}
-mfs_t
+void
init_mfs ()
{
mfs.head = NULL;
@@ -87,7 +87,6 @@ init_mfs ()
total_pb_released=0;
pbproc.head_tx=NULL;
pbproc.tail_tx=NULL;
- return (mfs);
}
@@ -546,7 +545,7 @@ tst(void)
{
int n=0;
int zadded=0;
- mfs=init_mfs();
+ init_mfs();
printf("take:%x free: %x\n", test.when_to_take,test.when_to_free);
for(n=0; n<10; n++)
{
@@ -569,7 +568,7 @@ int
main (void)
{
lib_rnd_init (&rnd, 456);
- mfs_t mfs = init_mfs();
+ init_mfs();
test.when_to_take=0;
test.when_to_free=0;
int t=0;
diff --git a/cesar/mac/pbproc/src/fsm_rx_sound.c b/cesar/mac/pbproc/src/fsm_rx_sound.c
index d784bbf0b5..abd7e3bce9 100644
--- a/cesar/mac/pbproc/src/fsm_rx_sound.c
+++ b/cesar/mac/pbproc/src/fsm_rx_sound.c
@@ -33,7 +33,7 @@ pbproc_frso_init (pbproc_t *ctx)
pbproc_frso__rx_sound__pbdma;
}
-void ARCH_ILRAM
+void ARCH_ILRAM_PRIO (2)
pbproc_frso__handle (pbproc_t *ctx, u32 rx_date,
const pbproc_fc_sound_t *sound)
{
@@ -198,7 +198,7 @@ pbproc_frso__handle (pbproc_t *ctx, u32 rx_date,
pbproc_frso__rx_sound__pbdma (ctx);
}
-void ARCH_ILRAM
+void ARCH_ILRAM_PRIO (2)
pbproc_frso__rx_sound__pbdma (pbproc_t *ctx)
{
dbg_claim (ctx);
@@ -292,7 +292,7 @@ pbproc_frso__rx_sound__pbdma (pbproc_t *ctx)
#if CONFIG_MAC_PBPROC_EOC_FC
static void
#else
-static void ARCH_ILRAM
+static void ARCH_ILRAM_PRIO (2)
#endif
pbproc_frso_vcs_restart (pbproc_t *ctx)
{
diff --git a/cesar/mac/pbproc/src/fsm_tx_sound.c b/cesar/mac/pbproc/src/fsm_tx_sound.c
index bca07ad9ef..98b05b6679 100644
--- a/cesar/mac/pbproc/src/fsm_tx_sound.c
+++ b/cesar/mac/pbproc/src/fsm_tx_sound.c
@@ -32,7 +32,7 @@ pbproc_ftso_init (pbproc_t *ctx)
pbproc_ftso__tx_sound_wait_ack__access;
}
-void ARCH_ILRAM
+void ARCH_ILRAM_PRIO (2)
pbproc_ftso__handle (pbproc_t *ctx)
{
dbg_claim (ctx);
@@ -50,7 +50,7 @@ pbproc_ftso__handle (pbproc_t *ctx)
ctx->stats.tx_sound++;
}
-void ARCH_ILRAM
+void ARCH_ILRAM_PRIO (2)
pbproc_ftso__tx_sound_wait_ack__rx_fc (pbproc_t *ctx, u32 rx_date,
const pbproc_fc_t *fc_av)
{
@@ -112,7 +112,7 @@ pbproc_ftso__tx_sound_wait_ack__rx_fc (pbproc_t *ctx, u32 rx_date,
#if CONFIG_MAC_PBPROC_EOC_FC
void
#else
-void ARCH_ILRAM
+void ARCH_ILRAM_PRIO (2)
#endif
pbproc_ftso__tx_sound_wait_ack__access (pbproc_t *ctx)
{
diff --git a/cesar/mac/pbproc/src/prep_mpdu.c b/cesar/mac/pbproc/src/prep_mpdu.c
index 0e34d6a0e2..52a149b38b 100644
--- a/cesar/mac/pbproc/src/prep_mpdu.c
+++ b/cesar/mac/pbproc/src/prep_mpdu.c
@@ -113,7 +113,7 @@ pbproc_get_segments_nb (mfs_tx_t *mfs)
#if (CONFIG_MAC_PBPROC_EOC_FC)
void /*ARCH_ILRAM: TODO ugly */
#else
-void ARCH_ILRAM
+void ARCH_ILRAM_PRIO (1)
#endif
pbproc_prep_beacon (pbproc_t *ctx, mfs_tx_t *mfs)
{
diff --git a/cesar/mac/pbproc/test/int/sparc-Config b/cesar/mac/pbproc/test/int/sparc-Config
index 556d1a6160..34df90d773 100644
--- a/cesar/mac/pbproc/test/int/sparc-Config
+++ b/cesar/mac/pbproc/test/int/sparc-Config
@@ -5,3 +5,4 @@ CONFIG_INTERFACE_SNIFFER = n
CONFIG_MAC_COMMON_EOC_SCHED = y
CONFIG_MAC_PBPROC_EOC_FC = y
CONFIG_MAC_COMMON_EOC_MFS = y
+CONFIG_ARCH_ILRAM_PRIO = 0
diff --git a/cesar/mac/sar/inc/sar_context.h b/cesar/mac/sar/inc/sar_context.h
index e47f2912a1..dc5aaacb42 100644
--- a/cesar/mac/sar/inc/sar_context.h
+++ b/cesar/mac/sar/inc/sar_context.h
@@ -17,6 +17,7 @@
#include "mac/pbproc/pbproc.h"
#include "lib/slist.h"
#include "lib/rnd.h"
+#include "lib/seq_check.h"
#include "hal/phy/bridgedma.h"
#ifdef STATION_H_
@@ -201,6 +202,9 @@ struct sar_t
#if CONFIG_STATS
sar_stats_t stats;
#endif
+#if CONFIG_SEQ_CHECK
+ lib_seq_check_t seq;
+#endif
};
#endif /*SAR_CONTEXT_H_*/
diff --git a/cesar/mac/sar/inc/trace.h b/cesar/mac/sar/inc/trace.h
index 93ce021c61..ebd8af078c 100644
--- a/cesar/mac/sar/inc/trace.h
+++ b/cesar/mac/sar/inc/trace.h
@@ -43,6 +43,7 @@ enum
SAR_TRACE_PB_TX_RELEASE,
SAR_TRACE_PB_RX_RELEASE,
SAR_TRACE_EXHAUSTED_MEMORY,
+ SAR_TRACE_SEQ_CHECK,
};
BEGIN_DECLS
diff --git a/cesar/mac/sar/src/sar.c b/cesar/mac/sar/src/sar.c
index 5fd30818b6..ae405375f4 100644
--- a/cesar/mac/sar/src/sar.c
+++ b/cesar/mac/sar/src/sar.c
@@ -24,6 +24,7 @@
#include "mac/sar/inc/sar_context.h"
#include "mac/sar/inc/sar.h"
#include "mac/sar/inc/sar_expiration.h"
+#include "lib/seq_check.h"
#include "hal/arch/arch.h"
#include "common/defs/priority.h"
@@ -53,6 +54,26 @@
static struct sar_t sar_global;
/**
+ * Callback when the lib sequencer detect a wrong sequencing.
+ * \param user user data
+ * \param vlan the VLAN id
+ * \param seq_expected the sequence number expected
+ * \param seq_actual the actual sequence number found in the packet
+ */
+void
+sar_lib_seq_check_cb (void *user, uint vlan, uint seq_expected,
+ uint seq_actual);
+
+void
+sar_lib_seq_check_cb (void *user, uint vlan, uint seq_expected,
+ uint seq_actual)
+{
+ dbg_assert (user);
+ trace_do (sar_t *ctx = (sar_t *) user);
+ SAR_TRACE (SEQ_CHECK, vlan, seq_expected, seq_actual);
+}
+
+/**
* Compute the gap between two SSNs.
* \param a the first SSN,
* \param b the Second SSN.
@@ -500,6 +521,8 @@ sar_init (mac_store_t *mac_store, pbproc_t *pbproc, ca_t *ca, u32 seed)
/** Trace system. */
ctx = &sar_global;
sar_trace_init(ctx);
+ /* Initialize sequence checker. */
+ lib_seq_check_init (&ctx->seq, sar_lib_seq_check_cb, &sar_global);
#if CONFIG_STATS
sar_stats_init (&ctx->stats);
#endif
@@ -827,6 +850,9 @@ sar_msdu_add (sar_t *ctx, u8 *buffer, u16 length, mfs_tx_t *mfs,
mfs->stats.num_msdus ++;
mfs->stats.octets += length;
+ /* Check sequence. */
+ lib_seq_check_packet (&ctx->seq, buffer, length);
+
/* Enough block available to send a frame and SAR is activated ? */
if ((blk_slack () || mfs->common.mme) && ctx->activate)
{
@@ -1838,7 +1864,7 @@ sar_tx_mac_framing (sar_t *ctx, sar_msdu_t *md_data)
&ctx->job_tx->job);
}
-pb_t * ARCH_ILRAM
+pb_t * ARCH_ILRAM_PRIO (1)
sar_tx_job_desc_create (sar_t *ctx, sar_msdu_t *md_data, mfs_tx_t * mfs,
sar_job_mfs_t *job_mfs)
{
diff --git a/cesar/mac/sar/src/trace.c b/cesar/mac/sar/src/trace.c
index cf4a0dcab3..a951e34075 100644
--- a/cesar/mac/sar/src/trace.c
+++ b/cesar/mac/sar/src/trace.c
@@ -51,6 +51,8 @@ sar_trace_init (sar_t *ctx)
"PB expire ssn %d in mfs : %x"),
TRACE_EVENT (SAR_TRACE_EXHAUSTED_MEMORY,
"exhausted memory, Frame drop from SSN %d to %d"),
+ TRACE_EVENT (SAR_TRACE_SEQ_CHECK, "[SeqCheck] output to PLC: "
+ "[%02d] expected=%04X, actual=%04X"),
};
dbg_assert (ctx);
trace_namespace_init (&namespace, event_ids, COUNT (event_ids));
diff --git a/cesar/maximus/channel/src/ChannelComputerTest.cpp b/cesar/maximus/channel/src/ChannelComputerTest.cpp
index 31e980c5f8..fead652382 100644
--- a/cesar/maximus/channel/src/ChannelComputerTest.cpp
+++ b/cesar/maximus/channel/src/ChannelComputerTest.cpp
@@ -145,69 +145,69 @@ void ChannelComputerTest::protectedTest (void)
// Test PowerScale
Channel_Mod modulation = MAXIMUS_CHANNEL_MOD_BPSK;
float powerScale = channelComputer.getPowerScaleTest(modulation);
- CPPUNIT_ASSERT_MESSAGE ( "getPowerScale failed", 1 == powerScale);
+ CPPUNIT_ASSERT_MESSAGE ( "getPowerScale failed", almost_eqf (1, powerScale, 5));
modulation = MAXIMUS_CHANNEL_MOD_QPSK;
powerScale = channelComputer.getPowerScaleTest(modulation);
- CPPUNIT_ASSERT_MESSAGE ( "getPowerScale failed", 2 == powerScale);
+ CPPUNIT_ASSERT_MESSAGE ( "getPowerScale failed", almost_eqf (2, powerScale, 5));
modulation = MAXIMUS_CHANNEL_MOD_QAM8;
powerScale = channelComputer.getPowerScaleTest(modulation);
- CPPUNIT_ASSERT_MESSAGE ( "getPowerScale failed", (float)(5+pow(1.29,2)) == powerScale);
+ CPPUNIT_ASSERT_MESSAGE ( "getPowerScale failed", almost_eqf (5 + pow (1.29, 2), powerScale, 5));
modulation = MAXIMUS_CHANNEL_MOD_QAM16;
powerScale = channelComputer.getPowerScaleTest(modulation);
- CPPUNIT_ASSERT_MESSAGE ( "getPowerScale failed", 10 == powerScale);
+ CPPUNIT_ASSERT_MESSAGE ( "getPowerScale failed", almost_eqf (10, powerScale, 5));
modulation = MAXIMUS_CHANNEL_MOD_QAM64;
powerScale = channelComputer.getPowerScaleTest(modulation);
- CPPUNIT_ASSERT_MESSAGE ( "getPowerScale failed", 42 == powerScale);
+ CPPUNIT_ASSERT_MESSAGE ( "getPowerScale failed", almost_eqf (42, powerScale, 5));
modulation = MAXIMUS_CHANNEL_MOD_QAM256;
powerScale = channelComputer.getPowerScaleTest(modulation);
- CPPUNIT_ASSERT_MESSAGE ( "getPowerScale failed", 170 == powerScale);
+ CPPUNIT_ASSERT_MESSAGE ( "getPowerScale failed", almost_eqf (170, powerScale, 5));
modulation = MAXIMUS_CHANNEL_MOD_QAM1024;
powerScale = channelComputer.getPowerScaleTest(modulation);
- CPPUNIT_ASSERT_MESSAGE ( "getPowerScale failed", 682 == powerScale);
+ CPPUNIT_ASSERT_MESSAGE ( "getPowerScale failed", almost_eqf (682, powerScale, 5));
// Test linear SNR
float snr = 10; // in dB
double linearSnr = channelComputer.getLinearSnrTest(snr);
- CPPUNIT_ASSERT_MESSAGE ( "getLinearSnr failed", 10 == linearSnr);
+ CPPUNIT_ASSERT_MESSAGE ( "getLinearSnr failed", almost_eqf (10, linearSnr, 5));
snr = 16; // in dB
linearSnr = channelComputer.getLinearSnrTest(snr);
- CPPUNIT_ASSERT_MESSAGE ( "getLinearSnr failed", (float)pow(10, 1.6) == linearSnr);
+ CPPUNIT_ASSERT_MESSAGE ( "getLinearSnr failed", almost_eqf (pow (10, 1.6), linearSnr, 5));
snr = 15.55555; // in dB
linearSnr = channelComputer.getLinearSnrTest(snr);
- CPPUNIT_ASSERT_MESSAGE ( "getLinearSnr failed", (float)pow(10, 1.555555) == linearSnr);
+ CPPUNIT_ASSERT_MESSAGE ( "getLinearSnr failed", almost_eqf (pow (10, 1.555555), linearSnr, 5));
// Test sigma factor
modulation = MAXIMUS_CHANNEL_MOD_BPSK;
snr = 10; // in dB
double sigma = channelComputer.getSigmaTest(modulation, snr);
- CPPUNIT_ASSERT_MESSAGE ( "getSigma failed", (double)sqrt(1/(2*channelComputer.getLinearSnrTest(snr))) == sigma);
+ CPPUNIT_ASSERT_MESSAGE ( "getSigma failed", almost_eqf (sqrt(1/(2*channelComputer.getLinearSnrTest(snr))), sigma, 5));
modulation = MAXIMUS_CHANNEL_MOD_QPSK;
snr = 11.1; // in dB
sigma = channelComputer.getSigmaTest(modulation, snr);
- CPPUNIT_ASSERT_MESSAGE ( "getSigma failed", (double)sqrt(2/(2*channelComputer.getLinearSnrTest(snr))) == sigma);
+ CPPUNIT_ASSERT_MESSAGE ( "getSigma failed", almost_eqf (sqrt(2/(2*channelComputer.getLinearSnrTest(snr))), sigma, 5));
modulation = MAXIMUS_CHANNEL_MOD_QAM8;
snr = 12.2; // in dB
sigma = channelComputer.getSigmaTest(modulation, snr);
- CPPUNIT_ASSERT_MESSAGE ( "getSigma failed", (double)sqrt((float)(5+pow(1.29, 2))/(2*channelComputer.getLinearSnrTest(snr))) == sigma);
+ CPPUNIT_ASSERT_MESSAGE ( "getSigma failed", almost_eqf (sqrt((5+pow(1.29, 2))/(2*channelComputer.getLinearSnrTest(snr))), sigma, 5));
modulation = MAXIMUS_CHANNEL_MOD_QAM16;
snr = 13.3; // in dB
sigma = channelComputer.getSigmaTest(modulation, snr);
- CPPUNIT_ASSERT_MESSAGE ( "getSigma failed", (double)sqrt(10/(2*channelComputer.getLinearSnrTest(snr))) == sigma);
+ CPPUNIT_ASSERT_MESSAGE ( "getSigma failed", almost_eqf (sqrt(10/(2*channelComputer.getLinearSnrTest(snr))), sigma, 5));
modulation = MAXIMUS_CHANNEL_MOD_QAM64;
snr = 14.4; // in dB
sigma = channelComputer.getSigmaTest(modulation, snr);
- CPPUNIT_ASSERT_MESSAGE ( "getSigma failed", (double)sqrt(42/(2*channelComputer.getLinearSnrTest(snr))) == sigma);
+ CPPUNIT_ASSERT_MESSAGE ( "getSigma failed", almost_eqf (sqrt(42/(2*channelComputer.getLinearSnrTest(snr))), sigma, 5));
modulation = MAXIMUS_CHANNEL_MOD_QAM256;
snr = 15.5; // in dB
sigma = channelComputer.getSigmaTest(modulation, snr);
- CPPUNIT_ASSERT_MESSAGE ( "getSigma failed", (double)sqrt(170/(2*channelComputer.getLinearSnrTest(snr))) == sigma);
+ CPPUNIT_ASSERT_MESSAGE ( "getSigma failed", almost_eqf (sqrt(170/(2*channelComputer.getLinearSnrTest(snr))), sigma, 5));
modulation = MAXIMUS_CHANNEL_MOD_QAM1024;
snr = 16.6; // in dB
sigma = channelComputer.getSigmaTest(modulation, snr);
- CPPUNIT_ASSERT_MESSAGE ( "getSigma failed", (double)sqrt(682/(2*channelComputer.getLinearSnrTest(snr))) == sigma);
+ CPPUNIT_ASSERT_MESSAGE ( "getSigma failed", almost_eqf (sqrt(682/(2*channelComputer.getLinearSnrTest(snr))), sigma, 5));
snr = 0; // in dB
sigma = channelComputer.getSigmaTest(modulation, snr);
- CPPUNIT_ASSERT_MESSAGE ( "getSigma failed", (double)sqrt(682/(2*channelComputer.getLinearSnrTest(snr))) == sigma);
+ CPPUNIT_ASSERT_MESSAGE ( "getSigma failed", almost_eqf (sqrt(682/(2*channelComputer.getLinearSnrTest(snr))), sigma, 5));
// Test noise point
ChannelPoint point(1, 0);
@@ -268,7 +268,7 @@ void ChannelComputerTest::protectedTest (void)
modulation = MAXIMUS_CHANNEL_MOD_BPSK;
float fer = channelComputer.computeFerTest(ber, n, modulation);
float expectedFer = pow(10, 1-(unsigned short int)100*exp(-pow((unsigned short int)50*ber, 2)))/10;
- CPPUNIT_ASSERT_MESSAGE ( "computeFer 1 failed", expectedFer == fer);
+ CPPUNIT_ASSERT_MESSAGE ( "computeFer 1 failed", almost_eqf (expectedFer, fer, 5));
modulation = MAXIMUS_CHANNEL_MOD_QPSK;
fer = channelComputer.computeFerTest(ber, n, modulation);
expectedFer = pow(10, 1-(unsigned short int)100*exp(-pow((unsigned short int)50*(ber-0.01*(float)4.6), 2)))/10;
diff --git a/cesar/maximus/coreengine/src/Maximus.cpp b/cesar/maximus/coreengine/src/Maximus.cpp
index 2dc2068d1b..8a885d6c69 100644
--- a/cesar/maximus/coreengine/src/Maximus.cpp
+++ b/cesar/maximus/coreengine/src/Maximus.cpp
@@ -1317,6 +1317,7 @@ void Maximus::stop ( )
if (0 <= mEtherLogFileDescriptor)
{
close(mEtherLogFileDescriptor);
+ mEtherLogFileDescriptor = -1;
}
// Warning: delete the Core Engine is the last task to do!
diff --git a/cesar/maximus/ethernet/src/EthernetProcessor.cpp b/cesar/maximus/ethernet/src/EthernetProcessor.cpp
index b318fc89f3..1d7c7267ef 100644
--- a/cesar/maximus/ethernet/src/EthernetProcessor.cpp
+++ b/cesar/maximus/ethernet/src/EthernetProcessor.cpp
@@ -202,6 +202,12 @@ File_Descriptor EthernetProcessor::allocTap ( char * dev ) const
}
else
{
+ /* Set persistent status */
+ if (0 > ioctl(etherLogFileDescriptor, TUNSETPERSIST, 1))
+ {
+ throw Error(__PRETTY_FUNCTION__, "enabling TUNSETPERSIST failed", errno);
+ }
+
/* We don't need checksums calculated for packets coming in this device */
ioctl(etherLogFileDescriptor, TUNSETNOCSUM, 1);
diff --git a/cesar/maximus/prototest/fcall/src/test_fcall.c b/cesar/maximus/prototest/fcall/src/test_fcall.c
index a09b7b66a7..878170d44d 100644
--- a/cesar/maximus/prototest/fcall/src/test_fcall.c
+++ b/cesar/maximus/prototest/fcall/src/test_fcall.c
@@ -14,7 +14,7 @@
*/
#include <cyg/infra/diag.h>
#include <cyg/kernel/kapi.h>
-#include <malloc.h>
+#include <stdlib.h>
#include <errno.h>
#include "common/std.h"
#include "interface/fcall/interface_fcall.h"
@@ -22,6 +22,7 @@
#include "lib/swap.h" // for 'swap16()' and 'swap32()'
#include "lib/read_word.h" // for 'read_u16_from_word()'
#include "maximus/prototest/fcall/inc/syscall.h"
+#include "common/defs/ethernet.h"
#define MY_THREAD_STACK_SIZE (8192 / sizeof(int))
@@ -47,10 +48,14 @@ void my_thread(cyg_addrword_t index)
memset(my_mme, '\0', SCI_MSG_MAX_SIZE);
while (INTERFACE_FCALL_PAYLOAD_OFFSET != len)
{
- len = read(proto_in_fd, my_mme, INTERFACE_FCALL_PAYLOAD_OFFSET);
+ int r = read (proto_in_fd, my_mme + len,
+ INTERFACE_FCALL_PAYLOAD_OFFSET - len);
+ dbg_assert (r != -1 || errno == EINTR);
+ if (r > 0)
+ len += r;
}
- dbg_assert(INTERFACE_FCALL_PAYLOAD_OFFSET == len);
data_length = swap16(read_u16_from_word(my_mme + INTERFACE_FCALL_PAYLOAD_OFFSET - sizeof(u16)));
+ data_length = MAX (ETH_PACKET_MIN_SIZE - len, data_length);
if ((len = read(proto_in_fd, my_mme + INTERFACE_FCALL_PAYLOAD_OFFSET, data_length)) < 0)
{
diag_printf("errno = %d: error when reading proto in file (data_length = %d)\n", errno, data_length);
diff --git a/cesar/maximus/python/maximus/ethernet/scapy.py b/cesar/maximus/python/maximus/ethernet/scapy.py
index a7074d4f5c..df9bde3943 100644
--- a/cesar/maximus/python/maximus/ethernet/scapy.py
+++ b/cesar/maximus/python/maximus/ethernet/scapy.py
@@ -99,7 +99,6 @@ if __name__ == "__main__":
import socket, sys, getopt, string, struct, random, code
import cPickle, copy, types, gzip, base64, re, zlib, array
-from sets import Set
from select import select
from glob import glob
from fcntl import ioctl
diff --git a/cesar/maximus/python/maximus/station/sta.py b/cesar/maximus/python/maximus/station/sta.py
index 0a867d9257..0dd9a89d07 100644
--- a/cesar/maximus/python/maximus/station/sta.py
+++ b/cesar/maximus/python/maximus/station/sta.py
@@ -157,15 +157,8 @@ class STA:
.send(self.get())
else: # we need to build an MME
- # Use the OSA with a default mac address.
- osa = DEFAULT_MAC_ADDRESS
-
- # Get the mac address provided in the Station configuration.
- if self.get_mac_address() is not None:
- oda = self.get_mac_address()
- else:
- oda = DEFAULT_MAC_ADDRESS
- mmheader = MMHeader(ODA=oda, OSA=osa, MMV=0x01, MMTYPE = DRV_STA_START + MME_TYPES['REQ'])
+ # Computes MM Header
+ mmheader = MMHeader(ODA=self.__get_oda(), OSA=DEFAULT_MAC_ADDRESS, MMV=0x01, MMTYPE = DRV_STA_START + MME_TYPES['REQ'])
# Create the MME
data = ''
@@ -196,12 +189,7 @@ class STA:
else: # we need to build an MME
# Computes MM Header
- osa = DEFAULT_MAC_ADDRESS
- if self.get_mac_address() is not None:
- oda = self.get_mac_address()
- else:
- oda = DEFAULT_MAC_ADDRESS
- mmheader = MMHeader(ODA=oda, OSA=osa, MMV=0x01, MMTYPE = DRV_STA_STOP + MME_TYPES['REQ'])
+ mmheader = MMHeader(ODA=self.__get_oda(), OSA=DEFAULT_MAC_ADDRESS, MMV=0x01, MMTYPE = DRV_STA_STOP + MME_TYPES['REQ'])
# Create the MME
mme = MME(MMHeader=mmheader)
@@ -530,6 +518,17 @@ class STA:
"""
return self.__maximus
+ def __get_oda(self):
+ """Get the ODA to be used to send DRV MME-s.
+ The ODA is a Python tuple of 6 Python integers or a Python long.
+ """
+ # Get the mac address provided in the STA config if any
+ if self.get_mac_address() is not None:
+ oda = self.get_mac_address()
+ else:
+ oda = DEFAULT_MAC_ADDRESS
+ return oda
+
def get(self):
"""Get the station.
The station is a Sta object.
@@ -658,7 +657,7 @@ class STA:
else: # we need to build an MME
# Computes MM Header
- mmheader = MMHeader(ODA=DEFAULT_MAC_ADDRESS, OSA=self.get_mac_address(), MMV=0x01, MMTYPE = DRV_STA_SET_MAC_ADDR + MME_TYPES['REQ'])
+ mmheader = MMHeader(ODA=DEFAULT_MAC_ADDRESS, OSA=DEFAULT_MAC_ADDRESS, MMV=0x01, MMTYPE = DRV_STA_SET_MAC_ADDR + MME_TYPES['REQ'])
# Computes MM Entry: Mac address of the station
# Octet Number = 0 - 5
@@ -691,12 +690,7 @@ class STA:
else: # we need to build an MME
# Computes MM Header
- osa = DEFAULT_MAC_ADDRESS
- if self.get_mac_address() is not None:
- oda = self.get_mac_address()
- else:
- oda = DEFAULT_MAC_ADDRESS
- mmheader = MMHeader(ODA=oda, OSA=osa, MMV=0x01, MMTYPE = DRV_STA_SET_CCO_PREF + MME_TYPES['REQ'])
+ mmheader = MMHeader(ODA=self.__get_oda(), OSA=DEFAULT_MAC_ADDRESS, MMV=0x01, MMTYPE = DRV_STA_SET_CCO_PREF + MME_TYPES['REQ'])
# Computes MM Entry:
# - 0x00 = Station is not CCo
@@ -733,12 +727,7 @@ class STA:
else: # we need to build an MME
# Computes MM Header
- osa = self.get_mac_address()
- if self.get_mac_address() is not None:
- oda = self.get_mac_address()
- else:
- oda = DEFAULT_MAC_ADDRESS
- mmheader = MMHeader(ODA=oda, OSA=osa, MMV=0x01, MMTYPE = DRV_STA_SET_WAS_CCO + MME_TYPES['REQ'])
+ mmheader = MMHeader(ODA=self.__get_oda(), OSA=DEFAULT_MAC_ADDRESS, MMV=0x01, MMTYPE = DRV_STA_SET_WAS_CCO + MME_TYPES['REQ'])
# Computes MM Entry:
# - 0x00 = Station was not CCo
@@ -775,12 +764,7 @@ class STA:
else: # we need to build an MME
# Computes MM Header
- osa = DEFAULT_MAC_ADDRESS
- if self.get_mac_address() is not None:
- oda = self.get_mac_address()
- else:
- oda = DEFAULT_MAC_ADDRESS
- mmheader = MMHeader(ODA=oda, OSA=osa, MMV=0x01, MMTYPE = DRV_STA_SET_NPW + MME_TYPES['REQ'])
+ mmheader = MMHeader(ODA=self.__get_oda(), OSA=DEFAULT_MAC_ADDRESS, MMV=0x01, MMTYPE = DRV_STA_SET_NPW + MME_TYPES['REQ'])
# Computes MM Entry: Human-Readable (ASCII) Station Network Password
# Octet Number = 0 - 63
@@ -813,12 +797,7 @@ class STA:
else: # we need to build an MME
# Computes MM Header
- osa = DEFAULT_MAC_ADDRESS
- if self.get_mac_address() is not None:
- oda = self.get_mac_address()
- else:
- oda = DEFAULT_MAC_ADDRESS
- mmheader = MMHeader(ODA=oda, OSA=osa, MMV=0x01, MMTYPE = DRV_STA_SET_DPW + MME_TYPES['REQ'])
+ mmheader = MMHeader(ODA=self.__get_oda(), OSA=DEFAULT_MAC_ADDRESS, MMV=0x01, MMTYPE = DRV_STA_SET_DPW + MME_TYPES['REQ'])
# Computes MM Entry: Human-Readable (ASCII) Station Device Password
# Octet Number = 0 - 63
@@ -851,12 +830,7 @@ class STA:
else: # we need to build an MME
# Computes MM Header
- osa = DEFAULT_MAC_ADDRESS
- if self.get_mac_address() is not None:
- oda = self.get_mac_address()
- else:
- oda = DEFAULT_MAC_ADDRESS
- mmheader = MMHeader(ODA=oda, OSA=osa, MMV=0x01, MMTYPE = DRV_STA_SET_M_STA_HFID + MME_TYPES['REQ'])
+ mmheader = MMHeader(ODA=self.__get_oda(), OSA=DEFAULT_MAC_ADDRESS, MMV=0x01, MMTYPE = DRV_STA_SET_M_STA_HFID + MME_TYPES['REQ'])
# Computes MM Entry: Manufacturer Station Human-Friendly ID in ASCII format
# Octet Number = 0 - 63
@@ -889,12 +863,7 @@ class STA:
else: # we need to build an MME
# Computes MM Header
- osa = DEFAULT_MAC_ADDRESS
- if self.get_mac_address() is not None:
- oda = self.get_mac_address()
- else:
- oda = DEFAULT_MAC_ADDRESS
- mmheader = MMHeader(ODA=oda, OSA=osa, MMV=0x01, MMTYPE = DRV_STA_SET_U_STA_HFID + MME_TYPES['REQ'])
+ mmheader = MMHeader(ODA=self.__get_oda(), OSA=DEFAULT_MAC_ADDRESS, MMV=0x01, MMTYPE = DRV_STA_SET_U_STA_HFID + MME_TYPES['REQ'])
# Computes MM Entry: User Station Human-Friendly ID in ASCII format
# Octet Number = 0 - 63
@@ -927,12 +896,7 @@ class STA:
else: # we need to build an MME
# Computes MM Header
- osa = DEFAULT_MAC_ADDRESS
- if self.get_mac_address() is not None:
- oda = self.get_mac_address()
- else:
- oda = DEFAULT_MAC_ADDRESS
- mmheader = MMHeader(ODA=oda, OSA=osa, MMV=0x01, MMTYPE = DRV_STA_SET_AVLN_HFID + MME_TYPES['REQ'])
+ mmheader = MMHeader(ODA=self.__get_oda(), OSA=DEFAULT_MAC_ADDRESS, MMV=0x01, MMTYPE = DRV_STA_SET_AVLN_HFID + MME_TYPES['REQ'])
# Computes MM Entry: AVLN Station Human-Readable ID in ASCII format
# Octet Number = 0 - 63
@@ -965,12 +929,7 @@ class STA:
else: # we need to build an MME
# Computes MM Header
- osa = DEFAULT_MAC_ADDRESS
- if self.get_mac_address() is not None:
- oda = self.get_mac_address()
- else:
- oda = DEFAULT_MAC_ADDRESS
- mmheader = MMHeader(ODA=oda, OSA=osa, MMV=0x01, MMTYPE = DRV_STA_SET_SL + MME_TYPES['REQ'])
+ mmheader = MMHeader(ODA=self.__get_oda(), OSA=DEFAULT_MAC_ADDRESS, MMV=0x01, MMTYPE = DRV_STA_SET_SL + MME_TYPES['REQ'])
# Computes MM Entry: Security Level for New NMK
# Octet Number = 0
@@ -1001,12 +960,7 @@ class STA:
else: # we need to build an MME
# Computes MM Header
- osa = DEFAULT_MAC_ADDRESS
- if self.get_mac_address() is not None:
- oda = self.get_mac_address()
- else:
- oda = DEFAULT_MAC_ADDRESS
- mmheader = MMHeader(ODA=oda, OSA=osa, MMV=0x01, MMTYPE = DRV_STA_SET_TONEMASK + MME_TYPES['REQ'])
+ mmheader = MMHeader(ODA=self.__get_oda(), OSA=DEFAULT_MAC_ADDRESS, MMV=0x01, MMTYPE = DRV_STA_SET_TONEMASK + MME_TYPES['REQ'])
# Computes MM Entry: Station Tonemask bitfield
# Octet Number = 0 - 191
diff --git a/cesar/maximus/python/src/interface_module.cpp b/cesar/maximus/python/src/interface_module.cpp
index 5b4e976ffb..33c66156d1 100644
--- a/cesar/maximus/python/src/interface_module.cpp
+++ b/cesar/maximus/python/src/interface_module.cpp
@@ -294,7 +294,7 @@ void init_wrap ( Maximus & m, object args )
void uninit_wrap ( Maximus & m )
{
/* Free all resources. */
- delete (&m);
+ m.stop();
}
diff --git a/cesar/maximus/python/test/test_lib_cesar.py b/cesar/maximus/python/test/test_lib_cesar.py
index bdcb694c23..d3340925d7 100644
--- a/cesar/maximus/python/test/test_lib_cesar.py
+++ b/cesar/maximus/python/test/test_lib_cesar.py
@@ -98,10 +98,7 @@ class TestMaximusDurFunctions(unittest.TestCase):
# Maximum modulations
tonemap = ''
for i in range (0, PHY_CARRIER_NB / 2):
- if PHY_CARRIER_NB % 2 == 0:
- tonemap += pack('B', 0x07)
- else:
- tonemap += pack('B', 0x77)
+ tonemap += pack('B', 0x77)
bits_ref = 917 * 10
bits = maximus_dur_bits_per_symbol(self.maximus, self.station.get(), 3, # PHY_MOD_TM
self.station.get_tonemask(), tonemap, 917)
diff --git a/cesar/maximus/python/tools/csi/csicore.py b/cesar/maximus/python/tools/csi/csicore.py
index 7b37988982..c11f387170 100644
--- a/cesar/maximus/python/tools/csi/csicore.py
+++ b/cesar/maximus/python/tools/csi/csicore.py
@@ -222,6 +222,10 @@ class csiCore:
self.__test = csiTest()
+ def process_uninit (self):
+ """Unitialise Maximus, stop it, free resources."""
+ self.__maximus.uninit ()
+
def process_sta_start (self, station = None):
"""Start a station which was not launched yet."""
if station == None:
diff --git a/cesar/maximus/stationtest/src/test_send.c b/cesar/maximus/stationtest/src/test_send.c
index 70a03398ee..bcb264b163 100644
--- a/cesar/maximus/stationtest/src/test_send.c
+++ b/cesar/maximus/stationtest/src/test_send.c
@@ -40,8 +40,11 @@ bool phy_rx_fc_cb (void *user, u32 rx_date, const u32 *fc_av)
diag_write_string("=> phy_rx_fc_cb\n");
// When the FC is received, prepare RX
- phy_rx_prepare(ctx, 1, PHY_COMBO_PARAMS (mod, fecrate, pb_size),
- (phy_gil_t)gil, 0, 1);
+ if (short_ppdu)
+ phy_rx_prepare_short (ctx);
+ else
+ phy_rx_prepare(ctx, 1, PHY_COMBO_PARAMS (mod, fecrate, pb_size),
+ (phy_gil_t)gil, 0, 1);
return true;
}
diff --git a/cesar/maximus/stationtest/src/test_tx_rx.c b/cesar/maximus/stationtest/src/test_tx_rx.c
index 9abcf09218..dcbcc23e71 100644
--- a/cesar/maximus/stationtest/src/test_tx_rx.c
+++ b/cesar/maximus/stationtest/src/test_tx_rx.c
@@ -132,8 +132,11 @@ bool phy_rx_fc_cb (void *user, u32 rx_date, const u32 *fc_av)
maximus_pending_isrs &= (0 << PHY_HAL_INTERRUPT_PHY);
// When the FC is received, prepare RX
- phy_rx_prepare(ctx, 1, PHY_COMBO_PARAMS (mod, fecrate, pb_size),
- (phy_gil_t)gil, 0, 1);
+ if (short_ppdu)
+ phy_rx_prepare_short (ctx);
+ else
+ phy_rx_prepare(ctx, 1, PHY_COMBO_PARAMS (mod, fecrate, pb_size),
+ (phy_gil_t)gil, 0, 1);
return true;
}
diff --git a/cesar/projects/plc/Config.traces b/cesar/projects/plc/Config.traces
new file mode 100644
index 0000000000..cb793a0b04
--- /dev/null
+++ b/cesar/projects/plc/Config.traces
@@ -0,0 +1,10 @@
+CONFIG_DEBUG_CLAIM = n
+CONFIG_BLK_NB = 6144
+CONFIG_GPIO_LED_TRAFFIC = y
+CONFIG_BLK_SLACK = 512
+CONFIG_STATS_ON_FATAL = y
+
+CONFIG_TRACE = y
+CONFIG_TRACE_ON_FATAL = y
+CONFIG_TRACE_ALL_FAST = y
+CONFIG_ARCH_ILRAM_PRIO = 0
diff --git a/cesar/station/src/station.c b/cesar/station/src/station.c
index 406ecfb272..d09a51d7ea 100644
--- a/cesar/station/src/station.c
+++ b/cesar/station/src/station.c
@@ -29,6 +29,8 @@
# include "config/hal/trace/cpu.h"
#endif
+#include "lib/seq_check.h"
+
#include "lib/init.h"
/** Static declaration. */
@@ -53,6 +55,8 @@ cesar_init (void)
lib_stats_init ();
+ lib_seq_check_config_init ();
+
/* Initialise the mac store. */
cesar.mac_store = mac_store_init ();
diff --git a/cesar/test_general/maximus/integration/interface-dp/src/station.c b/cesar/test_general/maximus/integration/interface-dp/src/station.c
index 06b59016d4..b62a7363ee 100644
--- a/cesar/test_general/maximus/integration/interface-dp/src/station.c
+++ b/cesar/test_general/maximus/integration/interface-dp/src/station.c
@@ -79,9 +79,9 @@ ce_measurement_cb (void *data, pbproc_rx_params_t *rx_params,
}
static void
-cp_beacon_recv (void *ul, pb_beacon_t * beacon, bsu_params_t *params)
+cp_beacon_recv (void *ul, bsu_beacon_t *beacon)
{
- blk_release_desc ((blk_t*) beacon);
+ blk_release (beacon);
}
static void
@@ -157,7 +157,7 @@ cp_mme_recv (void *user_data, uint tei, u8 *buffer,
mytei == 1 ? BSU_UPDATE_STA_TYPE_CCO :
BSU_UPDATE_STA_TYPE_STA);
bsu_power_on (station_test.bsu, 0);
- bsu_activate (true);
+ bsu_activate (station_test.bsu, true);
sar_activate (station_test.sar, true);
pbproc_activate (station_test.pbproc, true);
}
@@ -266,7 +266,6 @@ cyg_user_start (void)
beacon->vf.rtsbf = false;
beacon->vf.nm = BSU_BEACON_NM_CSMA_ONLY;
beacon->vf.ccocap = 0;
- beacon->vf.rsvd = 0;
/* Regions. */
beacon->bmis.region.nb = 1;
beacon->bmis.region.region[0].rt = BSU_BEACON_REGION_SHARED_CSMA;
diff --git a/cesar/test_general/maximus/integration/sar-pbproc/src/station.c b/cesar/test_general/maximus/integration/sar-pbproc/src/station.c
index 2dbf28ceda..bd2116e325 100644
--- a/cesar/test_general/maximus/integration/sar-pbproc/src/station.c
+++ b/cesar/test_general/maximus/integration/sar-pbproc/src/station.c
@@ -39,6 +39,7 @@
#include "mac/ca/ca.h"
#include "mac/sar/inc/trace.h"
+#include "mac/common/timings.h"
struct tei_node_t
{
@@ -255,7 +256,7 @@ void create_schedule_csma_only (station_test_t *int_sta, uint beacon_period_nb)
for (i = 0; i < beacon_period_nb; i++)
{
beacons_periods[i].start_date = 1000000 * i
- + my_station.current_tick_tck;
+ + my_station.current_tick_tck - MAC_MS_TO_TCK (30);
beacons_periods[i].schedule_index = int_sta->sched_index;
}
@@ -282,10 +283,11 @@ void create_schedule_csma_only (station_test_t *int_sta, uint beacon_period_nb)
void pbproc_sched (cyg_addrword_t int_sta)
{
station_test_t *station_test = (station_test_t *) int_sta;
+ cyg_thread_delay (3);
while (true)
{
create_schedule_csma_only (station_test, CA_SCHEDULE_NB / 2);
- cyg_thread_delay (1);
+ cyg_thread_delay (4);
}
}
@@ -628,7 +630,7 @@ int fc_station_init_config (fcall_ctx_t *fcall, fcall_param_t **param,
uint tei;
uint snid;
uint beacon_period_auto;
- mac_t mac;
+ mac_t mac = 0;
tei = 0;
snid = 0;
diff --git a/cesar/test_general/station/cco0/s1/py/sc12_five_stations.py b/cesar/test_general/station/cco0/s1/py/sc12_five_stations.py
index 3189b85583..3fe8b6a166 100644
--- a/cesar/test_general/station/cco0/s1/py/sc12_five_stations.py
+++ b/cesar/test_general/station/cco0/s1/py/sc12_five_stations.py
@@ -52,5 +52,7 @@ csi.process_wait_sec (1)
#csi.process_avlns_stop ()
result = csi.process_end_get_result ()
+csi.process_uninit ()
+
# For nightly build errors
sys.exit ((1, 0)[result])
diff --git a/cesar/test_general/station/cco0/s1/py/sc13_10stations.py b/cesar/test_general/station/cco0/s1/py/sc13_10stations.py
index 499e1c2c88..76ef84c079 100644
--- a/cesar/test_general/station/cco0/s1/py/sc13_10stations.py
+++ b/cesar/test_general/station/cco0/s1/py/sc13_10stations.py
@@ -67,5 +67,7 @@ csi.process_avlns_remove()
sys.stderr.write("Ending\n")
result = csi.process_end_get_result ()
+csi.process_uninit ()
+
# For nightly build errors
sys.exit ((1, 0)[result])
diff --git a/cesar/test_general/station/cco0/s1/py/sc9_cco_leaving.py b/cesar/test_general/station/cco0/s1/py/sc9_cco_leaving.py
index f75b01cca9..48ab2443a4 100644
--- a/cesar/test_general/station/cco0/s1/py/sc9_cco_leaving.py
+++ b/cesar/test_general/station/cco0/s1/py/sc9_cco_leaving.py
@@ -40,10 +40,10 @@ csi.process_wait_association (15)
csi.process_wait_authentication (15)
csi.authentication_status (avln1)
-# Deactivate the CCo.
+# Remove the CCo.
stas[0].get_sta_cesar().stop()
csi.process_wait_sec (1)
-csi.process_sta_deactivate (stas[0])
+csi.process_sta_remove (avln1, stas[0])
csi.process_wait_sec (1)
# Activate the sniffer on the second station.
diff --git a/cesar/test_general/station/maximus/Makefile b/cesar/test_general/station/maximus/Makefile
index ffcb021416..82ceb3d3fc 100644
--- a/cesar/test_general/station/maximus/Makefile
+++ b/cesar/test_general/station/maximus/Makefile
@@ -8,7 +8,7 @@ TARGET_PROGRAMS= sta_maximus
sta_maximus_SOURCES =
sta_maximus_MODULES = lib mac/common mac cl hle interface cp hal station host \
- cp/av \
+ cp/av bsu \
test_general/station/fcall \
test_general/station/common ce/stub
diff --git a/cesar/test_general/station/maximus/py/sc01_long_simu.py b/cesar/test_general/station/maximus/py/sc01_long_simu.py
index 1c5357612c..c91c282dc3 100644
--- a/cesar/test_general/station/maximus/py/sc01_long_simu.py
+++ b/cesar/test_general/station/maximus/py/sc01_long_simu.py
@@ -44,7 +44,7 @@ for i in range(avln_sta_count):
1, False, 0)
# Start the simulation.
-csi.process_init(sys.path[0] + '/../obj/sta_maximus.elf')
+csi.process_init(sys.argv + ['-e', sys.path[0] + '/../obj/sta_maximus.elf'])
# Start the AVLN and STA.
csi.process_avlns_launch()
# Wait for association.
diff --git a/cesar/test_general/station/maximus/py/sc02_long_simu_data.py b/cesar/test_general/station/maximus/py/sc02_long_simu_data.py
index ab20db1174..945471e5b5 100644
--- a/cesar/test_general/station/maximus/py/sc02_long_simu_data.py
+++ b/cesar/test_general/station/maximus/py/sc02_long_simu_data.py
@@ -50,7 +50,7 @@ for i in range(avln_sta_count):
1, False, 0)
# Start the simulation.
-csi.process_init(sys.path[0] + '/../obj/sta_maximus.elf')
+csi.process_init(sys.argv + ['-e', sys.path[0] + '/../obj/sta_maximus.elf'])
# Start the AVLN and STA.
csi.process_avlns_launch()
# Wait for association.
diff --git a/cesar/test_general/station/tonemap/py/sc01_bl_initial.py b/cesar/test_general/station/tonemap/py/sc01_bl_initial.py
index 9605b4d314..3a22ef624e 100644
--- a/cesar/test_general/station/tonemap/py/sc01_bl_initial.py
+++ b/cesar/test_general/station/tonemap/py/sc01_bl_initial.py
@@ -32,9 +32,16 @@ class TestBitloadingInitial (unittest.TestCase):
# Wait for association and authentication.
self.failUnless (csi.process_wait_association () == True)
self.failUnless (csi.process_wait_authentication () == True)
+ # Send traffic to initiate tonemap negociation.
+ packets = [ csiPacket (100, avln, sta_src = txsta, sta_dest = rxsta)
+ for txsta, rxsta in ((csista[0], csista[1]),
+ (csista[1], csista[0])) ]
+ csi.process_data_send_traffic (packets)
+ csi.process_wait_sec (1)
+ csi.process_verify_transmission ()
+ # For each STA
tmi_list_rx = []
tmi_list_tx = []
- # For each STA
for i in range (sta_count):
# Get TEI and peer TEI.
sta_own = Station_own_data ()
diff --git a/cesar/test_general/station/tonemap/py/sc02_vs_get_tonemap.py b/cesar/test_general/station/tonemap/py/sc02_vs_get_tonemap.py
index 6bf0c56e06..d4e7c2031d 100644
--- a/cesar/test_general/station/tonemap/py/sc02_vs_get_tonemap.py
+++ b/cesar/test_general/station/tonemap/py/sc02_vs_get_tonemap.py
@@ -167,8 +167,13 @@ class TestVsGetTonemap (unittest.TestCase):
# Wait for association and authentication.
self.failUnless (csi.process_wait_association () == True)
self.failUnless (csi.process_wait_authentication () == True)
- # Wait a little bit.
- csi.process_wait_sec (3)
+ # Send traffic to initiate tonemap negociation.
+ packets = [ csiPacket (100, avln, sta_src = txsta, sta_dest = rxsta)
+ for txsta, rxsta in ((csista[0], csista[1]),
+ (csista[1], csista[0])) ]
+ csi.process_data_send_traffic (packets)
+ csi.process_wait_sec (1)
+ csi.process_verify_transmission ()
print "\nGet valid tonemap indexes and intervals lists only"
req_tmi = 0xFF
@@ -208,7 +213,7 @@ class TestVsGetTonemap (unittest.TestCase):
#Check results
self.failUnless (result == 2) # 2 is bad version
print "\nTry to get a tonemap not available"
- req_tmi = 0
+ req_tmi = 0x1f
version = int_id
(result, int_id, tmi_dflt, tmi_length, tmis, int_length, int_ets, int_tmis, tmi, tm_fec, tm_gi, mods) = send_vs_get_tonemap_req (self, req_tmi, version, 1, csista[0], csista[1])
#Check results
diff --git a/cleopatre/Makefile b/cleopatre/Makefile
index 7a60b7dbf6..ff8fc65cb4 100644
--- a/cleopatre/Makefile
+++ b/cleopatre/Makefile
@@ -12,8 +12,11 @@ FLASHFS_UNUSE=tools/flashfs/image/etc/init.d/S50plctest \
NVRAM_AV_UNUSE=
NVRAM_EOC_UNUSE=
SPIDUPD_UNUSE=tools/spidupd/Makefile tools/spidupd/spidupd_host.c tools/spidupd/spidupd_host.h
-AV_UNUSE=devkit Makefile application/onlined $(FCM3_UNUSE) $(FLASHFS_UNUSE) $(NVRAM_AV_UNUSE) $(SPIDUPD_UNUSE)
-EOC_UNUSE=devkit Makefile $(FCM3_UNUSE) $(FLASHFS_UNUSE) $(NVRAM_EOC_UNUSE) $(SPIDUPD_UNUSE)
+AV_UNUSE=devkit Makefile application/onlined application/upnpd $(FCM3_UNUSE) $(FLASHFS_UNUSE) $(NVRAM_AV_UNUSE) $(SPIDUPD_UNUSE)
+EOC_UNUSE=devkit Makefile application/upnpd $(FCM3_UNUSE) $(FLASHFS_UNUSE) $(NVRAM_EOC_UNUSE) $(SPIDUPD_UNUSE)
+
+AV_DEBUG_BINS= cesar-plc-debug
+EOC_DEBUG_BINS=
AV_PLC_BINS= plcd plcdrv cesar-plc
EOC_PLC_BINS=plcd plcdrv cesar-eoc-master cesar-eoc-slave
@@ -74,10 +77,10 @@ bundle: bundle-av bundle-eoc
bundle-clean: bundle-av-clean bundle-eoc-clean
bundle-av:
- $(Q)$(MAKE) bundle-standalone BUNDLE_TYPE=av BOARDS="$(AV_BOARDS)" PLC_BINS="$(AV_PLC_BINS)" UNUSE="$(AV_UNUSE)"
+ $(Q)$(MAKE) bundle-standalone BUNDLE_TYPE=av BOARDS="$(AV_BOARDS)" PLC_BINS="$(AV_PLC_BINS)" UNUSE="$(AV_UNUSE)" DEBUG_BINS="$(AV_DEBUG_BINS)"
bundle-eoc:
- $(Q)$(MAKE) bundle-standalone BUNDLE_TYPE=eoc BOARDS="$(EOC_BOARDS)" PLC_BINS="$(EOC_PLC_BINS)" UNUSE="$(EOC_UNUSE)"
+ $(Q)$(MAKE) bundle-standalone BUNDLE_TYPE=eoc BOARDS="$(EOC_BOARDS)" PLC_BINS="$(EOC_PLC_BINS)" UNUSE="$(EOC_UNUSE)" DEBUG_BINS="$(EOC_DEBUG_BINS)"
bundle-av-clean:
$(Q)$(MAKE) bundle-clean-standalone BUNDLE_TYPE=av
@@ -114,14 +117,22 @@ bundle-standalone:
$(Q)echo "Generate end of Bundle archive..."
$(Q)cd $(BUNDLE_UPPER_PATH) ; tar -rf $(BUNDLE_NAME).tar $(notdir $(BUNDLE_PATH))/$(notdir $(BUNDLE_GENBIN_PATH))
$(Q)bzip2 $(BUNDLE_UPPER_PATH)/$(BUNDLE_NAME).tar
+ $(Q)[ "$(DEBUG_BINS)" = "" ] || $(MAKE) $(DEBUG_BINS)
bundle-clean-standalone:
$(Q)rm -rf $(BUNDLE_PATH)
+cesar-plc-debug:
+ $(Q)$(MAKE) -C $(CESAR_PATH)/plc clean
+ $(Q)rm -fr $(CESAR_PATH)/plc/obj
+ $(Q)$(MAKE) -C $(CESAR_PATH)/plc PROJECT_CONFIG=Config.traces
+ $(Q)cp $(CESAR_PATH)/plc/obj/plc.rom $(BUNDLE_UPPER_PATH)/plc-with-traces.rom
+
cesar-plc:
$(Q)$(MAKE) -C $(CESAR_PATH)/plc clean
+ $(Q)rm -fr $(CESAR_PATH)/plc/obj
$(Q)$(MAKE) -C $(CESAR_PATH)/plc
$(Q)cp $(CESAR_PATH)/plc/obj/plc.rom $(BUNDLE_PLCBIN_PATH)/$(CESAR_PLC_NAME)
diff --git a/cleopatre/application/upnpd/Makefile b/cleopatre/application/upnpd/Makefile
new file mode 100644
index 0000000000..069c31f1ff
--- /dev/null
+++ b/cleopatre/application/upnpd/Makefile
@@ -0,0 +1,40 @@
+BIN=upnpd
+OBJPATH=obj
+SRCPATH=src
+INCPATH=inc
+
+ifeq ($(CC_FOR_TARGET),) #direct compile
+CC=arm-linux-gcc
+CC_WITH_CFLAGS=$(CC) -I/opt/spidcom/spc300/usr/include -g -Os
+CC_WITHOUT_CFLAGS=$(CC)
+LINUX_DIR=../../linux-2.6.25.10-spc300
+else #compile from buildroot
+CC_WITH_CFLAGS=$(CC)
+CC_WITHOUT_CFLAGS=$(CC_FOR_TARGET)
+endif
+EXTRA_CFLAGS=-I$(INCPATH) -I$(LINUX_DIR)/include/asm-arm/arch-spc300 -MMD
+
+SRCS=$(subst $(SRCPATH)/,,$(wildcard $(SRCPATH)/*.c))
+OBJS=$(addprefix $(OBJPATH)/,$(SRCS:.c=.o))
+DEPS=$(patsubst %o,%d,$(OBJS))
+
+all: $(BIN)
+
+$(BIN): $(OBJPATH) $(OBJS)
+ $(CC_WITHOUT_CFLAGS) -static -o $@ $(OBJS) $(LIBS)
+
+$(OBJPATH)/%.o: $(SRCPATH)/%.c
+ $(CC_WITH_CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $<
+
+$(OBJPATH):
+ mkdir -p $(OBJPATH)
+
+
+
+-include $(DEPS)
+
+.PHONY: all clean
+
+clean:
+ rm -f $(OBJS) $(DEPS) $(BIN)
+
diff --git a/cleopatre/application/upnpd/README b/cleopatre/application/upnpd/README
new file mode 100644
index 0000000000..4b952afadc
--- /dev/null
+++ b/cleopatre/application/upnpd/README
@@ -0,0 +1,22 @@
+1)Prerequisites
+
+The embedded busybox has to include the zcip command.
+
+
+2)General
+upnpd is a UPnP software solution to be embedded on the SPC300. To use it, the following files must be pasted at the correct location.
+
+
+"upnpd" : this executable is located at "/usr/local/bin"
+"upnpd.conf" : this configuration file is located at "/usr/local/etc"
+"zcip.script" : this script is located at "/usr/local/etc"
+"S98upnpd" : this script is located at "/usr/local/etc/init.d/"
+
+3)Adding and removing a function
+
+To add or remove a function, only two files are to be changed:
+
+upnpdescgen.c: Definition of the presentation given to a control point. Define the state variables (allowed values, type...) and the way arguments are managed by the function(in->1, out->2). Link the function to the related service (action structure).
+
+upnpsoap.c: Define the new state variables at beginning and implement your function. To get a value from user, use "ParseNameValue" and "GetValueFromNameValueList". Link the implemented function to the called-by-user function in "soapMethods".
+To store values from a "system(cmd)" call (normally printed to stdout) in a file (located in "/tmp") and to retrieve those values, refer to "Ping" and "GetPingResult" implementation.
diff --git a/cleopatre/application/upnpd/S98upnpd b/cleopatre/application/upnpd/S98upnpd
new file mode 100755
index 0000000000..1681300dd9
--- /dev/null
+++ b/cleopatre/application/upnpd/S98upnpd
@@ -0,0 +1,43 @@
+#!/bin/sh
+#
+# Start the upnp daemon...
+#
+start() {
+ echo "Starting the upnp daemon..."
+ if [ -f /usr/local/bin/upnpd ]
+ then
+ echo "Configuring br0 with zcip..."
+ zcip br0 /usr/local/etc/zcip.script
+ fi
+
+}
+
+stop() {
+ echo "Stopping the upnp daemon..."
+ if [ -f /usr/local/bin/upnpd ]
+ then
+ killall upnpd
+ fi
+}
+
+restart() {
+ stop
+ start
+}
+
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ restart|reload)
+ restart
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|restart}"
+ exit 1
+esac
+
+exit $?
diff --git a/cleopatre/application/upnpd/inc/config.h b/cleopatre/application/upnpd/inc/config.h
new file mode 100644
index 0000000000..394dd8b9a7
--- /dev/null
+++ b/cleopatre/application/upnpd/inc/config.h
@@ -0,0 +1,56 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CONFIG_H__
+# define __CONFIG_H__
+
+# define OS_NAME " Ubuntu "
+# define OS_VERSION " Ubuntu/11.04 "
+# define OS_URL "http://www.debian.org/"
+# define DEBUG
+
+/* full path of the log directory */
+# define DEFAULT_LOG_PATH "/var/log"
+
+/* Comment the following line to use home made daemonize() func instead
+ * of BSD daemon() */
+# define USE_DAEMON
+
+/* Enable if the system inotify.h exists. Otherwise our own inotify.h will be used. */
+# define HAVE_INOTIFY_H
+
+
+#endif
diff --git a/cleopatre/application/upnpd/inc/daemonize.h b/cleopatre/application/upnpd/inc/daemonize.h
new file mode 100644
index 0000000000..3636fee6f0
--- /dev/null
+++ b/cleopatre/application/upnpd/inc/daemonize.h
@@ -0,0 +1,57 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __DAEMONIZE_H__
+# define __DAEMONIZE_H__
+
+# include "config.h"
+
+/* daemonize()
+ * "fork" to background, detach from terminal, etc...
+ * returns: pid of the daemon, exits upon failure */
+int daemonize (void);
+
+/* writepidfile()
+ * write the pid to a file */
+int writepidfile (const char *fname, int pid);
+
+/* checkforrunning()
+ * check for another instance running
+ * returns: 0 only instance
+ * -1 invalid filename
+ * -2 another instance running */
+int checkforrunning (const char *fname);
+
+#endif
diff --git a/cleopatre/application/upnpd/inc/getifaddr.h b/cleopatre/application/upnpd/inc/getifaddr.h
new file mode 100644
index 0000000000..4afcab9288
--- /dev/null
+++ b/cleopatre/application/upnpd/inc/getifaddr.h
@@ -0,0 +1,62 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __GETIFADDR_H__
+# define __GETIFADDR_H__
+# include <arpa/inet.h>
+# define MACADDR_IS_ZERO(x) \
+ ((x[0] == 0x00) && \
+ (x[1] == 0x00) && \
+ (x[2] == 0x00) && \
+ (x[3] == 0x00) && \
+ (x[4] == 0x00) && \
+ (x[5] == 0x00))
+
+/* getifaddr()
+ * take a network interface name and write the
+ * ip v4 address as text in the buffer
+ * returns: 0 success, -1 failure */
+int getifaddr (const char *ifname, char *buf, int len);
+
+
+
+int getsysaddr (char *buf, int len);
+
+int getsyshwaddr (char *buf, int len);
+
+int get_remote_mac (struct in_addr ip_addr, unsigned char *mac);
+
+#endif
diff --git a/cleopatre/application/upnpd/inc/minissdp.h b/cleopatre/application/upnpd/inc/minissdp.h
new file mode 100644
index 0000000000..36691b2e1c
--- /dev/null
+++ b/cleopatre/application/upnpd/inc/minissdp.h
@@ -0,0 +1,59 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MINISSDP_H__
+# define __MINISSDP_H__
+
+
+int OpenAndConfSSDPReceiveSocket (void);
+
+
+int OpenAndConfSSDPNotifySockets (int *sockets);
+
+void
+SendSSDPNotifies (int s, const char *host, unsigned short port,
+ unsigned int lifetime);
+void
+SendSSDPNotifies2 (int *sockets, unsigned short port, unsigned int lifetime);
+
+void ProcessSSDPRequest (int s, unsigned short port);
+
+int SendSSDPGoodbye (int *sockets, int n);
+
+
+int SubmitServicesToMiniSSDPD (const char *host, unsigned short port);
+
+#endif
diff --git a/cleopatre/application/upnpd/inc/minixml.h b/cleopatre/application/upnpd/inc/minixml.h
new file mode 100644
index 0000000000..20a99e8589
--- /dev/null
+++ b/cleopatre/application/upnpd/inc/minixml.h
@@ -0,0 +1,68 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MINIXML_H__
+# define __MINIXML_H__
+# define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n'))
+
+
+
+
+
+
+/* if a callback function pointer is set to NULL,
+ * the function is not called */
+struct xmlparser
+{
+ const char *xmlstart;
+ const char *xmlend;
+ const char *xml; /* pointer to current character */
+ int xmlsize;
+ void *data;
+ void (*starteltfunc) (void *, const char *, int);
+ void (*endeltfunc) (void *, const char *, int);
+ void (*datafunc) (void *, const char *, int);
+ void (*attfunc) (void *, const char *, int, const char *, int);
+};
+
+/* parsexml()
+ * the xmlparser structure must be initialized before the call
+ * the following structure members have to be initialized :
+ * xmlstart, xmlsize, data, *func
+ * xml is for internal usage, xmlend is computed automatically */
+void parsexml (struct xmlparser *);
+
+#endif
diff --git a/cleopatre/application/upnpd/inc/options.h b/cleopatre/application/upnpd/inc/options.h
new file mode 100644
index 0000000000..e5d60a27f3
--- /dev/null
+++ b/cleopatre/application/upnpd/inc/options.h
@@ -0,0 +1,79 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __OPTIONS_H__
+# define __OPTIONS_H__
+
+# include "config.h"
+
+
+
+/* enum of option available in the miniupnpd.conf */
+enum upnpconfigoptions
+{
+ UPNP_INVALID = 0,
+ UPNPIFNAME = 1,
+ UPNPPRESENTATIONURL,
+ UPNPSERIAL,
+ UPNPLISTENING_IP, /* listening_ip */
+ UPNPPORT, /* port */
+ UPNPNOTIFY_INTERVAL, /* notify_interval */
+ UPNPUUID, /* uuid */
+ UPNPMODEL_NAME, /* model_name */
+ UPNPMODEL_NUMBER, /* model_number */
+ UPNPFRIENDLYNAME, /* how the system should show up to control points */
+};
+
+/* readoptionsfile()
+ * parse and store the option file values
+ * returns: 0 success, -1 failure */
+int readoptionsfile (const char *fname);
+
+/* freeoptions()
+ * frees memory allocated to option values */
+void freeoptions (void);
+
+# define MAX_OPTION_VALUE_LEN (200)
+struct option
+{
+ enum upnpconfigoptions id;
+ char value[MAX_OPTION_VALUE_LEN];
+};
+
+extern struct option *ary_options;
+extern int num_options;
+
+#endif
diff --git a/cleopatre/application/upnpd/inc/upnpdescgen.h b/cleopatre/application/upnpd/inc/upnpdescgen.h
new file mode 100644
index 0000000000..50c47f7523
--- /dev/null
+++ b/cleopatre/application/upnpd/inc/upnpdescgen.h
@@ -0,0 +1,110 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __UPNPDESCGEN_H__
+# define __UPNPDESCGEN_H__
+
+# include "config.h"
+
+/* for the root description
+ * The child list reference is stored in "data" member using the
+ * INITHELPER macro with index/nchild always in the
+ * same order, whatever the endianness */
+
+
+
+
+
+struct XMLElt
+{
+ const char *eltname; /* begin with '/' if no child */
+ const char *data; /* Value */
+};
+
+/* for service description */
+struct serviceDesc
+{
+ const struct action *actionList;
+ const struct stateVar *serviceStateTable;
+};
+
+struct action
+{
+ const char *name;
+ const struct argument *args;
+};
+
+struct argument
+{
+ const char *name; /* the name of the argument */
+ unsigned char dir; /* 1 = in, 2 = out */
+ unsigned char relatedVar; /* index of the related variable */
+};
+
+struct stateVar
+{
+ const char *name;
+ unsigned char itype; /* MSB: sendEvent flag, 7 LSB: index in upnptypes */
+ unsigned char idefault; /* default value */
+ unsigned char iallowedlist; /* index in allowed values list */
+ unsigned char irange; /*This is just a flag. Put 1 in stateVar then the minimum and maximum values in iallowedValueList to produce the correct XML description */
+ unsigned char ieventvalue; /* fixed value returned or magical values */
+};
+
+/* little endian
+ * The code has now be tested on big endian architecture */
+# define INITHELPER(i, n) ((char *)((n<<16)|i))
+
+/* char * genRootDesc(int *);
+ * returns: NULL on error, string allocated on the heap */
+char *genRootDesc (int *len);
+
+char *genBasicManagement (int *len);
+
+char *genConfigurationManagement (int *len);
+
+char *genSoftwareManagement (int *len);
+
+char *genLowPowerDevice (int *len);
+
+char *getVarsBasicManagement (int *len);
+
+char *getVarsConfigurationManagement (int *len);
+
+char *getVarsSoftwareManagement (int *len);
+
+char *getVarsLowPowerDevice (int *len);
+#endif
diff --git a/cleopatre/application/upnpd/inc/upnpdescstrings.h b/cleopatre/application/upnpd/inc/upnpdescstrings.h
new file mode 100644
index 0000000000..bcf3013080
--- /dev/null
+++ b/cleopatre/application/upnpd/inc/upnpdescstrings.h
@@ -0,0 +1,50 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __UPNPDESCSTRINGS_H__
+# define __UPNPDESCSTRINGS_H__
+
+# include "config.h"
+
+/* strings used in the root device xml description */
+
+# define ROOTDEV_MANUFACTURERURL "http://www.spidcom.com/"
+# define ROOTDEV_MANUFACTURER "Spidcom Technologies"
+# define ROOTDEV_MODELNAME "upnpd"
+# define ROOTDEV_MODELURL OS_URL
+# define ROOTDEV_MODELDESCRIPTION "upnpd for SPC300"
+
+#endif
diff --git a/cleopatre/application/upnpd/inc/upnpdpath.h b/cleopatre/application/upnpd/inc/upnpdpath.h
new file mode 100644
index 0000000000..7d81d4a8f3
--- /dev/null
+++ b/cleopatre/application/upnpd/inc/upnpdpath.h
@@ -0,0 +1,63 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __UPNPDPATH_H__
+# define __UPNPDPATH_H__
+
+
+# include "config.h"
+
+/* Paths and other URLs in the upnpd http server */
+
+
+# define ROOTDESC_PATH "/rootDesc.xml"
+
+# define BASICMANAGEMENT_PATH "/BasicManagement.xml"
+# define BASICMANAGEMENT_CONTROLURL "/ctl/BasicManagement"
+# define BASICMANAGEMENT_EVENTURL "/evt/BasicManagement"
+
+# define CONFIGURATIONMANAGEMENT_PATH "/ConfigurationManagement.xml"
+# define CONFIGURATIONMANAGEMENT_CONTROLURL "/ctl/ConfigurationManagement"
+# define CONFIGURATIONMANAGEMENT_EVENTURL "/evt/ConfigurationManagement"
+
+# define SOFTWAREMANAGEMENT_PATH "/SoftwareManagement.xml"
+# define SOFTWAREMANAGEMENT_CONTROLURL "/ctl/SoftwareManagement"
+# define SOFTWAREMANAGEMENT_EVENTURL "/evt/SoftwareManagement"
+
+# define LOWPOWERDEVICE_PATH "/LowPowerDevice.xml"
+# define LOWPOWERDEVICE_CONTROLURL "/ctl/LowPowerDevice"
+# define LOWPOWERDEVICE_EVENTURL "/evt/LowPowerDevice"
+
+#endif
diff --git a/cleopatre/application/upnpd/inc/upnpdtypes.h b/cleopatre/application/upnpd/inc/upnpdtypes.h
new file mode 100644
index 0000000000..c612809337
--- /dev/null
+++ b/cleopatre/application/upnpd/inc/upnpdtypes.h
@@ -0,0 +1,56 @@
+/* upnpd project
+ *
+ *
+ * upnpd Device manager
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __UPNPDTYPES_H__
+# define __UPNPDTYPES_H__
+
+# include "config.h"
+# include <netinet/in.h>
+
+struct lan_addr_s
+{
+ char str[16]; /* example: 192.168.0.1 */
+ struct in_addr addr, mask; /* ip/mask */
+};
+
+struct runtime_vars_s
+{
+ int port; /*http port */
+ int notify_interval; /*interval between ssdp announcements */
+};
+
+
+
+#endif
diff --git a/cleopatre/application/upnpd/inc/upnpevents.h b/cleopatre/application/upnpd/inc/upnpevents.h
new file mode 100644
index 0000000000..065a0b2f4f
--- /dev/null
+++ b/cleopatre/application/upnpd/inc/upnpevents.h
@@ -0,0 +1,65 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __UPNPEVENTS_H__
+# define __UPNPEVENTS_H__
+enum subscriber_service_enum
+{
+ EBasicManagement = 1,
+ EConfigurationManagement,
+ ESoftwareManagement,
+ ELowPowerDevice
+};
+
+void upnp_event_var_change_notify (enum subscriber_service_enum service);
+
+const char *upnpevents_addSubscriber (const char *eventurl,
+ const char *callback, int callbacklen,
+ int timeout);
+
+int upnpevents_removeSubscriber (const char *sid);
+
+int renewSubscription (const char *sid, int timeout);
+
+void upnpevents_selectfds (fd_set * readset, fd_set * writeset, int *max_fd);
+void upnpevents_processfds (fd_set * readset, fd_set * writeset);
+
+# ifdef USE_UPNPDCTL
+void write_events_details (int s);
+# endif
+
+#endif
diff --git a/cleopatre/application/upnpd/inc/upnpglobalvars.h b/cleopatre/application/upnpd/inc/upnpglobalvars.h
new file mode 100644
index 0000000000..09abb95e12
--- /dev/null
+++ b/cleopatre/application/upnpd/inc/upnpglobalvars.h
@@ -0,0 +1,88 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __UPNPGLOBALVARS_H__
+# define __UPNPGLOBALVARS_H__
+
+# include <time.h>
+# include "upnpdtypes.h"
+# include "config.h"
+# include <stdbool.h>
+
+# define CLIENT_CACHE_SLOTS 20
+# define SYSTIMEUPMASK 0x0002
+/* statup time */
+extern time_t startup_time;
+
+/* runtime boolean flags */
+extern int runtime_flags;
+
+
+# define SSDP_PORT (1900)
+# define SSDP_MCAST_ADDR ("239.255.255.250")
+
+# define UPNPD_SERVER_STRING OS_VERSION "UPNP/1.0 upnpd/" UPNPD_VERSION
+
+# define UPNPD_VERSION "1.0"
+extern const char *pidfilename;
+
+extern char uuidvalue[];
+# define MODELNAME_MAX_LEN (64)
+extern char modelname[];
+
+# define MODELNUMBER_MAX_LEN (16)
+extern char modelnumber[];
+
+# define SERIALNUMBER_MAX_LEN (16)
+extern char serialnumber[];
+
+# define PRESENTATIONURL_MAX_LEN (64)
+extern char presentationurl[];
+/* lan addresses */
+/* MAX_LAN_ADDR : maximum number of interfaces
+ * to listen to SSDP traffic */
+# define MAX_LAN_ADDR (4)
+extern int n_lan_addr;
+extern struct lan_addr_s lan_addr[];
+
+extern const char *minissdpsocketpath;
+# define FRIENDLYNAME_MAX_LEN (64)
+extern char friendly_name[];
+extern char log_path[];
+extern volatile short int quitting;
+extern volatile uint32_t updateID;
+extern struct runtime_vars_s runtime_vars;
+#endif
diff --git a/cleopatre/application/upnpd/inc/upnphttp.h b/cleopatre/application/upnpd/inc/upnphttp.h
new file mode 100644
index 0000000000..9e5fb72923
--- /dev/null
+++ b/cleopatre/application/upnpd/inc/upnphttp.h
@@ -0,0 +1,153 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __UPNPHTTP_H__
+# define __UPNPHTTP_H__
+
+# include <netinet/in.h>
+# include <sys/queue.h>
+
+# include "upnpdtypes.h"
+# include "config.h"
+
+
+
+
+
+
+/*
+ states :
+ 0 - waiting for data to read
+ 1 - waiting for HTTP Post Content.
+ ...
+ >= 100 - to be deleted
+*/
+enum httpCommands
+{
+ EUnknown = 0,
+ EGet,
+ EPost,
+ EHead,
+ ESubscribe,
+ EUnSubscribe
+};
+
+struct upnphttp
+{
+ int socket;
+ struct in_addr clientaddr; /* client address */
+ int state;
+ char HttpVer[16];
+ /* request */
+ char *req_buf;
+ int req_buflen;
+ int req_contentlen;
+ int req_contentoff; /* header length */
+ enum httpCommands req_command;
+ const char *req_soapAction;
+ int req_soapActionLen;
+ const char *req_Callback; /* For SUBSCRIBE */
+ int req_CallbackLen;
+ int req_Timeout;
+ const char *req_SID; /* For UNSUBSCRIBE */
+ int req_SIDLen;
+ off_t req_RangeStart;
+ off_t req_RangeEnd;
+ long int req_chunklen;
+ uint32_t reqflags;
+ uint32_t respflags;
+ /* response */
+ char *res_buf;
+ int res_buflen;
+ int res_buf_alloclen;
+ LIST_ENTRY (upnphttp) entries;
+};
+
+# define FLAG_TIMEOUT 0x00000001
+# define FLAG_SID 0x00000002
+# define FLAG_RANGE 0x00000004
+# define FLAG_HOST 0x00000008
+
+# define FLAG_HTML 0x00000080
+# define FLAG_INVALID_REQ 0x00000010
+
+# define FLAG_CHUNKED 0x00000100
+# define FLAG_TIMESEEK 0x00000200
+# define FLAG_REALTIMEINFO 0x00000400
+
+
+/*New_upnphttp()*/
+struct upnphttp *New_upnphttp (int);
+
+/* CloseSocket_upnphttp() */
+void CloseSocket_upnphttp (struct upnphttp *);
+
+/* Delete_upnphttp() */
+void Delete_upnphttp (struct upnphttp *);
+
+/* Process_upnphttp() */
+void Process_upnphttp (struct upnphttp *);
+
+/* BuildHeader_upnphttp()
+ * build the header for the HTTP Response
+ * also allocate the buffer for body data */
+void
+BuildHeader_upnphttp (struct upnphttp *h, int respcode,
+ const char *respmsg, int bodylen);
+
+/* BuildResp_upnphttp()
+ * fill the res_buf buffer with the complete
+ * HTTP 200 OK response from the body passed as argument */
+void BuildResp_upnphttp (struct upnphttp *, const char *, int);
+
+/* BuildResp2_upnphttp()
+ * same but with given response code/message */
+void
+BuildResp2_upnphttp (struct upnphttp *h, int respcode,
+ const char *respmsg, const char *body, int bodylen);
+
+/* Error messages*/
+
+void Send400 (struct upnphttp *h);
+void Send404 (struct upnphttp *h);
+void Send406 (struct upnphttp *h);
+void Send416 (struct upnphttp *h);
+void Send501 (struct upnphttp *h);
+void Send500 (struct upnphttp *h);
+
+/* SendResp_upnphttp() */
+void SendResp_upnphttp (struct upnphttp *);
+#endif
diff --git a/cleopatre/application/upnpd/inc/upnpreplyparse.h b/cleopatre/application/upnpd/inc/upnpreplyparse.h
new file mode 100644
index 0000000000..5dfd803e3a
--- /dev/null
+++ b/cleopatre/application/upnpd/inc/upnpreplyparse.h
@@ -0,0 +1,84 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __UPNPREPLYPARSE_H__
+# define __UPNPREPLYPARSE_H__
+
+# include <sys/queue.h>
+
+# ifdef __cplusplus
+extern "C"
+{
+# endif
+
+ struct NameValue
+ {
+ LIST_ENTRY (NameValue) entries;
+ char name[64];
+ char value[512];
+ };
+
+ struct NameValueParserData
+ {
+ LIST_HEAD (listhead, NameValue) head;
+ char curelt[64];
+ };
+
+/* ParseNameValue() */
+ void ParseNameValue (const char *buffer, int bufsize,
+ struct NameValueParserData *data);
+
+/* ClearNameValueList() */
+ void ClearNameValueList (struct NameValueParserData *pdata);
+
+/* GetValueFromNameValueList() */
+ char *GetValueFromNameValueList (struct NameValueParserData *pdata,
+ const char *Name);
+
+/* GetValueFromNameValueListIgnoreNS() */
+ char *GetValueFromNameValueListIgnoreNS (struct NameValueParserData
+ *pdata, const char *Name);
+
+/* DisplayNameValueList() */
+# ifdef DEBUG
+ void DisplayNameValueList (char *buffer, int bufsize);
+# endif
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
diff --git a/cleopatre/application/upnpd/inc/upnpsoap.h b/cleopatre/application/upnpd/inc/upnpsoap.h
new file mode 100644
index 0000000000..b941826740
--- /dev/null
+++ b/cleopatre/application/upnpd/inc/upnpsoap.h
@@ -0,0 +1,69 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __UPNPSOAP_H__
+# define __UPNPSOAP_H__
+
+# define MAX_RESPONSE_SIZE 1048576
+
+# define CONTENT_DIRECTORY_SCHEMAS \
+ " xmlns:dc=\"http://purl.org/dc/elements/1.1/\"" \
+ " xmlns:upnp=\"urn:schemas-upnp-org:metadata-1-0/upnp/\"" \
+ " xmlns=\"urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/\""
+# define DLNA_NAMESPACE \
+ " xmlns:dlna=\"urn:schemas-dlna-org:metadata-1-0/\""
+
+struct Response
+{
+ char *resp;
+ int start;
+ int returned;
+ int requested;
+ int size;
+ int alloced;
+ u_int32_t filter;
+ u_int32_t flags;
+};
+
+/* ExecuteSoapAction():
+ * this method executes the requested Soap Action */
+void ExecuteSoapAction (struct upnphttp *, const char *, int);
+
+/* SoapError():
+ * sends a correct SOAP error with an UPNPError code and
+ * description */
+void SoapError (struct upnphttp *h, int errCode, const char *errDesc);
+
+#endif
diff --git a/cleopatre/application/upnpd/inc/uuid.h b/cleopatre/application/upnpd/inc/uuid.h
new file mode 100644
index 0000000000..feef6e3463
--- /dev/null
+++ b/cleopatre/application/upnpd/inc/uuid.h
@@ -0,0 +1,42 @@
+/* upnpd project
+ *
+ *
+ * upnpd
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __UUID_H__
+# define __UUID_H__
+
+int get_uuid_string (char *buf);
+
+#endif
diff --git a/cleopatre/application/upnpd/src/.upnpd.c.swp b/cleopatre/application/upnpd/src/.upnpd.c.swp
new file mode 100644
index 0000000000..0b1d13580c
--- /dev/null
+++ b/cleopatre/application/upnpd/src/.upnpd.c.swp
Binary files differ
diff --git a/cleopatre/application/upnpd/src/daemonize.c b/cleopatre/application/upnpd/src/daemonize.c
new file mode 100644
index 0000000000..550200c26f
--- /dev/null
+++ b/cleopatre/application/upnpd/src/daemonize.c
@@ -0,0 +1,156 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include "daemonize.h"
+#include "config.h"
+#include <syslog.h>
+
+
+int
+daemonize (void)
+{
+ int pid, i;
+
+ switch (fork ())
+ {
+ /* fork error */
+ case -1:
+ perror ("fork()");
+ exit (1);
+
+ /* child process */
+ case 0:
+ /* obtain a new process group */
+ if ((pid = setsid ()) < 0)
+ {
+ perror ("setsid()");
+ exit (1);
+ }
+ else
+ {
+ syslog (LOG_WARNING,
+ "successfully created child process with pid:%d\n", pid);
+ }
+ /* close all descriptors */
+ for (i = getdtablesize (); i >= 0; --i)
+ close (i);
+
+ i = open ("/dev/null", O_RDWR); /* open stdin */
+
+ umask (027);
+
+ return pid;
+
+ /* parent process */
+ default:
+ exit (0);
+ }
+}
+
+int
+writepidfile (const char *fname, int pid)
+{
+ char pidstring[16];
+ int pidstringlen;
+ int pidfile;
+
+ if (!fname || (strlen (fname) == 0))
+ return -1;
+ if ((pidfile = open (fname, O_WRONLY | O_CREAT, 0644)) < 0)
+ {
+ syslog (LOG_WARNING, "Unable to open pidfile for writing %s: %m", fname);
+ return -1;
+ }
+
+ pidstringlen = snprintf (pidstring, sizeof (pidstring), "%d\n", pid);
+ if (pidstringlen <= 0)
+ {
+ syslog (LOG_WARNING,
+ "Unable to write to pidfile %s: snprintf(): FAILED", fname);
+ close (pidfile);
+
+ return -1;
+ }
+ else
+ {
+ if (write (pidfile, pidstring, pidstringlen) < 0)
+ syslog (LOG_WARNING, "Unable to write to pidfile %s: %m", fname);
+ }
+
+ close (pidfile);
+
+ return 0;
+}
+
+int
+checkforrunning (const char *fname)
+{
+ char buffer[64];
+ int pidfile;
+ pid_t pid;
+
+ if (!fname || (strlen (fname) == 0))
+ return -1;
+
+ if ((pidfile = open (fname, O_RDONLY)) < 0)
+ return 0;
+
+ memset (buffer, 0, 64);
+
+ if (read (pidfile, buffer, 63))
+ {
+ if ((pid = atol (buffer)) > 0)
+ {
+ if (!kill (pid, 0))
+ {
+ close (pidfile);
+ return -2;
+ }
+ }
+ }
+
+ close (pidfile);
+
+ return 0;
+}
diff --git a/cleopatre/application/upnpd/src/getifaddr.c b/cleopatre/application/upnpd/src/getifaddr.c
new file mode 100644
index 0000000000..523fbbfe84
--- /dev/null
+++ b/cleopatre/application/upnpd/src/getifaddr.c
@@ -0,0 +1,211 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include "getifaddr.h"
+#include <errno.h>
+#include <syslog.h>
+
+
+
+
+int
+getifaddr (const char *ifname, char *buf, int len)
+{
+ /* SIOCGIFADDR struct ifreq * */
+ int s;
+ struct ifreq ifr;
+ int ifrlen;
+ struct sockaddr_in *addr;
+ ifrlen = sizeof (ifr);
+
+ s = socket (PF_INET, SOCK_DGRAM, 0);
+ if (s < 0)
+ {
+ syslog (LOG_ERR, "socket(PF_INET, SOCK_DGRAM): %m");
+ return -1;
+ }
+ strncpy (ifr.ifr_name, ifname, IFNAMSIZ);
+ if (ioctl (s, SIOCGIFADDR, &ifr, &ifrlen) < 0)
+ {
+ syslog (LOG_ERR, "ioctl(s, SIOCGIFADDR, ...): %m");
+ close (s);
+ return -1;
+ }
+ addr = (struct sockaddr_in *) &ifr.ifr_addr;
+ if (!inet_ntop (AF_INET, &addr->sin_addr, buf, len))
+ {
+ syslog (LOG_ERR, "inet_ntop(): %m");
+ close (s);
+ return -1;
+ }
+ close (s);
+ return 0;
+}
+
+
+
+
+
+int
+getsysaddr (char *buf, int len)
+{
+ int i;
+ int s = socket (PF_INET, SOCK_STREAM, 0);
+ struct sockaddr_in addr;
+ struct ifreq ifr;
+ int ret = -1;
+
+ for (i = 1; i > 0; i++)
+ {
+ ifr.ifr_ifindex = i;
+ if (ioctl (s, SIOCGIFNAME, &ifr) < 0)
+ break;
+ if (ioctl (s, SIOCGIFADDR, &ifr, sizeof (struct ifreq)) < 0)
+ continue;
+ memcpy (&addr, &ifr.ifr_addr, sizeof (addr));
+ if (strncmp (inet_ntoa (addr.sin_addr), "127.", 4) == 0)
+ continue;
+ if (!inet_ntop (AF_INET, &addr.sin_addr, buf, len))
+ {
+ syslog (LOG_WARNING, "inet_ntop(): %s\n", strerror (errno));
+ close (s);
+ break;
+ }
+ ret = 0;
+ break;
+ }
+ close (s);
+
+ return (ret);
+}
+
+int
+getsyshwaddr (char *buf, int len)
+{
+ struct if_nameindex *ifaces, *if_idx;
+ unsigned char mac[6];
+ struct ifreq ifr;
+ int fd;
+ int ret = -1;
+
+ memset (&mac, '\0', sizeof (mac));
+ /* Get the spatially unique node identifier */
+ fd = socket (AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0)
+ return (ret);
+
+ ifaces = if_nameindex ();
+ if (!ifaces)
+ return (ret);
+
+ for (if_idx = ifaces; if_idx->if_index; if_idx++)
+ {
+ strncpy (ifr.ifr_name, if_idx->if_name, IFNAMSIZ);
+ if (ioctl (fd, SIOCGIFFLAGS, &ifr) < 0)
+ continue;
+ if (ifr.ifr_ifru.ifru_flags & IFF_LOOPBACK)
+ continue;
+ if (ioctl (fd, SIOCGIFHWADDR, &ifr) < 0)
+ continue;
+ if (MACADDR_IS_ZERO (ifr.ifr_hwaddr.sa_data))
+ continue;
+ ret = 0;
+ break;
+ }
+ if_freenameindex (ifaces);
+ close (fd);
+
+ if (ret == 0)
+ {
+ if (len > 12)
+ {
+ memmove (mac, ifr.ifr_hwaddr.sa_data, 6);
+ sprintf (buf, "%02x%02x%02x%02x%02x%02x",
+ mac[0] & 0xFF, mac[1] & 0xFF, mac[2] & 0xFF,
+ mac[3] & 0xFF, mac[4] & 0xFF, mac[5] & 0xFF);
+ }
+ else if (len == 6)
+ {
+ memmove (buf, ifr.ifr_hwaddr.sa_data, 6);
+ }
+ }
+ return ret;
+}
+
+int
+get_remote_mac (struct in_addr ip_addr, unsigned char *mac)
+{
+ struct in_addr arp_ent;
+ FILE *arp;
+ char remote_ip[16];
+ int matches, hwtype, flags;
+ memset (mac, 0xFF, 6);
+
+ arp = fopen ("/proc/net/arp", "r");
+ if (!arp)
+ return 1;
+ while (!feof (arp))
+ {
+ matches = fscanf (arp, "%s 0x%X 0x%X %hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
+ remote_ip, &hwtype, &flags,
+ &mac[0], &mac[1], &mac[2], &mac[3], &mac[4],
+ &mac[5]);
+ if (matches != 9)
+ continue;
+ inet_pton (AF_INET, remote_ip, &arp_ent);
+ if (ip_addr.s_addr == arp_ent.s_addr)
+ break;
+ mac[0] = 0xFF;
+ }
+ fclose (arp);
+
+ if (mac[0] == 0xFF)
+ {
+ memset (mac, 0xFF, 6);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/cleopatre/application/upnpd/src/minissdp.c b/cleopatre/application/upnpd/src/minissdp.c
new file mode 100644
index 0000000000..017ed36b8d
--- /dev/null
+++ b/cleopatre/application/upnpd/src/minissdp.c
@@ -0,0 +1,604 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "config.h"
+#include "upnpdescstrings.h"
+#include "upnpdpath.h"
+#include "upnphttp.h"
+#include "upnpglobalvars.h"
+#include "minissdp.h"
+#include <sys/un.h>
+#include <syslog.h>
+#include <stdlib.h>
+#include <errno.h>
+
+
+
+
+static int
+AddMulticastMembership (int s, in_addr_t ifaddr)
+{
+ struct ip_mreq imr;
+ /* setting up imr structure */
+ imr.imr_multiaddr.s_addr = inet_addr (SSDP_MCAST_ADDR);
+ imr.imr_interface.s_addr = ifaddr;
+ if (setsockopt
+ (s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *) &imr,
+ sizeof (struct ip_mreq)) < 0)
+ {
+ syslog (LOG_ERR, "setsockopt(udp, IP_ADD_MEMBERSHIP): (%d) %m",
+ errno);
+ return -1;
+ }
+ return 0;
+}
+
+
+
+
+
+/* Open and configure the socket listening for
+ * SSDP udp packets sent on 239.255.255.250 port 1900 */
+int
+OpenAndConfSSDPReceiveSocket (void)
+{
+ int s;
+ int i = 1;
+ struct sockaddr_in sockname;
+
+ if ((s = socket (PF_INET, SOCK_DGRAM, 0)) < 0)
+ {
+ syslog (LOG_ERR, "socket(udp): %m");
+ return -1;
+ }
+
+ memset (&sockname, 0, sizeof (struct sockaddr_in));
+ sockname.sin_family = AF_INET;
+ sockname.sin_port = htons (SSDP_PORT);
+ sockname.sin_addr.s_addr = htonl (INADDR_ANY);
+
+
+
+ if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof (i)) < 0)
+ {
+ syslog (LOG_WARNING, "setsockopt(udp, SO_REUSEADDR): %m");
+ }
+
+
+ if (bind (s, (struct sockaddr *) &sockname, sizeof (struct sockaddr_in)) <
+ 0)
+ {
+ syslog (LOG_ERR, "bind(udp): %m");
+ close (s);
+ return -1;
+ }
+
+ i = n_lan_addr;
+ while (i > 0)
+ {
+ i--;
+ if (AddMulticastMembership (s, lan_addr[i].addr.s_addr) < 0)
+ {
+ syslog (LOG_WARNING,
+ "Failed to add multicast membership for address %s",
+ lan_addr[i].str);
+ }
+ else
+ {
+ syslog (LOG_WARNING,
+ "Successfully added multicast membership for adress %s",
+ lan_addr[i].str);
+ }
+ }
+ return s;
+}
+
+
+
+/* open the UDP socket used to send SSDP notifications to
+ * the multicast group reserved for them */
+static int
+OpenAndConfSSDPNotifySocket (in_addr_t addr)
+{
+ int s;
+ unsigned char loopchar = 0;
+ int bcast = 1;
+ struct in_addr mc_if;
+ struct sockaddr_in sockname;
+
+ if ((s = socket (PF_INET, SOCK_DGRAM, 0)) < 0)
+ {
+ syslog (LOG_ERR, "socket(udp_notify): %m");
+ return -1;
+ }
+
+ mc_if.s_addr = htonl (INADDR_ANY);
+ if (setsockopt
+ (s, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &loopchar,
+ sizeof (loopchar)) < 0)
+ {
+ syslog (LOG_ERR, "setsockopt(udp_notify, IP_MULTICAST_LOOP): %m");
+ close (s);
+ return -1;
+ }
+ if (setsockopt
+ (s, IPPROTO_IP, IP_MULTICAST_IF, (char *) &mc_if, sizeof (mc_if)) < 0)
+ {
+ syslog (LOG_ERR, "setsockopt(udp_notify, IP_MULTICAST_IF): %m");
+ close (s);
+ return -1;
+ }
+
+ if (setsockopt (s, SOL_SOCKET, SO_BROADCAST, &bcast, sizeof (bcast)) < 0)
+ {
+ syslog (LOG_ERR, "setsockopt(udp_notify, SO_BROADCAST): %m");
+ close (s);
+ return -1;
+ }
+
+ memset (&sockname, 0, sizeof (struct sockaddr_in));
+ sockname.sin_family = AF_INET;
+ sockname.sin_addr.s_addr = addr;
+
+ if (bind (s, (struct sockaddr *) &sockname, sizeof (struct sockaddr_in)) <
+ 0)
+ {
+ syslog (LOG_ERR, "bind(udp_notify): %m");
+ close (s);
+ return -1;
+ }
+
+ return s;
+}
+
+int
+OpenAndConfSSDPNotifySockets (int *sockets)
+{
+ int i, j;
+
+ for (i = 0; i < n_lan_addr; i++)
+ {
+ lan_addr[i].addr.s_addr = inet_addr (SSDP_MCAST_ADDR);
+ sockets[i] = OpenAndConfSSDPNotifySocket (lan_addr[i].addr.s_addr);
+ if (sockets[i] < 0)
+ {
+ for (j = 0; j < i; j++)
+ {
+ close (sockets[j]);
+ sockets[j] = -1;
+ }
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * response from a LiveBox (Wanadoo)
+ HTTP/1.1 200 OK
+ CACHE-CONTROL: max-age=1800
+DATE: Thu, 01 Jan 1970 04:03:23 GMT
+EXT:
+LOCATION: http://192.168.0.1:49152/gatedesc.xml
+SERVER: Linux/2.4.17, UPnP/1.0, Intel SDK for UPnP devices /1.2
+ST: upnp:rootdevice
+USN: uuid:75802409-bccb-40e7-8e6c-fa095ecce13e::upnp:rootdevice
+
+ * response from a Linksys 802.11b :
+ HTTP/1.1 200 OK
+ Cache-Control:max-age=120
+Location:http://192.168.5.1:5678/rootDesc.xml
+Server:NT/5.0 UPnP/1.0
+ST:upnp:rootdevice
+USN:uuid:upnp-InternetGatewayDevice-1_0-0090a2777777::upnp:rootdevice
+EXT:
+*/
+
+
+static const char *const known_service_types[] = {
+ uuidvalue,
+ "upnp:rootdevice",
+ "urn:schemas-upnp-org:device:ManageableDevice:1",
+ "urn:schemas-upnp-org:service:BasicManagement:1",
+ "urn:schemas-upnp-org:service:ConfigurationManagement:1",
+ "urn:schemas-upnp-org:service:SoftwareManagement:1",
+ "urn:schemas-upnp-org:service:LowPowerDevice:1",
+ 0
+};
+
+
+
+
+
+
+/* not really an SSDP "announce" as it is the response
+ * to a SSDP "M-SEARCH" */
+static void
+SendSSDPAnnounce2 (int s, struct sockaddr_in sockname, int st_no,
+ const char *host, unsigned short port)
+{
+ int l, n = 0;
+ char buf[512];
+ /* TODO :
+ * follow guideline from document "UPnP Device Architecture 1.0"
+ * put in uppercase.
+ * DATE: is recommended
+ * SERVER: OS/ver UPnP/1.0 minidlna/1.0
+ * - check what to put in the 'Cache-Control' header
+ * */
+ char szTime[30];
+ time_t tTime = time (NULL);
+ strftime (szTime, 30, "%a, %d %b %Y %H:%M:%S GMT", gmtime (&tTime));
+
+ l = snprintf (buf, sizeof (buf), "HTTP/1.1 200 OK\r\n"
+ "CACHE-CONTROL: max-age=%u\r\n"
+ "DATE: %s\r\n"
+ "ST: %s%s\r\n"
+ "USN: %s%s%s%s\r\n"
+ "EXT:\r\n"
+ "SERVER: " UPNPD_SERVER_STRING "\r\n"
+ "LOCATION: http://%s:%u" ROOTDESC_PATH "\r\n"
+ "Content-Length: 0\r\n"
+ "\r\n",
+ (runtime_vars.notify_interval << 1) + 10,
+ szTime,
+ known_service_types[st_no], (st_no > 1 ? "1" : ""),
+ uuidvalue, (st_no > 0 ? "::" : ""),
+ (st_no > 0 ? known_service_types[st_no] : ""),
+ (st_no > 1 ? "1" : ""), host, (unsigned int) port);
+#ifdef MSG
+ syslog (LOG_INFO, "SSDP Announce %d bytes to %s:%d ST: %.*s", n,
+ inet_ntoa (sockname.sin_addr), ntohs (sockname.sin_port), l, buf);
+ syslog (LOG_WARNING, "Sending M-SEARCH response:\n%s", buf);
+#endif
+ n = sendto (s, buf, l, 0,
+ (struct sockaddr *) &sockname, sizeof (struct sockaddr_in));
+
+#ifdef MSG
+ syslog (LOG_INFO, "SSDP Announce %d bytes to %s:%d ST: %.*s", n,
+ inet_ntoa (sockname.sin_addr), ntohs (sockname.sin_port), l, buf);
+#endif
+ if (n < 0)
+ {
+ syslog (LOG_ERR, "sendto(udp): %m");
+ }
+}
+
+
+
+
+void
+SendSSDPNotifies (int s, const char *host, unsigned short port,
+ unsigned int lifetime)
+{
+ struct sockaddr_in sockname;
+ int l, n, dup, i = 0;
+ char bufr[512];
+
+ memset (&sockname, 0, sizeof (struct sockaddr_in));
+
+ sockname.sin_family = AF_INET;
+ sockname.sin_port = htons (SSDP_PORT);
+ sockname.sin_addr.s_addr = inet_addr (SSDP_MCAST_ADDR);
+
+ for (dup = 0; dup < 2; dup++)
+ {
+ if (dup)
+ usleep (200000);
+ i = 0;
+ while (known_service_types[i])
+ {
+ l = snprintf (bufr, sizeof (bufr),
+ "NOTIFY * HTTP/1.1\r\n"
+ "HOST:%s:%d\r\n"
+ "CACHE-CONTROL:max-age=%u\r\n"
+ "LOCATION:http://%s:%d" ROOTDESC_PATH "\r\n"
+ "SERVER: " UPNPD_SERVER_STRING "\r\n"
+ "NT:%s%s\r\n"
+ "USN:%s%s%s%s\r\n"
+ "NTS:ssdp:alive\r\n"
+ "\r\n",
+ SSDP_MCAST_ADDR, SSDP_PORT,
+ lifetime,
+ host, port,
+ known_service_types[i], (i > 1 ? "1" : ""),
+ uuidvalue, (i > 0 ? "::" : ""),
+ (i > 0 ? known_service_types[i] : ""),
+ (i > 1 ? "1" : ""));
+ /*casting int l into unsigned could result in a false value (unsigned int)(-1)= 4294967295.... */
+ if (l < 0)
+ {
+ syslog (LOG_WARNING, "snprintf error");
+ }
+ else
+ {
+ if ((unsigned int) (l) >= sizeof (bufr))
+ {
+ syslog (LOG_WARNING,
+ "SendSSDPNotifies(): truncated output\n");
+ l = sizeof (bufr);
+
+ }
+ }
+#ifdef MSG
+ syslog (LOG_WARNING, "Sending NOTIFY:\n%s", bufr);
+#endif
+ n = sendto (s, bufr, l, 0,
+ (struct sockaddr *) &sockname,
+ sizeof (struct sockaddr_in));
+ if (n < 0)
+ {
+ syslog (LOG_WARNING, "sendto(udp_notify=%d, %s): %s\n", s,
+ host, strerror (errno));
+ }
+ i++;
+ }
+ }
+}
+
+
+
+
+void
+SendSSDPNotifies2 (int *sockets, unsigned short port, unsigned int lifetime)
+{
+ int i;
+ for (i = 0; i < n_lan_addr; i++)
+ {
+ SendSSDPNotifies (sockets[i], lan_addr[i].str, port, lifetime);
+ }
+}
+
+
+
+
+/* ProcessSSDPRequest()
+ * process SSDP M-SEARCH requests and responds to them */
+void
+ProcessSSDPRequest (int s, unsigned short port)
+{
+ syslog (LOG_ERR, "Processing SSDP M-Search\n");
+
+ int n;
+ char bufr[1500];
+ socklen_t len_r;
+ struct sockaddr_in sendername;
+ int i, l;
+ int lan_addr_index = 0;
+ char *st = NULL, *mx = NULL, *man = NULL, *mx_end = NULL;
+ int st_len = 0, mx_len = 0, man_len = 0, mx_val = 0;
+ len_r = sizeof (struct sockaddr_in);
+
+ n = recvfrom (s, bufr, sizeof (bufr), 0,
+ (struct sockaddr *) &sendername, &len_r);
+ if (n < 0)
+ {
+ syslog (LOG_ERR, "recvfrom(udp): %m");
+ return;
+ }
+
+ if (memcmp (bufr, "NOTIFY", 6) == 0)
+ {
+ /* ignore NOTIFY packets. We could log the sender and device type */
+ return;
+ }
+ else if (memcmp (bufr, "M-SEARCH", 8) == 0)
+ {
+#ifdef DEBUG
+ syslog (LOG_WARNING, "Received SSDP request:\n%.*s", n, bufr);
+#endif
+ /*Loop to check http version */
+
+ for (i = 0; i < n; i++)
+ {
+ if (bufr[i] == '*')
+ break;
+ }
+ if (!strcasestr (bufr + i, "HTTP/1.1"))
+ {
+ return;
+ }
+
+
+ while (i < n)
+ {
+ while ((i < n - 1) && (bufr[i] != '\r' || bufr[i + 1] != '\n'))
+ i++;
+ i += 2;
+ if ((i < n - 3) && (strncasecmp (bufr + i, "ST:", 3) == 0))
+ {
+ st = bufr + i + 3;
+ st_len = 0;
+ while (*st == ' ' || *st == '\t')
+ st++;
+ while (st[st_len] != '\r' && st[st_len] != '\n')
+ st_len++;
+ }
+ else if (strncasecmp (bufr + i, "MX:", 3) == 0)
+ {
+ mx = bufr + i + 3;
+ mx_len = 0;
+ while (*mx == ' ' || *mx == '\t')
+ mx++;
+ while (mx[mx_len] != '\r' && mx[mx_len] != '\n')
+ mx_len++;
+ mx_val = strtol (mx, &mx_end, 10);
+ }
+ else if (strncasecmp (bufr + i, "MAN:", 4) == 0)
+ {
+ man = bufr + i + 4;
+ man_len = 0;
+ while (*man == ' ' || *man == '\t')
+ man++;
+ while (man[man_len] != '\r' && man[man_len] != '\n')
+ man_len++;
+ }
+ }
+ syslog (LOG_WARNING, "SSDP M-SEARCH packet received from %s:%d\n",
+ inet_ntoa (sendername.sin_addr), ntohs (sendername.sin_port));
+ if (ntohs (sendername.sin_port) <= 1024
+ || ntohs (sendername.sin_port) == 1900)
+ {
+ syslog (LOG_WARNING,
+ "WARNING: Ignoring invalid SSDP M-SEARCH from %s [bad source port %d]\n",
+ inet_ntoa (sendername.sin_addr),
+ ntohs (sendername.sin_port));
+ }
+ else if (!man || (strncmp (man, "\"ssdp:discover\"", 15) != 0))
+ {
+ syslog (LOG_WARNING,
+ "WARNING: Ignoring invalid SSDP M-SEARCH from %s [bad MAN header %.*s]\n",
+ inet_ntoa (sendername.sin_addr), man_len, man);
+ }
+ else if (!mx || mx == mx_end || mx_val < 0)
+ {
+ syslog (LOG_WARNING,
+ "WARNING: Ignoring invalid SSDP M-SEARCH from %s [bad MX header %.*s]\n",
+ inet_ntoa (sendername.sin_addr), mx_len, mx);
+ }
+ else if (st && (st_len > 0))
+ {
+ syslog (LOG_WARNING,
+ "SSDP M-SEARCH from %s:%d ST: %.*s, MX: %.*s, MAN: %.*s\n",
+ inet_ntoa (sendername.sin_addr),
+ ntohs (sendername.sin_port), st_len, st, mx_len, mx,
+ man_len, man);
+ /* find in which sub network the client is */
+ for (i = 0; i < n_lan_addr; i++)
+ {
+ if ((sendername.sin_addr.s_addr & lan_addr[i].mask.s_addr)
+ == (lan_addr[i].addr.s_addr & lan_addr[i].mask.s_addr))
+ {
+ lan_addr_index = i;
+ break;
+ }
+ }
+ /* Responds to request with a device as ST header */
+ for (i = 0; known_service_types[i]; i++)
+ {
+ l = strlen (known_service_types[i]);
+ if (l <= st_len
+ && (0 == memcmp (st, known_service_types[i], l)))
+ {
+ /* Check version number - must always be 1 currently. */
+ if ((st[st_len - 2] == ':')
+ && (atoi (st + st_len - 1) != 1))
+ break;
+ usleep (random () >> 20);
+ SendSSDPAnnounce2 (s, sendername,
+ i, lan_addr[lan_addr_index].str, port);
+ break;
+ }
+ }
+ /* Responds to request with ST: ssdp:all */
+ if (st_len == 8 && (0 == memcmp (st, "ssdp:all", 8)))
+ {
+ for (i = 0; known_service_types[i]; i++)
+ {
+ l = (int) strlen (known_service_types[i]);
+ SendSSDPAnnounce2 (s, sendername,
+ i, lan_addr[lan_addr_index].str, port);
+ }
+ }
+ }
+ else
+ {
+ syslog (LOG_WARNING, "Invalid SSDP M-SEARCH from %s:%d\n",
+ inet_ntoa (sendername.sin_addr),
+ ntohs (sendername.sin_port));
+
+ }
+ }
+ else
+ {
+ syslog (LOG_WARNING, "Unknown udp packet received from %s:%d\n",
+ inet_ntoa (sendername.sin_addr), ntohs (sendername.sin_port));
+ }
+}
+
+
+
+
+/*This will inform the network that UPnP is going down. */
+int
+SendSSDPGoodbye (int *sockets, int n_sockets)
+{
+ struct sockaddr_in sockname;
+ int n, l;
+ int i, j;
+ char bufr[512];
+
+ memset (&sockname, 0, sizeof (struct sockaddr_in));
+ sockname.sin_family = AF_INET;
+ sockname.sin_port = htons (SSDP_PORT);
+ sockname.sin_addr.s_addr = inet_addr (SSDP_MCAST_ADDR);
+
+ for (j = 0; j < n_sockets; j++)
+ {
+ for (i = 0; known_service_types[i]; i++)
+ {
+ l = snprintf (bufr, sizeof (bufr),
+ "NOTIFY * HTTP/1.1\r\n"
+ "HOST:%s:%d\r\n"
+ "NT:%s%s\r\n"
+ "USN:%s%s%s%s\r\n"
+ "NTS:ssdp:byebye\r\n"
+ "\r\n",
+ SSDP_MCAST_ADDR, SSDP_PORT,
+ known_service_types[i], (i > 1 ? "1" : ""),
+ uuidvalue, (i > 0 ? "::" : ""),
+ (i > 0 ? known_service_types[i] : ""),
+ (i > 1 ? "1" : ""));
+#ifdef MSG
+ syslog (LOG_WARNING, "Sending NOTIFY:\n%s", bufr);
+#endif
+ n = sendto (sockets[j], bufr, l, 0,
+ (struct sockaddr *) &sockname,
+ sizeof (struct sockaddr_in));
+ if (n < 0)
+ {
+ syslog (LOG_WARNING, "sendto(udp_shutdown=%d): %s\n",
+ sockets[j], strerror (errno));
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
diff --git a/cleopatre/application/upnpd/src/minixml.c b/cleopatre/application/upnpd/src/minixml.c
new file mode 100644
index 0000000000..098e5dbba1
--- /dev/null
+++ b/cleopatre/application/upnpd/src/minixml.c
@@ -0,0 +1,214 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "minixml.h"
+#include <string.h>
+
+
+
+/* parseatt : used to parse the argument list
+ * return 0 (false) in case of success and -1 (true) if the end
+ * of the xmlbuffer is reached. */
+
+int
+parseatt (struct xmlparser *p)
+{
+ const char *attname;
+ int attnamelen;
+ const char *attvalue;
+ int attvaluelen;
+ while (p->xml < p->xmlend)
+ {
+ if (*p->xml == '/' || *p->xml == '>')
+ return 0;
+ if (!IS_WHITE_SPACE (*p->xml))
+ {
+ char sep;
+ attname = p->xml;
+ attnamelen = 0;
+ while (*p->xml != '=' && !IS_WHITE_SPACE (*p->xml))
+ {
+ attnamelen++;
+ p->xml++;
+ if (p->xml >= p->xmlend)
+ return -1;
+ }
+ while (*(p->xml++) != '=')
+ {
+ if (p->xml >= p->xmlend)
+ return -1;
+ }
+ while (IS_WHITE_SPACE (*p->xml))
+ {
+ p->xml++;
+ if (p->xml >= p->xmlend)
+ return -1;
+ }
+ sep = *p->xml;
+ if (sep == '\'' || sep == '\"')
+ {
+ p->xml++;
+ if (p->xml >= p->xmlend)
+ return -1;
+ attvalue = p->xml;
+ attvaluelen = 0;
+ while (*p->xml != sep)
+ {
+ attvaluelen++;
+ p->xml++;
+ if (p->xml >= p->xmlend)
+ return -1;
+ }
+ }
+ else
+ {
+ attvalue = p->xml;
+ attvaluelen = 0;
+ while (!IS_WHITE_SPACE (*p->xml)
+ && *p->xml != '>' && *p->xml != '/')
+ {
+ attvaluelen++;
+ p->xml++;
+ if (p->xml >= p->xmlend)
+ return -1;
+ }
+ }
+ if (p->attfunc)
+ p->attfunc (p->data, attname, attnamelen, attvalue,
+ attvaluelen);
+ }
+ p->xml++;
+ }
+ return -1;
+}
+
+
+
+
+
+
+/* parseelt parse the xml stream and
+ * call the callback functions when needed... */
+
+
+void
+parseelt (struct xmlparser *p)
+{
+ int i;
+ const char *elementname;
+ while (p->xml < (p->xmlend - 1))
+ {
+ if ((p->xml)[0] == '<' && (p->xml)[1] != '?')
+ {
+ i = 0;
+ elementname = ++p->xml;
+ while (!IS_WHITE_SPACE (*p->xml)
+ && (*p->xml != '>') && (*p->xml != '/'))
+ {
+ i++;
+ p->xml++;
+ if (p->xml >= p->xmlend)
+ return;
+ /* to ignore namespace : */
+ if (*p->xml == ':')
+ {
+ i = 0;
+ elementname = ++p->xml;
+ }
+ }
+ if (i > 0)
+ {
+ if (p->starteltfunc)
+ p->starteltfunc (p->data, elementname, i);
+ if (parseatt (p))
+ return;
+ if (*p->xml != '/')
+ {
+ const char *data;
+ i = 0;
+ data = ++p->xml;
+ if (p->xml >= p->xmlend)
+ return;
+ while (IS_WHITE_SPACE (*p->xml))
+ {
+ p->xml++;
+ if (p->xml >= p->xmlend)
+ return;
+ }
+ while (*p->xml != '<')
+ {
+ i++;
+ p->xml++;
+ if (p->xml >= p->xmlend)
+ return;
+ }
+ if (i > 0 && p->datafunc)
+ p->datafunc (p->data, data, i);
+ }
+ }
+ else if (*p->xml == '/')
+ {
+ i = 0;
+ elementname = ++p->xml;
+ if (p->xml >= p->xmlend)
+ return;
+ while ((*p->xml != '>'))
+ {
+ i++;
+ p->xml++;
+ if (p->xml >= p->xmlend)
+ return;
+ }
+ if (p->endeltfunc)
+ p->endeltfunc (p->data, elementname, i);
+ p->xml++;
+ }
+ }
+ else
+ {
+ p->xml++;
+ }
+ }
+}
+
+/* the parser must be initialized before calling this function */
+void
+parsexml (struct xmlparser *parser)
+{
+ parser->xml = parser->xmlstart;
+ parser->xmlend = parser->xmlstart + parser->xmlsize;
+ parseelt (parser);
+}
diff --git a/cleopatre/application/upnpd/src/options.c b/cleopatre/application/upnpd/src/options.c
new file mode 100644
index 0000000000..5ea54b4728
--- /dev/null
+++ b/cleopatre/application/upnpd/src/options.c
@@ -0,0 +1,193 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "options.h"
+#include "upnpglobalvars.h"
+
+
+
+
+struct option *ary_options = NULL;
+int num_options = 0;
+
+static const struct
+{
+ enum upnpconfigoptions id;
+ const char *name;
+} optionids[] =
+{
+ {
+ UPNPIFNAME, "network_interface"},
+ {
+ UPNPLISTENING_IP, "listening_ip"},
+ {
+ UPNPPORT, "port"},
+ {
+ UPNPPRESENTATIONURL, "presentation_url"},
+ {
+ UPNPNOTIFY_INTERVAL, "notify_interval"},
+ {
+ UPNPUUID, "uuid"},
+ {
+ UPNPSERIAL, "serial"},
+ {
+ UPNPMODEL_NAME, "model_name"},
+ {
+ UPNPMODEL_NUMBER, "model_number"},
+ {
+UPNPFRIENDLYNAME, "friendly_name"},};
+
+
+int
+readoptionsfile (const char *fname)
+{
+ FILE *hfile = NULL;
+ char buffer[1024];
+ char *equals;
+ char *name;
+ char *value;
+ char *t;
+ int linenum = 0;
+ unsigned int i;
+ enum upnpconfigoptions id;
+
+ if (!fname || (strlen (fname) == 0))
+ return -1;
+
+ memset (buffer, 0, sizeof (buffer));
+
+
+ if (!(hfile = fopen (fname, "r")))
+ return -1;
+
+ if (ary_options != NULL)
+ {
+ free (ary_options);
+ num_options = 0;
+ }
+
+ while (fgets (buffer, sizeof (buffer), hfile))
+ {
+ linenum++;
+ t = strchr (buffer, '\n');
+ if (t)
+ {
+ *t = '\0';
+ t--;
+ while ((t >= buffer) && isspace (*t))
+ {
+ *t = '\0';
+ t--;
+ }
+ }
+
+ /* skip leading whitespaces */
+ name = buffer;
+ while (isspace (*name))
+ name++;
+
+ /* check for comments or empty lines */
+ if (name[0] == '#' || name[0] == '\0')
+ continue;
+
+ if (!(equals = strchr (name, '=')))
+ {
+ fprintf (stderr, "parsing error file %s line %d : %s\n",
+ fname, linenum, name);
+ continue;
+ }
+
+ /* remove ending whitespaces */
+ for (t = equals - 1; t > name && isspace (*t); t--)
+ *t = '\0';
+
+ *equals = '\0';
+ value = equals + 1;
+
+ /* skip leading whitespaces */
+ while (isspace (*value))
+ value++;
+
+ id = UPNP_INVALID;
+ for (i = 0; i < sizeof (optionids) / sizeof (optionids[0]); i++)
+ {
+
+ if (0 == strcmp (name, optionids[i].name))
+ {
+ id = optionids[i].id;
+ break;
+ }
+ }
+
+ if (id == UPNP_INVALID)
+ {
+ fprintf (stderr, "parsing error file %s line %d : %s=%s\n",
+ fname, linenum, name, value);
+ }
+ else
+ {
+ num_options += 1;
+ ary_options =
+ (struct option *) realloc (ary_options,
+ num_options *
+ sizeof (struct option));
+
+ ary_options[num_options - 1].id = id;
+ strncpy (ary_options[num_options - 1].value, value,
+ MAX_OPTION_VALUE_LEN);
+ }
+
+ }
+
+ fclose (hfile);
+
+ return 0;
+}
+
+void
+freeoptions (void)
+{
+ if (ary_options)
+ {
+ free (ary_options);
+ ary_options = NULL;
+ num_options = 0;
+ }
+}
diff --git a/cleopatre/application/upnpd/src/upnpd.c b/cleopatre/application/upnpd/src/upnpd.c
new file mode 100644
index 0000000000..4b60f3ad57
--- /dev/null
+++ b/cleopatre/application/upnpd/src/upnpd.c
@@ -0,0 +1,809 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <time.h>
+#include <signal.h>
+#include <sys/param.h>
+#include <syslog.h>
+#include <errno.h>
+#include "upnpglobalvars.h"
+#include "upnphttp.h"
+#include "upnpdescgen.h"
+#include "upnpdpath.h"
+#include "getifaddr.h"
+#include "upnpsoap.h"
+#include "options.h"
+#include "minissdp.h"
+#include "upnpdtypes.h"
+#include "daemonize.h"
+#include "upnpevents.h"
+#include "config.h"
+
+
+
+
+/*OpenAndConfHTTPSocket()
+ * setup the socket used to handle incoming HTTP connections. */
+static int
+OpenAndConfHTTPSocket (unsigned short port)
+{
+ int s;
+ int i = 1;
+ struct sockaddr_in listenname;
+
+ if ((s = socket (PF_INET, SOCK_STREAM, 0)) < 0)
+ {
+ syslog (LOG_ERR, "socket(http): %m");
+ return -1;
+ }
+
+ if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof (i)) < 0)
+ {
+ syslog (LOG_WARNING, "setsockopt(http, SO_REUSEADDR): %m");
+ }
+
+ memset (&listenname, 0, sizeof (struct sockaddr_in));
+ listenname.sin_family = AF_INET;
+ listenname.sin_port = htons (port);
+ listenname.sin_addr.s_addr = htonl (INADDR_ANY);
+
+ if (bind (s, (struct sockaddr *) &listenname, sizeof (struct sockaddr_in))
+ < 0)
+ {
+ syslog (LOG_ERR, "bind(http): %m");
+ close (s);
+ return -1;
+ }
+
+ if (listen (s, 6) < 0)
+ {
+ syslog (LOG_ERR, "listen(http): %m");
+ close (s);
+ return -1;
+ }
+
+ return s;
+}
+
+/* Handler for the SIGTERM signal (kill)
+ * SIGINT is also handled */
+static void
+sigterm (int sig)
+{
+ signal (sig, SIG_IGN); /* Ignore this signal while we are quitting */
+
+
+ syslog (LOG_NOTICE, "received signal %d, good-bye", sig);
+
+ quitting = 1;
+}
+
+/* record the startup time, for returning uptime */
+static void
+set_startup_time (void)
+{
+ startup_time = time (NULL);
+}
+
+/* parselanaddr()
+ * parse address with mask
+ * ex: 192.168.1.1/24
+ * return value :
+ * 0 : ok
+ * -1 : error */
+static int
+parselanaddr (struct lan_addr_s *lan_addr, const char *str)
+{
+ const char *p;
+ int nbits = 24;
+ int n;
+ p = str;
+ while (*p && *p != '/' && !isspace (*p))
+ p++;
+ n = p - str;
+ if (*p == '/')
+ {
+ nbits = atoi (++p);
+ while (*p && !isspace (*p))
+ p++;
+ }
+ if (n > 15)
+ {
+ syslog (LOG_WARNING, "Error parsing address/mask %s\n", str);
+ return -1;
+ }
+ memcpy (lan_addr->str, str, n);
+ lan_addr->str[n] = '\0';
+ if (!inet_aton (lan_addr->str, &lan_addr->addr))
+ {
+ syslog (LOG_WARNING, "Error parsing address/mask: %s\n", str);
+ return -1;
+ }
+ lan_addr->mask.s_addr = htonl (nbits ? (0xffffffff << (32 - nbits)) : 0);
+ return 0;
+}
+
+void
+getfriendlyname (char *buf, int len)
+{
+ char *dot = NULL;
+ char *hn = calloc (1, 256);
+ int off;
+ if (gethostname (hn, 256) == 0)
+ {
+ strncpy (buf, hn, len - 1);
+ buf[len-1] = '\0';
+ dot = strchr (buf, '.');
+ if (dot)
+ *dot = '\0';
+ }
+ else
+ {
+ strcpy (buf, "Unknown");
+ }
+ free (hn);
+ off = strlen (buf);
+ off += snprintf (buf + off, len - off, ": ");
+}
+
+
+
+/*skpi spaces configuration file
+ * 2) read command line arguments
+ * 3) daemonize
+ * 4) open syslog
+ * 5) check and write pid file
+ * 6) set startup time stamp;;eo
+ * 7) compute presentation URL
+ * 8) set signal handlers */
+
+static int
+init (int argc, char * *argv)
+{
+ int i;
+ int pid = 0;
+ int debug_flag = 0;
+ int options_flag = 0;
+ struct sigaction sa;
+ char ext_ip_addr[INET_ADDRSTRLEN] = { '\0' };
+ const char *presurl = 0;
+ const char *optionsfile = "/usr/local/etc/upnpd.conf";
+ char mac_str[13];
+ openlog ("upnpd", LOG_ODELAY, LOG_USER);
+ /* first check if "-f" option is used */
+ for (i = 2; i < argc; i++)
+ {
+ if (0 == strcmp (argv[i - 1], "-f"))
+ {
+ optionsfile = argv[i];
+ options_flag = 1;
+ break;
+ }
+ }
+ /* set up uuid based on mac address */
+ if (getsyshwaddr (mac_str, sizeof (mac_str)) < 0)
+ {
+ syslog (LOG_WARNING,
+ "No MAC address found. Falling back to generic UUID.\n");
+ strcpy (mac_str, "554e4b4e4f57");
+ }
+ strcpy (uuidvalue + 5, "4d696e69-444c-164e-9d41-");
+ strncat (uuidvalue, mac_str, 12);
+ getfriendlyname (friendly_name, FRIENDLYNAME_MAX_LEN);
+ runtime_vars.port = -1;
+ runtime_vars.notify_interval = 3; /* seconds between SSDP announces */
+
+ /* read options file first since
+ * command line arguments have final say */
+ if (readoptionsfile (optionsfile) < 0)
+ {
+ /* only error if file exists or using -f */
+ if (access (optionsfile, F_OK) == 0 || options_flag)
+ syslog (LOG_WARNING, "Error reading configuration file.\n");
+ }
+ else
+ {
+ for (i = 0; i < num_options; i++)
+ {
+ switch (ary_options[i].id)
+ {
+ case UPNPIFNAME:
+ if (getifaddr
+ (ary_options[i].value, ext_ip_addr, INET_ADDRSTRLEN) >= 0)
+ {
+ if (*ext_ip_addr
+ && parselanaddr (&lan_addr[n_lan_addr],
+ ext_ip_addr) == 0)
+ n_lan_addr++;
+ }
+ else
+ fprintf (stderr, "Interface %s not found, ignoring.\n",
+ ary_options[i].value);
+ break;
+ case UPNPLISTENING_IP:
+ if (n_lan_addr < MAX_LAN_ADDR)
+ {
+ if (parselanaddr (&lan_addr[n_lan_addr],
+ ary_options[i].value) == 0)
+ n_lan_addr++;
+ }
+ else
+ {
+ fprintf (stderr,
+ "Too many listening ips (max: %d), ignoring %s\n",
+ MAX_LAN_ADDR, ary_options[i].value);
+ }
+ break;
+ case UPNPPORT:
+ runtime_vars.port = atoi (ary_options[i].value);
+ break;
+ case UPNPPRESENTATIONURL:
+ presurl = ary_options[i].value;
+ break;
+ case UPNPNOTIFY_INTERVAL:
+ runtime_vars.notify_interval = atoi (ary_options[i].value);
+ break;
+ case UPNPSERIAL:
+ strncpy (serialnumber, ary_options[i].value,
+ SERIALNUMBER_MAX_LEN);
+ serialnumber[SERIALNUMBER_MAX_LEN - 1] = '\0';
+ break;
+ case UPNPMODEL_NAME:
+ strncpy (modelname, ary_options[i].value, MODELNAME_MAX_LEN);
+ modelname[MODELNAME_MAX_LEN - 1] = '\0';
+ break;
+ case UPNPMODEL_NUMBER:
+ strncpy (modelnumber, ary_options[i].value,
+ MODELNUMBER_MAX_LEN);
+ modelnumber[MODELNUMBER_MAX_LEN - 1] = '\0';
+ break;
+ case UPNPFRIENDLYNAME:
+ strncpy (friendly_name, ary_options[i].value,
+ FRIENDLYNAME_MAX_LEN);
+ friendly_name[FRIENDLYNAME_MAX_LEN - 1] = '\0';
+ break;
+ default:
+ fprintf (stderr, "Unknown option in file %s\n", optionsfile);
+ }
+ }
+ }
+ /* command line arguments processing */
+ for (i = 1; i < argc; i++)
+ {
+ if (argv[i][0] != '-')
+ {
+ fprintf (stderr, "Unknown option: %s\n", argv[i]);
+ }
+ else if (strcmp (argv[i], "--help") == 0)
+ {
+ runtime_vars.port = 0;
+ break;
+ }
+ else
+ switch (argv[i][1])
+ {
+ case 't':
+ if (i + 1 < argc)
+ runtime_vars.notify_interval = atoi (argv[++i]);
+ else
+ fprintf (stderr, "Option -%c takes one argument.\n",
+ argv[i][1]);
+ break;
+ case 's':
+ if (i + 1 < argc)
+ strncpy (serialnumber, argv[++i], SERIALNUMBER_MAX_LEN);
+ else
+ fprintf (stderr, "Option -%c takes one argument.\n",
+ argv[i][1]);
+ serialnumber[SERIALNUMBER_MAX_LEN - 1] = '\0';
+ break;
+ case 'm':
+ if (i + 1 < argc)
+ strncpy (modelnumber, argv[++i], MODELNUMBER_MAX_LEN);
+ else
+ fprintf (stderr, "Option -%c takes one argument.\n",
+ argv[i][1]);
+ modelnumber[MODELNUMBER_MAX_LEN - 1] = '\0';
+ break;
+ case 'p':
+ if (i + 1 < argc)
+ runtime_vars.port = atoi (argv[++i]);
+ else
+ fprintf (stderr, "Option -%c takes one argument.\n",
+ argv[i][1]);
+ break;
+ case 'P':
+ if (i + 1 < argc)
+ pidfilename = argv[++i];
+ else
+ fprintf (stderr, "Option -%c takes one argument.\n",
+ argv[i][1]);
+ break;
+ case 'd':
+ debug_flag = 1;
+ break;
+ case 'w':
+ if (i + 1 < argc)
+ presurl = argv[++i];
+ else
+ fprintf (stderr, "Option -%c takes one argument.\n",
+ argv[i][1]);
+ break;
+ case 'a':
+ if (i + 1 < argc)
+ {
+ int address_already_there = 0;
+ int j;
+ i++;
+ for (j = 0; j < n_lan_addr; j++)
+ {
+ struct lan_addr_s tmpaddr;
+ parselanaddr (&tmpaddr, argv[i]);
+ if (0 == strcmp (lan_addr[j].str, tmpaddr.str))
+ address_already_there = 1;
+ }
+ if (address_already_there)
+ break;
+ if (n_lan_addr < MAX_LAN_ADDR)
+ {
+ if (parselanaddr (&lan_addr[n_lan_addr], argv[i]) ==
+ 0)
+ n_lan_addr++;
+ }
+ else
+ {
+ fprintf (stderr,
+ "Too many listening ips (max: %d), ignoring %s\n",
+ MAX_LAN_ADDR, argv[i]);
+ }
+ }
+ else
+ fprintf (stderr, "Option -%c takes one argument.\n",
+ argv[i][1]);
+ break;
+ case 'i':
+ if (i + 1 < argc)
+ {
+ int address_already_there = 0;
+ int j;
+ i++;
+ if (getifaddr (argv[i], ext_ip_addr, INET_ADDRSTRLEN) < 0)
+ {
+ fprintf (stderr,
+ "Network interface '%s' not found.\n",
+ argv[i]);
+ exit (-1);
+ }
+ for (j = 0; j < n_lan_addr; j++)
+ {
+ struct lan_addr_s tmpaddr;
+ parselanaddr (&tmpaddr, ext_ip_addr);
+ if (0 == strcmp (lan_addr[j].str, tmpaddr.str))
+ address_already_there = 1;
+ }
+ if (address_already_there)
+ break;
+ if (n_lan_addr < MAX_LAN_ADDR)
+ {
+ if (parselanaddr (&lan_addr[n_lan_addr], ext_ip_addr)
+ == 0)
+ n_lan_addr++;
+ }
+ else
+ {
+ printf
+ ("Too many listening ips (max: %d), ignoring %s\n",
+ MAX_LAN_ADDR, argv[i]);
+ }
+ }
+ else
+ {
+ printf ("Option -%c takes one argument.\n", argv[i][1]);
+ }
+ break;
+ case 'f':
+ i++; /* discarding, the config file is already read */
+ break;
+ case 'h':
+ runtime_vars.port = 0; // triggers help display
+
+
+
+
+ break;
+ case 'V':
+ printf ("Version " UPNPD_VERSION "\n");
+ exit (0);
+ break;
+ default:
+ fprintf (stderr, "Unknown option: %s\n", argv[i]);
+ }
+ }
+ /* If no IP was specified, try to detect one */
+ if (n_lan_addr < 1)
+ {
+ if ((getsysaddr (ext_ip_addr, INET_ADDRSTRLEN) < 0) &&
+ (getifaddr ("eth0", ext_ip_addr, INET_ADDRSTRLEN) < 0) &&
+ (getifaddr ("eth1", ext_ip_addr, INET_ADDRSTRLEN) < 0))
+ {
+ syslog (LOG_WARNING, "No IP address automatically detected!\n");
+ }
+ if (*ext_ip_addr
+ && parselanaddr (&lan_addr[n_lan_addr], ext_ip_addr) == 0)
+ {
+ n_lan_addr++;
+ }
+ }
+
+ if ((n_lan_addr == 0) || (runtime_vars.port <= 0))
+ {
+ fprintf (stderr, "Usage:\n\t"
+ "%s [-d] [-f config_file]\n"
+ "\t\t[-a listening_ip] [-p port]\n"
+ /*"[-l logfile] " not functionnal */
+ "\t\t[-s serial] [-m model_number] \n"
+ "\t\t[-t notify_interval] [-P pid_filename]\n"
+ "\t\t[-w url] [-R] [-V] [-h]\n"
+ "\nNotes:\n\tNotify interval is in seconds. Default is 895 seconds.\n"
+ "\tDefault pid file is %s.\n"
+ "\tWith -d upnpd will run in debug mode (not daemonize).\n"
+ "\t-w sets the presentation url. Default is http address on port 80\n"
+ "\t-h displays this text\n"
+ "\t-R forces a full rescan\n"
+ "\t-V print the version number\n\n"
+ "\tShould check if the configuration file is available \n", argv[0], pidfilename);
+ return 1;
+ }
+
+
+
+
+ if (debug_flag)
+ {
+ pid = getpid ();
+ }
+ else
+ {
+ }
+ if (checkforrunning (pidfilename) < 0)
+ {
+ syslog (LOG_ERR, "upnpd is already running. EXITING");
+ return 1;
+ }
+
+ set_startup_time ();
+
+ /* presentation url */
+ if (presurl)
+ {
+ strncpy (presentationurl, presurl, PRESENTATIONURL_MAX_LEN);
+ presentationurl[PRESENTATIONURL_MAX_LEN - 1] = '\0';
+ }
+ else
+ {
+ snprintf (presentationurl, PRESENTATIONURL_MAX_LEN,
+ "http://%s:%d/", lan_addr[0].str, runtime_vars.port);
+ }
+ /* set signal handler */
+ signal (SIGCLD, SIG_IGN);
+ memset (&sa, 0, sizeof (struct sigaction));
+ sa.sa_handler = sigterm;
+
+ if (sigaction (SIGTERM, &sa, NULL))
+ {
+ syslog (LOG_WARNING, "Failed to set %s handler. EXITING", "SIGTERM");
+ return 1;
+ }
+ if (sigaction (SIGINT, &sa, NULL))
+ {
+ syslog (LOG_WARNING, "Failed to set %s handler. EXITING", "SIGINT");
+ return 1;
+ }
+
+ if (signal (SIGPIPE, SIG_IGN) == SIG_ERR)
+ {
+ syslog (LOG_WARNING, "Failed to ignore SIGPIPE signals");
+ }
+ writepidfile (pidfilename, pid);
+
+ return 0;
+}
+
+/* === main === */
+/* process HTTP or SSDP requests */
+int
+main (int argc, char * *argv)
+{
+ int i, send = 0, loop = 0;
+ int sudp = -1, shttpl = -1;
+ int snotify[MAX_LAN_ADDR];
+ LIST_HEAD (httplisthead, upnphttp) upnphttphead;
+ struct upnphttp *e = 0;
+ struct upnphttp *next;
+ fd_set readset; /* for select() */
+ fd_set writeset;
+ struct timeval timeout, timeofday, lastnotifytime = { 0, 0 };
+ int max_fd = -1;
+ if (init (argc, argv) != 0)
+ {
+ syslog (LOG_WARNING, "init error");
+ return 1;
+ }
+ LIST_INIT (&upnphttphead);
+ sudp = OpenAndConfSSDPReceiveSocket ();
+ if (sudp < 0)
+ {
+ syslog (LOG_ERR,
+ "Failed to open socket for receiving SSDP. EXITING\n");
+ }
+ /* open socket for HTTP connections. Listen on the 1st LAN address */
+ shttpl = OpenAndConfHTTPSocket (runtime_vars.port);
+ if (shttpl < 0)
+ {
+ syslog (LOG_ERR, "Failed to open socket for HTTP. EXITING\n");
+ }
+ else
+ {
+ syslog (LOG_WARNING, "HTTP Listening on port %d\n",
+ runtime_vars.port);
+ }
+ /* open socket for sending notifications */
+ if (OpenAndConfSSDPNotifySockets (snotify) < 0)
+ {
+ syslog (LOG_ERR,
+ "Failed to open sockets for sending SSDP notify messages. EXITING");
+ }
+ else
+ {
+ syslog (LOG_ERR,
+ "succeeded to open sockets for sending SSDP notify messages.");
+ }
+
+
+
+
+
+
+
+ /* main loop */
+ while (!quitting)
+ {
+ /* Check if we need to send SSDP NOTIFY messages and do it if
+ * needed */
+ if (gettimeofday (&timeofday, 0) < 0)
+ {
+ syslog (LOG_WARNING, "gettimeofday(): %s\n", strerror (errno));
+ timeout.tv_sec = runtime_vars.notify_interval;
+ timeout.tv_usec = 0;
+ }
+ else
+ {
+ /* the comparaison is not very precise but who cares ? */
+ if (timeofday.tv_sec >=
+ (lastnotifytime.tv_sec + runtime_vars.notify_interval))
+ {
+ send++;
+ SendSSDPNotifies2 (snotify,
+ (unsigned short) runtime_vars.port,
+ (runtime_vars.notify_interval << 1) + 10);
+ memcpy (&lastnotifytime, &timeofday, sizeof (struct timeval));
+ timeout.tv_sec = runtime_vars.notify_interval;
+ timeout.tv_usec = 0;
+ }
+ else
+ {
+ timeout.tv_sec =
+ lastnotifytime.tv_sec + runtime_vars.notify_interval -
+ timeofday.tv_sec;
+ if (timeofday.tv_usec > lastnotifytime.tv_usec)
+ {
+ timeout.tv_usec =
+ 1000000 + lastnotifytime.tv_usec - timeofday.tv_usec;
+ timeout.tv_sec--;
+ }
+ else
+ {
+ timeout.tv_usec =
+ lastnotifytime.tv_usec - timeofday.tv_usec;
+ }
+ }
+
+
+ }
+ /* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */
+ FD_ZERO (&readset);
+
+ if (sudp >= 0)
+ {
+ FD_SET (sudp, &readset);
+ max_fd = MAX (max_fd, sudp);
+ }
+
+ if (shttpl >= 0)
+ {
+ FD_SET (shttpl, &readset);
+ max_fd = MAX (max_fd, shttpl);
+ }
+ i = 0; /* active HTTP connections count */
+ for (e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
+ {
+ if ((e->socket >= 0) && (e->state <= 2))
+ {
+ FD_SET (e->socket, &readset);
+ max_fd = MAX (max_fd, e->socket);
+ i++;
+ }
+ }
+#ifdef DEBUG
+ /* for debug */
+ if (i > 1)
+ {
+ syslog (LOG_WARNING, "%d active incoming HTTP connections\n", i);
+ }
+#endif
+ FD_ZERO (&writeset);
+ upnpevents_selectfds (&readset, &writeset, &max_fd);
+
+ if (select (max_fd + 1, &readset, &writeset, 0, &timeout) < 0)
+ {
+ if (quitting)
+ goto shutdown;
+ syslog (LOG_ERR, "select(all): %s\n", strerror (errno));
+ syslog (LOG_WARNING, "Failed to select open sockets. EXITING\n");
+ }
+
+ upnpevents_processfds (&readset, &writeset);
+ /* process SSDP packets */
+ if (sudp >= 0 && FD_ISSET (sudp, &readset))
+ {
+ ProcessSSDPRequest (sudp, (unsigned short) runtime_vars.port);
+ }
+
+
+
+
+
+
+ /* process active HTTP connections */
+ for (e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
+ {
+ if ((e->socket >= 0) && (e->state <= 2)
+ && (FD_ISSET (e->socket, &readset)))
+ {
+ Process_upnphttp (e);
+ syslog (LOG_WARNING, "processing over");
+
+ }
+ }
+ /* process incoming HTTP connections */
+ if (shttpl >= 0 && FD_ISSET (shttpl, &readset))
+ {
+ int shttp;
+ socklen_t clientnamelen;
+ struct sockaddr_in clientname;
+ clientnamelen = sizeof (struct sockaddr_in);
+ shttp =
+ accept (shttpl, (struct sockaddr *) &clientname,
+ &clientnamelen);
+ if (shttp < 0)
+ {
+ syslog (LOG_WARNING, "accept(http): %s\n", strerror (errno));
+ }
+ else
+ {
+ struct upnphttp *tmp = 0;
+ syslog (LOG_WARNING, "HTTP connection from %s:%d\n",
+ inet_ntoa (clientname.sin_addr),
+ ntohs (clientname.sin_port));
+ /* Create a new upnphttp object and add it to
+ * the active upnphttp object list */
+ tmp = New_upnphttp (shttp);
+ if (tmp)
+ {
+ tmp->clientaddr = clientname.sin_addr;
+ LIST_INSERT_HEAD (&upnphttphead, tmp, entries);
+ }
+ else
+ {
+ syslog (LOG_WARNING, "New_upnphttp() failed\n");
+ close (shttp);
+ }
+ }
+ }
+ /* delete finished HTTP connections */
+ for (e = upnphttphead.lh_first; e != NULL;)
+ {
+ next = e->entries.le_next;
+ if (e->state >= 100)
+ {
+ LIST_REMOVE (e, entries);
+ Delete_upnphttp (e);
+ }
+ e = next;
+ }
+ }
+shutdown:
+ /* close out open sockets */
+ while (upnphttphead.lh_first != NULL)
+ {
+ e = upnphttphead.lh_first;
+ LIST_REMOVE (e, entries);
+ Delete_upnphttp (e);
+ }
+
+ if (sudp >= 0)
+ close (sudp);
+ if (shttpl >= 0)
+ close (shttpl);
+
+ if (SendSSDPGoodbye (snotify, n_lan_addr) < 0)
+ {
+ syslog (LOG_WARNING, "Failed to broadcast good-bye notifications\n");
+ }
+ else
+ {
+ syslog (LOG_WARNING, "Sent good-bye notifications\n");
+ }
+ for (i = 0; i < n_lan_addr; i++)
+ close (snotify[i]);
+
+
+
+
+ if (unlink (pidfilename) < 0)
+ {
+ syslog (LOG_WARNING, "Failed to remove pidfile %s: %s\n", pidfilename,
+ strerror (errno));
+ }
+
+ freeoptions ();
+
+
+ exit (EXIT_SUCCESS);
+}
diff --git a/cleopatre/application/upnpd/src/upnpdescgen.c b/cleopatre/application/upnpd/src/upnpdescgen.c
new file mode 100644
index 0000000000..d7e2a93a2c
--- /dev/null
+++ b/cleopatre/application/upnpd/src/upnpdescgen.c
@@ -0,0 +1,1192 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include "config.h"
+#include "getifaddr.h"
+#include "upnpdescgen.h"
+#include "upnpdpath.h"
+#include "upnpglobalvars.h"
+#include "upnpdescstrings.h"
+#define DESC_DEBUG
+#undef DESC_DEBUG
+#define SERVDESC_DEBUG
+#undef SERVDESC_DEBUG
+
+static const char *const upnptypes[] = {
+ "string", /*0 */
+ "boolean",
+ "ui2",
+ "ui4",
+ "i4",
+ "uri", /*5 */
+ "ui1",
+ "bin.base64",
+ "dateTime.tz",
+};
+
+static const char *const upnpdefaultvalues[] = {
+ 0,
+ "Unconfigured",
+};
+
+static const char *const upnpallowedvalues[] = {
+ /* Basic Management */
+ 0, /*DeviceStatus */
+ "OK", /*1 */
+ "Error",
+ "Warning",
+ "Fatal",
+ 0, /*A_ARG_TYPE_RebootStatus */
+ "RebootNow", /*6 */
+ "RebootLater",
+ 0, /*A_ARG_TYPE_TestType */
+ "NSLookup", /*9 */
+ "Ping",
+ "SelfTest",
+ "Traceroute",
+ 0, /*A_ARG_Type_TestState */
+ "Requested", /*14 */
+ "InProgress",
+ "Canceled",
+ "Completed",
+ 0, /*A_ARG_TYPE_DSCP */
+ "0", /*19 */
+ "63",
+ 0,
+ /*A_ARG_TYPE_PingStatus */
+ "Success", /*22 */
+ "Error_CannotResolveHostName",
+ "Error_Internal",
+ "Error_Other",
+ 0, /*A_ARG_TYPE_NSLookupStatus */
+ "Success", /*27 */
+ "Error_DNSServerNotResolved",
+ "Error_Internal",
+ "Error_Other",
+ 0, /*A_ARG_TYPE_TracerouteStatus */
+ "Success", /*32 */
+ "Error_CannotResolveHostName",
+ "Error_MaxHopCountExceeded",
+ "Error_Internal",
+ "Error_Other",
+ 0, /*A_ARG_TYPE_Interfaces */
+ "AllInterfaces", /*38 */
+ "RequestInterface",
+ "NorthboundInterfaces",
+ 0, /*ARG_TYPE_InterfaceResetStatus */
+ "Success", /*42 */
+ "Error",
+ 0, /*A_ARG_TYPE_LogLevel */
+ "Emergency", /*46 */
+ "Alert",
+ "Critical",
+ "Error",
+ "Warning",
+ "Notice",
+ "Informational",
+ "Debug",
+
+
+
+ /* Configuration Manager */
+ 0, /*A_ARG_TYPE_ChangeStatus */
+ "ChangesComitted", /*54 */
+ "ChangesApplied",
+
+
+
+ /* Software Management */
+ 0, /*A_ARG_TYPE_OperationState */
+ "Requested", /*57 */
+ "InProgress",
+ "Committed",
+ "Completed",
+ "Error",
+ 0, /*A_ARG_TYPE_Action */
+ "Install", /*63 */
+ "Update",
+ "Uninstall",
+ "Start",
+ "Stop",
+ 0, /*A_ARG_TYPE_ErrorDescription */
+ "Error_None", /*69 */
+ "Error_ConcurrentAccess",
+ "Error_MissingDependency",
+ "Error_Network",
+ "Error_CorruptedFile",
+ "Error_DiskFull",
+ "Error_Other",
+ 0, /*A_ARG_TYPE_DUType */
+ "Firmware", /*77 */
+ "Application",
+ "Configuration",
+ "Other",
+ 0, /*A_ARG_TYPE_DUState */
+ "Installing", /*82 */
+ "Unresolved",
+ "Installed",
+ "Uninstalling",
+ "Uninstalled",
+ 0, /*A_ARG_TYPE_EURequestedState */
+ "Active", /*88 */
+ "Inactive",
+ 0, /*A_ARG_TYPE_EUExecutionState */
+ "Running", /*91 */
+ "Stopped",
+ "Starting",
+ "Stopping",
+
+
+
+
+ /* Low Power Service */
+ 0, /*PowerState */
+ "0", /*Active *//*96 */
+ "1", /*Transparent */
+ "2", /*Deep Sleep online */
+ "4", /*Deep Sleep offline */
+ 0, /*ExternalPowerSupplySource */
+ "0", /*internal power source *//*101 */
+ "1", /*AC*/
+ 0
+};
+
+
+
+static const char xmlver[] = "<?xml version=\"1.0\"?>\r\n";
+static const char root_service[] =
+ "scpd xmlns=\"urn:schemas-upnp-org:service-1-0\"";
+static const char root_device[] =
+ "root xmlns=\"urn:schemas-upnp-org:device-1-0\"";
+/* root Description of the UPnP Device */
+/* Build the description with INITHELPER (First child index, Children count)*/
+static const struct XMLElt rootDesc[] = {
+ {root_device, INITHELPER (1, 2)},
+ {"specVersion", INITHELPER (3, 2)},
+ {"device", INITHELPER (5, 9)},
+ {"/major", "1"},
+ {"/minor", "0"},
+ {"/deviceType", "urn:schemas-upnp-org:device:ManageableDevice:1"},
+ {"/friendlyName", friendly_name}, /* required */
+ {"/manufacturer", ROOTDEV_MANUFACTURER}, /* required */
+ {"/manufacturerURL", ROOTDEV_MANUFACTURERURL}, /* optional */
+ {"/modelDescription", ROOTDEV_MODELDESCRIPTION}, /* recommended */
+ {"/modelName", modelname}, /* required */
+ {"/modelNumber", modelnumber},
+ {"/UDN", uuidvalue}, /* required */
+ {"serviceList", INITHELPER (14, 4)},
+ {"service", INITHELPER (18, 5)},
+ {"service", INITHELPER (23, 5)},
+ {"service", INITHELPER (28, 5)},
+ {"service", INITHELPER (33, 5)},
+ {"/serviceType", "urn:schemas-upnp-org:service:BasicManagement:1"},
+ {"/serviceId", "urn:upnp-org:serviceId:BasicManagement"},
+ {"/controlURL", BASICMANAGEMENT_CONTROLURL},
+ {"/eventSubURL", BASICMANAGEMENT_EVENTURL},
+ {"/SCPDURL", BASICMANAGEMENT_PATH},
+ {"/serviceType",
+ "urn:schemas-upnp-org:service:ConfigurationManagement:1"},
+ {"/serviceId", "urn:upnp-org:serviceId:ConfigurationManagement"},
+ {"/controlURL", CONFIGURATIONMANAGEMENT_CONTROLURL},
+ {"/eventSubURL", CONFIGURATIONMANAGEMENT_EVENTURL},
+ {"/SCPDURL", CONFIGURATIONMANAGEMENT_PATH},
+ {"/serviceType", "urn:schemas-upnp-org:service:SoftwareManagement:1"},
+ {"/serviceId", "urn:upnp-org:serviceId:SoftwareManagement"},
+ {"/controlURL", SOFTWAREMANAGEMENT_CONTROLURL},
+ {"/eventSubURL", SOFTWAREMANAGEMENT_EVENTURL},
+ {"/SCPDURL", SOFTWAREMANAGEMENT_PATH},
+ {"/serviceType", "urn:schemas-upnp-org:service:LowPowerDevice:1"},
+ {"/serviceId", "urn:upnp-org:serviceId:LowPowerDevice"},
+ {"/controlURL", LOWPOWERDEVICE_CONTROLURL},
+ {"/eventSubURL", LOWPOWERDEVICE_EVENTURL},
+ {"/SCPDURL", LOWPOWERDEVICE_PATH},
+ {0, 0}
+};
+
+
+
+
+/* Definition of Basic Management statevar(for each service) and arguments(for each action) */
+
+static const struct argument Reboot[] = {
+ {"RebootStatus", 2, 10},
+ {NULL, 0, 0}
+};
+
+/*Function without arguments*/
+static const struct argument BaselineReset[] = {
+ {NULL, 0, 0}
+};
+
+static const struct argument GetDeviceStatus[] = {
+ {"DeviceStatus", 2, 0},
+ {NULL, 0, 0}
+};
+
+static const struct argument SetSequenceMode[] = {
+ {"NewSequenceMode", 1, 1},
+ {"OldSequenceMode", 2, 1},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetSequenceMode[] = {
+ {"SequenceMode", 2, 1},
+ {NULL, 0, 0}
+};
+
+static const struct argument Ping[] = {
+ {"Host", 1, 14},
+ {"NumberOfRepetitions", 1, 7},
+ {"Timeout", 1, 9},
+ {"DataBlockSize", 1, 6},
+#if 0
+ {"DSCP",1,15},/*Though in the specification, DSCP option isn't available on SPC300's busybox ping command*/
+#endif
+ {"TestID", 2, 11},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetPingResult[] = {
+ {"TestID", 1, 11},
+ {"Status", 2, 18},
+ {"AdditionalInfo", 2, 5},
+ {"SuccessCount", 2, 7},
+ {"FailureCount", 2, 7},
+ {"AverageResponseTime", 2, 9},
+ {"MinimumResponseTime", 2, 9},
+ {"MaximumResponseTime", 2, 9},
+ {NULL, 0, 0}
+};
+
+static const struct argument NSLookup[] = {
+ {"HostName", 1, 17},
+ {"DNSServer", 1, 14},
+ {"NumberOfRepetitions", 1, 7},
+ {"Timeout", 1, 9},
+ {"TestID", 2, 11},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetNSLookupResult[] = {
+ {"TestID", 1, 11},
+ {"Status", 2, 19},
+ {"AdditionalInfo", 2, 5},
+ {"SuccessCount", 2, 7},
+ {"Result", 2, 20},
+ {NULL, 0, 0}
+};
+
+static const struct argument Traceroute[] = {
+ {"Host", 1, 14},
+ {"Timeout", 1, 9},
+ {"DataBlockSize", 1, 6},
+ {"MaxHopCount", 1, 7},
+ {"DSCP", 1, 15},
+ {"TestID", 2, 11},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetTracerouteResult[] = {
+ {"TestID", 1, 11},
+ {"Status", 2, 21},
+ {"AdditionalInfo", 2, 5},
+ {"ResponseTime", 2, 9},
+ {"HopHosts", 2, 16},
+ {NULL, 0, 0}
+};
+
+static const struct argument InterfaceReset[] = {
+ {"Interfaces", 1, 22},
+ {"TestID", 2, 11},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetInterfaceResetResult[] = {
+ {"TestID", 1, 11},
+ {"Status", 2, 23},
+ {"AdditionalInfo", 2, 5},
+ {"NumberOfSuccesses", 2, 6},
+ {"NumberOfFailures", 2, 6},
+ {NULL, 0, 0}
+};
+
+static const struct argument SelfTest[] = {
+ {"TestID", 2, 11},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetSelfTestResult[] = {
+ {"TestID", 1, 11},
+ {"Status", 2, 4},
+ {"AdditionalInfo", 2, 5},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetActiveTestIDs[] = {
+ {"ActiveTestIDs", 2, 2},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetTestInfo[] = {
+ {"TestID", 1, 11},
+ {"Type", 2, 12},
+ {"State", 2, 13},
+ {NULL, 0, 0}
+};
+
+static const struct argument CancelTest[] = {
+ {"TestID", 1, 11},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetLogURIs[] = {
+ {"LogURIs", 2, 3},
+ {NULL, 0, 0}
+};
+
+static const struct argument SetLogInfo[] = {
+ {"LogURI", 1, 24},
+ {"Enabled", 1, 4},
+ {"LogLevel", 1, 26},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetLogInfo[] = {
+ {"LogURI", 1, 24},
+ {"Configurable", 2, 4},
+ {"Enabled", 2, 4},
+ {"LogLevel", 2, 26},
+ {"LogURL", 2, 25},
+ {"MaxSize", 2, 27},
+ {"LastChange", 2, 8},
+ {NULL, 0, 0}
+};
+
+
+
+static const struct stateVar BasicManagementVars[] = {
+ {"DeviceStatus", 0 << 7, 0, 0, 0, 0}, /*0 */
+ {"SequenceMode", 1 << 7, 0, 0, 0, 0},
+ {"ActiveTestIDs", 0 << 7, 0, 0, 0, 0},
+ {"LogURIs", 0 << 7, 0, 0, 0, 0},
+ {"A_ARG_TYPE_Boolean", 1, 0, 0, 0, 0},
+ {"A_ARG_TYPE_String", 0, 0, 0, 0, 0}, /*5 */
+ {"A_ARG_TYPE_UShort", 2, 0, 0, 0, 0},
+ {"A_ARG_TYPE_UInt", 3, 0, 0, 0, 0},
+ {"A_ARG_TYPE_DateTime", 8, 0, 0, 0, 0},
+ {"A_ARG_TYPE_MSecs", 3, 0, 0, 0, 0},
+ {"A_ARG_TYPE_RebootStatus", 0, 0, 6, 0, 0}, /*10 */
+ {"A_ARG_TYPE_TestID", 3, 0, 0, 0, 0},
+ {"A_ARG_TYPE_TestType", 0, 0, 9, 0, 0},
+ {"A_ARG_TYPE_TestState", 0, 0, 14, 0, 0},
+ {"A_ARG_TYPE_Host", 0, 0, 0, 0, 0},
+ {"A_ARG_TYPE_DSCP", 6, 0, 19, 1, 0},
+ {"A_ARG_TYPE_Hosts", 0, 0, 0, 0, 0},
+ {"A_ARG_TYPE_HostName", 0, 0, 0, 0, 0},
+ {"A_ARG_TYPE_PingStatus", 0, 0, 22, 0, 0},
+ {"A_ARG_TYPE_NSLookupStatus", 0, 0, 27, 0, 0},
+ {"A_ARG_TYPE_NSLookupResult", 0, 0, 0, 0, 0}, /*20 */
+ {"A_ARG_TYPE_TracerouteStatus", 0, 0, 32, 0, 0},
+ {"A_ARG_TYPE_Interfaces", 0, 0, 38, 0, 0},
+ {"A_ARG_TYPE_InterfaceResetStatus", 0, 0, 42, 0, 0},
+ {"A_ARG_TYPE_LogURI", 5, 0, 0, 0, 0},
+ {"A_ARG_TYPE_LogURL", 5, 0, 0, 0, 0}, /*25 */
+ {"A_ARG_TYPE_LogLevel", 0, 0, 46, 0, 0},
+ {"A_ARG_TYPE_LogMaxSize", 3, 0, 0, 0, 0},
+ {NULL, 0, 0, 0, 0, 0}
+
+
+};
+
+
+
+
+
+/* Definition of Configuration Management statevar(for each service) and arguments(for each action) */
+static const struct argument GetSupportedDataModels[] = {
+ {"SupportedDataModels", 2, 13},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetSupportedParameters[] = {
+ {"StartingNode", 1, 6},
+ {"SearchDepth", 1, 14},
+ {"Result", 2, 7},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetInstances[] = {
+ {"StartingNode", 1, 8},
+ {"SearchDepth", 1, 14},
+ {"Result", 2, 16},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetValues[] = {
+ {"Parameters", 1, 17},
+ {"ParameterValueList", 2, 9},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetSelectedValues[] = {
+ {"StartingNode", 1, 6},
+ {"Filter", 1, 12},
+ {"ParameterValueList", 2, 9},
+ {NULL, 0, 0}
+};
+
+static const struct argument SetValues[] = {
+ {"ParameterValueList", 1, 9},
+ {"Status", 2, 15},
+ {NULL, 0, 0}
+};
+
+static const struct argument CreateInstance[] = {
+ {"MultiInstanceName", 1, 18},
+ {"ChildrenInitialization", 1, 11},
+ {"InstanceIdentifier", 2, 19},
+ {"Status", 2, 15},
+ {NULL, 0, 0}
+};
+
+static const struct argument DeleteInstance[] = {
+ {"InstanceIdentifier", 1, 19},
+ {"Status", 2, 15},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetAttributes[] = {
+ {"Parameters", 1, 20},
+ {"NodeAttributeValueList", 2, 10},
+ {NULL, 0, 0}
+};
+
+static const struct argument SetAttributes[] = {
+ {"NodeAttributeValueList", 1, 10},
+ {"Status", 2, 15},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetInconsistentStatus[] = {
+ {"StateVariableValue", 2, 5},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetConfigurationUpdate[] = {
+ {"StateVariableValue", 2, 0},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetCurrentConfigurationVersion[] = {
+ {"StateVariableValue", 2, 1},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetSupportedDataModelsUpdate[] = {
+ {"StateVariableValue", 2, 2},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetSupportedParametersUpdate[] = {
+ {"StateVariableValue", 2, 3},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetAttributeValuesUpdate[] = {
+ {"StateVariableValue", 2, 4},
+ {NULL, 0, 0}
+};
+
+static const struct stateVar ConfigurationManagementVars[] = {
+ {"ConfigurationUpdate", 0 << 7, 0, 0, 0, 0}, /*0 */
+ {"CurrentConfigurationVersion", 3, 0, 0, 0, 0},
+ {"SupportedDataModelsUpdate", 0 << 7, 0, 0, 0, 0},
+ {"SupportedParametersUpdate", 0 << 7, 0, 0, 0, 0},
+ {"AttributeValuesUpdate", 0 << 7, 0, 0, 0, 0},
+ {"InconsistentStatus", 1 << 7, 0, 0, 0, 0}, /*5 */
+ {"A_ARG_TYPE_StructurePath", 0, 0, 0, 0, 0},
+ {"A_ARG_TYPE_StructurePathList", 0, 0, 0, 0, 0},
+ {"A_ARG_TYPE_PartialPath", 0, 0, 0, 0, 0},
+ {"A_ARG_TYPE_ParameterValueList", 0, 0, 0, 0, 0},
+ {"A_ARG_TYPE_NodeAttributeValueList", 0, 0, 0, 0, 0}, /*10 */
+ {"A_ARG_TYPE_ParameterInitialValueList", 0, 0, 0, 0, 0},
+ {"A_ARG_TYPE_Filter", 0, 0, 0, 0, 0},
+ {"A_ARG_TYPE_SupportedDataModels", 0, 0, 0, 0, 0},
+ {"A_ARG_TYPE_SearchDepth", 3, 0, 0, 0, 0},
+ {"A_ARG_TYPE_ChangeStatus", 0, 0, 54, 0, 0}, /*15 */
+ {"A_ARG_TYPE_InstancePathList", 0, 0, 0, 0, 0},
+ {"A_ARG_TYPE_ContentPathList", 0, 0, 0, 0, 0},
+ {"A_ARG_TYPE_MultiInstancePath", 0, 0, 0, 0, 0},
+ {"A_ARG_TYPE_InstancePath", 0, 0, 0, 0, 0},
+ {"A_ARG_TYPE_NodeAttributePathList", 0, 0, 0, 0, 0}, /*20 */
+ {NULL, 0, 0, 0, 0, 0}
+};
+
+/* Definition of Software Management statevar(for each service) and arguments(for each action) */
+
+
+static const struct argument Install[] = {
+ {"DUURI", 1, 11},
+ {"DUType", 1, 14},
+ {"HandleDependencies", 1, 6},
+ {"OperationID", 2, 8},
+ {NULL, 0, 0}
+};
+
+static const struct argument Update[] = {
+ {"DUID", 1, 8},
+ {"NewDUURI", 1, 11},
+ {"HandleDependencies", 1, 6},
+ {"OperationID", 2, 8},
+ {NULL, 0, 0}
+};
+
+static const struct argument Uninstall[] = {
+ {"DUID", 1, 8},
+ {"HandleDependencies", 1, 6},
+ {"OperationID", 2, 8},
+ {NULL, 0, 0}
+};
+
+static const struct argument Start[] = {
+ {"EUID", 1, 8},
+ {"HandleDependencies", 1, 6},
+ {"OperationID", 2, 8},
+ {NULL, 0, 0}
+};
+
+static const struct argument Stop[] = {
+ {"EUID", 1, 8},
+ {"HandleDependencies", 1, 6},
+ {"OperationID", 2, 8},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetDUIDs[] = {
+ {"DUIDs", 2, 1},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetEUIDs[] = {
+ {"EUIDs", 2, 2},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetActiveEUIDs[] = {
+ {"ActiveEUIDs", 2, 3},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetRunningEUIDs[] = {
+ {"RunningEUIDs", 2, 4},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetOperationInfo[] = {
+ {"OperationID", 1, 8},
+ {"OperationState", 2, 10},
+ {"TargetedIDs", 2, 9},
+ {"Action", 2, 12},
+ {"ErrorDescription", 2, 13},
+ {"AdditionalInfo", 2, 7},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetOperationIDs[] = {
+ {"OperationIDs", 2, 0},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetErrorEUIDs[] = {
+ {"ErrorEUIDs", 2, 5},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetDUInfo[] = {
+ {"DUID", 1, 8},
+ {"DUName", 2, 15},
+ {"DUVersion", 2, 16},
+ {"DUType", 2, 14},
+ {"DUState", 2, 17},
+ {"DUURI", 2, 11},
+ {NULL, 0, 0}
+};
+
+static const struct argument GetEUInfo[] = {
+ {"EUID", 1, 8},
+ {"EUName", 2, 15},
+ {"EUVersion", 2, 16},
+ {"EURequestedState", 2, 18},
+ {"EUExecutionState", 2, 19},
+ {NULL, 0, 0}
+};
+
+
+static const struct stateVar SoftwareManagementVars[] = {
+ {"OperationIDs", 0 << 7, 0, 0, 0, 0}, /*0 */
+ {"DUIDs", 0 << 7, 0, 0, 0, 0},
+ {"EUIDs", 0 << 7, 0, 0, 0, 0},
+ {"ActiveEUIDs", 0 << 7, 0, 0, 0, 0},
+ {"RunningEUIDs", 0 << 7, 0, 0, 0, 0},
+ {"ErrorEUIDs", 0 << 7, 0, 0, 0, 0}, /*5 */
+ {"A_ARG_TYPE_Boolean", 1, 0, 0, 0, 0},
+ {"A_ARG_TYPE_String", 0, 0, 0, 0, 0},
+ {"A_ARG_TYPE_ID", 3, 0, 0, 0, 0},
+ {"A_ARG_TYPE_IDs", 0, 0, 0, 0, 0},
+ {"A_ARG_TYPE_OperationState", 0, 0, 57, 0, 0}, /*10 */
+ {"A_ARG_TYPE_URI", 5, 0, 0, 0, 0},
+ {"A_ARG_TYPE_Action", 0, 0, 63, 0, 0},
+ {"A_ARG_TYPE_ErrorDescription", 0, 0, 69, 0, 0},
+ {"A_ARG_TYPE_DUType", 0, 0, 77, 0, 0},
+ {"A_ARG_TYPE_Name", 0, 0, 0, 0, 0}, /*15 */
+ {"A_ARG_TYPE_Version", 0, 0, 0, 0, 0},
+ {"A_ARG_TYPE_DUState", 0, 0, 82, 0, 0},
+ {"A_ARG_TYPE_EURequestedState", 0, 0, 88, 0, 0},
+ {"A_ARG_TYPE_EUExecutionState", 0, 0, 91, 0, 0},
+ {NULL, 0, 0, 0, 0, 0}
+};
+
+/* Definition of LowPower Service statevar(for each service) and arguments(for each action) */
+
+static const struct argument GetPowerManagementInfo[] = {
+ {"WakeupMethod", 2, 0},
+ {"PowerSupplyStatus", 2, 1},
+ {NULL, 0, 0}
+};
+
+static const struct argument Wakeup[] = {
+ {NULL, 0, 0}
+};
+
+static const struct argument GoToSleep[] = {
+ {"RecommendedSleepPeriod", 1, 2},
+ {"RecommendedPowerState", 1, 3},
+ {"SleepPeriod", 2, 4},
+ {NULL, 0, 0}
+};
+
+static const struct stateVar LowPowerVars[] = {
+ {"WakeupMethod", 0, 0, 0, 0, 0},
+ {"PowerSupplyStatus", 0, 0, 0, 0, 0},
+ {"SleepPeriod", 3, 0, 0, 0, 0},
+ {"PowerState", 0, 0, 96, 0, 0},
+ {"SleepPeriod", 0, 0, 0, 0, 0},
+ {"BatteryLow", 1 << 7, 0, 0, 0, 0},
+ {"ExternalPowerSupplySource", 6 << 7, 0, 101, 0, 0},
+ {NULL, 0, 0, 0, 0, 0}
+};
+
+/* End of statevar(for each service) and arguments(for each action) definition*/
+
+
+
+
+
+/* action structure for Basic Management*/
+static const struct action BasicManagementActions[] = {
+ {"Reboot", Reboot},
+ {"BaselineReset", BaselineReset},
+ {"GetDeviceStatus", GetDeviceStatus},
+ {"GetSequenceMode", GetSequenceMode},
+ {"SetSequenceMode", SetSequenceMode},
+ {"Ping", Ping},
+ {"GetPingResult", GetPingResult},
+ {"NSLookup", NSLookup},
+ {"GetNSLookupResult", GetNSLookupResult},
+ {"Traceroute", Traceroute},
+ {"GetTracerouteResult", GetTracerouteResult},
+ {"InterfaceReset", InterfaceReset},
+ {"GetInterfaceResetResult", GetInterfaceResetResult},
+ {"SelfTest", SelfTest},
+ {"GetSelfTestResult", GetSelfTestResult},
+ {"GetActiveTestIDs", GetActiveTestIDs},
+ {"GetTestInfo", GetTestInfo},
+ {"CancelTest", CancelTest},
+ {"GetLogURIs", GetLogURIs},
+ {"SetLogInfo", SetLogInfo},
+ {"GetLogInfo", GetLogInfo},
+ {0, 0}
+};
+
+
+/* action structure for Configuration Management*/
+static const struct action ConfigurationManagementActions[] = {
+ {"GetSupportedDataModels", GetSupportedDataModels},
+ {"GetSupportedParameters", GetSupportedParameters},
+ {"GetInstances", GetInstances},
+ {"GetValues", GetValues},
+ {"GetSelectedValues", GetSelectedValues},
+ {"SetValues", SetValues},
+ {"CreateInstance", CreateInstance},
+ {"DeleteInstance", DeleteInstance},
+ {"GetAttributes", GetAttributes},
+ {"SetAttributes", SetAttributes},
+ {"GetInconsistentStatus", GetInconsistentStatus},
+ {"GetConfigurationUpdate", GetConfigurationUpdate},
+ {"GetCurrentConfigurationVersion", GetCurrentConfigurationVersion},
+ {"GetSupportedDataModelsUpdate", GetSupportedDataModelsUpdate},
+ {"GetSupportedParametersUpdate", GetSupportedParametersUpdate},
+ {"GetAttributeValuesUpdate", GetAttributeValuesUpdate},
+ {0, 0}
+};
+
+
+
+/*action structure for Software Management*/
+static const struct action SoftwareManagementActions[] = {
+ {"Install", Install},
+ {"Update", Update},
+ {"Uninstall", Uninstall},
+ {"Start", Start},
+ {"Stop", Stop},
+ {"GetDUIDs", GetDUIDs},
+ {"GetEUIDs", GetEUIDs},
+ {"GetActiveEUIDs", GetActiveEUIDs},
+ {"GetRunningEUIDs", GetRunningEUIDs},
+ {"GetOperationInfo", GetOperationInfo},
+ {"GetOperationIDs", GetOperationIDs},
+ {"GetErrorEUIDs", GetErrorEUIDs},
+ {"GetDUInfo", GetDUInfo},
+ {"GetEUInfo", GetEUInfo},
+ {0, 0}
+};
+
+
+/*action structure for Low Power Service*/
+
+static const struct action LowPowerActions[] = {
+ {"GetPowerManagementInfo", GetPowerManagementInfo},
+ {"Wakeup", Wakeup},
+ {"GoToSleep", GoToSleep},
+ {0, 0}
+};
+
+/*Linking requested service with actions and variables*/
+static const struct serviceDesc scpdBasicManagement =
+ { BasicManagementActions, BasicManagementVars };
+
+static const struct serviceDesc scpdConfigurationManagement =
+ { ConfigurationManagementActions, ConfigurationManagementVars };
+
+static const struct serviceDesc scpdSoftwareManagement =
+ { SoftwareManagementActions, SoftwareManagementVars };
+
+static const struct serviceDesc scpdLowPowerDevice =
+ { LowPowerActions, LowPowerVars };
+
+
+
+/* strcat_str()
+ * concatenate the string and use realloc to increase the
+ * memory buffer if needed. */
+static char *
+strcat_str (char *str, int *len, int *tmplen, const char *s2)
+{
+ int s2len;
+ s2len = (int) strlen (s2);
+ if (*tmplen <= (*len + s2len))
+ {
+ if (s2len < 256)
+ *tmplen += 256;
+ else
+ *tmplen += s2len + 1;
+ str = (char *) realloc (str, *tmplen);
+ }
+ memcpy (str + *len, s2, s2len + 1);
+ *len += s2len;
+ return str;
+}
+
+/* strcat_char() :
+ * concatenate a character and use realloc to increase the
+ * size of the memory buffer if needed */
+static char *
+strcat_char (char *str, int *len, int *tmplen, char c)
+{
+ if (*tmplen <= (*len + 1))
+ {
+ *tmplen += 256;
+ str = (char *) realloc (str, *tmplen);
+ }
+ str[*len] = c;
+ (*len)++;
+ return str;
+}
+
+/* iterative subroutine using a small stack
+ * This way, the progam stack usage is kept low */
+static char *
+genXML (char *str, int *len, int *tmplen, const struct XMLElt *p)
+{
+ u_int16_t i, j, k;
+ int top;
+ const char *eltname, *s;
+ char c;
+ char element[64];
+ struct
+ {
+ unsigned short i;
+ unsigned short j;
+ const char *eltname;
+ } pile[16]; /* stack */
+ top = -1;
+ i = 0; /* current node */
+ j = 1; /* i + number of nodes */
+ for (;;)
+ {
+ eltname = p[i].eltname;
+ if (!eltname)
+ return str;
+ if (eltname[0] == '/')
+ {
+#ifdef DESC_DEBUG
+ printf ("DBG: <%s>%s<%s>\n", eltname + 1, p[i].data, eltname);
+#endif
+ str = strcat_char (str, len, tmplen, '<');
+ str = strcat_str (str, len, tmplen, eltname + 1);
+ str = strcat_char (str, len, tmplen, '>');
+ str = strcat_str (str, len, tmplen, p[i].data);
+ str = strcat_char (str, len, tmplen, '<');
+ sscanf (eltname, "%s", element);
+ str = strcat_str (str, len, tmplen, element);
+ str = strcat_char (str, len, tmplen, '>');
+ for (;;)
+ {
+ if (top < 0)
+ return str;
+ i = ++(pile[top].i);
+ j = pile[top].j;
+#ifdef DESC_DEBUG
+ printf ("1DBG: pile[%d]\t%d %d\n", top, i, j);
+#endif
+ if (i == j)
+ {
+#ifdef DESC_DEBUG
+ printf ("DBG: i==j, </%s>\n", pile[top].eltname);
+#endif
+ str = strcat_char (str, len, tmplen, '<');
+ str = strcat_char (str, len, tmplen, '/');
+ s = pile[top].eltname;
+ for (c = *s; c > ' '; c = *(++s))
+ str = strcat_char (str, len, tmplen, c);
+ str = strcat_char (str, len, tmplen, '>');
+ top--;
+ }
+ else
+ break;
+ }
+ }
+ else
+ {
+#ifdef DESC_DEBUG
+ printf ("2DBG: [%d] <%s>\n", i, eltname);
+#endif
+ str = strcat_char (str, len, tmplen, '<');
+ str = strcat_str (str, len, tmplen, eltname);
+ str = strcat_char (str, len, tmplen, '>');
+ k = i;
+ i = (unsigned long) p[k].data & 0xffff;
+ j = i + ((unsigned long) p[k].data >> 16);
+ top++;
+#ifdef DESC_DEBUG
+ printf ("3DBG: +pile[%d]\t%d %d\n", top, i, j);
+#endif
+ pile[top].i = i;
+ pile[top].j = j;
+ pile[top].eltname = eltname;
+ }
+ }
+}
+
+/* genRootDesc() :
+ * - Generate the root description of the UPnP device.
+ * - the len argument is used to return the length of
+ * the returned string.
+ * - tmp_uuid argument is used to build the uuid string */
+char *
+genRootDesc (int *len)
+{
+ char *str;
+ int tmplen;
+ tmplen = 2048;
+ str = (char *) malloc (tmplen);
+ if (str == NULL)
+ return NULL;
+ *len = strlen (xmlver);
+ memcpy (str, xmlver, *len + 1);
+ str = genXML (str, len, &tmplen, rootDesc);
+ str[*len] = '\0';
+ return str;
+}
+
+/* genServiceDesc() :
+ * Generate service description with allowed methods and
+ * related variables. */
+static char *
+genServiceDesc (int *len, const struct serviceDesc *s)
+{
+ int i, j;
+ const struct action *acts;
+ const struct stateVar *vars;
+ const struct argument *args;
+ const char *p;
+ char *str;
+ int tmplen;
+ tmplen = 2048;
+ str = (char *) malloc (tmplen);
+ if (str == NULL)
+ return NULL;
+ *len = strlen (xmlver);
+ memcpy (str, xmlver, *len + 1);
+
+ acts = s->actionList;
+ vars = s->serviceStateTable;
+
+ str = strcat_char (str, len, &tmplen, '<');
+ str = strcat_str (str, len, &tmplen, root_service);
+ str = strcat_char (str, len, &tmplen, '>');
+
+ str = strcat_str (str, len, &tmplen,
+ "<specVersion><major>1</major><minor>0</minor></specVersion>");
+
+ i = 0;
+ str = strcat_str (str, len, &tmplen, "<actionList>");
+ while (acts[i].name)
+ {
+ str = strcat_str (str, len, &tmplen, "<action><name>");
+ str = strcat_str (str, len, &tmplen, acts[i].name);
+ str = strcat_str (str, len, &tmplen, "</name>");
+ /* argument List */
+ args = acts[i].args;
+ if (args)
+ {
+ str = strcat_str (str, len, &tmplen, "<argumentList>");
+ j = 0;
+#ifdef SERVDESC_DEBUG
+ syslog (LOG_WARNING, "%s", acts[i].name);
+#endif
+ while (args[j].dir)
+ {
+ str = strcat_str (str, len, &tmplen, "<argument><name>");
+ p = vars[args[j].relatedVar].name;
+ str =
+ strcat_str (str, len, &tmplen,
+ (args[j].name ? args[j].name : p));
+ str = strcat_str (str, len, &tmplen, "</name><direction>");
+ str =
+ strcat_str (str, len, &tmplen,
+ args[j].dir == 1 ? "in" : "out");
+ str =
+ strcat_str (str, len, &tmplen,
+ "</direction><relatedStateVariable>");
+ str = strcat_str (str, len, &tmplen, p);
+ str = strcat_str (str, len, &tmplen,
+ "</relatedStateVariable></argument>");
+#ifdef SERVDESC_DEBUG
+ syslog (LOG_WARNING, "%s", args[j].name);
+#endif
+ j++;
+ }
+ str = strcat_str (str, len, &tmplen, "</argumentList>");
+ }
+ str = strcat_str (str, len, &tmplen, "</action>");
+ i++;
+ }
+ str = strcat_str (str, len, &tmplen, "</actionList><serviceStateTable>");
+ i = 0;
+ while (vars[i].name)
+ {
+ str = strcat_str (str, len, &tmplen, "<stateVariable sendEvents=\"");
+ str =
+ strcat_str (str, len, &tmplen,
+ (vars[i].itype & 0x80) ? "yes" : "no");
+ str = strcat_str (str, len, &tmplen, "\"><name>");
+ str = strcat_str (str, len, &tmplen, vars[i].name);
+ str = strcat_str (str, len, &tmplen, "</name><dataType>");
+ str = strcat_str (str, len, &tmplen, upnptypes[vars[i].itype & 0x0f]);
+ str = strcat_str (str, len, &tmplen, "</dataType>");
+
+ if (vars[i].irange)
+ {
+ j = vars[i].iallowedlist;
+ str = strcat_str (str, len, &tmplen, "<allowedValueRange>");
+ str = strcat_str (str, len, &tmplen, "<minimum>");
+ str = strcat_str (str, len, &tmplen, upnpallowedvalues[j]);
+ str = strcat_str (str, len, &tmplen, "</minimum>");
+ str = strcat_str (str, len, &tmplen, "<maximum>");
+ str = strcat_str (str, len, &tmplen, upnpallowedvalues[j + 1]);
+ str = strcat_str (str, len, &tmplen, "</maximum>");
+ str = strcat_str (str, len, &tmplen, "</allowedValueRange>");
+ }
+
+ if (vars[i].iallowedlist)
+ {
+ str = strcat_str (str, len, &tmplen, "<allowedValueList>");
+ for (j = vars[i].iallowedlist; upnpallowedvalues[j]; j++)
+ {
+ str = strcat_str (str, len, &tmplen, "<allowedValue>");
+ str = strcat_str (str, len, &tmplen, upnpallowedvalues[j]);
+ str = strcat_str (str, len, &tmplen, "</allowedValue>");
+ }
+ str = strcat_str (str, len, &tmplen, "</allowedValueList>");
+ }
+
+ if (vars[i].idefault)
+ {
+ str = strcat_str (str, len, &tmplen, "<defaultValue>");
+ str =
+ strcat_str (str, len, &tmplen,
+ upnpdefaultvalues[vars[i].idefault]);
+ str = strcat_str (str, len, &tmplen, "</defaultValue>");
+ }
+ str = strcat_str (str, len, &tmplen, "</stateVariable>");
+ i++;
+ }
+ str = strcat_str (str, len, &tmplen, "</serviceStateTable></scpd>");
+ str[*len] = '\0';
+ return str;
+}
+
+char *
+genBasicManagement (int *len)
+{
+ return genServiceDesc (len, &scpdBasicManagement);
+}
+
+char *
+genConfigurationManagement (int *len)
+{
+ return genServiceDesc (len, &scpdConfigurationManagement);
+}
+
+char *
+genSoftwareManagement (int *len)
+{
+ return genServiceDesc (len, &scpdSoftwareManagement);
+}
+
+char *
+genLowPowerDevice (int *len)
+{
+ return genServiceDesc (len, &scpdLowPowerDevice);
+}
+
+
+
+static char *
+genEventVars (int *len, const struct serviceDesc *s, const char *servns)
+{
+ const struct stateVar *v;
+ char *str;
+ int tmplen;
+ char buf[512];
+ tmplen = 512;
+ str = (char *) malloc (tmplen);
+ if (str == NULL)
+ return NULL;
+ *len = 0;
+ v = s->serviceStateTable;
+ snprintf (buf, sizeof (buf),
+ "<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\" xmlns:s=\"%s\">",
+ servns);
+ str = strcat_str (str, len, &tmplen, buf);
+ while (v->name)
+ {
+ if (v->itype & 0x80)
+ {
+ snprintf (buf, sizeof (buf), "<e:property><%s>", v->name);
+ str = strcat_str (str, len, &tmplen, buf);
+ switch (v->ieventvalue)
+ {
+ case 0:
+ break;
+ case 255: /* Magical values should go around here */
+ if (strcmp (v->name, "SystemUpdateID") == 0)
+ {
+ snprintf (buf, sizeof (buf), "%d", updateID);
+ str = strcat_str (str, len, &tmplen, buf);
+ }
+ break;
+ default:
+ str =
+ strcat_str (str, len, &tmplen,
+ upnpallowedvalues[v->ieventvalue]);
+ }
+ snprintf (buf, sizeof (buf), "</%s></e:property>", v->name);
+ str = strcat_str (str, len, &tmplen, buf);
+ }
+ v++;
+ }
+ str = strcat_str (str, len, &tmplen, "</e:propertyset>");
+ str[*len] = '\0';
+ return str;
+}
+
+
+
+char *
+getVarsBasicManagement (int *l)
+{
+ return genEventVars (l, &scpdBasicManagement,
+ "urn:schemas-upnp-org:service:BasicManagement:1");
+}
+
+char *
+getVarsConfigurationManagement (int *l)
+{
+ return genEventVars (l, &scpdConfigurationManagement,
+ "urn:schemas-upnp-org:service:ConfigurationManagement:1");
+}
+
+
+char *
+getVarsSoftwareManagement (int *l)
+{
+ return genEventVars (l, &scpdSoftwareManagement,
+ "urn:schemas-upnp-org:service:SoftwareManagement:1");
+}
+
+
+char *
+getVarsLowPowerDevice (int *l)
+{
+ return genEventVars (l, &scpdLowPowerDevice,
+ "urn:schemas-upnp-org:service:LowPowerDevice:1");
+}
diff --git a/cleopatre/application/upnpd/src/upnpevents.c b/cleopatre/application/upnpd/src/upnpevents.c
new file mode 100644
index 0000000000..8ba4236e64
--- /dev/null
+++ b/cleopatre/application/upnpd/src/upnpevents.c
@@ -0,0 +1,571 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include "config.h"
+#include "upnpevents.h"
+#include "upnpdpath.h"
+#include "upnpglobalvars.h"
+#include "upnpdescgen.h"
+#include <errno.h>
+#include "uuid.h"
+
+
+
+
+
+/* stuctures definitions */
+struct subscriber
+{
+ LIST_ENTRY (subscriber) entries;
+ struct upnp_event_notify *notify;
+ time_t timeout;
+ uint32_t seq;
+ enum subscriber_service_enum service;
+ char uuid[42];
+ char callback[];
+};
+
+struct upnp_event_notify
+{
+ LIST_ENTRY (upnp_event_notify) entries;
+ int s; /* socket */
+ enum
+ { ECreated = 1,
+ EConnecting,
+ ESending,
+ EWaitingForResponse,
+ EFinished,
+ EError
+ } state;
+ struct subscriber *sub;
+ char *buffer;
+ int buffersize;
+ int tosend;
+ int sent;
+ const char *path;
+ char addrstr[16];
+ char portstr[8];
+};
+
+/* prototypes */
+static void upnp_event_create_notify (struct subscriber *sub);
+
+/* Subscriber list */
+LIST_HEAD (listhead, subscriber) subscriberlist =
+{
+NULL};
+
+/* notify list */
+LIST_HEAD (listheadnotif, upnp_event_notify) notifylist =
+{
+NULL};
+
+
+
+
+
+
+/* create a new subscriber */
+static struct subscriber *
+newSubscriber (const char *eventurl, const char *callback, int callbacklen)
+{
+ struct subscriber *tmp;
+ if (!eventurl || !callback || !callbacklen)
+ return NULL;
+ tmp = calloc (1, sizeof (struct subscriber) + callbacklen + 1);
+ if (strcmp (eventurl, BASICMANAGEMENT_EVENTURL) == 0)
+ tmp->service = EBasicManagement;
+ else if (strcmp (eventurl, CONFIGURATIONMANAGEMENT_EVENTURL) == 0)
+ tmp->service = EConfigurationManagement;
+ else if (strcmp (eventurl, SOFTWAREMANAGEMENT_EVENTURL) == 0)
+ tmp->service = ESoftwareManagement;
+ else
+ {
+ free (tmp);
+ return NULL;
+ }
+ memcpy (tmp->callback, callback, callbacklen);
+ tmp->callback[callbacklen] = '\0';
+ /* make a dummy uuid */
+ strncpy (tmp->uuid, uuidvalue, sizeof (tmp->uuid));
+ if (get_uuid_string (tmp->uuid + 5) != 0)
+ {
+ tmp->uuid[sizeof (tmp->uuid) - 1] = '\0';
+ snprintf (tmp->uuid + 37, 5, "%04lx", random () & 0xffff);
+ }
+
+ return tmp;
+}
+
+/* creates a new subscriber and adds it to the subscriber list
+ * also initiate 1st notify */
+const char *
+upnpevents_addSubscriber (const char *eventurl,
+ const char *callback, int callbacklen, int timeout)
+{
+ struct subscriber *tmp;
+ syslog (LOG_DEBUG, "addSubscriber(%s, %.*s, %d)",
+ eventurl, callbacklen, callback, timeout);
+
+
+ tmp = newSubscriber (eventurl, callback, callbacklen);
+ if (!tmp)
+ return NULL;
+ if (timeout)
+ tmp->timeout = time (NULL) + timeout;
+ LIST_INSERT_HEAD (&subscriberlist, tmp, entries);
+ upnp_event_create_notify (tmp);
+ return tmp->uuid;
+}
+
+/* renew a subscription (update the timeout) */
+int
+renewSubscription (const char *sid, int timeout)
+{
+ struct subscriber *sub;
+ for (sub = subscriberlist.lh_first; sub != NULL;
+ sub = sub->entries.le_next)
+ {
+ if (memcmp (sid, sub->uuid, 41) == 0)
+ {
+ sub->timeout = (timeout ? time (NULL) + timeout : 0);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+int
+upnpevents_removeSubscriber (const char *sid)
+{
+ struct subscriber *sub;
+ if (!sid)
+ return -1;
+ for (sub = subscriberlist.lh_first; sub != NULL;
+ sub = sub->entries.le_next)
+ {
+ if (memcmp (sid, sub->uuid, 41) == 0)
+ {
+ if (sub->notify)
+ {
+ sub->notify->sub = NULL;
+ }
+ LIST_REMOVE (sub, entries);
+ free (sub);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+/* notifies all subscriber of a number of port mapping change
+ * or external ip address change */
+void
+upnp_event_var_change_notify (enum subscriber_service_enum service)
+{
+ struct subscriber *sub;
+ for (sub = subscriberlist.lh_first; sub != NULL;
+ sub = sub->entries.le_next)
+ {
+ if (sub->service == service && sub->notify == NULL)
+ upnp_event_create_notify (sub);
+ }
+}
+
+/* create and add the notify object to the list */
+static void
+upnp_event_create_notify (struct subscriber *sub)
+{
+ struct upnp_event_notify *obj;
+ int flags;
+ obj = calloc (1, sizeof (struct upnp_event_notify));
+ if (!obj)
+ {
+
+ syslog (LOG_ERR, "%s: calloc(): %m", "upnp_event_create_notify");
+ return;
+ }
+ obj->sub = sub;
+ obj->state = ECreated;
+ obj->s = socket (PF_INET, SOCK_STREAM, 0);
+ if (obj->s < 0)
+ {
+
+ syslog (LOG_ERR, "%s: socket(): %m", "upnp_event_create_notify");
+ goto error;
+ }
+ if ((flags = fcntl (obj->s, F_GETFL, 0)) < 0)
+ {
+ syslog (LOG_ERR, "%s: fcntl(..F_GETFL..): %m",
+ "upnp_event_create_notify");
+ goto error;
+ }
+ if (fcntl (obj->s, F_SETFL, flags | O_NONBLOCK) < 0)
+ {
+ syslog (LOG_ERR, "%s: fcntl(..F_SETFL..): %m",
+ "upnp_event_create_notify");
+ goto error;
+ }
+ if (sub)
+ sub->notify = obj;
+ LIST_INSERT_HEAD (&notifylist, obj, entries);
+ return;
+ error:
+ if (obj->s >= 0)
+ close (obj->s);
+ free (obj);
+}
+
+
+
+
+
+static void
+upnp_event_notify_connect (struct upnp_event_notify *obj)
+{
+ int i;
+ const char *p;
+ unsigned short port;
+ struct sockaddr_in addr;
+ if (!obj)
+ return;
+ memset (&addr, 0, sizeof (addr));
+ i = 0;
+ if (obj->sub == NULL)
+ {
+ obj->state = EError;
+ return;
+ }
+ p = obj->sub->callback;
+ p += 7; /* http:// */
+ while (*p != '/' && *p != ':')
+ obj->addrstr[i++] = *(p++);
+ obj->addrstr[i] = '\0';
+ if (*p == ':')
+ {
+ obj->portstr[0] = *p;
+ i = 1;
+ p++;
+ port = (unsigned short) atoi (p);
+ while (*p != '/' && *p != '\0')
+ {
+ if (i < 7)
+ obj->portstr[i++] = *p;
+ p++;
+ }
+ obj->portstr[i] = 0;
+ }
+ else
+ {
+ port = 80;
+ obj->portstr[0] = '\0';
+ }
+ if (*p)
+ obj->path = p;
+ else
+ obj->path = "/";
+ addr.sin_family = AF_INET;
+ inet_aton (obj->addrstr, &addr.sin_addr);
+ addr.sin_port = htons (port);
+
+ syslog (LOG_DEBUG, "%s: '%s' %hu '%s'", "upnp_event_notify_connect",
+ obj->addrstr, port, obj->path);
+ obj->state = EConnecting;
+ if (connect (obj->s, (struct sockaddr *) &addr, sizeof (addr)) < 0)
+ {
+ if (errno != EINPROGRESS && errno != EWOULDBLOCK)
+ {
+ syslog (LOG_ERR, "%s: connect(): %m",
+ "upnp_event_notify_connect");
+ obj->state = EError;
+ }
+ }
+}
+
+static void
+upnp_event_prepare (struct upnp_event_notify *obj)
+{
+ static const char notifymsg[] =
+ "NOTIFY %s HTTP/1.1\r\n"
+ "Host: %s%s\r\n"
+ "Content-Type: text/xml; charset=\"utf-8\"\r\n"
+ "Content-Length: %d\r\n"
+ "NT: upnp:event\r\n"
+ "NTS: upnp:propchange\r\n"
+ "SID: %s\r\n"
+ "SEQ: %u\r\n"
+ "Connection: close\r\n"
+ "Cache-Control: no-cache\r\n" "\r\n" "%.*s\r\n";
+ char *xml;
+ int l;
+ if (obj->sub == NULL)
+ {
+ obj->state = EError;
+ return;
+ }
+ switch (obj->sub->service)
+ {
+ case EBasicManagement:
+ xml = getVarsBasicManagement (&l);
+ break;
+ case EConfigurationManagement:
+ xml = getVarsConfigurationManagement (&l);
+ break;
+ case ESoftwareManagement:
+ xml = getVarsSoftwareManagement (&l);
+ break;
+ case ELowPowerDevice:
+ xml = getVarsLowPowerDevice (&l);
+ break;
+ default:
+ xml = NULL;
+ l = 0;
+ }
+
+ obj->tosend = asprintf (&(obj->buffer), notifymsg,
+ obj->path, obj->addrstr, obj->portstr, l + 2,
+ obj->sub->uuid, obj->sub->seq, l, xml);
+ obj->buffersize = obj->tosend;
+ if (xml)
+ {
+ free (xml);
+ xml = NULL;
+ }
+ syslog (LOG_WARNING, "Sending UPnP Event response:\n%s\n", obj->buffer);
+ obj->state = ESending;
+}
+
+static void
+upnp_event_send (struct upnp_event_notify *obj)
+{
+ int i;
+ syslog (LOG_DEBUG, "%s: sending event notify message to %s:%s",
+ "upnp_event_send", obj->addrstr, obj->portstr);
+ syslog (LOG_DEBUG, "%s: msg: %s",
+ "upnp_event_send", obj->buffer + obj->sent);
+ i = send (obj->s, obj->buffer + obj->sent, obj->tosend - obj->sent, 0);
+ if (i < 0)
+ {
+ syslog (LOG_NOTICE, "%s: send(): %m", "upnp_event_send");
+ obj->state = EError;
+ return;
+ }
+ else if (i != (obj->tosend - obj->sent))
+ syslog (LOG_NOTICE, "%s: %d bytes send out of %d",
+ "upnp_event_send", i, obj->tosend - obj->sent);
+ obj->sent += i;
+ if (obj->sent == obj->tosend)
+ obj->state = EWaitingForResponse;
+}
+
+static void
+upnp_event_recv (struct upnp_event_notify *obj)
+{
+ int n;
+ n = recv (obj->s, obj->buffer, obj->buffersize, 0);
+ if (n < 0)
+ {
+ syslog (LOG_ERR, "%s: recv(): %m", "upnp_event_recv");
+ obj->state = EError;
+ return;
+ }
+ syslog (LOG_DEBUG, "%s: (%dbytes) %.*s", "upnp_event_recv",
+ n, n, obj->buffer);
+ obj->state = EFinished;
+ if (obj->sub)
+ obj->sub->seq++;
+}
+
+static void
+upnp_event_process_notify (struct upnp_event_notify *obj)
+{
+ switch (obj->state)
+ {
+ case EConnecting:
+ /* now connected or failed to connect */
+ upnp_event_prepare (obj);
+ upnp_event_send (obj);
+ break;
+ case ESending:
+ upnp_event_send (obj);
+ break;
+ case EWaitingForResponse:
+ upnp_event_recv (obj);
+ break;
+ case EFinished:
+ close (obj->s);
+ obj->s = -1;
+ break;
+ default:
+ syslog (LOG_ERR, "upnp_event_process_notify: unknown state");
+ }
+}
+
+
+void
+upnpevents_selectfds (fd_set * readset, fd_set * writeset, int *max_fd)
+{
+ struct upnp_event_notify *obj;
+ for (obj = notifylist.lh_first; obj != NULL; obj = obj->entries.le_next)
+ {
+ syslog (LOG_DEBUG, "upnpevents_selectfds: %p %d %d",
+ obj, obj->state, obj->s);
+ if (obj->s >= 0)
+ {
+ switch (obj->state)
+ {
+ case ECreated:
+ upnp_event_notify_connect (obj);
+ if (obj->state != EConnecting)
+ break;
+ case EConnecting:
+ case ESending:
+ FD_SET (obj->s, writeset);
+ if (obj->s > *max_fd)
+ *max_fd = obj->s;
+ break;
+ case EFinished:
+ case EError:
+ case EWaitingForResponse:
+ FD_SET (obj->s, readset);
+ if (obj->s > *max_fd)
+ *max_fd = obj->s;
+ break;
+ }
+ }
+ }
+}
+
+
+
+void
+upnpevents_processfds (fd_set * readset, fd_set * writeset)
+{
+ struct upnp_event_notify *obj;
+ struct upnp_event_notify *next;
+ struct subscriber *sub;
+ struct subscriber *subnext;
+ time_t curtime;
+ for (obj = notifylist.lh_first; obj != NULL; obj = obj->entries.le_next)
+ {
+ syslog (LOG_DEBUG, "%s: %p %d %d %d %d",
+ "upnpevents_processfds", obj, obj->state, obj->s,
+ FD_ISSET (obj->s, readset), FD_ISSET (obj->s, writeset));
+ if (obj->s >= 0)
+ {
+ if (FD_ISSET (obj->s, readset) || FD_ISSET (obj->s, writeset))
+ upnp_event_process_notify (obj);
+ }
+ }
+ obj = notifylist.lh_first;
+ while (obj != NULL)
+ {
+ next = obj->entries.le_next;
+ if (obj->state == EError || obj->state == EFinished)
+ {
+ if (obj->s >= 0)
+ {
+ close (obj->s);
+ }
+ if (obj->sub)
+ obj->sub->notify = NULL;
+ if (obj->buffer)
+ {
+ free (obj->buffer);
+ }
+ LIST_REMOVE (obj, entries);
+ free (obj);
+ }
+ obj = next;
+ }
+ /* remove timeouted subscribers */
+ curtime = time (NULL);
+ for (sub = subscriberlist.lh_first; sub != NULL;)
+ {
+ subnext = sub->entries.le_next;
+ if (sub->timeout && curtime > sub->timeout && sub->notify == NULL)
+ {
+ LIST_REMOVE (sub, entries);
+ free (sub);
+ }
+ sub = subnext;
+ }
+}
+
+#ifdef USE_UPNPDCTL
+
+void
+write_events_details (int s)
+{
+ int n;
+ char buff[80];
+ struct upnp_event_notify *obj;
+ struct subscriber *sub;
+ write (s, "Events details :\n", 17);
+ for (obj = notifylist.lh_first; obj != NULL; obj = obj->entries.le_next)
+ {
+ n = snprintf (buff, sizeof (buff), " %p sub=%p state=%d s=%d\n",
+ obj, obj->sub, obj->state, obj->s);
+ write (s, buff, n);
+ }
+ write (s, "Subscribers :\n", 14);
+ for (sub = subscriberlist.lh_first; sub != NULL;
+ sub = sub->entries.le_next)
+ {
+ n = snprintf (buff, sizeof (buff),
+ " %p timeout=%d seq=%u service=%d\n", sub, sub->timeout,
+ sub->seq, sub->service);
+ write (s, buff, n);
+ n = snprintf (buff, sizeof (buff), " notify=%p %s\n",
+ sub->notify, sub->uuid);
+ write (s, buff, n);
+ n = snprintf (buff, sizeof (buff), " %s\n", sub->callback);
+ write (s, buff, n);
+ }
+}
+#endif
diff --git a/cleopatre/application/upnpd/src/upnpglobalvars.c b/cleopatre/application/upnpd/src/upnpglobalvars.c
new file mode 100644
index 0000000000..7faacb018e
--- /dev/null
+++ b/cleopatre/application/upnpd/src/upnpglobalvars.c
@@ -0,0 +1,80 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/types.h>
+#include <netinet/in.h>
+#define INOTIFY_MASK 0x0001
+#include "config.h"
+#include "upnpglobalvars.h"
+#include <linux/limits.h>
+#include "upnpdescstrings.h"
+#include "upnpdtypes.h"
+#include <syslog.h>
+#include <sys/syscall.h>
+#define SYSUPTIMEMASK 0x0002
+
+
+/* startup time */
+time_t startup_time = 0;
+
+struct runtime_vars_s runtime_vars;
+int runtime_flags = INOTIFY_MASK;
+
+
+char uuidvalue[] = "uuid:2234ce-28ad-4977-95b2-b514e343ff21";
+
+/*modelname to be renamed*/
+char modelnumber[MODELNUMBER_MAX_LEN] = "1";
+char serialnumber[SERIALNUMBER_MAX_LEN] = "00000000";
+char modelname[] = "upnpd";
+/* presentation url :
+ * http://nnn.nnn.nnn.nnn:ppppp/ => max 30 bytes including terminating 0 */
+char presentationurl[PRESENTATIONURL_MAX_LEN];
+
+int n_lan_addr = 0;
+struct lan_addr_s lan_addr[MAX_LAN_ADDR];
+
+
+char friendly_name[FRIENDLYNAME_MAX_LEN] = "upnpd";
+char log_path[PATH_MAX] = { '\0' };
+
+//struct client_cache_s clients[CLIENT_CACHE_SLOTS];
+volatile short int quitting = 0;
+
+
+volatile uint32_t updateID = 0;
+
+
+const char *pidfilename = "/var/run/upnpdpid";
diff --git a/cleopatre/application/upnpd/src/upnphttp.c b/cleopatre/application/upnpd/src/upnphttp.c
new file mode 100644
index 0000000000..5832108ee5
--- /dev/null
+++ b/cleopatre/application/upnpd/src/upnphttp.c
@@ -0,0 +1,756 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/param.h>
+#include <ctype.h>
+#include "config.h"
+#include "upnphttp.h"
+#include "upnpdescgen.h"
+#include "upnpdpath.h"
+#include "upnpsoap.h"
+#include "upnpevents.h"
+#include <syslog.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/sendfile.h>
+#include <arpa/inet.h>
+#include "upnpglobalvars.h"
+#include "getifaddr.h"
+#if 0
+#define MAX_BUFFER_SIZE 4194304 // 4MB -- Too much?
+#endif
+#define MAX_BUFFER_SIZE 2147483647 // 2GB -- Too much?
+#define MIN_BUFFER_SIZE 65536
+
+
+
+
+struct upnphttp *
+New_upnphttp (int s)
+{
+ struct upnphttp *ret;
+ if (s < 0)
+ return NULL;
+ ret = (struct upnphttp *) malloc (sizeof (struct upnphttp));
+ if (ret == NULL)
+ return NULL;
+ memset (ret, 0, sizeof (struct upnphttp));
+ ret->socket = s;
+ return ret;
+}
+
+void
+CloseSocket_upnphttp (struct upnphttp *h)
+{
+ if (close (h->socket) < 0)
+ {
+ syslog (LOG_ERR, "CloseSocket_upnphttp: close(%d): %m", h->socket);
+ }
+ h->socket = -1;
+ h->state = 100;
+}
+
+void
+Delete_upnphttp (struct upnphttp *h)
+{
+ if (h)
+ {
+ if (h->socket >= 0)
+ CloseSocket_upnphttp (h);
+ if (h->req_buf)
+ free (h->req_buf);
+ if (h->res_buf)
+ free (h->res_buf);
+ free (h);
+ }
+}
+
+
+
+static void
+ParseHttpHeaders (struct upnphttp *h)
+{
+ char *line;
+ char *colon;
+ char *p;
+ int n;
+ line = h->req_buf;
+ /* TODO : check if req_buf, contentoff are ok */
+ while (line < (h->req_buf + h->req_contentoff))
+ {
+ colon = strchr (line, ':');
+ if (colon)
+ {
+ if (strncasecmp (line, "Content-Length", 14) == 0)
+ {
+ p = colon;
+ while (*p < '0' || *p > '9')
+ p++;
+ h->req_contentlen = atoi (p);
+ }
+ else if (strncasecmp (line, "SOAPAction", 10) == 0)
+ {
+ p = colon;
+ n = 0;
+ while (*p == ':' || *p == ' ' || *p == '\t')
+ p++;
+ while (p[n] >= ' ')
+ {
+ n++;
+ }
+ if ((p[0] == '"' && p[n - 1] == '"')
+ || (p[0] == '\'' && p[n - 1] == '\''))
+ {
+ p++;
+ n -= 2;
+ }
+ h->req_soapAction = p;
+ h->req_soapActionLen = n;
+ }
+
+ else if (strncasecmp (line, "Callback", 8) == 0)
+ {
+ p = colon;
+ while (*p != '<' && *p != '\r')
+ p++;
+ n = 0;
+ while (p[n] != '>' && p[n] != '\r')
+ n++;
+ h->req_Callback = p + 1;
+ h->req_CallbackLen = MAX (0, n - 1);
+ }
+ else if (strncasecmp (line, "SID", 3) == 0)
+ {
+ //Skip extra headers like "SIDHEADER: xxxxxx xxx"
+ for (p = line + 3; p < colon; p++)
+ {
+ if (!isspace (*p))
+ {
+ p = NULL; //unexpected header
+ break;
+ }
+ }
+ if (p)
+ {
+ p = colon + 1;
+ while (isspace (*p))
+ p++;
+ n = 0;
+ while (!isspace (p[n]))
+ n++;
+ h->req_SID = p;
+ h->req_SIDLen = n;
+ }
+ }
+ /* Timeout: Seconds-nnnn */
+ /* TIMEOUT
+ * Recommended. Requested duration until subscription expires,
+ * either number of seconds or infinite. Recommendation
+ * by a UPnP Forum working committee. Defined by UPnP vendor.
+ * Consists of the keyword "Second-" followed (without an
+ * intervening space) by either an integer or the keyword "infinite". */
+ else if (strncasecmp (line, "Timeout", 7) == 0)
+ {
+ p = colon + 1;
+ while (isspace (*p))
+ p++;
+ if (strncasecmp (p, "Second-", 7) == 0)
+ {
+ h->req_Timeout = atoi (p + 7);
+ }
+ }
+ // Range: bytes=xxx-yyy
+ else if (strncasecmp (line, "Range", 5) == 0)
+ {
+ p = colon + 1;
+ while (isspace (*p))
+ p++;
+ if (strncasecmp (p, "bytes=", 6) == 0)
+ {
+ h->reqflags |= FLAG_RANGE;
+ h->req_RangeEnd = atoll (strchr (p + 6, '-') + 1);
+ h->req_RangeStart = atoll (p + 6);
+ }
+ }
+
+ }
+ while (!(line[0] == '\r' && line[1] == '\n'))
+ line++;
+ line += 2;
+ }
+}
+
+
+void
+Send400 (struct upnphttp *h)
+{
+ static const char body400[] =
+ "<HTML><HEAD><TITLE>400 Bad Request</TITLE></HEAD>"
+ "<BODY><H1>Bad Request</H1>The request is invalid"
+ " for this HTTP version.</BODY></HTML>\r\n";
+ h->respflags = FLAG_HTML;
+ BuildResp2_upnphttp (h, 400, "Bad Request",
+ body400, sizeof (body400) - 1);
+ SendResp_upnphttp (h);
+ CloseSocket_upnphttp (h);
+}
+
+/* very minimalistic 404 error message */
+void
+Send404 (struct upnphttp *h)
+{
+ static const char body404[] =
+ "<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>"
+ "<BODY><H1>Not Found</H1>The requested URL was not found"
+ " on this server.</BODY></HTML>\r\n";
+ h->respflags = FLAG_HTML;
+ BuildResp2_upnphttp (h, 404, "Not Found", body404, sizeof (body404) - 1);
+ SendResp_upnphttp (h);
+ CloseSocket_upnphttp (h);
+}
+
+/* very minimalistic 406 error message */
+void
+Send406 (struct upnphttp *h)
+{
+ static const char body406[] =
+ "<HTML><HEAD><TITLE>406 Not Acceptable</TITLE></HEAD>"
+ "<BODY><H1>Not Acceptable</H1>An unsupported operation"
+ " was requested.</BODY></HTML>\r\n";
+ h->respflags = FLAG_HTML;
+ BuildResp2_upnphttp (h, 406, "Not Acceptable",
+ body406, sizeof (body406) - 1);
+ SendResp_upnphttp (h);
+ CloseSocket_upnphttp (h);
+}
+
+/* very minimalistic 416 error message */
+void
+Send416 (struct upnphttp *h)
+{
+ static const char body416[] =
+ "<HTML><HEAD><TITLE>416 Requested Range Not Satisfiable</TITLE></HEAD>"
+ "<BODY><H1>Requested Range Not Satisfiable</H1>The requested range"
+ " was outside the file's size.</BODY></HTML>\r\n";
+ h->respflags = FLAG_HTML;
+ BuildResp2_upnphttp (h, 416, "Requested Range Not Satisfiable",
+ body416, sizeof (body416) - 1);
+ SendResp_upnphttp (h);
+ CloseSocket_upnphttp (h);
+}
+
+/* very minimalistic 500 error message */
+void
+Send500 (struct upnphttp *h)
+{
+ static const char body500[] =
+ "<HTML><HEAD><TITLE>500 Internal Server Error</TITLE></HEAD>"
+ "<BODY><H1>Internal Server Error</H1>Server encountered "
+ "and Internal Error.</BODY></HTML>\r\n";
+ h->respflags = FLAG_HTML;
+ BuildResp2_upnphttp (h, 500, "Internal Server Errror",
+ body500, sizeof (body500) - 1);
+ SendResp_upnphttp (h);
+ CloseSocket_upnphttp (h);
+}
+
+/* very minimalistic 501 error message */
+void
+Send501 (struct upnphttp *h)
+{
+ static const char body501[] =
+ "<HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD>"
+ "<BODY><H1>Not Implemented</H1>The HTTP Method "
+ "is not implemented by this server.</BODY></HTML>\r\n";
+ h->respflags = FLAG_HTML;
+ BuildResp2_upnphttp (h, 501, "Not Implemented",
+ body501, sizeof (body501) - 1);
+ SendResp_upnphttp (h);
+ CloseSocket_upnphttp (h);
+}
+
+const char *
+findendheaders (const char *s, int len)
+{
+ while (len-- > 0)
+ {
+ if (s[0] == '\r' && s[1] == '\n' && s[2] == '\r' && s[3] == '\n')
+ return s;
+ s++;
+ }
+ return NULL;
+}
+
+/* Sends the description generated by the parameter */
+void
+sendXMLdesc (struct upnphttp *h, char *(f) (int *))
+{
+ char *desc;
+ int len;
+ desc = f (&len);
+ if (!desc)
+ {
+ static const char error500[] = "<HTML><HEAD><TITLE>Error 500</TITLE>"
+ "</HEAD><BODY>Internal Server Error</BODY></HTML>\r\n";
+ syslog (LOG_ERR, "Failed to generate XML description");
+ h->respflags = FLAG_HTML;
+ BuildResp2_upnphttp (h, 500, "Internal Server Error",
+ error500, sizeof (error500) - 1);
+ }
+ else
+ {
+ BuildResp_upnphttp (h, desc, len);
+ }
+ SendResp_upnphttp (h);
+ CloseSocket_upnphttp (h);
+ free (desc);
+}
+
+/* ProcessHTTPPOST_upnphttp()
+ * executes the SOAP query if it is possible */
+void
+ProcessHTTPPOST_upnphttp (struct upnphttp *h)
+{
+ if ((h->req_buflen - h->req_contentoff) >= h->req_contentlen)
+ {
+ if (h->req_soapAction)
+ {
+ /* we can process the request */
+ syslog (LOG_INFO, "SOAPAction: %.*s",
+ h->req_soapActionLen, h->req_soapAction);
+ ExecuteSoapAction (h, h->req_soapAction, h->req_soapActionLen);
+ }
+ else
+ {
+ static const char err400str[] =
+ "<html><body>Bad request</body></html>";
+ syslog (LOG_INFO, "No SOAPAction in HTTP headers");
+ h->respflags = FLAG_HTML;
+ BuildResp2_upnphttp (h, 400, "Bad Request",
+ err400str, sizeof (err400str) - 1);
+ SendResp_upnphttp (h);
+ CloseSocket_upnphttp (h);
+ }
+ }
+ else
+ {
+ /* waiting for remaining data */
+ h->state = 1;
+ }
+}
+
+void
+ProcessHTTPSubscribe_upnphttp (struct upnphttp *h, const char *path)
+{
+ const char *sid;
+ syslog (LOG_DEBUG, "ProcessHTTPSubscribe %s", path);
+ syslog (LOG_DEBUG, "Callback '%.*s' Timeout=%d",
+ h->req_CallbackLen, h->req_Callback, h->req_Timeout);
+ syslog (LOG_DEBUG, "SID '%.*s'", h->req_SIDLen, h->req_SID);
+ if (!h->req_Callback && !h->req_SID)
+ {
+ /* Missing or invalid CALLBACK : 412 Precondition Failed.
+ * If CALLBACK header is missing or does not contain a valid HTTP URL,
+ * the publisher must respond with HTTP error 412 Precondition Failed*/
+ BuildResp2_upnphttp (h, 412, "Precondition Failed", 0, 0);
+ SendResp_upnphttp (h);
+ CloseSocket_upnphttp (h);
+ }
+ else
+ {
+ /* - add to the subscriber list
+ * - respond HTTP/x.x 200 OK
+ * - Send the initial event message */
+ /* Server:, SID:; Timeout: Second-(xx|infinite) */
+ if (h->req_Callback)
+ {
+ sid = upnpevents_addSubscriber (path, h->req_Callback,
+ h->req_CallbackLen,
+ h->req_Timeout);
+ h->respflags = FLAG_TIMEOUT;
+ if (sid)
+ {
+ syslog (LOG_DEBUG, "generated sid=%s", sid);
+ h->respflags |= FLAG_SID;
+ h->req_SID = sid;
+ h->req_SIDLen = strlen (sid);
+ }
+ BuildResp_upnphttp (h, 0, 0);
+ }
+ else
+ {
+ /* subscription renew */
+ /* Invalid SID
+ * 412 Precondition Failed. If a SID does not correspond to a known,
+ * un-expired subscription, the publisher must respond
+ * with HTTP error 412 Precondition Failed. */
+ if (renewSubscription (h->req_SID, h->req_Timeout) < 0)
+ {
+ BuildResp2_upnphttp (h, 412, "Precondition Failed", 0, 0);
+ }
+ else
+ {
+ BuildResp_upnphttp (h, 0, 0);
+ }
+ }
+ SendResp_upnphttp (h);
+ CloseSocket_upnphttp (h);
+ }
+}
+
+
+
+
+
+void
+ProcessHTTPUnSubscribe_upnphttp (struct upnphttp *h, const char *path)
+{
+ syslog (LOG_DEBUG, "ProcessHTTPUnSubscribe %s", path);
+ syslog (LOG_DEBUG, "SID '%.*s'", h->req_SIDLen, h->req_SID);
+ /* Remove from the list */
+ if (upnpevents_removeSubscriber (h->req_SID) < 0)
+ {
+ BuildResp2_upnphttp (h, 412, "Precondition Failed", 0, 0);
+ }
+ else
+ {
+ BuildResp_upnphttp (h, 0, 0);
+ }
+ SendResp_upnphttp (h);
+ CloseSocket_upnphttp (h);
+}
+
+/* Parse and process Http Query
+ * called once all the HTTP headers have been received. */
+void
+ProcessHttpQuery_upnphttp (struct upnphttp *h)
+{
+ char HttpCommand[16];
+ char HttpUrl[512];
+ char *HttpVer;
+ char *p;
+ int i;
+ p = h->req_buf;
+ if (!p)
+ return;
+ for (i = 0; i < 15 && *p != ' ' && *p != '\r'; i++)
+ HttpCommand[i] = *(p++);
+ HttpCommand[i] = '\0';
+ while (*p == ' ')
+ p++;
+ if (strncmp (p, "http://", 7) == 0)
+ {
+ p = p + 7;
+ while (*p != '/')
+ p++;
+ }
+ for (i = 0; i < 511 && *p != ' ' && *p != '\r'; i++)
+ HttpUrl[i] = *(p++);
+ HttpUrl[i] = '\0';
+ while (*p == ' ')
+ p++;
+ HttpVer = h->HttpVer;
+ for (i = 0; i < 15 && *p != '\r'; i++)
+ HttpVer[i] = *(p++);
+ HttpVer[i] = '\0';
+ syslog (LOG_INFO, "HTTP REQUEST : %s %s (%s)", HttpCommand, HttpUrl,
+ HttpVer);
+ ParseHttpHeaders (h);
+ /* see if we need to wait for remaining data */
+ if ((h->reqflags & FLAG_CHUNKED))
+ {
+ if (h->req_chunklen)
+ {
+ h->state = 2;
+ return;
+ }
+ char *chunkstart, *chunk, *endptr, *endbuf;
+ chunk = endbuf = chunkstart = h->req_buf + h->req_contentoff;
+
+ while ((h->req_chunklen = strtol (chunk, &endptr, 16))
+ && (endptr != chunk))
+ {
+ while (!(endptr[0] == '\r' && endptr[1] == '\n'))
+ {
+ endptr++;
+ }
+ endptr += 2;
+
+ memmove (endbuf, endptr, h->req_chunklen);
+
+ endbuf += h->req_chunklen;
+ chunk = endptr + h->req_chunklen;
+ }
+ h->req_contentlen = endbuf - chunkstart;
+ h->req_buflen = endbuf - h->req_buf;
+ h->state = 100;
+ }
+
+ syslog (LOG_WARNING, "HTTP REQUEST: %.*s\n", h->req_buflen, h->req_buf);
+ if (strcmp ("POST", HttpCommand) == 0)
+ {
+ h->req_command = EPost;
+ ProcessHTTPPOST_upnphttp (h);
+ }
+ else if ((strcmp ("GET", HttpCommand) == 0)
+ || (strcmp ("HEAD", HttpCommand) == 0))
+ {
+ h->req_command = EGet;
+ if (strcmp (ROOTDESC_PATH, HttpUrl) == 0)
+ {
+ sendXMLdesc (h, genRootDesc);
+ }
+ else if (strcmp (BASICMANAGEMENT_PATH, HttpUrl) == 0)
+ {
+ sendXMLdesc (h, genBasicManagement);
+ }
+ else if (strcmp (CONFIGURATIONMANAGEMENT_PATH, HttpUrl) == 0)
+ {
+ sendXMLdesc (h, genConfigurationManagement);
+ }
+ else if (strcmp (SOFTWAREMANAGEMENT_PATH, HttpUrl) == 0)
+ {
+ sendXMLdesc (h, genSoftwareManagement);
+ }
+ else if (strcmp (LOWPOWERDEVICE_PATH, HttpUrl) == 0)
+ {
+ sendXMLdesc (h, genLowPowerDevice);
+ }
+ else
+ {
+ syslog (LOG_NOTICE, "%s not found, responding ERROR 404",
+ HttpUrl);
+ Send404 (h);
+ }
+ }
+
+ else if (strcmp ("SUBSCRIBE", HttpCommand) == 0)
+ {
+ h->req_command = ESubscribe;
+ ProcessHTTPSubscribe_upnphttp (h, HttpUrl);
+ }
+ else if (strcmp ("UNSUBSCRIBE", HttpCommand) == 0)
+ {
+ h->req_command = EUnSubscribe;
+ ProcessHTTPUnSubscribe_upnphttp (h, HttpUrl);
+ }
+ else
+ {
+ syslog (LOG_NOTICE, "Unsupported HTTP Command %s", HttpCommand);
+ Send501 (h);
+ }
+}
+
+void
+Process_upnphttp (struct upnphttp *h)
+{
+ char buf[2048];
+ int n;
+ if (!h)
+ return;
+ switch (h->state)
+ {
+ case 0:
+ n = recv (h->socket, buf, 2048, 0);
+ if (n < 0)
+ {
+ syslog (LOG_ERR, "recv (state0): %m");
+ h->state = 100;
+ }
+ else if (n == 0)
+ {
+ syslog (LOG_WARNING, "HTTP Connection closed unexpectedly");
+ h->state = 100;
+ }
+ else
+ {
+ const char *endheaders;
+ /* if 1st arg of realloc() is null,
+ * realloc behaves the same as malloc() */
+ h->req_buf = (char *) realloc (h->req_buf, n + h->req_buflen + 1);
+ memcpy (h->req_buf + h->req_buflen, buf, n);
+ h->req_buflen += n;
+ h->req_buf[h->req_buflen] = '\0';
+ /* search for the string "\r\n\r\n" */
+ endheaders = findendheaders (h->req_buf, h->req_buflen);
+ if (endheaders)
+ {
+ h->req_contentoff = endheaders - h->req_buf + 4;
+ h->req_contentlen = h->req_buflen - h->req_contentoff;
+ ProcessHttpQuery_upnphttp (h);
+ }
+ }
+ break;
+ case 1:
+ case 2:
+ n = recv (h->socket, buf, 2048, 0);
+ if (n < 0)
+ {
+ syslog (LOG_WARNING, "recv (state%d): %s\n", h->state,
+ strerror (errno));
+ h->state = 100;
+ }
+ else if (n == 0)
+ {
+ syslog (LOG_WARNING, "HTTP Connection closed unexpectedly\n");
+ h->state = 100;
+ }
+ else
+ {
+ h->req_buf = (char *) realloc (h->req_buf, n + h->req_buflen);
+ memcpy (h->req_buf + h->req_buflen, buf, n);
+ h->req_buflen += n;
+ if ((h->req_buflen - h->req_contentoff) >= h->req_contentlen)
+ {
+ /* Need the struct to point to the realloc'd memory locations */
+ if (h->state == 1)
+ {
+ ParseHttpHeaders (h);
+ ProcessHTTPPOST_upnphttp (h);
+ }
+ else if (h->state == 2)
+ {
+ ProcessHttpQuery_upnphttp (h);
+ }
+ }
+ }
+ break;
+ default:
+ syslog (LOG_WARNING, "Unexpected state: %d", h->state);
+ }
+}
+
+static const char httpresphead[] =
+ "%s %d %s\r\n"
+ "Content-Type: text/xml; charset=\"utf-8\"\r\n"
+ "Content-Type: %s\r\n"
+ "Connection: close\r\n"
+ "Content-Length: %d\r\n" "Server: " UPNPD_SERVER_STRING "\r\n";
+/* with response code and response message
+ * also allocate enough memory */
+
+void
+BuildHeader_upnphttp (struct upnphttp *h, int respcode,
+ const char *respmsg, int bodylen)
+{
+ int templen;
+ if (!h->res_buf)
+ {
+ templen = sizeof (httpresphead) + 192 + bodylen;
+ h->res_buf = (char *) malloc (templen);
+ h->res_buf_alloclen = templen;
+ }
+ h->res_buflen = snprintf (h->res_buf, h->res_buf_alloclen,
+ httpresphead, "HTTP/1.1",
+ respcode, respmsg,
+ (h->
+ respflags & FLAG_HTML) ? "text/html" :
+ "text/xml", bodylen);
+ /* Additional headers */
+ if (h->respflags & FLAG_TIMEOUT)
+ {
+ h->res_buflen += snprintf (h->res_buf + h->res_buflen,
+ h->res_buf_alloclen - h->res_buflen,
+ "Timeout: Second-");
+ if (h->req_Timeout)
+ {
+ h->res_buflen += snprintf (h->res_buf + h->res_buflen,
+ h->res_buf_alloclen - h->res_buflen,
+ "%d\r\n", h->req_Timeout);
+ }
+ else
+ {
+ h->res_buflen += snprintf (h->res_buf + h->res_buflen,
+ h->res_buf_alloclen - h->res_buflen,
+ "infinite\r\n");
+ }
+ }
+ if (h->respflags & FLAG_SID)
+ {
+ h->res_buflen += snprintf (h->res_buf + h->res_buflen,
+ h->res_buf_alloclen - h->res_buflen,
+ "SID: %s\r\n", h->req_SID);
+ }
+
+ h->res_buf[h->res_buflen++] = '\r';
+ h->res_buf[h->res_buflen++] = '\n';
+ if (h->res_buf_alloclen < (h->res_buflen + bodylen))
+ {
+ h->res_buf = (char *) realloc (h->res_buf, (h->res_buflen + bodylen));
+ h->res_buf_alloclen = h->res_buflen + bodylen;
+ }
+}
+
+void
+BuildResp2_upnphttp (struct upnphttp *h, int respcode,
+ const char *respmsg, const char *body, int bodylen)
+{
+ BuildHeader_upnphttp (h, respcode, respmsg, bodylen);
+ if (body)
+ memcpy (h->res_buf + h->res_buflen, body, bodylen);
+ h->res_buflen += bodylen;
+}
+
+/* responding 200 OK ! */
+void
+BuildResp_upnphttp (struct upnphttp *h, const char *body, int bodylen)
+{
+ BuildResp2_upnphttp (h, 200, "OK", body, bodylen);
+}
+
+void
+SendResp_upnphttp (struct upnphttp *h)
+{
+ int n;
+ n = send (h->socket, h->res_buf, h->res_buflen, 0);
+ if (n < 0)
+ {
+ syslog (LOG_ERR, "send(res_buf): %m");
+ }
+ else if (n < h->res_buflen)
+ {
+ /* TODO : handle correctly this case */
+ syslog (LOG_ERR, "send(res_buf): %d bytes sent (out of %d)",
+ n, h->res_buflen);
+ }
+}
diff --git a/cleopatre/application/upnpd/src/upnpreplyparse.c b/cleopatre/application/upnpd/src/upnpreplyparse.c
new file mode 100644
index 0000000000..0faaae484e
--- /dev/null
+++ b/cleopatre/application/upnpd/src/upnpreplyparse.c
@@ -0,0 +1,137 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "upnpreplyparse.h"
+#include "minixml.h"
+
+static void
+NameValueParserStartElt (void *d, const char *name, int l)
+{
+ struct NameValueParserData *data = (struct NameValueParserData *) d;
+ if (l > 63)
+ l = 63;
+ memcpy (data->curelt, name, l);
+ data->curelt[l] = '\0';
+
+ /* store root element */
+ if (!data->head.lh_first)
+ {
+ struct NameValue *nv;
+ nv = malloc (sizeof (struct NameValue));
+ strcpy (nv->name, "rootElement");
+ memcpy (nv->value, name, l);
+ nv->value[l] = '\0';
+ LIST_INSERT_HEAD (&(data->head), nv, entries);
+ }
+}
+
+static void
+NameValueParserGetData (void *d, const char *datas, int l)
+{
+ struct NameValueParserData *data = (struct NameValueParserData *) d;
+ struct NameValue *nv;
+ nv = malloc (sizeof (struct NameValue));
+ if (l > 511)
+ l = 511;
+ strncpy (nv->name, data->curelt, 64);
+ nv->name[63] = '\0';
+ memcpy (nv->value, datas, l);
+ nv->value[l] = '\0';
+ LIST_INSERT_HEAD (&(data->head), nv, entries);
+}
+
+void
+ParseNameValue (const char *buffer, int bufsize,
+ struct NameValueParserData *data)
+{
+ struct xmlparser parser;
+ LIST_INIT (&(data->head));
+ /* init xmlparser object */
+ parser.xmlstart = buffer;
+ parser.xmlsize = bufsize;
+ parser.data = data;
+ parser.starteltfunc = NameValueParserStartElt;
+ parser.endeltfunc = 0;
+ parser.datafunc = NameValueParserGetData;
+ parser.attfunc = 0;
+ parsexml (&parser);
+}
+
+void
+ClearNameValueList (struct NameValueParserData *pdata)
+{
+ struct NameValue *nv;
+ while ((nv = pdata->head.lh_first) != NULL)
+ {
+ LIST_REMOVE (nv, entries);
+ free (nv);
+ }
+}
+
+char *
+GetValueFromNameValueList (struct NameValueParserData *pdata,
+ const char *Name)
+{
+ struct NameValue *nv;
+ char *p = NULL;
+ for (nv = pdata->head.lh_first;
+ (nv != NULL) && (p == NULL); nv = nv->entries.le_next)
+ {
+ if (strcmp (nv->name, Name) == 0)
+ p = nv->value;
+ }
+ return p;
+}
+
+/* debug all-in-one function
+ * do parsing then display to stdout */
+#ifdef DEBUG
+void
+DisplayNameValueList (char *buffer, int bufsize)
+{
+ struct NameValueParserData pdata;
+ struct NameValue *nv;
+ ParseNameValue (buffer, bufsize, &pdata);
+ for (nv = pdata.head.lh_first; nv != NULL; nv = nv->entries.le_next)
+ {
+ printf ("%s = %s\n", nv->name, nv->value);
+ }
+ ClearNameValueList (&pdata);
+}
+#endif
diff --git a/cleopatre/application/upnpd/src/upnpsoap.c b/cleopatre/application/upnpd/src/upnpsoap.c
new file mode 100644
index 0000000000..ee7d07b6d5
--- /dev/null
+++ b/cleopatre/application/upnpd/src/upnpsoap.c
@@ -0,0 +1,1590 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <stdbool.h>
+#include <syslog.h>
+#include "config.h"
+#include "upnpglobalvars.h"
+#include "upnphttp.h"
+#include "upnpsoap.h"
+#include "upnpreplyparse.h"
+#include "getifaddr.h"
+#include "minissdp.h"
+#include "upnpdescgen.h"
+
+/*for device management*/
+char *RebootStatus, *DeviceStatus, *AdditionalInfo, *HopHosts, *LogLevel,
+ *SupportedDataModels, *Result, *ParameterValueList, *Status,
+ *InstanceIdentifier, *NodeAttributeValueList, *DUIDs, *EUIDs,
+ *ActiveEUIDs, *RunningEUIDs, *OperationState, *TargetedIDs, *Action,
+ *ErrorDescription, *AdditionalInfo, *ErrorEUIDs, *DUName, *DUVersion,
+ *DUType, *DUState, *EUName, *EUVersion, *EURequestedState,
+ *EUExecutionState, *OperationIDs, *Type, *State, *TestIDs, *LogURIs;
+volatile unsigned long int TestID, TotalCount, SuccessCount, FailureCount,
+ AverageResponseTime, MinimumResponseTime, MaximumResponseTime,
+ ResponseTime, MaxSize, LastChange, OperationID;
+volatile unsigned short int NumberOfSuccesses, NumberOfFailures;
+volatile bool SequenceMode, Configurable, Enabled;
+volatile unsigned long int LogURI, LogURL, DUURI;
+
+/*for Low Power Service*/
+char *WakeupMethod, *PowerSupplyStatus, *PowerState;
+volatile unsigned long int SleepPeriod;
+volatile unsigned long int ExternalPowerSupplySource;
+volatile bool BatteryLow;
+
+static void
+BuildSendAndCloseSoapResp (struct upnphttp *h, const char *body, int bodylen)
+{
+ static const char beforebody[] =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n"
+ "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
+ "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
+ "<s:Body>";
+
+ static const char afterbody[] = "</s:Body>" "</s:Envelope>\r\n";
+
+ BuildHeader_upnphttp (h, 200, "OK", sizeof (beforebody) - 1
+ + sizeof (afterbody) - 1 + bodylen);
+
+ memcpy (h->res_buf + h->res_buflen, beforebody, sizeof (beforebody) - 1);
+ h->res_buflen += sizeof (beforebody) - 1;
+
+ memcpy (h->res_buf + h->res_buflen, body, bodylen);
+ h->res_buflen += bodylen;
+
+ memcpy (h->res_buf + h->res_buflen, afterbody, sizeof (afterbody) - 1);
+ h->res_buflen += sizeof (afterbody) - 1;
+
+ SendResp_upnphttp (h);
+ CloseSocket_upnphttp (h);
+}
+
+
+
+
+
+
+static void
+Reboot (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<RebootStatus>%s</RebootStatus>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ int snotify[MAX_LAN_ADDR];
+ syslog (LOG_WARNING, "called rebooting");
+ printf ("Rebooting via UPnP");
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:BasicManagement:1",
+ RebootStatus, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+ syslog (LOG_WARNING, "Calling rebooting");
+
+ if (0) /*Some critical state preventing from rebooting (For instance, it is the Cco and first needs to call backup Cco) */
+ {
+ while (0) /*Waiting to exit the critical state */
+ {
+ RebootStatus = "RebootLater";
+ }
+ RebootStatus = "RebootNow";
+ SendSSDPGoodbye (snotify, n_lan_addr);
+ system ("reboot");
+ }
+ else
+ {
+ RebootStatus = "RebootNow";
+ SendSSDPGoodbye (snotify, n_lan_addr);
+ system ("reboot");
+ }
+}
+
+static void
+BaselineReset (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called BaselineReset");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:BasicManagement:1",
+ action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetDeviceStatus (struct upnphttp *h, const char *action)
+{
+ char body[512];
+ int bodylen;
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<DeviceStatus>%s</DeviceStatus>"
+ "</u:%sResponse>";
+
+ syslog (LOG_WARNING, "called GetDeviceStatus");
+ DeviceStatus = "OK, 0001-01-01T00:00:00";
+#if 0
+ /*A correct implementation of the function should be as: */
+
+ DeviceStatus = "%s,%s";
+ char state; /*Can be either "OK", "Error", "Warning", "Fatal" */
+ char time; /*should retrieve it from /proc/uptime and put it in form, i.e. date if the device was started at midnight the first of january year 1 */
+
+ if (0) /*No problem */
+ {
+ state = "OK";
+ }
+ else if (0) /*Error problem */
+ {
+ state = "Error";
+ }
+ else if (0) /*Warning problem */
+ {
+ state = "Warning";
+ }
+ else if (0) /*Fatal problem */
+ {
+ state = "Fatal";
+ }
+
+ bodylen = snprintf (body, sizeof (body), DeviceStatus, state, time);
+#endif
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:BasicManagement:1",
+ DeviceStatus, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+void
+SetSequenceMode (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<OldSequenceMode>%s</OldSequenceMode>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ struct NameValueParserData data;
+
+ ParseNameValue (h->req_buf + h->req_contentoff, h->req_contentlen, &data);
+ char *NewSequenceMode =
+ GetValueFromNameValueList (&data, "NewSequenceMode");
+ char *OldSequenceMode = (SequenceMode) ? "1" : "0";
+ OldSequenceMode = (SequenceMode) ? "1" : "0";
+ SequenceMode = atoi (NewSequenceMode);
+ syslog (LOG_WARNING, "called SetSequenceMode");
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:BasicManagement:1",
+ OldSequenceMode, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+
+}
+
+void
+GetSequenceMode (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<SequenceMode>%s</SequenceMode>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetSequenceMode");
+ bodylen =
+ snprintf (body, sizeof (body), resp, action,
+ "urn:schemas-upnp-org:service:BasicManagement:1",
+ (SequenceMode) ? "1" : "0", action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+Ping (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<TestID>%lu</TestID>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ struct NameValueParserData data;
+ ParseNameValue (h->req_buf + h->req_contentoff, h->req_contentlen, &data);
+ char *Host = GetValueFromNameValueList (&data, "Host");
+ char *NumberOfRepetitions =
+ GetValueFromNameValueList (&data, "NumberOfRepetitions");
+ char *Timeout = GetValueFromNameValueList (&data, "Timeout");
+ char *DataBlockSize = GetValueFromNameValueList (&data, "DataBlockSize");
+ char ShellCmd[512];
+ TestID = TestID + 1;
+ FILE *fp;
+ char path[512];
+ fp = fopen (path, "w");
+ snprintf (path, sizeof (path), "/tmp/Test_%lu", TestID);
+ bodylen =
+ snprintf (ShellCmd, sizeof (ShellCmd), "ping -c %d -W %d -s %d %s >> %s",
+ atoi (NumberOfRepetitions), atoi (Timeout),
+ atoi (DataBlockSize), Host, path);
+ system (ShellCmd);
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:BasicManagement:1",
+ TestID, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetPingResult (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<Status>%s</Status>"
+ "<AdditionalInfo>%s</AdditionalInfo>"
+ "<SuccessCount>%lu</SuccessCount>"
+ "<FailureCount>%lu</FailureCount>"
+ "<AverageResponseTime>%lu</AverageResponseTime>"
+ "<MinimumResponseTime>%lu</MinimumResponseTime>"
+ "<MaximumResponseTime>%lu</MaximumResponseTime>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ struct NameValueParserData data;
+ ParseNameValue (h->req_buf + h->req_contentoff, h->req_contentlen, &data);
+ char *TestID = GetValueFromNameValueList (&data, "TestID");
+
+ FILE *fp;
+ char path[512];
+ int i;
+ size_t read = 0;
+ size_t len = 0;
+ char *line = NULL;
+ i = snprintf (path, sizeof (path), "tmp/Test_%s", TestID);
+
+ fp = fopen (path, "rb");
+ if (fp==NULL) {syslog (LOG_WARNING,"File error while retrieving ping result");}
+
+ while((int)(read = getline (&line, &len, fp)) != -1)
+ {
+ }
+
+ sscanf (line, "%lu packets transmitted, %lu packets received", &TotalCount, &SuccessCount);
+ FailureCount = TotalCount - SuccessCount;
+ AdditionalInfo = line;
+ if (FailureCount == 0)
+ {
+ Status = "Success";
+ }
+ else if (FailureCount == TotalCount)
+ {
+ Status = "Error_CannotResolveHostName";
+ }
+
+ /*allocate memory to contain the whole file:*/
+ fclose (fp);
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:BasicManagement:1",
+ Status, AdditionalInfo, SuccessCount, FailureCount,
+ AverageResponseTime, MinimumResponseTime,
+ MaximumResponseTime, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+NSLookup (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<TestID>%lu</TestID>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called NSLookup");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:BasicManagement:1",
+ TestID, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetNSLookupResult (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<Status>%s</Status>"
+ "<AdditionalInfo>%s</AdditionalInfo>"
+ "<SuccessCount>%lu</SuccessCount>"
+ "<Result>%s</Result>" "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetNSLookupResult");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:BasicManagement:1",
+ Status, AdditionalInfo, SuccessCount, Result, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+Traceroute (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<TestID>%lu</TestID>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called Traceroute");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:BasicManagement:1",
+ TestID, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetTracerouteResult (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<Status>%s</Status>"
+ "<AdditionalInfo>%s</AdditionalInfo>"
+ "<ResponseTime>%lu</ResponseTime>"
+ "<HopHosts>%s</HopHosts>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetTracerouteResult");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:BasicManagement:1",
+ Status, AdditionalInfo, ResponseTime, HopHosts,
+ action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+InterfaceReset (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<TestID>%lu</TestID"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called InterfaceReset");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:BasicManagement:1",
+ TestID, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetInterfaceResetResult (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<Status>%s</Status>"
+ "<AdditionalInfo>%s</AdditionalInfo>"
+ "<NumberOfSuccesses>%u</NumberOfSuccesses>"
+ "<NumberOfFailures>%u</NumberOfFailures>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetInterfaceResetResult");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:BasicManagement:1",
+ Status, AdditionalInfo, NumberOfSuccesses,
+ NumberOfFailures, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+SelfTest (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<TestID>%lu</TestID>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called SelfTest");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:BasicManagement:1",
+ TestID, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetSelfTestResult (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<Status>%s</Status>"
+ "<AdditionalInfo>%s</AdditionalInfo>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetSelfTestResult");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:BasicManagement:1",
+ Status, AdditionalInfo, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetActiveTestIDs (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<TestIDs>%s</TestIDs>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetActiveTestIDs");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:BasicManagement:1",
+ TestIDs, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetTestInfo (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<Type>%s</Type>"
+ "<State>%s</State>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetTestInfo");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:BasicManagement:1",
+ Type, State, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+CancelTest (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called CancelTest");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:BasicManagement:1",
+ action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetLogURIs (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<LogURIs>%s</LogURIs>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetLogURIs");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:BasicManagement:1",
+ LogURIs, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+SetLogInfo (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called SetLogInfo");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:BasicManagement:1",
+ action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetLogInfo (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<Configurable>%s</Configurable>"
+ "<Enabled>%s</Enabled>"
+ "<LogLevel>%s</LogLevel>"
+ "<LogURL>%lu</LogURL>"
+ "<MaxSize>%lu</MaxSize>"
+ "<LastChange>%lu</LastChange>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetLogInfo");
+ printf ("Function not yet implemented!");
+
+ bodylen =
+ snprintf (body, sizeof (body), resp, action,
+ "urn:schemas-upnp-org:service:BasicManagement:1",
+ (Configurable) ? "1" : "0", (Enabled) ? "1" : "0", LogLevel,
+ LogURL, MaxSize, LastChange, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+/*Configuration Management*/
+static void
+GetSupportedDataModels (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<SupportedDataModels>%s</SupportedDataModels>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetSupportedDataModels");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:ConfigurationManagement:1",
+ SupportedDataModels, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetSupportedParameters (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<Result>%s</Result>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetSupportedParameters");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:ConfigurationManagement:1",
+ Result, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetInstances (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<Result>%s</Result>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetInstances");
+ printf ("Function not yet implemented!");
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:ConfigurationManagement:1",
+ Result, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetValues (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<ParameterValueList>%s</ParameterValueList>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetValues");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:ConfigurationManagement:1",
+ ParameterValueList, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetSelectedValues (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<ParameterValueList>%s</ParameterValueList>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetSelectedValues");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:ConfigurationManagement:1",
+ ParameterValueList, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+SetValues (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<Status>%s</Status>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called SetValues");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:ConfigurationManagement:1",
+ Status, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+CreateInstance (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<InstanceIdentifier>%s</InstanceIdentifier>"
+ "<Status>%s</Status>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called CreateInstance");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:ConfigurationManagement:1",
+ InstanceIdentifier, Status, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+DeleteInstance (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<Status>%s</Status>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called DeleteInstance");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:ConfigurationManagement:1",
+ Status, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetAttributes (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<NodeAttributeValueList>%s</NodeAttributeValueList>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetAttributes");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:ConfigurationManagement:1",
+ NodeAttributeValueList, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+SetAttributes (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<Status>%s</Status>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called SetAttributes");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:ConfigurationManagement:1",
+ Status, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetInconsistentStatus (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<StateVariableValue>%s</StateVariableValue>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetInconsistentStatus");
+ printf ("Function not yet implemented!");
+ bool StateVariableValue = false;
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:ConfigurationManagement:1",
+ (StateVariableValue) ? "1" : "0", action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetConfigurationUpdate (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<StateVariableValue>%s</StateVariablevalue>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetConfigurationUpdate");
+ printf ("Function not yet implemented!");
+ char *StateVariableValue = NULL;
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:ConfigurationManagement:1",
+ StateVariableValue, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetCurrentConfigurationVersion (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<StateVariableValue>%lu</StateVariableValue>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetCurrentConfigurationVersion");
+ printf ("Function not yet implemented!");
+ unsigned long int StateVariableValue = 0;
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:ConfigurationManagement:1",
+ StateVariableValue, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetSupportedDataModelsUpdate (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<StateVariableValue>%s</StateVariableValue>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetSupportedDataModelsUpdate");
+ printf ("Function not yet implemented!");
+ char *StateVariableValue = NULL;
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:ConfigurationManagement:1",
+ StateVariableValue, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetSupportedParametersUpdate (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<StateVariableValue>%s</StateVariableValue>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetSupportedParametersUpdate");
+ printf ("Function not yet implemented!");
+ char *StateVariableValue = NULL;
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:ConfigurationManagement:1",
+ StateVariableValue, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetAttributeValuesUpdate (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<StateVariableValue>%s</StateVariableValue>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetAttributeValuesUpdate");
+ printf ("Function not yet implemented!");
+ char *StateVariableValue = NULL;
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:ConfigurationManagement:1",
+ StateVariableValue, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+/*Software Management*/
+static void
+Install (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<OperationID>%lu</OperationID>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called Install");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:SoftwareManagement:1",
+ OperationID, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+Update (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<OperationID>%lu</OperationID>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called Update");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:SoftwareManagement:1",
+ OperationID, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+Uninstall (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<OperationID>%lu</OperationID>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called Uninstall");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:SoftwareManagement:1",
+ OperationID, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+
+static void
+Stop (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<OperationID>%lu</OperationID>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called Stop");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:SoftwareManagement:1",
+ OperationID, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+Start (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<OperationID>%lu</OperationID>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called Start");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:SoftwareManagement:1",
+ OperationID, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetDUIDs (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<DUIDs>%s</DUIDs>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetDUIDs");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:SoftwareManagement:1",
+ DUIDs, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetEUIDs (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<EUIDs>%s</EUIDs>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetEUIDs");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:SoftwareManagement:1",
+ EUIDs, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetActiveEUIDs (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<ActiveEUIDs>%s</ActiveEUIDs>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetActiveEUIDs");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:SoftwareManagement:1",
+ ActiveEUIDs, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetRunningEUIDs (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<RunningEUIDs>%s</RunningEUIDs>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetRunningEUIDs");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:SoftwareManagement:1",
+ RunningEUIDs, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetOperationInfo (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<OperationState>%s</OperationState>"
+ "<TargetedIDs>%s</TargetedIDs>"
+ "<Action>%s</Action>"
+ "<ErrorDescription>%s</ErrorDescription>"
+ "<AdditionalInfo>%s</AdditionalInfo>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetOperationInfo");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:SoftwareManagement:1",
+ OperationState, TargetedIDs, Action, ErrorDescription,
+ AdditionalInfo, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetOperationIDs (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<OperationIDs>%s</OperationIDs>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetOperationIDs");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:SoftwareManagement:1",
+ OperationIDs, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetErrorEUIDs (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<ErrorEUIDs>%s</ErrorEUIDs>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetErrorEUIDs");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:SoftwareManagement:1",
+ ErrorEUIDs, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetDUInfo (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<DUName>%s</DUName>"
+ "<DUVersion>%s</DUVersion>"
+ "<DUType>%s</DUType>"
+ "<DUState>%s</DUState>"
+ "<DUURI>%lu</DUURI>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetDUInfo");
+ printf ("Function not yet implemented!");
+
+ bodylen =
+ snprintf (body, sizeof (body), resp, action,
+ "urn:schemas-upnp-org:service:SoftwareManagement:1", DUName,
+ DUVersion, DUType, DUState, DUURI, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GetEUInfo (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<EUName>%s</EUName>"
+ "<EUVersion>%s</EUVersion>"
+ "<EURequestedState>%s</EURequestedState>"
+ "<EUExecutionState>%s</ExecutionState>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetEUInfo");
+ printf ("Function not yet implemented!");
+
+ bodylen = snprintf (body, sizeof (body), resp,
+ action,
+ "urn:schemas-upnp-org:service:SoftwareManagement:1",
+ EUName, EUVersion, EURequestedState, EUExecutionState,
+ action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+/*Low Power service*/
+
+static void
+GetPowerManagementInfo (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<WakeupMethod>%s</WakeupMethod>"
+ "<PowerSupplyStatus>%s</PowerSupplyStatus>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GetPowerManagementInfo");
+ printf ("Function not yet implemented!");
+
+ bodylen =
+ snprintf (body, sizeof (body), resp, action,
+ "urn:schemas-upnp-org:service:LowPower", WakeupMethod,
+ PowerSupplyStatus, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+Wakeup (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called Wakeup");
+ printf ("Function not yet implemented!");
+
+ bodylen =
+ snprintf (body, sizeof (body), resp, action,
+ "urn:schemas-upnp-org:service:LowPower", action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+static void
+GoToSleep (struct upnphttp *h, const char *action)
+{
+ static const char resp[] =
+ "<u:%sResponse "
+ "xmlns:u=\"%s\">"
+ "<SleepPeriod>%lu</SleepPeriod>"
+ "<PowerState>%s</PowerState>"
+ "</u:%sResponse>";
+
+ char body[512];
+ int bodylen;
+ syslog (LOG_WARNING, "called GoToSleep");
+ printf ("Function not yet implemented!");
+
+ bodylen =
+ snprintf (body, sizeof (body), resp, action,
+ "urn:schemas-upnp-org:service:LowPower", SleepPeriod,
+ PowerState, action);
+ BuildSendAndCloseSoapResp (h, body, bodylen);
+}
+
+
+static const struct
+{
+ const char *methodName;
+ void (*methodImpl) (struct upnphttp *, const char *);
+}
+soapMethods[] =
+{
+ {
+ "Reboot", Reboot},
+ {
+ "BaseLineReset", BaselineReset},
+ {
+ "GetDeviceStatus", GetDeviceStatus},
+ {
+ "GetSequenceMode", GetSequenceMode},
+ {
+ "SetSequenceMode", SetSequenceMode},
+ {
+ "Ping", Ping},
+ {
+ "GetPingResult", GetPingResult},
+ {
+ "NSLookup", NSLookup},
+ {
+ "GetNSLookupResult", GetNSLookupResult},
+ {
+ "Traceroute", Traceroute},
+ {
+ "GetTracerouteResult", GetTracerouteResult},
+ {
+ "InterfaceReset", InterfaceReset},
+ {
+ "GetInterfaceResetResult", GetInterfaceResetResult},
+ {
+ "SelfTest", SelfTest},
+ {
+ "GetSelfTestResult", GetSelfTestResult},
+ {
+ "GetActiveTestIDs", GetActiveTestIDs},
+ {
+ "GetTestInfo", GetTestInfo},
+ {
+ "CancelTest", CancelTest},
+ {
+ "GetLogURIs", GetLogURIs},
+ {
+ "SetLogInfo", SetLogInfo},
+ {
+ "LogInfo", GetLogInfo},
+ /*Configuration Management */
+ {
+ "GetSupportedDataModels", GetSupportedDataModels},
+ {
+ "GetSupportedParameters", GetSupportedParameters},
+ {
+ "GetInstances", GetInstances},
+ {
+ "GetValues", GetValues},
+ {
+ "GetSelectedValues", GetSelectedValues},
+ {
+ "SetValues", SetValues},
+ {
+ "CreateInstance", CreateInstance},
+ {
+ "DeleteInstance", DeleteInstance},
+ {
+ "GetAttributes", GetAttributes},
+ {
+ "SetAttributes", SetAttributes},
+ {
+ "GetInconsistentStatus", GetInconsistentStatus},
+ {
+ "GetConfigurationUpdate", GetConfigurationUpdate},
+ {
+ "GetCurrentConfigurationVersion", GetCurrentConfigurationVersion},
+ {
+ "GetSupportedDataModelsUpdate", GetSupportedDataModelsUpdate},
+ {
+ "GetSupportedParametersUpdate", GetSupportedParametersUpdate},
+ {
+ "GetAttributeValuesUpdate", GetAttributeValuesUpdate},
+ /*Software Management */
+ {
+ "Install", Install},
+ {
+ "Update", Update},
+ {
+ "Uninstall", Uninstall},
+ {
+ "Start", Start},
+ {
+ "Stop", Stop},
+ {
+ "GetDUIDs", GetDUIDs},
+ {
+ "GetEUIDs", GetEUIDs},
+ {
+ "GetActiveEUIDs", GetActiveEUIDs},
+ {
+ "GetRunningEUIDs", GetRunningEUIDs},
+ {
+ "GetOperationInfo", GetOperationInfo},
+ {
+ "GetOperationIDs", GetOperationIDs},
+ {
+ "GetErrorEUIDs", GetErrorEUIDs},
+ {
+ "GetDUInfo", GetDUInfo},
+ {
+ "GetEUInfo", GetEUInfo},
+ /*Low Power Service */
+ {
+ "GetPowerManagementInfo", GetPowerManagementInfo},
+ {
+ "Wakeup", Wakeup},
+ {
+ "GoToSleep", GoToSleep},
+ {
+ 0, 0}
+};
+
+void
+ExecuteSoapAction (struct upnphttp *h, const char *action, int n)
+{
+ char *p;
+ char *p2;
+ int i, len, methodlen;
+
+ i = 0;
+ p = strchr (action, '#');
+
+ if (p)
+ {
+ p++;
+ p2 = strchr (p, '"');
+ if (p2)
+ methodlen = p2 - p;
+ else
+ methodlen = n - (p - action);
+ syslog (LOG_WARNING, "SoapMethod: %.*s\n", methodlen, p);
+ while (soapMethods[i].methodName)
+ {
+ len = strlen (soapMethods[i].methodName);
+ if (strncmp (p, soapMethods[i].methodName, len) == 0)
+ {
+ soapMethods[i].methodImpl (h, soapMethods[i].methodName);
+ return;
+ }
+ i++;
+ }
+
+ syslog (LOG_WARNING, "SoapMethod: Unknown: %.*s\n", methodlen, p);
+ }
+
+ SoapError (h, 401, "Invalid Action");
+}
+
+/* Standard Errors:
+ *
+ * errorCode errorDescription Description
+ * -------- ---------------- -----------
+ * 401 Invalid Action No action by that name at this service.
+ * 402 Invalid Args Could be any of the following: not enough in args,
+ * too many in args, no in arg by that name,
+ * one or more in args are of the wrong data type.
+ * 403 Out of Sync Out of synchronization.
+ * 501 Action Failed May be returned in current state of service
+ * prevents invoking that action.
+ * 600-699 TBD Common action errors. Defined by UPnP Forum
+ * Technical Committee.
+ * 700-799 TBD Action-specific errors for standard actions.
+ * Defined by UPnP Forum working committee.
+ * 800-899 TBD Action-specific errors for non-standard actions.
+ * Defined by UPnP vendor.
+ */
+void
+SoapError (struct upnphttp *h, int errCode, const char *errDesc)
+{
+ static const char resp[] =
+ "<s:Envelope "
+ "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
+ "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
+ "<s:Body>"
+ "<s:Fault>"
+ "<faultcode>s:Client</faultcode>"
+ "<faultstring>UPnPError</faultstring>"
+ "<detail>"
+ "<UPnPError xmlns=\"urn:schemas-upnp-org:control-1-0\">"
+ "<errorCode>%d</errorCode>"
+ "<errorDescription>%s</errorDescription>"
+ "</UPnPError>"
+ "</detail>"
+ "</s:Fault>"
+ "</s:Body>"
+ "</s:Envelope>";
+
+ char body[2048];
+ int bodylen;
+
+ syslog (LOG_WARNING, "Returning UPnPError %d: %s\n", errCode, errDesc);
+ printf ("Returning UPnPError %d: %s\n", errCode, errDesc);
+ bodylen = snprintf (body, sizeof (body), resp, errCode, errDesc);
+ BuildResp2_upnphttp (h, 500, "Internal Server Error", body, bodylen);
+ SendResp_upnphttp (h);
+ CloseSocket_upnphttp (h);
+}
diff --git a/cleopatre/application/upnpd/src/uuid.c b/cleopatre/application/upnpd/src/uuid.c
new file mode 100644
index 0000000000..3f78a5468f
--- /dev/null
+++ b/cleopatre/application/upnpd/src/uuid.c
@@ -0,0 +1,247 @@
+/* upnpd project
+ *
+ *
+ * upnpd device
+ *
+ * This file is part of upnpd.
+ *
+ *
+ * Portions of the code from the MiniUPnP project:
+ *
+ * Copyright (c) 2006-2007, Thomas Bernard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <string.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <syslog.h>
+#include "getifaddr.h"
+#define ETH_ALEN 6
+#define NSEC_PER_SEC 1000000000L
+#define NSEC_PER_MSEC 1000000L
+
+static u_int32_t clock_seq;
+static const u_int32_t clock_seq_max = 0x3fff; /* 14 bits */
+static int clock_seq_initialized;
+
+unsigned long long
+monotonic_us (void)
+{
+ struct timespec ts;
+
+ syscall (__NR_clock_gettime, CLOCK_MONOTONIC, &ts);
+ return ts.tv_sec * 1000000ULL + ts.tv_nsec / 1000;
+}
+
+int
+read_bootid_node (unsigned char *buf, size_t size)
+{
+ FILE *boot_id;
+
+ if (size != 6)
+ return -1;
+
+ boot_id = fopen ("/proc/sys/kernel/random/boot_id", "r");
+ if (!boot_id)
+ return -1;
+ if ((fseek (boot_id, 24, SEEK_SET) < 0) ||
+ (fscanf (boot_id, "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
+ &buf[0], &buf[1], &buf[2], &buf[3], &buf[4], &buf[5]) != 6))
+ {
+ fclose (boot_id);
+ return -1;
+ }
+
+ fclose (boot_id);
+ return 0;
+}
+
+static void
+read_random_bytes (unsigned char *buf, size_t size)
+{
+ int i;
+ pid_t pid;
+
+ i = open ("/dev/urandom", O_RDONLY);
+ if (i >= 0)
+ {
+ if (read (i, buf, size) < 0)
+
+ {
+ syslog (LOG_WARNING, "Could not read byte number.\n");
+ }
+ else
+ close (i);
+ }
+ /* Paranoia. /dev/urandom may be missing.
+ * rand() is guaranteed to generate at least [0, 2^15) range,
+ * but lowest bits in some libc are not so "random". */
+ srand (monotonic_us ());
+ pid = getpid ();
+ while (1)
+ {
+ for (i = 0; i < (int) (size); i++)
+ buf[i] ^= rand () >> 5;
+ if (pid == 0)
+ break;
+ srand (pid);
+ pid = 0;
+ }
+}
+
+void
+init_clockseq (void)
+{
+ unsigned char buf[4];
+
+ read_random_bytes (buf, 4);
+ memcpy (&clock_seq, &buf, sizeof (clock_seq));
+ clock_seq &= clock_seq_max;
+ clock_seq_initialized = 1;
+}
+
+int
+generate_uuid (unsigned char uuid_out[16])
+{
+ static u_int64_t last_time_all;
+ static unsigned int clock_seq_started;
+ static char last_node[6] = { 0, 0, 0, 0, 0, 0 };
+
+ struct timespec ts;
+ u_int64_t time_all;
+ int inc_clock_seq = 0;
+
+ unsigned char mac[6];
+ int mac_error;
+
+ memset (&mac, '\0', sizeof (mac));
+ /* Get the spatially unique node identifier */
+
+ mac_error = getsyshwaddr ((char *) mac, sizeof (mac));
+
+ if (!mac_error)
+ {
+ memcpy (&uuid_out[10], mac, ETH_ALEN);
+ }
+ else
+ {
+ /* use bootid's nodeID if no network interface found */
+ syslog (LOG_WARNING, "Could not find MAC. Use bootid's nodeID.\n");
+ if (read_bootid_node (&uuid_out[10], 6) != 0)
+ {
+ syslog (LOG_WARNING, "bootid node not successfully read.\n");
+ read_random_bytes (&uuid_out[10], 6);
+ }
+ }
+
+ if (memcmp (last_node, uuid_out + 10, 6) != 0)
+ {
+ inc_clock_seq = 1;
+ memcpy (last_node, uuid_out + 10, 6);
+ }
+
+ /* Determine 60-bit timestamp value. For UUID version 1, this is
+ * represented by Coordinated Universal Time (UTC) as a count of 100-
+ * nanosecond intervals since 00:00:00.00, 15 October 1582 (the date of
+ * Gregorian reform to the Christian calendar).
+ */
+ syscall (__NR_clock_gettime, CLOCK_REALTIME, &ts);
+ time_all = ((u_int64_t) ts.tv_sec) * (NSEC_PER_SEC / 100);
+ time_all += ts.tv_nsec / 100;
+
+ /* add offset from Gregorian Calendar to Jan 1 1970 */
+ time_all += 12219292800000ULL * (NSEC_PER_MSEC / 100);
+ time_all &= 0x0fffffffffffffffULL; /* limit to 60 bits */
+
+ /* Determine clock sequence (max. 14 bit) */
+ if (!clock_seq_initialized)
+ {
+ init_clockseq ();
+ clock_seq_started = clock_seq;
+ }
+ else
+ {
+ if (inc_clock_seq || time_all <= last_time_all)
+ {
+ clock_seq = (clock_seq + 1) & clock_seq_max;
+ if (clock_seq == clock_seq_started)
+ {
+ clock_seq = (clock_seq - 1) & clock_seq_max;
+ }
+ }
+ else
+ clock_seq_started = clock_seq;
+ }
+ last_time_all = time_all;
+
+ /* Fill in timestamp and clock_seq values */
+ uuid_out[3] = (u_int8_t) time_all;
+ uuid_out[2] = (u_int8_t) (time_all >> 8);
+ uuid_out[1] = (u_int8_t) (time_all >> 16);
+ uuid_out[0] = (u_int8_t) (time_all >> 24);
+ uuid_out[5] = (u_int8_t) (time_all >> 32);
+ uuid_out[4] = (u_int8_t) (time_all >> 40);
+ uuid_out[7] = (u_int8_t) (time_all >> 48);
+ uuid_out[6] = (u_int8_t) (time_all >> 56);
+
+ uuid_out[8] = clock_seq >> 8;
+ uuid_out[9] = clock_seq & 0xff;
+
+ /* Set UUID version to 1 --- time-based generation */
+ uuid_out[6] = (uuid_out[6] & 0x0F) | 0x10;
+ /* Set the UUID variant to DCE */
+ uuid_out[8] = (uuid_out[8] & 0x3F) | 0x80;
+
+ return 0;
+}
+
+/* Places a null-terminated 37-byte time-based UUID string in the buffer pointer to by buf.
+ * A large enough buffer must already be allocated. */
+int
+get_uuid_string (char *buf)
+{
+ unsigned char uuid[16];
+
+ if (generate_uuid (uuid) != 0)
+ return -1;
+
+ sprintf (buf,
+ "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6],
+ uuid[7], uuid[8], uuid[9], uuid[10], uuid[11], uuid[12],
+ uuid[13], uuid[14], uuid[15]);
+ buf[36] = '\0';
+
+ return 0;
+}
diff --git a/cleopatre/application/upnpd/upnpd.conf b/cleopatre/application/upnpd/upnpd.conf
new file mode 100644
index 0000000000..e41a2a4721
--- /dev/null
+++ b/cleopatre/application/upnpd/upnpd.conf
@@ -0,0 +1,29 @@
+
+
+# if the WAN interface has several IP addresses, you
+# can specify the one to use below
+#ext_ip=
+
+# LAN network interfaces IPs / networks
+# there can be multiple listening ips for SSDP traffic.
+# should be under the form nnn.nnn.nnn.nnn/nn
+# HTTP is available on all interfaces
+# When MULTIPLE_EXTERNAL_IP is enabled, the external ip
+# address associated with the subnet follows. for example :
+# listening_ip=10.3.1.41/16 255.255.0.0
+
+# port for HTTP (descriptions and SOAP) traffic. set 0 for autoselect.
+port=1900
+
+# notify interval in seconds. default is 30 seconds.
+notify_interval=30
+
+# uuid : generate your own with "make genuuid"
+#uuid=fc4ec57e-b051-11db-88f8-0060085db3f6
+
+# serial and model number the daemon will report to clients
+# in its XML description
+serial=12345678
+model_number=1
+
+
diff --git a/cleopatre/application/upnpd/zcip.script b/cleopatre/application/upnpd/zcip.script
new file mode 100755
index 0000000000..a1d75ae433
--- /dev/null
+++ b/cleopatre/application/upnpd/zcip.script
@@ -0,0 +1,39 @@
+#!/bin/sh
+# only for use as "zcip" callback script
+if [ "x$interface" = x ]
+then
+ exit 1
+fi
+
+#zcip should start on boot/resume and various media changes
+case "$1" in
+init)
+ # for now, zcip requires the link to be already up,
+ # and it drops links when they go down. that isn't
+ # the most robust model...
+ exit 0
+ ;;
+config)
+ if [ "x$ip" = x ]
+ then
+ exit 1
+ fi
+ # remember $ip for $interface, to use on restart
+ if [ "x$IP" != x -a -w "$IP.$interface" ]
+ then
+ echo $ip > "$IP.$interface"
+ fi
+ ifconfig $interface $ip netmask 255.255.0.0
+ route add default $interface
+ echo "Starting upnpd..."
+ /usr/local/bin/upnpd &
+ ;;
+deconfig)
+ if [ x$ip = x ]
+ then
+ exit 1
+ fi
+ ifconfig $interface ifdown
+ ;;
+esac
+exit 1
diff --git a/cleopatre/buildroot/target/device/Spidcom/arizona/linux26.config b/cleopatre/buildroot/target/device/Spidcom/arizona/linux26.config
index 2d870a327d..e30ee6b776 100644
--- a/cleopatre/buildroot/target/device/Spidcom/arizona/linux26.config
+++ b/cleopatre/buildroot/target/device/Spidcom/arizona/linux26.config
@@ -398,6 +398,7 @@ CONFIG_LLC=y
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NET_TCPPROBE is not set
+# CONFIG_SEQ_CHECK is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
diff --git a/cleopatre/buildroot/target/device/Spidcom/scr310/linux26.config b/cleopatre/buildroot/target/device/Spidcom/scr310/linux26.config
index 48bf1ee085..ee13702113 100644
--- a/cleopatre/buildroot/target/device/Spidcom/scr310/linux26.config
+++ b/cleopatre/buildroot/target/device/Spidcom/scr310/linux26.config
@@ -354,6 +354,7 @@ CONFIG_LLC=y
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NET_TCPPROBE is not set
+# CONFIG_SEQ_CHECK is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
diff --git a/cleopatre/buildroot/target/device/Spidcom/spk300/linux26.config b/cleopatre/buildroot/target/device/Spidcom/spk300/linux26.config
index 52a7b8ec8e..868a73a590 100644
--- a/cleopatre/buildroot/target/device/Spidcom/spk300/linux26.config
+++ b/cleopatre/buildroot/target/device/Spidcom/spk300/linux26.config
@@ -354,6 +354,7 @@ CONFIG_LLC=y
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NET_TCPPROBE is not set
+# CONFIG_SEQ_CHECK is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
diff --git a/cleopatre/buildroot/target/device/Spidcom/spk300g/linux26.config b/cleopatre/buildroot/target/device/Spidcom/spk300g/linux26.config
index 327d33c2dc..0593f12365 100644
--- a/cleopatre/buildroot/target/device/Spidcom/spk300g/linux26.config
+++ b/cleopatre/buildroot/target/device/Spidcom/spk300g/linux26.config
@@ -356,6 +356,7 @@ CONFIG_LLC=y
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NET_TCPPROBE is not set
+# CONFIG_SEQ_CHECK is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
diff --git a/cleopatre/buildroot/target/device/Spidcom/spk310/linux26.config b/cleopatre/buildroot/target/device/Spidcom/spk310/linux26.config
index 9cae6e0a02..6b8702d47b 100644
--- a/cleopatre/buildroot/target/device/Spidcom/spk310/linux26.config
+++ b/cleopatre/buildroot/target/device/Spidcom/spk310/linux26.config
@@ -354,6 +354,7 @@ CONFIG_LLC=y
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NET_TCPPROBE is not set
+# CONFIG_SEQ_CHECK is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
diff --git a/cleopatre/buildroot/target/device/Spidcom/spr300/linux26.config b/cleopatre/buildroot/target/device/Spidcom/spr300/linux26.config
index 61665ae3f4..dfd7b774f4 100644
--- a/cleopatre/buildroot/target/device/Spidcom/spr300/linux26.config
+++ b/cleopatre/buildroot/target/device/Spidcom/spr300/linux26.config
@@ -354,6 +354,7 @@ CONFIG_LLC=y
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NET_TCPPROBE is not set
+# CONFIG_SEQ_CHECK is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
diff --git a/cleopatre/buildroot/target/device/Spidcom/spr310/linux26.config b/cleopatre/buildroot/target/device/Spidcom/spr310/linux26.config
index 88caef0323..d36907de83 100644
--- a/cleopatre/buildroot/target/device/Spidcom/spr310/linux26.config
+++ b/cleopatre/buildroot/target/device/Spidcom/spr310/linux26.config
@@ -354,6 +354,7 @@ CONFIG_LLC=y
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NET_TCPPROBE is not set
+# CONFIG_SEQ_CHECK is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
diff --git a/cleopatre/devkit/plcdrv/arm/Makefile b/cleopatre/devkit/plcdrv/arm/Makefile
index 7afc7c61a6..241a6ec954 100644
--- a/cleopatre/devkit/plcdrv/arm/Makefile
+++ b/cleopatre/devkit/plcdrv/arm/Makefile
@@ -16,6 +16,11 @@ endif
#1st for all files
EXTRA_CFLAGS += $(DEBFLAGS) -D__LINUX__ -DDRV_VERSION=\"$(VERSION)\"
EXTRA_CFLAGS += -I../$(PLCSUBPATH)/inc
+
+ifeq ($(CONFIG_SEQ_CHECK),y)
+ EXTRA_CFLAGS += -DCONFIG_SEQ_CHECK
+endif
+
#2nd for each file
#CFLAGS_linux_drv.o := $(DEBFLAGS) -D__LINUX__ -I../$(PLCSUBPATH)/inc
diff --git a/cleopatre/devkit/plcdrv/arm/inc/linux_drv.h b/cleopatre/devkit/plcdrv/arm/inc/linux_drv.h
index a0fb729963..c562a6b741 100644
--- a/cleopatre/devkit/plcdrv/arm/inc/linux_drv.h
+++ b/cleopatre/devkit/plcdrv/arm/inc/linux_drv.h
@@ -17,6 +17,7 @@
*/
#include <linux/netdevice.h>
+#include <net/seq_check.h>
#include "common.h"
#include "hal.h"
@@ -82,6 +83,9 @@ struct net_priv
uint8_t firmware_written;
uint8_t version[ROM_VERSION_SIZE];
int service_type;
+#ifdef CONFIG_SEQ_CHECK
+ struct seq_check_ctx seq_check_ctx;
+#endif
};
/**
diff --git a/cleopatre/devkit/plcdrv/arm/src/linux_drv.c b/cleopatre/devkit/plcdrv/arm/src/linux_drv.c
index f374e8379f..683fe8878d 100644
--- a/cleopatre/devkit/plcdrv/arm/src/linux_drv.c
+++ b/cleopatre/devkit/plcdrv/arm/src/linux_drv.c
@@ -38,6 +38,7 @@
#include <linux/netlink.h>
#include <linux/poll.h>
#include <linux/wait.h>
+#include "net/seq_check.h"
#include <asm/arch/nvram.h>
#include <asm/arch/hardware/spi.h>
@@ -49,6 +50,8 @@
#include "mailbox.h"
#include "hal.h"
#include "registers.h"
+
+
#else
#include "common.h"
#include "linux_drv.h"
@@ -1255,6 +1258,9 @@ int plcdrv_rx(void *packet, int length, enum pkt_dest dst, uint32_t mark)
else
{
skb->protocol = eth_type_trans(skb, plcdrv_device);
+
+ seq_check_rx(&priv->seq_check_ctx, skb);
+
netif_rx(skb);
}
result = 0;
@@ -1328,6 +1334,8 @@ int plcdrv_data_tx(struct sk_buff *skb, struct net_device *dev)
TRACE("\nTX: virt@skb=%x ; virt@skb->data=%x ; skb->len=%d\n",(uint32_t)skb, (uint32_t)skb->data, skb->len);
PRINTPKT("TX",skb, skb->len);
+ seq_check_tx(&priv->seq_check_ctx, skb);
+
//Store the sk_buff in sk_buff list in used
if((status = put_skb_addr(skb, TX_DATA)))
{
@@ -1996,6 +2004,8 @@ int plcdrv_init(struct net_device *dev)
atomic_set (&priv->plc_select.plc_error, 0);
init_waitqueue_head (&priv->plc_select.wq);
+ seq_check_init(&priv->seq_check_ctx, "plc_drv");
+
return 0;
}// plcdrv_init
diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/Makefile b/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/Makefile
index e83176ed0c..f3ae6b7e03 100644
--- a/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/Makefile
+++ b/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/Makefile
@@ -15,7 +15,16 @@ ifeq ($(CONFIG_SYNOP3504),m)
synop3504mod-objs := synop3504.o synop3504_hw.o
CFLAGS_synop3504.o := -g -O0
CFLAGS_synop3504_hw.o := -g -O0
+
+ ifeq ($(CONFIG_SEQ_CHECK),y)
+ CFLAGS_synop3504.o += -DCONFIG_SEQ_CHECK
+ endif
endif
+
ifeq ($(CONFIG_SYNOP3504),y)
obj-$(CONFIG_SYNOP3504) += synop3504.o synop3504_hw.o
+
+ ifeq ($(CONFIG_SEQ_CHECK),y)
+ CFLAGS_synop3504.o += -DCONFIG_SEQ_CHECK
+ endif
endif
diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504.c b/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504.c
index f7309dda81..3e7346d3a6 100644
--- a/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504.c
+++ b/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504.c
@@ -54,10 +54,12 @@
#include <linux/kthread.h>
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
+#include <net/seq_check.h>
#include "synop3504_hw.h"
#include "synop3504.h"
+
/** Max size of a eth frame (size for rx buffer) must be align on 4 bytes */
#define PKT_BUF_SZ 1524
@@ -130,6 +132,9 @@ struct net_priv
unsigned int speed;
unsigned int duplex;
unsigned int service_type;
+#ifdef CONFIG_SEQ_CHECK
+ struct seq_check_ctx seq_check_ctx;
+#endif
};
/** How many Tx buffers to clean */
@@ -769,6 +774,8 @@ static int synop3504_tx(struct sk_buff *skb, struct net_device *dev)
TRACE("%s: Transmit\n", dev->name);
+ seq_check_tx(&priv->seq_check_ctx, skb);
+
n = tx->head_ptr;
//Increase head pointer and check end of ring
@@ -955,6 +962,8 @@ static void synop3504_rx(struct net_device *dev, int *budget)
skb->protocol = eth_type_trans(skb, dev);
dev->last_rx = jiffies;
+ seq_check_rx(&priv->seq_check_ctx, skb);
+
//Send RX packet to Linux
netif_receive_skb(skb);
@@ -1791,6 +1800,8 @@ static int __init synop3504_module_probe(struct platform_device *pdev)
priv->support_rmii = pdata->support_rmii;
priv->phy_addr = pdata->phy_addr;
+ seq_check_init(&priv->seq_check_ctx, "eth_drv");
+
//Proceed the init driver
result = synop3504_init(dev);
if(result < 0)
diff --git a/cleopatre/linux-2.6.25.10-spc300/include/net/seq_check.h b/cleopatre/linux-2.6.25.10-spc300/include/net/seq_check.h
new file mode 100644
index 0000000000..633ae4eeb4
--- /dev/null
+++ b/cleopatre/linux-2.6.25.10-spc300/include/net/seq_check.h
@@ -0,0 +1,89 @@
+#ifndef SEQ_CHECK_H
+#define SEQ_CHECK_H
+
+/*
+ * seq_check
+ * Copyright (C) 2011 SPiDCOM Technologies
+ *
+ * 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.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * Checks the sequence numbers in specially crafted packets (like those sent by
+ * iperf), and reports the gaps.
+ * The purpose is to help investigate packet loss in a network chain.
+ * Concerned network drivers participate by calling the appropriate functions
+ * provided by seq_check.
+ * seq_check can be configured (via sysctl) to only check packets with a
+ * specific ethertype. The position of the sequence number in the packet can
+ * also be configured.
+ */
+
+#define SEQ_CHECK_VLAN_MAX 64
+#define SEQ_CHECK_DRV_NAME_SZ 10
+
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/sysctl.h>
+#include <linux/types.h>
+
+/* seq_check context. */
+struct seq_check_ctx
+{
+ /* Expected sequence number for the next received packet. For each VLAN. */
+ uint16_t seq_num_expected_rx[SEQ_CHECK_VLAN_MAX];
+
+ /* Expected sequence number for the next sent packet. For each VLAN. */
+ uint16_t seq_num_expected_tx[SEQ_CHECK_VLAN_MAX];
+
+ /* Name of the network driver. */
+ char drv_name[SEQ_CHECK_DRV_NAME_SZ];
+};
+
+#ifdef CONFIG_SEQ_CHECK
+
+/**
+ * Initialize the seq_check context for a particular network driver.
+ *
+ * \param ctx the seq_check context for the network driver.
+ * \param drv_name the name of the network driver.
+ */
+void seq_check_init(struct seq_check_ctx *ctx, const char *drv_name);
+
+/**
+ * Check the sequence number of a received packet.
+ *
+ * \param ctx the seq_check context for the network driver.
+ * \param skb the skb containing the packet to check.
+ */
+void seq_check_rx(struct seq_check_ctx *ctx, const struct sk_buff *skb);
+
+/**
+ * Check the sequence number of a to be sent packet.
+ *
+ * \param ctx the seq_check context for the network driver.
+ * \param skb the skb containing the packet to check.
+ */
+void seq_check_tx(struct seq_check_ctx *ctx, const struct sk_buff *skb);
+
+#else
+
+#define seq_check_init(ctx, drv_name) do {} while(0)
+#define seq_check_rx(ctx, skb) do {} while(0)
+#define seq_check_tx(ctx, skb) do {} while(0)
+
+#endif /* CONFIG_SEQ_CHECK */
+
+#endif /* SEQ_CHECK_H */
diff --git a/cleopatre/linux-2.6.25.10-spc300/net/Kconfig b/cleopatre/linux-2.6.25.10-spc300/net/Kconfig
index 6627c6ae5d..29d688f59e 100644
--- a/cleopatre/linux-2.6.25.10-spc300/net/Kconfig
+++ b/cleopatre/linux-2.6.25.10-spc300/net/Kconfig
@@ -225,6 +225,14 @@ config NET_TCPPROBE
To compile this code as a module, choose M here: the
module will be called tcp_probe.
+config SEQ_CHECK
+ bool "seq_check"
+ default n
+ help
+ This feature provides a check of the sequence numbers in specially crafted
+ packets(like those sent by the iperf tool), and reports the gaps.
+ The purpose is to help investigate packet loss in a network chain.
+
endmenu
endmenu
@@ -250,6 +258,7 @@ endmenu
source "net/rfkill/Kconfig"
source "net/9p/Kconfig"
+
endif # if NET
endmenu # Networking
diff --git a/cleopatre/linux-2.6.25.10-spc300/net/Makefile b/cleopatre/linux-2.6.25.10-spc300/net/Makefile
index b7a13643b5..c2868bb9a4 100644
--- a/cleopatre/linux-2.6.25.10-spc300/net/Makefile
+++ b/cleopatre/linux-2.6.25.10-spc300/net/Makefile
@@ -57,3 +57,5 @@ obj-$(CONFIG_NET_9P) += 9p/
ifeq ($(CONFIG_NET),y)
obj-$(CONFIG_SYSCTL) += sysctl_net.o
endif
+
+obj-$(CONFIG_SEQ_CHECK) += seq_check.o
diff --git a/cleopatre/linux-2.6.25.10-spc300/net/seq_check.c b/cleopatre/linux-2.6.25.10-spc300/net/seq_check.c
new file mode 100644
index 0000000000..56dc8f49e0
--- /dev/null
+++ b/cleopatre/linux-2.6.25.10-spc300/net/seq_check.c
@@ -0,0 +1,298 @@
+/*
+ * seq_check
+ * Copyright (C) 2011 SPiDCOM Technologies
+ *
+ * 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.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <net/seq_check.h>
+
+#include <asm/string.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/sysctl.h>
+#include <linux/types.h>
+
+#define SEQ_CHECK_LOG(ctx, dir, vlan_id, fmt, ...) \
+ printk (KERN_WARNING "seq_check %s %s: [%02u] " \
+ fmt, ctx->drv_name, dir, vlan_id, ##__VA_ARGS__)
+
+#define SEQ_CHECK_SYSCTL_ETHERTYPE_SZ 7 /* = 6 + 1
+ = strlen("0x0800") + '\0' */
+
+#define SEQ_CHECK_DEFAULT_ETHERTYPE "0x0800" /* ETH_P_IP */
+#define SEQ_CHECK_DEFAULT_SEQ_POS 44 /* The position of the sequence number
+ in an iperf packet. */
+
+/* Strings representing the direction (Rx or Tx). */
+static const char *seq_check_dir_rx_str = "Rx";
+static const char *seq_check_dir_tx_str = "Tx";
+
+/* Ethertype of the packets to check. */
+static uint16_t seq_check_ethertype;
+
+/* Position/offset (in bytes) of the sequence number in the packets, relative
+ * to the start of the MAC header. */
+static unsigned int seq_check_seq_num_pos;
+
+/* Sysctl: Ethertype in string format. */
+char seq_check_sysctl_ethertype_str[SEQ_CHECK_SYSCTL_ETHERTYPE_SZ];
+
+/*
+ * Set the ethertype numeric value from the specified string ethertype value.
+ */
+static int
+seq_check_set_ethertype_from_str(void)
+{
+ unsigned long temp;
+ int ret;
+
+ ret = strict_strtoul(seq_check_sysctl_ethertype_str, 16, &temp);
+
+ if (ret == 0)
+ {
+ /* temp is kept in uint16_t range by the size of
+ * sysctl_ethertype_str. */
+ seq_check_ethertype = htons((uint16_t)temp);
+ }
+
+ return ret;
+}
+
+/*
+ * Handler for setting the ethertype from sysctl.
+ */
+static int
+seq_check_sysctl_do_ethertype(ctl_table *table, int write, struct file *filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ int ret;
+
+ ret = proc_dostring(table, write, filp, buffer, lenp, ppos);
+
+ if ((ret == 0) && write)
+ {
+ ret = seq_check_set_ethertype_from_str();
+ }
+
+ return ret;
+}
+
+/* sysctl table: level 1. */
+static ctl_table seq_check_sysctl_table_lvl1[]=
+{
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "ethertype",
+ .data = &seq_check_sysctl_ethertype_str,
+ .maxlen = SEQ_CHECK_SYSCTL_ETHERTYPE_SZ,
+ .mode = 0644,
+ .proc_handler = seq_check_sysctl_do_ethertype,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "seq_num_pos",
+ .data = &seq_check_seq_num_pos,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec
+ },
+ { }
+};
+
+/* sysctl table: level 0. */
+static ctl_table seq_check_sysctl_table_lvl0[]=
+{
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "seq_check",
+ .mode = 0555,
+ .child = seq_check_sysctl_table_lvl1
+ },
+ { }
+};
+
+static struct ctl_table_header *seq_check_sysctl_table_header;
+
+static struct ctl_path seq_check_sysctl_path[] =
+{
+ { .procname = "net", .ctl_name = CTL_NET },
+ { }
+};
+
+void
+seq_check_init(struct seq_check_ctx *ctx, const char *drv_name)
+{
+ BUG_ON(ctx == NULL);
+ BUG_ON(drv_name == NULL);
+
+ memset(ctx->seq_num_expected_rx, 0, sizeof(ctx->seq_num_expected_rx));
+ memset(ctx->seq_num_expected_tx, 0, sizeof(ctx->seq_num_expected_tx));
+ strlcpy(ctx->drv_name, drv_name, sizeof(ctx->drv_name));
+}
+EXPORT_SYMBOL(seq_check_init);
+
+/**
+ * Check the sequence number.
+ *
+ * \param ctx the seq_check context.
+ * \param skb the skb containing the packet to check.
+ * \param seq_num_expected the relevant seq_num_expected (Rx or Tx).
+ * \param dir the relevant string describing the direction (Rx or Tx).
+ */
+static void
+__seq_check(struct seq_check_ctx *ctx, const struct sk_buff *skb,
+ uint16_t seq_num_expected[SEQ_CHECK_VLAN_MAX], const char *dir)
+{
+ unsigned char *mac_hdr; /* Start of the MAC header. */
+ struct ethhdr *ethhdr;
+ uint16_t pkt_ethertype; /* Ethertype of the packet. */
+ unsigned int vlan_id;
+ uint16_t seq_num_actual; /* actual sequence number,
+ ie: the one in the packet. */
+
+ BUG_ON(ctx == NULL);
+ BUG_ON(skb == NULL);
+ BUG_ON(seq_num_expected == NULL);
+ BUG_ON(dir == NULL);
+
+ /* Determine the start of the MAC header.
+ * Note that in Tx packets created via AF_PACKET/SOCK_RAW, skb_mac_header
+ * is not set, so skb->data is used. */
+ if (skb_mac_header_was_set(skb))
+ {
+ mac_hdr = skb_mac_header(skb);
+ }
+ else
+ {
+ mac_hdr = skb->data;
+ }
+
+ BUG_ON(mac_hdr == NULL);
+
+ ethhdr = (struct ethhdr *)mac_hdr;
+
+ /* Determine the Ethernet Type */
+
+ /* VLAN tagged packet ? */
+ if (ethhdr->h_proto == htons(ETH_P_8021Q))
+ {
+ struct vlan_ethhdr *vlan_ethhdr;
+
+ vlan_ethhdr = (struct vlan_ethhdr *)mac_hdr;
+ pkt_ethertype = vlan_ethhdr->h_vlan_encapsulated_proto;
+ vlan_id = (ntohs(vlan_ethhdr->h_vlan_TCI) & VLAN_VID_MASK);
+
+ if (vlan_id >= SEQ_CHECK_VLAN_MAX)
+ {
+ SEQ_CHECK_LOG(ctx, dir, vlan_id,
+ "VLAN_ID (= %u) >= SEQ_CHECK_VLAN_MAX\n", vlan_id);
+ return;
+ }
+ }
+ else
+ {
+ pkt_ethertype = ethhdr->h_proto;
+ vlan_id = 0;
+ }
+
+ if (pkt_ethertype != seq_check_ethertype)
+ {
+ return;
+ }
+
+ if (skb_is_nonlinear(skb))
+ {
+ /* Handling a nonlinear skb (ie where the data may be in additional
+ * pages) is not supported. */
+ SEQ_CHECK_LOG(ctx, dir, vlan_id,
+ "skb is non linear. Not supported.\n");
+ }
+
+ /* Extract the sequence number in the packet. */
+
+ if (seq_check_seq_num_pos >= skb->len)
+ {
+ SEQ_CHECK_LOG(ctx, dir, vlan_id, "packet too small\n");
+ return;
+ }
+
+ seq_num_actual = ntohs(*((uint16_t *)(mac_hdr + seq_check_seq_num_pos)));
+
+ if (seq_num_actual != seq_num_expected[vlan_id])
+ {
+ SEQ_CHECK_LOG(ctx, dir, vlan_id, "expected=%04X, actual=%04X\n",
+ (seq_num_expected[vlan_id]),
+ seq_num_actual);
+ }
+
+ seq_num_expected[vlan_id] = seq_num_actual + 1; /* the overflow will make it
+ loop back to 0. */
+}
+
+/*
+ * Check sequence number in Rx.
+ */
+void
+seq_check_rx(struct seq_check_ctx *ctx, const struct sk_buff *skb)
+{
+ __seq_check(ctx, skb, ctx->seq_num_expected_rx, seq_check_dir_rx_str);
+}
+EXPORT_SYMBOL(seq_check_rx);
+
+/*
+ * Check sequence number in Tx.
+ */
+void
+seq_check_tx(struct seq_check_ctx *ctx, const struct sk_buff *skb)
+{
+ __seq_check(ctx, skb, ctx->seq_num_expected_tx, seq_check_dir_tx_str);
+}
+EXPORT_SYMBOL(seq_check_tx);
+
+
+static int __init
+seq_check_module_init(void)
+{
+ strcpy(seq_check_sysctl_ethertype_str, SEQ_CHECK_DEFAULT_ETHERTYPE);
+ seq_check_set_ethertype_from_str();
+
+ seq_check_seq_num_pos = SEQ_CHECK_DEFAULT_SEQ_POS;
+
+ seq_check_sysctl_table_header
+ = register_sysctl_paths(seq_check_sysctl_path,
+ seq_check_sysctl_table_lvl0);
+
+ return 0;
+}
+
+static void __exit
+seq_check_module_exit(void)
+{
+ if (seq_check_sysctl_table_header != NULL)
+ {
+ unregister_sysctl_table(seq_check_sysctl_table_header);
+ }
+}
+
+module_init(seq_check_module_init);
+module_exit(seq_check_module_exit);
+
+MODULE_AUTHOR("SPiDCOM Technologies");
+MODULE_DESCRIPTION("Detects gaps in sequence numbers of specially crafted packets.");
+MODULE_LICENSE("GPL");