2 * luci-rpcd - LuCI UBUS RPC server
4 * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27 #include <sys/types.h>
29 #include <arpa/inet.h>
34 static struct blob_buf buf
;
35 static struct uci_context
*cursor
;
43 static const struct blobmsg_policy rpc_signal_policy
[__RPC_S_MAX
] = {
44 [RPC_S_PID
] = { .name
= "pid", .type
= BLOBMSG_TYPE_INT32
},
45 [RPC_S_SIGNAL
] = { .name
= "signal", .type
= BLOBMSG_TYPE_INT32
},
54 static const struct blobmsg_policy rpc_init_policy
[__RPC_I_MAX
] = {
55 [RPC_I_NAME
] = { .name
= "name", .type
= BLOBMSG_TYPE_STRING
},
56 [RPC_I_ACTION
] = { .name
= "action", .type
= BLOBMSG_TYPE_STRING
},
64 static const struct blobmsg_policy rpc_sshkey_policy
[__RPC_K_MAX
] = {
65 [RPC_K_KEYS
] = { .name
= "keys", .type
= BLOBMSG_TYPE_ARRAY
},
74 static const struct blobmsg_policy rpc_password_policy
[__RPC_P_MAX
] = {
75 [RPC_P_USER
] = { .name
= "user", .type
= BLOBMSG_TYPE_STRING
},
76 [RPC_P_PASSWORD
] = { .name
= "password", .type
= BLOBMSG_TYPE_STRING
},
81 rpc_errno_status(void)
86 return UBUS_STATUS_PERMISSION_DENIED
;
89 return UBUS_STATUS_INVALID_ARGUMENT
;
92 return UBUS_STATUS_NOT_FOUND
;
95 return UBUS_STATUS_INVALID_ARGUMENT
;
98 return UBUS_STATUS_UNKNOWN_ERROR
;
103 log_read(FILE *log
, int logsize
)
109 logsize
= RPC_LUCI2_DEF_LOGSIZE
;
111 len
= (logsize
> RPC_LUCI2_MAX_LOGSIZE
) ? RPC_LUCI2_MAX_LOGSIZE
: logsize
;
112 logbuf
= blobmsg_alloc_string_buffer(&buf
, "log", len
+ 1);
117 while (logsize
> RPC_LUCI2_MAX_LOGSIZE
)
119 len
= logsize
% RPC_LUCI2_MAX_LOGSIZE
;
122 len
= RPC_LUCI2_MAX_LOGSIZE
;
124 fread(logbuf
, 1, len
, log
);
128 len
= fread(logbuf
, 1, logsize
, log
);
131 blobmsg_add_string_buffer(&buf
);
135 rpc_luci2_system_log(struct ubus_context
*ctx
, struct ubus_object
*obj
,
136 struct ubus_request_data
*req
, const char *method
,
137 struct blob_attr
*msg
)
141 const char *logfile
= NULL
;
143 struct uci_package
*p
;
144 struct uci_element
*e
;
145 struct uci_section
*s
;
146 struct uci_ptr ptr
= { .package
= "system" };
148 uci_load(cursor
, ptr
.package
, &p
);
151 return UBUS_STATUS_NOT_FOUND
;
153 uci_foreach_element(&p
->sections
, e
)
155 s
= uci_to_section(e
);
157 if (strcmp(s
->type
, "system"))
161 ptr
.option
= "log_type";
162 ptr
.section
= e
->name
;
163 uci_lookup_ptr(cursor
, &ptr
, NULL
, true);
167 if (ptr
.o
&& ptr
.o
->type
== UCI_TYPE_STRING
&&
168 !strcmp(ptr
.o
->v
.string
, "file"))
171 ptr
.option
= "log_file";
172 uci_lookup_ptr(cursor
, &ptr
, NULL
, true);
174 if (ptr
.o
&& ptr
.o
->type
== UCI_TYPE_STRING
)
175 logfile
= ptr
.o
->v
.string
;
177 logfile
= "/var/log/messages";
179 if (stat(logfile
, &st
) || !(log
= fopen(logfile
, "r")))
182 logsize
= st
.st_size
;
187 ptr
.option
= "log_size";
188 uci_lookup_ptr(cursor
, &ptr
, NULL
, true);
190 if (ptr
.o
&& ptr
.o
->type
== UCI_TYPE_STRING
)
191 logsize
= atoi(ptr
.o
->v
.string
) * 1024;
193 if (!(log
= popen("logread", "r")))
197 blob_buf_init(&buf
, 0);
199 log_read(log
, logsize
);
202 uci_unload(cursor
, p
);
203 ubus_send_reply(ctx
, req
, buf
.head
);
207 uci_unload(cursor
, p
);
208 return rpc_errno_status();
212 rpc_luci2_system_dmesg(struct ubus_context
*ctx
, struct ubus_object
*obj
,
213 struct ubus_request_data
*req
, const char *method
,
214 struct blob_attr
*msg
)
218 if (!(log
= popen("dmesg", "r")))
219 return rpc_errno_status();
221 blob_buf_init(&buf
, 0);
223 log_read(log
, RPC_LUCI2_MAX_LOGSIZE
);
226 ubus_send_reply(ctx
, req
, buf
.head
);
231 rpc_luci2_process_list(struct ubus_context
*ctx
, struct ubus_object
*obj
,
232 struct ubus_request_data
*req
, const char *method
,
233 struct blob_attr
*msg
)
238 char *pid
, *ppid
, *user
, *stat
, *vsz
, *pvsz
, *pcpu
, *cmd
;
240 if (!(top
= popen("/bin/busybox top -bn1", "r")))
241 return rpc_errno_status();
243 blob_buf_init(&buf
, 0);
244 c
= blobmsg_open_array(&buf
, "processes");
246 while (fgets(line
, sizeof(line
) - 1, top
))
248 pid
= strtok(line
, " ");
250 if (*pid
< '0' || *pid
> '9')
253 ppid
= strtok(NULL
, " ");
254 user
= strtok(NULL
, " ");
255 stat
= strtok(NULL
, " ");
268 vsz
= strtok(stat
+ 4, " ");
269 pvsz
= strtok(NULL
, " ");
270 pcpu
= strtok(NULL
, " ");
271 cmd
= strtok(NULL
, "\n");
276 d
= blobmsg_open_table(&buf
, NULL
);
278 blobmsg_add_u32(&buf
, "pid", atoi(pid
));
279 blobmsg_add_u32(&buf
, "ppid", atoi(ppid
));
280 blobmsg_add_string(&buf
, "user", user
);
281 blobmsg_add_string(&buf
, "stat", stat
);
282 blobmsg_add_u32(&buf
, "vsize", atoi(vsz
) * 1024);
283 blobmsg_add_u32(&buf
, "vsize_percent", atoi(pvsz
));
284 blobmsg_add_u32(&buf
, "cpu_percent", atoi(pcpu
));
285 blobmsg_add_string(&buf
, "command", cmd
);
287 blobmsg_close_table(&buf
, d
);
291 blobmsg_close_array(&buf
, c
);
293 ubus_send_reply(ctx
, req
, buf
.head
);
298 rpc_luci2_process_signal(struct ubus_context
*ctx
, struct ubus_object
*obj
,
299 struct ubus_request_data
*req
, const char *method
,
300 struct blob_attr
*msg
)
303 struct blob_attr
*tb
[__RPC_S_MAX
];
305 blobmsg_parse(rpc_signal_policy
, __RPC_S_MAX
, tb
,
306 blob_data(msg
), blob_len(msg
));
308 if (!tb
[RPC_S_SIGNAL
] || !tb
[RPC_S_PID
])
311 return rpc_errno_status();
314 pid
= blobmsg_get_u32(tb
[RPC_S_PID
]);
315 sig
= blobmsg_get_u32(tb
[RPC_S_SIGNAL
]);
318 return rpc_errno_status();
324 rpc_luci2_init_list(struct ubus_context
*ctx
, struct ubus_object
*obj
,
325 struct ubus_request_data
*req
, const char *method
,
326 struct blob_attr
*msg
)
330 char *p
, path
[PATH_MAX
];
336 if (!(d
= opendir("/etc/init.d")))
337 return rpc_errno_status();
339 blob_buf_init(&buf
, 0);
340 c
= blobmsg_open_array(&buf
, "initscripts");
342 while ((e
= readdir(d
)) != NULL
)
344 snprintf(path
, sizeof(path
) - 1, "/etc/init.d/%s", e
->d_name
);
346 if (stat(path
, &s
) || !S_ISREG(s
.st_mode
) || !(s
.st_mode
& S_IXUSR
))
349 if ((f
= fopen(path
, "r")) != NULL
)
352 p
= fgets(path
, sizeof(path
) - 1, f
);
354 if (!p
|| !strstr(p
, "/etc/rc.common"))
357 t
= blobmsg_open_table(&buf
, NULL
);
359 blobmsg_add_string(&buf
, "name", e
->d_name
);
361 while (fgets(path
, sizeof(path
) - 1, f
))
363 p
= strtok(path
, "= \t");
365 if (!strcmp(p
, "START") && !!(p
= strtok(NULL
, "= \t\n")))
368 blobmsg_add_u32(&buf
, "start", n
);
370 else if (!strcmp(p
, "STOP") && !!(p
= strtok(NULL
, "= \t\n")))
372 blobmsg_add_u32(&buf
, "stop", atoi(p
));
379 snprintf(path
, sizeof(path
) - 1, "/etc/rc.d/S%02d%s",
382 blobmsg_add_u8(&buf
, "enabled",
383 (!stat(path
, &s
) && (s
.st_mode
& S_IXUSR
)));
387 blobmsg_add_u8(&buf
, "enabled", 0);
390 blobmsg_close_table(&buf
, t
);
398 blobmsg_close_array(&buf
, c
);
400 ubus_send_reply(ctx
, req
, buf
.head
);
405 rpc_luci2_init_action(struct ubus_context
*ctx
, struct ubus_object
*obj
,
406 struct ubus_request_data
*req
, const char *method
,
407 struct blob_attr
*msg
)
414 struct blob_attr
*tb
[__RPC_I_MAX
];
416 blobmsg_parse(rpc_init_policy
, __RPC_I_MAX
, tb
,
417 blob_data(msg
), blob_len(msg
));
419 if (!tb
[RPC_I_NAME
] || !tb
[RPC_I_ACTION
])
420 return UBUS_STATUS_INVALID_ARGUMENT
;
422 action
= blobmsg_data(tb
[RPC_I_ACTION
]);
424 if (strcmp(action
, "start") && strcmp(action
, "stop") &&
425 strcmp(action
, "reload") && strcmp(action
, "restart") &&
426 strcmp(action
, "enable") && strcmp(action
, "disable"))
427 return UBUS_STATUS_INVALID_ARGUMENT
;
429 snprintf(path
, sizeof(path
) - 1, "/etc/init.d/%s",
430 (char *)blobmsg_data(tb
[RPC_I_NAME
]));
433 return rpc_errno_status();
435 if (!(s
.st_mode
& S_IXUSR
))
436 return UBUS_STATUS_PERMISSION_DENIED
;
438 switch ((pid
= fork()))
441 return rpc_errno_status();
446 if ((fd
= open("/dev/null", O_RDWR
)) > -1)
457 if (execl(path
, path
, action
, NULL
))
458 return rpc_errno_status();
466 rpc_luci2_sshkeys_get(struct ubus_context
*ctx
, struct ubus_object
*obj
,
467 struct ubus_request_data
*req
, const char *method
,
468 struct blob_attr
*msg
)
474 if (!(f
= fopen("/etc/dropbear/authorized_keys", "r")))
475 return rpc_errno_status();
477 blob_buf_init(&buf
, 0);
478 c
= blobmsg_open_array(&buf
, "keys");
480 while (fgets(line
, sizeof(line
) - 1, f
))
482 for (p
= line
+ strlen(line
) - 1; (p
> line
) && isspace(*p
); p
--)
485 for (p
= line
; isspace(*p
); p
++)
489 blobmsg_add_string(&buf
, NULL
, p
);
492 blobmsg_close_array(&buf
, c
);
495 ubus_send_reply(ctx
, req
, buf
.head
);
500 rpc_luci2_sshkeys_set(struct ubus_context
*ctx
, struct ubus_object
*obj
,
501 struct ubus_request_data
*req
, const char *method
,
502 struct blob_attr
*msg
)
506 struct blob_attr
*cur
, *tb
[__RPC_K_MAX
];
508 blobmsg_parse(rpc_sshkey_policy
, __RPC_K_MAX
, tb
,
509 blob_data(msg
), blob_len(msg
));
512 return UBUS_STATUS_INVALID_ARGUMENT
;
514 if (!(f
= fopen("/etc/dropbear/authorized_keys", "w")))
515 return rpc_errno_status();
517 blobmsg_for_each_attr(cur
, tb
[RPC_K_KEYS
], rem
)
519 if (blobmsg_type(cur
) != BLOBMSG_TYPE_STRING
)
522 fwrite(blobmsg_data(cur
), blobmsg_data_len(cur
) - 1, 1, f
);
523 fwrite("\n", 1, 1, f
);
531 rpc_luci2_password_set(struct ubus_context
*ctx
, struct ubus_object
*obj
,
532 struct ubus_request_data
*req
, const char *method
,
533 struct blob_attr
*msg
)
538 struct blob_attr
*tb
[__RPC_P_MAX
];
540 blobmsg_parse(rpc_password_policy
, __RPC_P_MAX
, tb
,
541 blob_data(msg
), blob_len(msg
));
543 if (!tb
[RPC_P_USER
] || !tb
[RPC_P_PASSWORD
])
544 return UBUS_STATUS_INVALID_ARGUMENT
;
546 if (stat("/usr/bin/passwd", &s
))
547 return UBUS_STATUS_NOT_FOUND
;
549 if (!(s
.st_mode
& S_IXUSR
))
550 return UBUS_STATUS_PERMISSION_DENIED
;
553 return rpc_errno_status();
555 switch ((pid
= fork()))
560 return rpc_errno_status();
569 if ((fd
= open("/dev/null", O_RDWR
)) > -1)
578 if (execl("/usr/bin/passwd", "/usr/bin/passwd",
579 blobmsg_data(tb
[RPC_P_USER
]), NULL
))
580 return rpc_errno_status();
585 write(fds
[1], blobmsg_data(tb
[RPC_P_PASSWORD
]),
586 blobmsg_data_len(tb
[RPC_P_PASSWORD
]) - 1);
587 write(fds
[1], "\n", 1);
591 write(fds
[1], blobmsg_data(tb
[RPC_P_PASSWORD
]),
592 blobmsg_data_len(tb
[RPC_P_PASSWORD
]) - 1);
593 write(fds
[1], "\n", 1);
597 waitpid(pid
, NULL
, 0);
605 dnsmasq_leasefile(void)
608 struct uci_package
*p
;
609 struct uci_element
*e
;
610 struct uci_section
*s
;
611 struct uci_ptr ptr
= {
614 .option
= "leasefile"
617 uci_load(cursor
, ptr
.package
, &p
);
622 uci_foreach_element(&p
->sections
, e
)
624 s
= uci_to_section(e
);
626 if (strcmp(s
->type
, "dnsmasq"))
629 ptr
.section
= e
->name
;
630 uci_lookup_ptr(cursor
, &ptr
, NULL
, true);
634 if (ptr
.o
&& ptr
.o
->type
== UCI_TYPE_STRING
)
635 leases
= fopen(ptr
.o
->v
.string
, "r");
637 uci_unload(cursor
, p
);
643 rpc_luci2_network_leases(struct ubus_context
*ctx
, struct ubus_object
*obj
,
644 struct ubus_request_data
*req
, const char *method
,
645 struct blob_attr
*msg
)
650 char *ts
, *mac
, *addr
, *name
;
651 time_t now
= time(NULL
);
653 blob_buf_init(&buf
, 0);
654 c
= blobmsg_open_array(&buf
, "leases");
656 leases
= dnsmasq_leasefile();
661 while (fgets(line
, sizeof(line
) - 1, leases
))
663 ts
= strtok(line
, " \t");
664 mac
= strtok(NULL
, " \t");
665 addr
= strtok(NULL
, " \t");
666 name
= strtok(NULL
, " \t");
668 if (!ts
|| !mac
|| !addr
|| !name
)
671 if (strchr(addr
, ':'))
674 d
= blobmsg_open_table(&buf
, NULL
);
676 blobmsg_add_u32(&buf
, "expires", atoi(ts
) - now
);
677 blobmsg_add_string(&buf
, "macaddr", mac
);
678 blobmsg_add_string(&buf
, "ipaddr", addr
);
680 if (strcmp(name
, "*"))
681 blobmsg_add_string(&buf
, "hostname", name
);
683 blobmsg_close_table(&buf
, d
);
689 blobmsg_close_array(&buf
, c
);
690 ubus_send_reply(ctx
, req
, buf
.head
);
696 rpc_luci2_network_leases6(struct ubus_context
*ctx
, struct ubus_object
*obj
,
697 struct ubus_request_data
*req
, const char *method
,
698 struct blob_attr
*msg
)
703 char *ts
, *mac
, *addr
, *name
, *duid
;
704 time_t now
= time(NULL
);
706 blob_buf_init(&buf
, 0);
707 c
= blobmsg_open_array(&buf
, "leases");
709 leases
= fopen("/tmp/hosts/6relayd", "r");
713 while (fgets(line
, sizeof(line
) - 1, leases
))
715 if (strncmp(line
, "# ", 2))
718 strtok(line
+ 2, " \t"); /* iface */
720 duid
= strtok(NULL
, " \t");
722 strtok(NULL
, " \t"); /* iaid */
724 name
= strtok(NULL
, " \t");
725 ts
= strtok(NULL
, " \t");
727 strtok(NULL
, " \t"); /* id */
728 strtok(NULL
, " \t"); /* length */
730 addr
= strtok(NULL
, " \t\n");
735 d
= blobmsg_open_table(&buf
, NULL
);
737 blobmsg_add_u32(&buf
, "expires", atoi(ts
) - now
);
738 blobmsg_add_string(&buf
, "duid", duid
);
739 blobmsg_add_string(&buf
, "ip6addr", addr
);
741 if (strcmp(name
, "-"))
742 blobmsg_add_string(&buf
, "hostname", name
);
744 blobmsg_close_array(&buf
, d
);
751 leases
= dnsmasq_leasefile();
756 while (fgets(line
, sizeof(line
) - 1, leases
))
758 ts
= strtok(line
, " \t");
759 mac
= strtok(NULL
, " \t");
760 addr
= strtok(NULL
, " \t");
761 name
= strtok(NULL
, " \t");
762 duid
= strtok(NULL
, " \t\n");
764 if (!ts
|| !mac
|| !addr
|| !duid
)
767 if (!strchr(addr
, ':'))
770 d
= blobmsg_open_table(&buf
, NULL
);
772 blobmsg_add_u32(&buf
, "expires", atoi(ts
) - now
);
773 blobmsg_add_string(&buf
, "macaddr", mac
);
774 blobmsg_add_string(&buf
, "ip6addr", addr
);
776 if (strcmp(name
, "*"))
777 blobmsg_add_string(&buf
, "hostname", name
);
779 if (strcmp(duid
, "*"))
780 blobmsg_add_string(&buf
, "duid", name
);
782 blobmsg_close_table(&buf
, d
);
789 blobmsg_close_array(&buf
, c
);
790 ubus_send_reply(ctx
, req
, buf
.head
);
796 rpc_luci2_network_ct_count(struct ubus_context
*ctx
, struct ubus_object
*obj
,
797 struct ubus_request_data
*req
, const char *method
,
798 struct blob_attr
*msg
)
803 blob_buf_init(&buf
, 0);
805 if ((f
= fopen("/proc/sys/net/netfilter/nf_conntrack_count", "r")) != NULL
)
807 if (fgets(line
, sizeof(line
) - 1, f
))
808 blobmsg_add_u32(&buf
, "count", atoi(line
));
813 if ((f
= fopen("/proc/sys/net/netfilter/nf_conntrack_max", "r")) != NULL
)
815 if (fgets(line
, sizeof(line
) - 1, f
))
816 blobmsg_add_u32(&buf
, "limit", atoi(line
));
821 ubus_send_reply(ctx
, req
, buf
.head
);
827 rpc_luci2_network_ct_table(struct ubus_context
*ctx
, struct ubus_object
*obj
,
828 struct ubus_request_data
*req
, const char *method
,
829 struct blob_attr
*msg
)
837 blob_buf_init(&buf
, 0);
838 c
= blobmsg_open_array(&buf
, "entries");
840 if ((f
= fopen("/proc/net/nf_conntrack", "r")) != NULL
)
842 while (fgets(line
, sizeof(line
) - 1, f
))
844 d
= blobmsg_open_table(&buf
, NULL
);
845 memset(seen
, 0, sizeof(seen
));
847 for (i
= 0, p
= strtok(line
, " "); p
; i
++, p
= strtok(NULL
, " "))
850 blobmsg_add_u8(&buf
, "ipv6", !strcmp(p
, "ipv6"));
852 blobmsg_add_u32(&buf
, "protocol", atoi(p
));
854 blobmsg_add_u32(&buf
, "expires", atoi(p
));
860 if (!seen
[0] && !strncmp(p
, "src=", 4))
862 blobmsg_add_string(&buf
, "src", p
+ 4);
865 else if (!seen
[1] && !strncmp(p
, "dst=", 4))
867 blobmsg_add_string(&buf
, "dest", p
+ 4);
870 else if (!seen
[2] && !strncmp(p
, "sport=", 6))
872 blobmsg_add_u32(&buf
, "sport", atoi(p
+ 6));
875 else if (!seen
[3] && !strncmp(p
, "dport=", 6))
877 blobmsg_add_u32(&buf
, "dport", atoi(p
+ 6));
880 else if (!strncmp(p
, "packets=", 8))
882 blobmsg_add_u32(&buf
,
883 seen
[4] ? "tx_packets" : "rx_packets",
887 else if (!strncmp(p
, "bytes=", 6))
889 blobmsg_add_u32(&buf
,
890 seen
[5] ? "tx_bytes" : "rx_bytes",
897 blobmsg_close_table(&buf
, d
);
903 blobmsg_close_array(&buf
, c
);
904 ubus_send_reply(ctx
, req
, buf
.head
);
910 rpc_luci2_network_arp_table(struct ubus_context
*ctx
, struct ubus_object
*obj
,
911 struct ubus_request_data
*req
, const char *method
,
912 struct blob_attr
*msg
)
916 char *addr
, *mac
, *dev
, line
[128];
918 blob_buf_init(&buf
, 0);
919 c
= blobmsg_open_array(&buf
, "entries");
921 if ((f
= fopen("/proc/net/arp", "r")) != NULL
)
923 /* skip header line */
924 fgets(line
, sizeof(line
) - 1, f
);
926 while (fgets(line
, sizeof(line
) - 1, f
))
928 addr
= strtok(line
, " \t");
930 strtok(NULL
, " \t"); /* HW type */
931 strtok(NULL
, " \t"); /* Flags */
933 mac
= strtok(NULL
, " \t");
935 strtok(NULL
, " \t"); /* Mask */
937 dev
= strtok(NULL
, " \t\n");
942 d
= blobmsg_open_table(&buf
, NULL
);
943 blobmsg_add_string(&buf
, "ipaddr", addr
);
944 blobmsg_add_string(&buf
, "macaddr", mac
);
945 blobmsg_add_string(&buf
, "device", dev
);
946 blobmsg_close_table(&buf
, d
);
952 blobmsg_close_array(&buf
, c
);
953 ubus_send_reply(ctx
, req
, buf
.head
);
959 put_hexaddr(const char *name
, const char *s
, const char *m
)
963 char as
[sizeof("255.255.255.255/32\0")];
965 a
.s_addr
= strtoul(s
, NULL
, 16);
966 inet_ntop(AF_INET
, &a
, as
, sizeof(as
));
970 for (a
.s_addr
= ntohl(strtoul(m
, NULL
, 16)), bits
= 0;
971 a
.s_addr
& 0x80000000;
975 sprintf(as
+ strlen(as
), "/%u", bits
);
978 blobmsg_add_string(&buf
, name
, as
);
982 rpc_luci2_network_routes(struct ubus_context
*ctx
, struct ubus_object
*obj
,
983 struct ubus_request_data
*req
, const char *method
,
984 struct blob_attr
*msg
)
988 char *dst
, *dmask
, *next
, *metric
, *device
;
992 if (!(routes
= fopen("/proc/net/route", "r")))
993 return rpc_errno_status();
995 blob_buf_init(&buf
, 0);
996 c
= blobmsg_open_array(&buf
, "routes");
998 /* skip header line */
999 fgets(line
, sizeof(line
) - 1, routes
);
1001 while (fgets(line
, sizeof(line
) - 1, routes
))
1003 device
= strtok(line
, "\t ");
1004 dst
= strtok(NULL
, "\t ");
1005 next
= strtok(NULL
, "\t ");
1007 strtok(NULL
, "\t "); /* flags */
1008 strtok(NULL
, "\t "); /* refcount */
1009 strtok(NULL
, "\t "); /* usecount */
1011 metric
= strtok(NULL
, "\t ");
1012 dmask
= strtok(NULL
, "\t ");
1017 d
= blobmsg_open_table(&buf
, NULL
);
1019 put_hexaddr("target", dst
, dmask
);
1020 put_hexaddr("nexthop", next
, NULL
);
1022 n
= strtoul(metric
, NULL
, 10);
1023 blobmsg_add_u32(&buf
, "metric", n
);
1025 blobmsg_add_string(&buf
, "device", device
);
1027 blobmsg_close_table(&buf
, d
);
1030 blobmsg_close_array(&buf
, c
);
1033 ubus_send_reply(ctx
, req
, buf
.head
);
1038 put_hex6addr(const char *name
, const char *s
, const char *m
)
1042 char as
[INET6_ADDRSTRLEN
+ sizeof("/128")];
1045 (((x) <= '9') ? ((x) - '0') : \
1046 (((x) <= 'F') ? ((x) - 'A' + 10) : \
1049 for (i
= 0; i
< 16; i
++, s
+= 2)
1050 a
.s6_addr
[i
] = (16 * hex(*s
)) + hex(*(s
+1));
1052 inet_ntop(AF_INET6
, &a
, as
, sizeof(as
));
1055 sprintf(as
+ strlen(as
), "/%lu", strtoul(m
, NULL
, 16));
1057 blobmsg_add_string(&buf
, name
, as
);
1061 rpc_luci2_network_routes6(struct ubus_context
*ctx
, struct ubus_object
*obj
,
1062 struct ubus_request_data
*req
, const char *method
,
1063 struct blob_attr
*msg
)
1067 char *src
, *smask
, *dst
, *dmask
, *next
, *metric
, *flags
, *device
;
1071 if (!(routes
= fopen("/proc/net/ipv6_route", "r")))
1072 return rpc_errno_status();
1074 blob_buf_init(&buf
, 0);
1075 c
= blobmsg_open_array(&buf
, "routes");
1077 while (fgets(line
, sizeof(line
) - 1, routes
))
1079 dst
= strtok(line
, " ");
1080 dmask
= strtok(NULL
, " ");
1081 src
= strtok(NULL
, " ");
1082 smask
= strtok(NULL
, " ");
1083 next
= strtok(NULL
, " ");
1084 metric
= strtok(NULL
, " ");
1086 strtok(NULL
, " "); /* refcount */
1087 strtok(NULL
, " "); /* usecount */
1089 flags
= strtok(NULL
, " ");
1090 device
= strtok(NULL
, " \n");
1095 n
= strtoul(flags
, NULL
, 16);
1100 d
= blobmsg_open_table(&buf
, NULL
);
1102 put_hex6addr("target", dst
, dmask
);
1103 put_hex6addr("source", src
, smask
);
1104 put_hex6addr("nexthop", next
, NULL
);
1106 n
= strtoul(metric
, NULL
, 16);
1107 blobmsg_add_u32(&buf
, "metric", n
);
1109 blobmsg_add_string(&buf
, "device", device
);
1111 blobmsg_close_table(&buf
, d
);
1114 blobmsg_close_array(&buf
, c
);
1117 ubus_send_reply(ctx
, req
, buf
.head
);
1122 int rpc_luci2_api_init(struct ubus_context
*ctx
)
1126 static const struct ubus_method luci2_system_methods
[] = {
1127 UBUS_METHOD_NOARG("syslog", rpc_luci2_system_log
),
1128 UBUS_METHOD_NOARG("dmesg", rpc_luci2_system_dmesg
),
1129 UBUS_METHOD_NOARG("process_list", rpc_luci2_process_list
),
1130 UBUS_METHOD("process_signal", rpc_luci2_process_signal
,
1132 UBUS_METHOD_NOARG("init_list", rpc_luci2_init_list
),
1133 UBUS_METHOD("init_action", rpc_luci2_init_action
,
1135 UBUS_METHOD_NOARG("sshkeys_get", rpc_luci2_sshkeys_get
),
1136 UBUS_METHOD("sshkeys_set", rpc_luci2_sshkeys_set
,
1138 UBUS_METHOD("password_set", rpc_luci2_password_set
,
1139 rpc_password_policy
)
1142 static struct ubus_object_type luci2_system_type
=
1143 UBUS_OBJECT_TYPE("luci-rpc-luci2-system", luci2_system_methods
);
1145 static struct ubus_object system_obj
= {
1146 .name
= "luci2.system",
1147 .type
= &luci2_system_type
,
1148 .methods
= luci2_system_methods
,
1149 .n_methods
= ARRAY_SIZE(luci2_system_methods
),
1153 static const struct ubus_method luci2_network_methods
[] = {
1154 UBUS_METHOD_NOARG("conntrack_count", rpc_luci2_network_ct_count
),
1155 UBUS_METHOD_NOARG("conntrack_table", rpc_luci2_network_ct_table
),
1156 UBUS_METHOD_NOARG("arp_table", rpc_luci2_network_arp_table
),
1157 UBUS_METHOD_NOARG("dhcp_leases", rpc_luci2_network_leases
),
1158 UBUS_METHOD_NOARG("dhcp6_leases", rpc_luci2_network_leases6
),
1159 UBUS_METHOD_NOARG("routes", rpc_luci2_network_routes
),
1160 UBUS_METHOD_NOARG("routes6", rpc_luci2_network_routes6
),
1163 static struct ubus_object_type luci2_network_type
=
1164 UBUS_OBJECT_TYPE("luci-rpc-luci2-network", luci2_network_methods
);
1166 static struct ubus_object network_obj
= {
1167 .name
= "luci2.network",
1168 .type
= &luci2_network_type
,
1169 .methods
= luci2_network_methods
,
1170 .n_methods
= ARRAY_SIZE(luci2_network_methods
),
1173 cursor
= uci_alloc_context();
1176 return UBUS_STATUS_UNKNOWN_ERROR
;
1178 rv
|= ubus_add_object(ctx
, &system_obj
);
1179 rv
|= ubus_add_object(ctx
, &network_obj
);