-
Notifications
You must be signed in to change notification settings - Fork 31
Expand file tree
/
Copy pathnm.c
More file actions
130 lines (111 loc) · 4.55 KB
/
Copy pathnm.c
File metadata and controls
130 lines (111 loc) · 4.55 KB
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
/*
* nm.c - NoMount CLI Userspace Tool
*/
#include "nm.h"
/* --- MAIN --- */
__attribute__((noreturn, used))
void c_main(long *sp) {
long argc = *sp;
char **argv = (char **)(sp + 1);
int exit_code = 1;
if (argc < 2) {
print_str("nm <command>\n");
goto do_exit;
}
int fd = sys3(SYS_SOCKET, AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
if (fd < 0) { exit_code = 2; goto do_exit; }
int nm_family = -1;
if (do_nm_cmd(fd, 16, 3, 2, "nomount", 8, 1) > 0) {
unsigned short *fam_id = get_attr(rx_buf, 1);
if (fam_id) nm_family = *fam_id;
}
if (nm_family < 0) { exit_code = 3; goto do_exit; }
char cmd = argv[1][0];
if (cmd == 'a' || cmd == 'd') {
int is_add = (cmd == 'a');
int step = 1 + is_add;
if (argc < 2 + step) { exit_code = 0; goto do_exit; }
const char *cwd = (sys3(SYS_GETCWD, (long)cwd_buf, PATH_MAX, 0) > 0) ? cwd_buf : "/";
char *cursor = payload;
int target_cmd = 3 - is_add;
exit_code = 0;
for (int i = 2; i + step <= argc; i += step) {
char *v_end = resolve_path(v_resolved, cwd, argv[i]);
int v_len = v_end - v_resolved;
if (!v_len) { exit_code = 3; continue; }
int r_len = 0;
if (is_add) {
char *r_end = resolve_path(r_resolved, cwd, argv[i+1]);
r_len = r_end - r_resolved;
if (!r_len) { exit_code = 3; continue; }
}
if ((cursor - payload) + 8 + v_len + r_len > MAX_PAYLOAD) {
exit_code |= (do_nm_cmd(fd, nm_family, target_cmd, 6, payload, cursor - payload, 5) < 0);
cursor = payload;
}
*(unsigned short*)(cursor + (is_add << 2)) = v_len;
if (is_add) {
*(unsigned int*)cursor = 0;
*(unsigned short*)(cursor + 6) = r_len;
memcpy(cursor + 8, v_resolved, v_len);
memcpy(cursor + 8 + v_len, r_resolved, r_len);
cursor += 8 + v_len + r_len;
} else {
memcpy(cursor + 2, v_resolved, v_len);
cursor += 2 + v_len;
}
}
if (cursor > payload)
exit_code |= (do_nm_cmd(fd, nm_family, target_cmd, 6, payload, cursor - payload, 5) < 0);
goto do_exit;
} else if (cmd == 'b' || cmd == 'u') {
if (argc < 3) goto do_exit;
unsigned int uid = 0; const char *s = argv[2];
while (*s) uid = (uid << 3) + (uid << 1) + (*s++ - '0');
exit_code = (do_nm_cmd(fd, nm_family, 6 - (cmd == 'b'), 4, &uid, 4, 5) < 0);
goto do_exit;
} else if (cmd == 'c') {
exit_code = (do_nm_cmd(fd, nm_family, 4, 0, (void *)0, 0, 5) < 0);
goto do_exit;
} else if (cmd == 'v') {
if (do_nm_cmd(fd, nm_family, 1, 0, (void *)0, 0, 5) > 0) {
unsigned int *ver = get_attr(rx_buf, 5);
if (ver) {
unsigned int v = *ver; char v_str[4] = {0};
unsigned char tens = ((v << 7) + (v << 6) + (v << 3) + (v << 2) + v) >> 11;
v = v - ((tens << 3) + (tens << 1));
v_str[0] = tens + '0'; v_str[1] = v + '0'; v_str[2] = '\n';
print_str(v_str);
exit_code = 0; goto do_exit;
}
}
} else if (cmd == 'l') {
unsigned int len = do_nm_cmd(fd, nm_family, 7, 0, (void *)0, 0, 0x301);
int is_json = (argc > 2 && argv[2][0] == 'j');
int offset = 2;
if (is_json) print_str("[\n");
while (len > 0) {
for (struct nlmsghdr *msg = (void *)rx_buf; msg->nlmsg_len && msg->nlmsg_len <= len;
len -= msg->nlmsg_len, msg = (void *)((char *)msg + msg->nlmsg_len)) {
if (msg->nlmsg_type == 3 || msg->nlmsg_type == 2) goto list_done;
char *v = get_attr(msg, 1);
char *r = get_attr(msg, 2);
if (v && r) {
if (is_json) {
print_str((const char *)",\n {\n \"virtual\": \"" + offset); offset = 0;
print_str(v); print_str("\",\n \"real\": \""); print_str(r); print_str("\"\n }");
} else {
print_str(v); print_str(" -> "); print_str(r); print_str("\n");
}
}
}
len = sys3(SYS_READ, fd, (long)rx_buf, RX_BUF_SIZE);
}
list_done:
if (is_json) print_str("\n]\n");
exit_code = 0;
}
do_exit:
sys1(SYS_EXIT, exit_code);
__builtin_unreachable();
}