|
18 | 18 | #define SOL_NETLINK 270
|
19 | 19 | #endif
|
20 | 20 |
|
21 |
| -static int bpf_netlink_open(__u32 *nl_pid) |
| 21 | +int bpf_netlink_open(__u32 *nl_pid) |
22 | 22 | {
|
23 | 23 | struct sockaddr_nl sa;
|
24 | 24 | socklen_t addrlen;
|
@@ -61,7 +61,9 @@ static int bpf_netlink_open(__u32 *nl_pid)
|
61 | 61 | return ret;
|
62 | 62 | }
|
63 | 63 |
|
64 |
| -static int bpf_netlink_recv(int sock, __u32 nl_pid, int seq) |
| 64 | +static int bpf_netlink_recv(int sock, __u32 nl_pid, int seq, |
| 65 | + __dump_nlmsg_t _fn, dump_nlmsg_t fn, |
| 66 | + void *cookie) |
65 | 67 | {
|
66 | 68 | struct nlmsgerr *err;
|
67 | 69 | struct nlmsghdr *nh;
|
@@ -98,6 +100,11 @@ static int bpf_netlink_recv(int sock, __u32 nl_pid, int seq)
|
98 | 100 | default:
|
99 | 101 | break;
|
100 | 102 | }
|
| 103 | + if (_fn) { |
| 104 | + ret = _fn(nh, fn, cookie); |
| 105 | + if (ret) |
| 106 | + return ret; |
| 107 | + } |
101 | 108 | }
|
102 | 109 | }
|
103 | 110 | ret = 0;
|
@@ -157,9 +164,161 @@ int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
|
157 | 164 | ret = -errno;
|
158 | 165 | goto cleanup;
|
159 | 166 | }
|
160 |
| - ret = bpf_netlink_recv(sock, nl_pid, seq); |
| 167 | + ret = bpf_netlink_recv(sock, nl_pid, seq, NULL, NULL, NULL); |
161 | 168 |
|
162 | 169 | cleanup:
|
163 | 170 | close(sock);
|
164 | 171 | return ret;
|
165 | 172 | }
|
| 173 | + |
| 174 | +static int __dump_link_nlmsg(struct nlmsghdr *nlh, dump_nlmsg_t dump_link_nlmsg, |
| 175 | + void *cookie) |
| 176 | +{ |
| 177 | + struct nlattr *tb[IFLA_MAX + 1], *attr; |
| 178 | + struct ifinfomsg *ifi = NLMSG_DATA(nlh); |
| 179 | + int len; |
| 180 | + |
| 181 | + len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi)); |
| 182 | + attr = (struct nlattr *) ((void *) ifi + NLMSG_ALIGN(sizeof(*ifi))); |
| 183 | + if (nla_parse(tb, IFLA_MAX, attr, len, NULL) != 0) |
| 184 | + return -LIBBPF_ERRNO__NLPARSE; |
| 185 | + |
| 186 | + return dump_link_nlmsg(cookie, ifi, tb); |
| 187 | +} |
| 188 | + |
| 189 | +int nl_get_link(int sock, unsigned int nl_pid, dump_nlmsg_t dump_link_nlmsg, |
| 190 | + void *cookie) |
| 191 | +{ |
| 192 | + struct { |
| 193 | + struct nlmsghdr nlh; |
| 194 | + struct ifinfomsg ifm; |
| 195 | + } req = { |
| 196 | + .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)), |
| 197 | + .nlh.nlmsg_type = RTM_GETLINK, |
| 198 | + .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, |
| 199 | + .ifm.ifi_family = AF_PACKET, |
| 200 | + }; |
| 201 | + int seq = time(NULL); |
| 202 | + |
| 203 | + req.nlh.nlmsg_seq = seq; |
| 204 | + if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0) |
| 205 | + return -errno; |
| 206 | + |
| 207 | + return bpf_netlink_recv(sock, nl_pid, seq, __dump_link_nlmsg, |
| 208 | + dump_link_nlmsg, cookie); |
| 209 | +} |
| 210 | + |
| 211 | +static int __dump_class_nlmsg(struct nlmsghdr *nlh, |
| 212 | + dump_nlmsg_t dump_class_nlmsg, void *cookie) |
| 213 | +{ |
| 214 | + struct nlattr *tb[TCA_MAX + 1], *attr; |
| 215 | + struct tcmsg *t = NLMSG_DATA(nlh); |
| 216 | + int len; |
| 217 | + |
| 218 | + len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t)); |
| 219 | + attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t))); |
| 220 | + if (nla_parse(tb, TCA_MAX, attr, len, NULL) != 0) |
| 221 | + return -LIBBPF_ERRNO__NLPARSE; |
| 222 | + |
| 223 | + return dump_class_nlmsg(cookie, t, tb); |
| 224 | +} |
| 225 | + |
| 226 | +int nl_get_class(int sock, unsigned int nl_pid, int ifindex, |
| 227 | + dump_nlmsg_t dump_class_nlmsg, void *cookie) |
| 228 | +{ |
| 229 | + struct { |
| 230 | + struct nlmsghdr nlh; |
| 231 | + struct tcmsg t; |
| 232 | + } req = { |
| 233 | + .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)), |
| 234 | + .nlh.nlmsg_type = RTM_GETTCLASS, |
| 235 | + .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, |
| 236 | + .t.tcm_family = AF_UNSPEC, |
| 237 | + .t.tcm_ifindex = ifindex, |
| 238 | + }; |
| 239 | + int seq = time(NULL); |
| 240 | + |
| 241 | + req.nlh.nlmsg_seq = seq; |
| 242 | + if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0) |
| 243 | + return -errno; |
| 244 | + |
| 245 | + return bpf_netlink_recv(sock, nl_pid, seq, __dump_class_nlmsg, |
| 246 | + dump_class_nlmsg, cookie); |
| 247 | +} |
| 248 | + |
| 249 | +static int __dump_qdisc_nlmsg(struct nlmsghdr *nlh, |
| 250 | + dump_nlmsg_t dump_qdisc_nlmsg, void *cookie) |
| 251 | +{ |
| 252 | + struct nlattr *tb[TCA_MAX + 1], *attr; |
| 253 | + struct tcmsg *t = NLMSG_DATA(nlh); |
| 254 | + int len; |
| 255 | + |
| 256 | + len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t)); |
| 257 | + attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t))); |
| 258 | + if (nla_parse(tb, TCA_MAX, attr, len, NULL) != 0) |
| 259 | + return -LIBBPF_ERRNO__NLPARSE; |
| 260 | + |
| 261 | + return dump_qdisc_nlmsg(cookie, t, tb); |
| 262 | +} |
| 263 | + |
| 264 | +int nl_get_qdisc(int sock, unsigned int nl_pid, int ifindex, |
| 265 | + dump_nlmsg_t dump_qdisc_nlmsg, void *cookie) |
| 266 | +{ |
| 267 | + struct { |
| 268 | + struct nlmsghdr nlh; |
| 269 | + struct tcmsg t; |
| 270 | + } req = { |
| 271 | + .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)), |
| 272 | + .nlh.nlmsg_type = RTM_GETQDISC, |
| 273 | + .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, |
| 274 | + .t.tcm_family = AF_UNSPEC, |
| 275 | + .t.tcm_ifindex = ifindex, |
| 276 | + }; |
| 277 | + int seq = time(NULL); |
| 278 | + |
| 279 | + req.nlh.nlmsg_seq = seq; |
| 280 | + if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0) |
| 281 | + return -errno; |
| 282 | + |
| 283 | + return bpf_netlink_recv(sock, nl_pid, seq, __dump_qdisc_nlmsg, |
| 284 | + dump_qdisc_nlmsg, cookie); |
| 285 | +} |
| 286 | + |
| 287 | +static int __dump_filter_nlmsg(struct nlmsghdr *nlh, |
| 288 | + dump_nlmsg_t dump_filter_nlmsg, void *cookie) |
| 289 | +{ |
| 290 | + struct nlattr *tb[TCA_MAX + 1], *attr; |
| 291 | + struct tcmsg *t = NLMSG_DATA(nlh); |
| 292 | + int len; |
| 293 | + |
| 294 | + len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t)); |
| 295 | + attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t))); |
| 296 | + if (nla_parse(tb, TCA_MAX, attr, len, NULL) != 0) |
| 297 | + return -LIBBPF_ERRNO__NLPARSE; |
| 298 | + |
| 299 | + return dump_filter_nlmsg(cookie, t, tb); |
| 300 | +} |
| 301 | + |
| 302 | +int nl_get_filter(int sock, unsigned int nl_pid, int ifindex, int handle, |
| 303 | + dump_nlmsg_t dump_filter_nlmsg, void *cookie) |
| 304 | +{ |
| 305 | + struct { |
| 306 | + struct nlmsghdr nlh; |
| 307 | + struct tcmsg t; |
| 308 | + } req = { |
| 309 | + .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)), |
| 310 | + .nlh.nlmsg_type = RTM_GETTFILTER, |
| 311 | + .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, |
| 312 | + .t.tcm_family = AF_UNSPEC, |
| 313 | + .t.tcm_ifindex = ifindex, |
| 314 | + .t.tcm_parent = handle, |
| 315 | + }; |
| 316 | + int seq = time(NULL); |
| 317 | + |
| 318 | + req.nlh.nlmsg_seq = seq; |
| 319 | + if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0) |
| 320 | + return -errno; |
| 321 | + |
| 322 | + return bpf_netlink_recv(sock, nl_pid, seq, __dump_filter_nlmsg, |
| 323 | + dump_filter_nlmsg, cookie); |
| 324 | +} |
0 commit comments