1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
|
/*
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at https://mozilla.org/MPL/2.0/.
*/
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <string.h>
#include <zephyr/init.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/logging/log_backend.h>
#include <zephyr/logging/log_backend_net.h>
#include <zephyr/logging/log_ctrl.h>
#include <zephyr/logging/log_core.h>
#include <zephyr/net/conn_mgr_connectivity.h>
#include <zephyr/settings/settings.h>
#include <zephyr/sys/util.h>
#ifdef CONFIG_IOT_CONTACT_NETWORK_HACK
#include <zephyr/sys/reboot.h>
#endif // CONFIG_IOT_CONTACT_NETWORK_HACK
LOG_MODULE_REGISTER(syslog);
#define NETWORK_BUG_DELAY K_MSEC(4000)
#define L4_EVENT_MASK (NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED)
#define IPV6_STRLEN_MAX 39 // excluding '\0'
#define SYSLOG_TARGET_PORT 514
struct net_mgmt_event_callback l4_cb;
static K_SEM_DEFINE(network_connected, 0, 1);
static char target_ip[IPV6_STRLEN_MAX + 1] = "2001:db8::2";
void l4_event_handler(
struct net_mgmt_event_callback *cb,
uint32_t event,
struct net_if *iface)
{
LOG_DBG("Executing L4 event handler");
switch (event) {
case NET_EVENT_L4_CONNECTED:
k_sem_give(&network_connected);
LOG_INF("Network connected");
break;
case NET_EVENT_L4_DISCONNECTED:
LOG_INF("Network disconnected");
break;
default:
break;
}
}
int init_network_monitoring(void)
{
net_mgmt_init_event_callback(&l4_cb, l4_event_handler, L4_EVENT_MASK);
net_mgmt_add_event_callback(&l4_cb);
return 0;
}
SYS_INIT(init_network_monitoring, APPLICATION, 0);
int init_syslog(void)
{
LOG_DBG("Initializing syslog logging backend");
LOG_INF("Waiting for network ...");
#ifdef CONFIG_IOT_CONTACT_NETWORK_HACK
int ret = k_sem_take(&network_connected, NETWORK_BUG_DELAY);
if (ret == -EAGAIN) {
LOG_ERR("Could not connect to network - rebooting system");
log_flush();
sys_reboot(SYS_REBOOT_COLD);
}
#else
k_sem_take(&network_connected, K_FOREVER);
#endif // CONFIG_IOT_CONTACT_NETWORK_HACK
LOG_INF("Enabling syslog backend");
const struct log_backend *backend = log_backend_net_get();
if (log_backend_is_active(backend) == false) {
/* flush log messages to ensure first syslog message is reproducible */
while (log_process());
log_backend_init(backend);
log_backend_enable(backend, backend->cb->ctx, CONFIG_LOG_MAX_LEVEL);
LOG_INF("Syslog backend enabled");
} else {
LOG_INF("Syslog backend was already enabled");
}
return 0;
}
SYS_INIT(init_syslog, APPLICATION, 40);
int syslog_handle_set(const char *name, size_t len, settings_read_cb read_cb,
void *cb_arg)
{
const char* next = NULL;
if (settings_name_steq(name, "target/ip", &next) && !next) {
memset(target_ip, '\0', sizeof(target_ip));
ssize_t ret = read_cb(cb_arg, target_ip, MIN(sizeof(target_ip) - 1, len));
if (ret < 0) {
LOG_ERR("Failed to set target IP (%d)", ret);
return (int)ret;
}
LOG_INF("Set target IP to '%s'", target_ip);
return 0;
}
return 0;
}
int syslog_handle_commit(void)
{
char target[IPV6_STRLEN_MAX + 9]; // 9 for brackets, colon, port and \0
int ret = snprintf(target, sizeof(target), "[%s]:%d", target_ip,
SYSLOG_TARGET_PORT);
if (ret < 0) {
LOG_ERR("Failed to format target based on ip and port (%d)", ret);
return ret;
}
if (log_backend_net_set_addr(target) == false) {
LOG_ERR("Could not commit settings");
return -EINVAL;
}
LOG_INF("Committed settings");
return 0;
}
int syslog_handle_export(int (*cb)(const char *name, const void *value,
size_t val_len))
{
LOG_WRN("Settings export not implemented");
return 0;
}
int syslog_handle_get(const char *name, char *val, int val_len_max)
{
const char* next = NULL;
if (settings_name_steq(name, "target/ip", &next) && !next) {
size_t len = strnlen(target_ip, sizeof(target_ip));
memcpy(val, target_ip, MIN(len, val_len_max));
}
return 0;
}
SETTINGS_STATIC_HANDLER_DEFINE(
syslog_settings_handler,
"syslog",
syslog_handle_get,
syslog_handle_set,
syslog_handle_commit,
syslog_handle_export
);
|