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
|
#!/usr/bin/env ucode
import * as libubus from "ubus";
let script_path = ARGV[0];
let proto_name = ARGV[1];
let action = ARGV[2];
let iface_name = ARGV[3];
let config_json = ARGV[4];
let device = ARGV[5];
let config;
try {
let blob = json(config_json);
let inner = blob?._ucode_config;
config = inner ? json(inner) : blob;
} catch (e) {
warn(`Failed to parse config JSON: ${e}\n${e.stacktrace[0].context}\n`);
exit(1);
}
let ubus = libubus.connect();
if (!ubus) {
warn(`Failed to connect to ubus\n`);
exit(1);
}
let notify_path = `network.interface.${iface_name}`;
function proto_notify(data)
{
return ubus.call(notify_path, "notify_proto", data);
}
let proto = {
iface: iface_name,
proto: proto_name,
config,
device,
notify: proto_notify,
update_link: function(up, data) {
let msg = { action: 0, "link-up": up, ...(data ?? {}) };
return proto_notify(msg);
},
run_command: function(argv, env) {
let msg = { action: 1, command: argv };
if (env)
msg.env = env;
return proto_notify(msg);
},
kill_command: function(signal) {
return proto_notify({ action: 2, signal: signal ?? 15 });
},
error: function(errors) {
return proto_notify({ action: 3, error: errors });
},
block_restart: function() {
return proto_notify({ action: 4 });
},
set_available: function(available) {
return proto_notify({ action: 5, available });
},
add_host_dependency: function(host, ifname) {
let msg = { action: 6 };
if (host)
msg.host = host;
if (ifname)
msg.ifname = ifname;
return proto_notify(msg);
},
setup_failed: function() {
return proto_notify({ action: 7 });
},
};
let handlers = {};
let netifd_stub = {
add_proto: function(handler) {
if (handler?.name)
handlers[handler.name] = handler;
},
};
try {
include(script_path, { netifd: netifd_stub });
} catch (e) {
warn(`Failed to load proto handler script '${script_path}': ${e}\n${e.stacktrace[0].context}\n`);
exit(1);
}
let handler = handlers[proto_name];
if (!handler) {
warn(`No handler found for protocol '${proto_name}'\n`);
exit(1);
}
if (!handler[action]) {
warn(`Handler '${proto_name}' has no '${action}' function\n`);
exit(1);
}
handler[action](proto);
|