Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tools/bpftool: Remove libbpf_internal.h usage in bpftool

Most netlink-related functions were unique to bpftool usage, so I moved them
into net.c. Few functions are still used by both bpftool and libbpf itself
internally, so I've copy-pasted them (libbpf_nl_get_link,
libbpf_netlink_open). It's a bit of duplication of code, but better separation
of libbpf as a library with public API and bpftool, relying on unexposed
functions in libbpf.

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20200819013607.3607269-3-andriin@fb.com

authored by

Andrii Nakryiko and committed by
Alexei Starovoitov
7084566a 029258d7

+288 -150
-2
tools/bpf/bpftool/gen.c
··· 19 19 #include <sys/mman.h> 20 20 #include <bpf/btf.h> 21 21 22 - #include "bpf/libbpf_internal.h" 23 22 #include "json_writer.h" 24 23 #include "main.h" 25 - 26 24 27 25 #define MAX_OBJ_NAME_LEN 64 28 26
+282 -17
tools/bpf/bpftool/net.c
··· 6 6 #include <fcntl.h> 7 7 #include <stdlib.h> 8 8 #include <string.h> 9 + #include <time.h> 9 10 #include <unistd.h> 10 11 #include <bpf/bpf.h> 11 12 #include <bpf/libbpf.h> 12 13 #include <net/if.h> 13 14 #include <linux/if.h> 14 15 #include <linux/rtnetlink.h> 16 + #include <linux/socket.h> 15 17 #include <linux/tc_act/tc_bpf.h> 16 18 #include <sys/socket.h> 17 19 #include <sys/stat.h> 18 20 #include <sys/types.h> 19 21 20 22 #include "bpf/nlattr.h" 21 - #include "bpf/libbpf_internal.h" 22 23 #include "main.h" 23 24 #include "netlink_dumper.h" 25 + 26 + #ifndef SOL_NETLINK 27 + #define SOL_NETLINK 270 28 + #endif 24 29 25 30 struct ip_devname_ifindex { 26 31 char devname[64]; ··· 88 83 } 89 84 90 85 return net_attach_type_size; 86 + } 87 + 88 + typedef int (*dump_nlmsg_t)(void *cookie, void *msg, struct nlattr **tb); 89 + 90 + typedef int (*__dump_nlmsg_t)(struct nlmsghdr *nlmsg, dump_nlmsg_t, void *cookie); 91 + 92 + static int netlink_open(__u32 *nl_pid) 93 + { 94 + struct sockaddr_nl sa; 95 + socklen_t addrlen; 96 + int one = 1, ret; 97 + int sock; 98 + 99 + memset(&sa, 0, sizeof(sa)); 100 + sa.nl_family = AF_NETLINK; 101 + 102 + sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 103 + if (sock < 0) 104 + return -errno; 105 + 106 + if (setsockopt(sock, SOL_NETLINK, NETLINK_EXT_ACK, 107 + &one, sizeof(one)) < 0) { 108 + p_err("Netlink error reporting not supported"); 109 + } 110 + 111 + if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) { 112 + ret = -errno; 113 + goto cleanup; 114 + } 115 + 116 + addrlen = sizeof(sa); 117 + if (getsockname(sock, (struct sockaddr *)&sa, &addrlen) < 0) { 118 + ret = -errno; 119 + goto cleanup; 120 + } 121 + 122 + if (addrlen != sizeof(sa)) { 123 + ret = -LIBBPF_ERRNO__INTERNAL; 124 + goto cleanup; 125 + } 126 + 127 + *nl_pid = sa.nl_pid; 128 + return sock; 129 + 130 + cleanup: 131 + close(sock); 132 + return ret; 133 + } 134 + 135 + static int netlink_recv(int sock, __u32 nl_pid, __u32 seq, 136 + __dump_nlmsg_t _fn, dump_nlmsg_t fn, 137 + void *cookie) 138 + { 139 + bool multipart = true; 140 + struct nlmsgerr *err; 141 + struct nlmsghdr *nh; 142 + char buf[4096]; 143 + int len, ret; 144 + 145 + while (multipart) { 146 + multipart = false; 147 + len = recv(sock, buf, sizeof(buf), 0); 148 + if (len < 0) { 149 + ret = -errno; 150 + goto done; 151 + } 152 + 153 + if (len == 0) 154 + break; 155 + 156 + for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); 157 + nh = NLMSG_NEXT(nh, len)) { 158 + if (nh->nlmsg_pid != nl_pid) { 159 + ret = -LIBBPF_ERRNO__WRNGPID; 160 + goto done; 161 + } 162 + if (nh->nlmsg_seq != seq) { 163 + ret = -LIBBPF_ERRNO__INVSEQ; 164 + goto done; 165 + } 166 + if (nh->nlmsg_flags & NLM_F_MULTI) 167 + multipart = true; 168 + switch (nh->nlmsg_type) { 169 + case NLMSG_ERROR: 170 + err = (struct nlmsgerr *)NLMSG_DATA(nh); 171 + if (!err->error) 172 + continue; 173 + ret = err->error; 174 + libbpf_nla_dump_errormsg(nh); 175 + goto done; 176 + case NLMSG_DONE: 177 + return 0; 178 + default: 179 + break; 180 + } 181 + if (_fn) { 182 + ret = _fn(nh, fn, cookie); 183 + if (ret) 184 + return ret; 185 + } 186 + } 187 + } 188 + ret = 0; 189 + done: 190 + return ret; 191 + } 192 + 193 + static int __dump_class_nlmsg(struct nlmsghdr *nlh, 194 + dump_nlmsg_t dump_class_nlmsg, 195 + void *cookie) 196 + { 197 + struct nlattr *tb[TCA_MAX + 1], *attr; 198 + struct tcmsg *t = NLMSG_DATA(nlh); 199 + int len; 200 + 201 + len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t)); 202 + attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t))); 203 + if (libbpf_nla_parse(tb, TCA_MAX, attr, len, NULL) != 0) 204 + return -LIBBPF_ERRNO__NLPARSE; 205 + 206 + return dump_class_nlmsg(cookie, t, tb); 207 + } 208 + 209 + static int netlink_get_class(int sock, unsigned int nl_pid, int ifindex, 210 + dump_nlmsg_t dump_class_nlmsg, void *cookie) 211 + { 212 + struct { 213 + struct nlmsghdr nlh; 214 + struct tcmsg t; 215 + } req = { 216 + .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)), 217 + .nlh.nlmsg_type = RTM_GETTCLASS, 218 + .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, 219 + .t.tcm_family = AF_UNSPEC, 220 + .t.tcm_ifindex = ifindex, 221 + }; 222 + int seq = time(NULL); 223 + 224 + req.nlh.nlmsg_seq = seq; 225 + if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0) 226 + return -errno; 227 + 228 + return netlink_recv(sock, nl_pid, seq, __dump_class_nlmsg, 229 + dump_class_nlmsg, cookie); 230 + } 231 + 232 + static int __dump_qdisc_nlmsg(struct nlmsghdr *nlh, 233 + dump_nlmsg_t dump_qdisc_nlmsg, 234 + void *cookie) 235 + { 236 + struct nlattr *tb[TCA_MAX + 1], *attr; 237 + struct tcmsg *t = NLMSG_DATA(nlh); 238 + int len; 239 + 240 + len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t)); 241 + attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t))); 242 + if (libbpf_nla_parse(tb, TCA_MAX, attr, len, NULL) != 0) 243 + return -LIBBPF_ERRNO__NLPARSE; 244 + 245 + return dump_qdisc_nlmsg(cookie, t, tb); 246 + } 247 + 248 + static int netlink_get_qdisc(int sock, unsigned int nl_pid, int ifindex, 249 + dump_nlmsg_t dump_qdisc_nlmsg, void *cookie) 250 + { 251 + struct { 252 + struct nlmsghdr nlh; 253 + struct tcmsg t; 254 + } req = { 255 + .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)), 256 + .nlh.nlmsg_type = RTM_GETQDISC, 257 + .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, 258 + .t.tcm_family = AF_UNSPEC, 259 + .t.tcm_ifindex = ifindex, 260 + }; 261 + int seq = time(NULL); 262 + 263 + req.nlh.nlmsg_seq = seq; 264 + if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0) 265 + return -errno; 266 + 267 + return netlink_recv(sock, nl_pid, seq, __dump_qdisc_nlmsg, 268 + dump_qdisc_nlmsg, cookie); 269 + } 270 + 271 + static int __dump_filter_nlmsg(struct nlmsghdr *nlh, 272 + dump_nlmsg_t dump_filter_nlmsg, 273 + void *cookie) 274 + { 275 + struct nlattr *tb[TCA_MAX + 1], *attr; 276 + struct tcmsg *t = NLMSG_DATA(nlh); 277 + int len; 278 + 279 + len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t)); 280 + attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t))); 281 + if (libbpf_nla_parse(tb, TCA_MAX, attr, len, NULL) != 0) 282 + return -LIBBPF_ERRNO__NLPARSE; 283 + 284 + return dump_filter_nlmsg(cookie, t, tb); 285 + } 286 + 287 + static int netlink_get_filter(int sock, unsigned int nl_pid, int ifindex, int handle, 288 + dump_nlmsg_t dump_filter_nlmsg, void *cookie) 289 + { 290 + struct { 291 + struct nlmsghdr nlh; 292 + struct tcmsg t; 293 + } req = { 294 + .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)), 295 + .nlh.nlmsg_type = RTM_GETTFILTER, 296 + .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, 297 + .t.tcm_family = AF_UNSPEC, 298 + .t.tcm_ifindex = ifindex, 299 + .t.tcm_parent = handle, 300 + }; 301 + int seq = time(NULL); 302 + 303 + req.nlh.nlmsg_seq = seq; 304 + if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0) 305 + return -errno; 306 + 307 + return netlink_recv(sock, nl_pid, seq, __dump_filter_nlmsg, 308 + dump_filter_nlmsg, cookie); 309 + } 310 + 311 + static int __dump_link_nlmsg(struct nlmsghdr *nlh, 312 + dump_nlmsg_t dump_link_nlmsg, void *cookie) 313 + { 314 + struct nlattr *tb[IFLA_MAX + 1], *attr; 315 + struct ifinfomsg *ifi = NLMSG_DATA(nlh); 316 + int len; 317 + 318 + len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi)); 319 + attr = (struct nlattr *) ((void *) ifi + NLMSG_ALIGN(sizeof(*ifi))); 320 + if (libbpf_nla_parse(tb, IFLA_MAX, attr, len, NULL) != 0) 321 + return -LIBBPF_ERRNO__NLPARSE; 322 + 323 + return dump_link_nlmsg(cookie, ifi, tb); 324 + } 325 + 326 + static int netlink_get_link(int sock, unsigned int nl_pid, 327 + dump_nlmsg_t dump_link_nlmsg, void *cookie) 328 + { 329 + struct { 330 + struct nlmsghdr nlh; 331 + struct ifinfomsg ifm; 332 + } req = { 333 + .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)), 334 + .nlh.nlmsg_type = RTM_GETLINK, 335 + .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, 336 + .ifm.ifi_family = AF_PACKET, 337 + }; 338 + int seq = time(NULL); 339 + 340 + req.nlh.nlmsg_seq = seq; 341 + if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0) 342 + return -errno; 343 + 344 + return netlink_recv(sock, nl_pid, seq, __dump_link_nlmsg, 345 + dump_link_nlmsg, cookie); 91 346 } 92 347 93 348 static int dump_link_nlmsg(void *cookie, void *msg, struct nlattr **tb) ··· 433 168 tcinfo.array_len = 0; 434 169 435 170 tcinfo.is_qdisc = false; 436 - ret = libbpf_nl_get_class(sock, nl_pid, dev->ifindex, 437 - dump_class_qdisc_nlmsg, &tcinfo); 171 + ret = netlink_get_class(sock, nl_pid, dev->ifindex, 172 + dump_class_qdisc_nlmsg, &tcinfo); 438 173 if (ret) 439 174 goto out; 440 175 441 176 tcinfo.is_qdisc = true; 442 - ret = libbpf_nl_get_qdisc(sock, nl_pid, dev->ifindex, 443 - dump_class_qdisc_nlmsg, &tcinfo); 177 + ret = netlink_get_qdisc(sock, nl_pid, dev->ifindex, 178 + dump_class_qdisc_nlmsg, &tcinfo); 444 179 if (ret) 445 180 goto out; 446 181 ··· 448 183 filter_info.ifindex = dev->ifindex; 449 184 for (i = 0; i < tcinfo.used_len; i++) { 450 185 filter_info.kind = tcinfo.handle_array[i].kind; 451 - ret = libbpf_nl_get_filter(sock, nl_pid, dev->ifindex, 452 - tcinfo.handle_array[i].handle, 453 - dump_filter_nlmsg, &filter_info); 186 + ret = netlink_get_filter(sock, nl_pid, dev->ifindex, 187 + tcinfo.handle_array[i].handle, 188 + dump_filter_nlmsg, &filter_info); 454 189 if (ret) 455 190 goto out; 456 191 } ··· 458 193 /* root, ingress and egress handle */ 459 194 handle = TC_H_ROOT; 460 195 filter_info.kind = "root"; 461 - ret = libbpf_nl_get_filter(sock, nl_pid, dev->ifindex, handle, 462 - dump_filter_nlmsg, &filter_info); 196 + ret = netlink_get_filter(sock, nl_pid, dev->ifindex, handle, 197 + dump_filter_nlmsg, &filter_info); 463 198 if (ret) 464 199 goto out; 465 200 466 201 handle = TC_H_MAKE(TC_H_CLSACT, TC_H_MIN_INGRESS); 467 202 filter_info.kind = "clsact/ingress"; 468 - ret = libbpf_nl_get_filter(sock, nl_pid, dev->ifindex, handle, 469 - dump_filter_nlmsg, &filter_info); 203 + ret = netlink_get_filter(sock, nl_pid, dev->ifindex, handle, 204 + dump_filter_nlmsg, &filter_info); 470 205 if (ret) 471 206 goto out; 472 207 473 208 handle = TC_H_MAKE(TC_H_CLSACT, TC_H_MIN_EGRESS); 474 209 filter_info.kind = "clsact/egress"; 475 - ret = libbpf_nl_get_filter(sock, nl_pid, dev->ifindex, handle, 476 - dump_filter_nlmsg, &filter_info); 210 + ret = netlink_get_filter(sock, nl_pid, dev->ifindex, handle, 211 + dump_filter_nlmsg, &filter_info); 477 212 if (ret) 478 213 goto out; 479 214 ··· 651 386 struct bpf_attach_info attach_info = {}; 652 387 int i, sock, ret, filter_idx = -1; 653 388 struct bpf_netdev_t dev_array; 654 - unsigned int nl_pid; 389 + unsigned int nl_pid = 0; 655 390 char err_buf[256]; 656 391 657 392 if (argc == 2) { ··· 666 401 if (ret) 667 402 return -1; 668 403 669 - sock = libbpf_netlink_open(&nl_pid); 404 + sock = netlink_open(&nl_pid); 670 405 if (sock < 0) { 671 406 fprintf(stderr, "failed to open netlink sock\n"); 672 407 return -1; ··· 681 416 jsonw_start_array(json_wtr); 682 417 NET_START_OBJECT; 683 418 NET_START_ARRAY("xdp", "%s:\n"); 684 - ret = libbpf_nl_get_link(sock, nl_pid, dump_link_nlmsg, &dev_array); 419 + ret = netlink_get_link(sock, nl_pid, dump_link_nlmsg, &dev_array); 685 420 NET_END_ARRAY("\n"); 686 421 687 422 if (!ret) {
-12
tools/lib/bpf/libbpf_internal.h
··· 130 130 int bpf_object__variable_offset(const struct bpf_object *obj, const char *name, 131 131 __u32 *off); 132 132 133 - struct nlattr; 134 - typedef int (*libbpf_dump_nlmsg_t)(void *cookie, void *msg, struct nlattr **tb); 135 - int libbpf_netlink_open(unsigned int *nl_pid); 136 - int libbpf_nl_get_link(int sock, unsigned int nl_pid, 137 - libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie); 138 - int libbpf_nl_get_class(int sock, unsigned int nl_pid, int ifindex, 139 - libbpf_dump_nlmsg_t dump_class_nlmsg, void *cookie); 140 - int libbpf_nl_get_qdisc(int sock, unsigned int nl_pid, int ifindex, 141 - libbpf_dump_nlmsg_t dump_qdisc_nlmsg, void *cookie); 142 - int libbpf_nl_get_filter(int sock, unsigned int nl_pid, int ifindex, int handle, 143 - libbpf_dump_nlmsg_t dump_filter_nlmsg, void *cookie); 144 - 145 133 struct btf_ext_info { 146 134 /* 147 135 * info points to the individual info section (e.g. func_info and
+6 -119
tools/lib/bpf/netlink.c
··· 22 22 #define SOL_NETLINK 270 23 23 #endif 24 24 25 + typedef int (*libbpf_dump_nlmsg_t)(void *cookie, void *msg, struct nlattr **tb); 26 + 25 27 typedef int (*__dump_nlmsg_t)(struct nlmsghdr *nlmsg, libbpf_dump_nlmsg_t, 26 28 void *cookie); 27 29 ··· 33 31 struct xdp_link_info info; 34 32 }; 35 33 36 - int libbpf_netlink_open(__u32 *nl_pid) 34 + static int libbpf_netlink_open(__u32 *nl_pid) 37 35 { 38 36 struct sockaddr_nl sa; 39 37 socklen_t addrlen; ··· 285 283 return 0; 286 284 } 287 285 286 + static int libbpf_nl_get_link(int sock, unsigned int nl_pid, 287 + libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie); 288 + 288 289 int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info, 289 290 size_t info_size, __u32 flags) 290 291 { ··· 372 367 373 368 return bpf_netlink_recv(sock, nl_pid, seq, __dump_link_nlmsg, 374 369 dump_link_nlmsg, cookie); 375 - } 376 - 377 - static int __dump_class_nlmsg(struct nlmsghdr *nlh, 378 - libbpf_dump_nlmsg_t dump_class_nlmsg, 379 - void *cookie) 380 - { 381 - struct nlattr *tb[TCA_MAX + 1], *attr; 382 - struct tcmsg *t = NLMSG_DATA(nlh); 383 - int len; 384 - 385 - len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t)); 386 - attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t))); 387 - if (libbpf_nla_parse(tb, TCA_MAX, attr, len, NULL) != 0) 388 - return -LIBBPF_ERRNO__NLPARSE; 389 - 390 - return dump_class_nlmsg(cookie, t, tb); 391 - } 392 - 393 - int libbpf_nl_get_class(int sock, unsigned int nl_pid, int ifindex, 394 - libbpf_dump_nlmsg_t dump_class_nlmsg, void *cookie) 395 - { 396 - struct { 397 - struct nlmsghdr nlh; 398 - struct tcmsg t; 399 - } req = { 400 - .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)), 401 - .nlh.nlmsg_type = RTM_GETTCLASS, 402 - .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, 403 - .t.tcm_family = AF_UNSPEC, 404 - .t.tcm_ifindex = ifindex, 405 - }; 406 - int seq = time(NULL); 407 - 408 - req.nlh.nlmsg_seq = seq; 409 - if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0) 410 - return -errno; 411 - 412 - return bpf_netlink_recv(sock, nl_pid, seq, __dump_class_nlmsg, 413 - dump_class_nlmsg, cookie); 414 - } 415 - 416 - static int __dump_qdisc_nlmsg(struct nlmsghdr *nlh, 417 - libbpf_dump_nlmsg_t dump_qdisc_nlmsg, 418 - void *cookie) 419 - { 420 - struct nlattr *tb[TCA_MAX + 1], *attr; 421 - struct tcmsg *t = NLMSG_DATA(nlh); 422 - int len; 423 - 424 - len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t)); 425 - attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t))); 426 - if (libbpf_nla_parse(tb, TCA_MAX, attr, len, NULL) != 0) 427 - return -LIBBPF_ERRNO__NLPARSE; 428 - 429 - return dump_qdisc_nlmsg(cookie, t, tb); 430 - } 431 - 432 - int libbpf_nl_get_qdisc(int sock, unsigned int nl_pid, int ifindex, 433 - libbpf_dump_nlmsg_t dump_qdisc_nlmsg, void *cookie) 434 - { 435 - struct { 436 - struct nlmsghdr nlh; 437 - struct tcmsg t; 438 - } req = { 439 - .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)), 440 - .nlh.nlmsg_type = RTM_GETQDISC, 441 - .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, 442 - .t.tcm_family = AF_UNSPEC, 443 - .t.tcm_ifindex = ifindex, 444 - }; 445 - int seq = time(NULL); 446 - 447 - req.nlh.nlmsg_seq = seq; 448 - if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0) 449 - return -errno; 450 - 451 - return bpf_netlink_recv(sock, nl_pid, seq, __dump_qdisc_nlmsg, 452 - dump_qdisc_nlmsg, cookie); 453 - } 454 - 455 - static int __dump_filter_nlmsg(struct nlmsghdr *nlh, 456 - libbpf_dump_nlmsg_t dump_filter_nlmsg, 457 - void *cookie) 458 - { 459 - struct nlattr *tb[TCA_MAX + 1], *attr; 460 - struct tcmsg *t = NLMSG_DATA(nlh); 461 - int len; 462 - 463 - len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t)); 464 - attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t))); 465 - if (libbpf_nla_parse(tb, TCA_MAX, attr, len, NULL) != 0) 466 - return -LIBBPF_ERRNO__NLPARSE; 467 - 468 - return dump_filter_nlmsg(cookie, t, tb); 469 - } 470 - 471 - int libbpf_nl_get_filter(int sock, unsigned int nl_pid, int ifindex, int handle, 472 - libbpf_dump_nlmsg_t dump_filter_nlmsg, void *cookie) 473 - { 474 - struct { 475 - struct nlmsghdr nlh; 476 - struct tcmsg t; 477 - } req = { 478 - .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)), 479 - .nlh.nlmsg_type = RTM_GETTFILTER, 480 - .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, 481 - .t.tcm_family = AF_UNSPEC, 482 - .t.tcm_ifindex = ifindex, 483 - .t.tcm_parent = handle, 484 - }; 485 - int seq = time(NULL); 486 - 487 - req.nlh.nlmsg_seq = seq; 488 - if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0) 489 - return -errno; 490 - 491 - return bpf_netlink_recv(sock, nl_pid, seq, __dump_filter_nlmsg, 492 - dump_filter_nlmsg, cookie); 493 370 }