1 let ubus, sub, listener, global;
3 const dhcp_parser_proto = {
8 parseAt: function(offset) {
9 let id = hex(substr(this.buffer, offset, 2));
10 let len = hex(substr(this.buffer, offset + 2, 2)) * 2;
11 if (type(id) != "int" || type(len) != "int")
14 let data = substr(this.buffer, offset + 4, len);
15 if (length(data) != len)
18 return [ id, data, len + 4 ];
22 let data = this.parseAt(this.offset);
26 this.offset += data[2];
30 foreach: function(cb) {
34 while ((data = this.parseAt(offset)) != null) {
37 if (type(ret) == "boolean" && !ret)
43 function dhcp_opt_parser(data) {
49 proto(parser, dhcp_parser_proto);
54 function parse_array(data)
56 return map(match(data, /../g), (val) => val[0]);
59 function parse_string(data)
61 return join("", map(parse_array(data[1]), (val) => chr(hex(val))));
64 function parse_macaddr(addr)
66 return join(":", parse_array(addr));
69 function dhcp_cb(msg) {
70 if (msg.type != "discover" && msg.type != "request")
73 let packet = msg.data.packet;
77 let opts = substr(packet, 240 * 2);
78 if (length(opts) < 16)
81 let macaddr = parse_macaddr(substr(packet, 28 * 2, 12));
83 opts = dhcp_opt_parser(opts);
84 opts.foreach((data) => {
88 typestr = "%device_name|dhcp_device_name";
89 data = parse_string(data);
93 data = join(",", map(parse_array(data[1]), (val) => hex(val)));
96 typestr = "dhcp_vendorid";
97 data = parse_string(data);
102 global.device_add_data(macaddr, `${typestr}|${data}`);
110 gl.weight.dhcp_req = 1.1;
111 gl.weight.dhcp_device_name = 5.0;
112 sub = ubus.subscriber(dhcp_cb);
113 listener = ubus.listener("ubus.object.add", (event, msg) => {
114 if (msg.path == "dhcpsnoop")
115 sub.subscribe(msg.path);
117 sub.subscribe("dhcpsnoop");