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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
|
#!/bin/sh /etc/rc.common
START=60
STOP=01
USE_PROCD=1
MAINU=ripe-atlas
MEASU=ripe-atlas
GROUP=ripe-atlas
extra_command "get_key" "Print the public key to register the probe with"
extra_command "probeid" "Print the probe ID"
validate_config()
{
uci_load_validate 'ripe-atlas' 'ripe-atlas' "${1}" "${2}" \
'enabled:bool:1' \
'log_stderr:bool:0' \
'log_stdout:bool:0' \
'mode:string:prod' \
'rxtx_report:bool:0'
}
create_dir()
{
local user
local group
local mode
local dir
local ret=0
user="${1}"
shift
group="${1}"
shift
mode="${1}"
shift
while [ -n "${1}" ]; do
dir="${1}"
# The probe user may have put a link in its place.
[ -L "${dir}" ] && rm -f "${dir}"
mkdir -p "${dir}" || ret=1
chown ${user}:${group} "${dir}" || ret=1
chmod ${mode} "${dir}" || ret=1
shift
done
return ${ret}
}
setup_environment()
{
local stamp=/var/run/ripe-atlas/spool.done
create_dir root root 0755 /var/run/ripe-atlas
create_dir ${MEASU} ${GROUP} 0775 \
/var/run/ripe-atlas/pids \
/var/run/ripe-atlas/status
# Below a spool someone else made, links could be swapped in at any
# time.
mkdir -p /var/spool
if [ -n "$(find /var/spool /var/spool/ripe-atlas -maxdepth 0 \
! -user 0 2> /dev/null)" ]; then
logger -t ripe-atlas -p daemon.err \
'/var/spool/ripe-atlas was not made by root'
return 1
fi
# The probe user owns the spool directories and could swap in a link
# for root's chown and chmod to follow. Set them up only until that
# worked once since boot (/var is a tmpfs), so only while no probe
# runs.
[ -e "${stamp}" ] && [ -d /var/spool/ripe-atlas ] && return 0
create_dir ${MEASU} ${GROUP} 2775 \
/var/spool/ripe-atlas/crons \
/var/spool/ripe-atlas/crons/main \
/var/spool/ripe-atlas/crons/2 \
/var/spool/ripe-atlas/crons/3 \
/var/spool/ripe-atlas/crons/4 \
/var/spool/ripe-atlas/crons/5 \
/var/spool/ripe-atlas/crons/6 \
/var/spool/ripe-atlas/crons/7 \
/var/spool/ripe-atlas/crons/8 \
/var/spool/ripe-atlas/crons/9 \
/var/spool/ripe-atlas/crons/10 \
/var/spool/ripe-atlas/crons/11 \
/var/spool/ripe-atlas/crons/12 \
/var/spool/ripe-atlas/crons/13 \
/var/spool/ripe-atlas/crons/14 \
/var/spool/ripe-atlas/crons/15 \
/var/spool/ripe-atlas/crons/16 \
/var/spool/ripe-atlas/crons/17 \
/var/spool/ripe-atlas/crons/18 \
/var/spool/ripe-atlas/crons/19 \
/var/spool/ripe-atlas/crons/20 \
/var/spool/ripe-atlas/data \
/var/spool/ripe-atlas/data/new \
/var/spool/ripe-atlas/data/oneoff \
/var/spool/ripe-atlas/data/out \
/var/spool/ripe-atlas/data/out/ooq \
/var/spool/ripe-atlas/data/out/ooq10 &&
rm -f "${stamp}" && : > "${stamp}"
return 0
}
start_instance()
{
local cfg=/etc/ripe-atlas/config.txt
local mod=/etc/ripe-atlas/mode
local key=/etc/ripe-atlas/probe_key
if [ ${2} -ne 0 ]; then
echo 'validation failed'
return 1
fi
enabled="$(get_bool "${enabled}" 1)"
log_stderr="$(get_bool "${log_stderr}" 0)"
log_stdout="$(get_bool "${log_stdout}" 0)"
rxtx_report="$(get_bool "${rxtx_report}" 0)"
if [ ${enabled} -eq 0 ]; then
return 1
fi
case "${mode}" in
test|dev|prod)
;;
*)
return 1
;;
esac
# Only one probe may present the key: wait until the atlas-sw-probe
# one is taken over and atlas is disabled. While the key is not taken
# over, log the wait, as at boot the takeover runs before the log
# daemon and its errors are lost.
if [ -e /etc/uci-defaults/80-ripe-atlas ]; then
if [ ! -s "${key}" ] &&
{ [ -s /usr/libexec/atlas-probe-scripts/etc/probe_key ] ||
[ -s /etc/atlas/probe_key ]; }; then
logger -t ripe-atlas -p daemon.warn \
'waiting for /etc/uci-defaults/80-ripe-atlas'
fi
return 1
fi
# ripe-atlas-probe or -anchor brings the rest. apk installs it only after
# this package started the service, also over an older variant without
# this file.
[ -f /usr/share/ripe-atlas/variant ] || return 1
echo 'Starting RIPE Atlas'
umask 022
setup_environment || return 1
# /etc/ripe-atlas stays root's, so prepare what generic-ATLAS.sh would
# otherwise write there: the key, and the registration servers of the
# mode, which it copies only when they are missing.
if [ ! -s "${key}" ]; then
# ssh-keygen would ask before replacing an empty file.
rm -f "${key}" "${key}.pub"
if ! ssh-keygen -q -t rsa -P '' -C "$(uname -n)" -f "${key}" \
< /dev/null; then
logger -t ripe-atlas -p daemon.err "cannot create ${key}"
return 1
fi
logger -t ripe-atlas -p daemon.notice 'created a new probe key'
fi
# OpenSSH refuses a private key that others can read.
chmod 0600 "${key}"
rm -f /etc/ripe-atlas/reg_servers.sh "${cfg}" "${mod}"
cp /usr/lib/ripe-atlas/scripts/reg_servers.sh.${mode} \
/etc/ripe-atlas/reg_servers.sh || return 1
: > "${cfg}"
if [ ${rxtx_report} -ne 0 ]; then
echo 'RXTXRPT=yes' >> "${cfg}"
fi
echo "${mode}" > "${mod}"
procd_open_instance
procd_set_param command /usr/sbin/ripe-atlas
procd_set_param group ${GROUP}
procd_set_param stdout ${log_stdout}
procd_set_param stderr ${log_stderr}
procd_set_param respawn
if [ -x /sbin/ujail ] && user_exists ${MAINU}; then
chown ${MAINU}:${GROUP} "${key}" "${key}.pub"
procd_set_param user ${MAINU}
procd_add_jail ripe-atlas
procd_append_param capabilities /usr/share/ripe-atlas/capabilities.json
else
# procd grants capabilities only through ujail, and without
# CAP_NET_RAW ping and traceroute fail. Run as root, like
# atlas-sw-probe did; the group still tags the probe processes.
logger -t ripe-atlas -p daemon.warn \
"ujail or user ${MAINU} missing, running the probe as root"
fi
procd_close_instance
return 0
}
start_service()
{
config_load 'ripe-atlas'
config_foreach validate_config 'ripe-atlas' start_instance
}
stop_service()
{
local pids
local pid
local procs
# Up to OpenWrt 25.12, procd signals only the main script; the daemons,
# the ssh tunnel and telnetd it started would keep running. Take them
# from the instance's cgroup, or, when that holds none, from the group
# only the probe uses.
for procs in /sys/fs/cgroup/services/ripe-atlas/*/cgroup.procs; do
[ -f "${procs}" ] || continue
while read -r pid; do
pids="${pid} ${pids}"
done < "${procs}"
done
if [ -z "${pids}" ]; then
for pid in $(find /proc -maxdepth 1 -type d -group ${GROUP} \
2> /dev/null); do
pids="${pid##*/} ${pids}"
done
fi
if [ -n "${pids}" ]; then
kill ${pids} 1>/dev/null 2>&1
fi
}
# procd would not restart the probe when its options change, and up to
# OpenWrt 25.12, when it stops the instance, it signals only the main
# script.
reload_service()
{
stop
start
}
registered_id()
{
awk '$1 == "PROBE_ID" { print $2 }' \
/var/run/ripe-atlas/status/reg_init_reply.txt 2> /dev/null
}
get_key()
{
local pub=/etc/ripe-atlas/probe_key.pub
local variant
local id
variant="$(cat /usr/share/ripe-atlas/variant 2> /dev/null)"
if [ -z "${variant}" ]; then
echo 'Install ripe-atlas-probe or ripe-atlas-anchor first' >&2
return 1
fi
if [ ! -s "${pub}" ]; then
echo "${pub} is missing, start the probe to create it" >&2
return 1
fi
id="$(registered_id)"
if [ -n "${id}" ]; then
echo "Registered as probe ${id} with:"
elif [ "${variant}" = anchor ]; then
echo 'Register the anchor at https://atlas.ripe.net/anchors/apply/ with:'
else
echo 'Register the probe at https://atlas.ripe.net/apply/swprobe/ with:'
fi
cat "${pub}"
}
probeid()
{
local id
id="$(registered_id)"
if [ -z "${id}" ]; then
echo 'The probe has not registered since boot' >&2
return 1
fi
echo "Probe ID is ${id}"
}
service_triggers()
{
procd_add_reload_trigger 'ripe-atlas'
procd_add_validation validate_config
}
|