11bc38b8fSAlexei Starovoitov // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2f7010770SYonghong Song /* Copyright (c) 2018 Facebook */ 3f7010770SYonghong Song 4f7010770SYonghong Song #include <stdlib.h> 5f7010770SYonghong Song #include <memory.h> 6f7010770SYonghong Song #include <unistd.h> 7f7010770SYonghong Song #include <linux/bpf.h> 8f7010770SYonghong Song #include <linux/rtnetlink.h> 9f7010770SYonghong Song #include <sys/socket.h> 10f7010770SYonghong Song #include <errno.h> 11f7010770SYonghong Song #include <time.h> 12f7010770SYonghong Song 13f7010770SYonghong Song #include "bpf.h" 14f7010770SYonghong Song #include "libbpf.h" 15b6e99b01SToke Høiland-Jørgensen #include "libbpf_internal.h" 16f7010770SYonghong Song #include "nlattr.h" 17f7010770SYonghong Song 18f7010770SYonghong Song #ifndef SOL_NETLINK 19f7010770SYonghong Song #define SOL_NETLINK 270 20f7010770SYonghong Song #endif 21f7010770SYonghong Song 227084566aSAndrii Nakryiko typedef int (*libbpf_dump_nlmsg_t)(void *cookie, void *msg, struct nlattr **tb); 237084566aSAndrii Nakryiko 24aae57780SAndrey Ignatov typedef int (*__dump_nlmsg_t)(struct nlmsghdr *nlmsg, libbpf_dump_nlmsg_t, 25434fe9d4SAndrey Ignatov void *cookie); 26434fe9d4SAndrey Ignatov 2750db9f07SMaciej Fijalkowski struct xdp_id_md { 2850db9f07SMaciej Fijalkowski int ifindex; 2950db9f07SMaciej Fijalkowski __u32 flags; 30473f4e13SToke Høiland-Jørgensen struct xdp_link_info info; 3150db9f07SMaciej Fijalkowski }; 3250db9f07SMaciej Fijalkowski 337084566aSAndrii Nakryiko static int libbpf_netlink_open(__u32 *nl_pid) 34f7010770SYonghong Song { 35f7010770SYonghong Song struct sockaddr_nl sa; 36f7010770SYonghong Song socklen_t addrlen; 37f7010770SYonghong Song int one = 1, ret; 38f7010770SYonghong Song int sock; 39f7010770SYonghong Song 40f7010770SYonghong Song memset(&sa, 0, sizeof(sa)); 41f7010770SYonghong Song sa.nl_family = AF_NETLINK; 42f7010770SYonghong Song 43*58bfd95bSKumar Kartikeya Dwivedi sock = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE); 44f7010770SYonghong Song if (sock < 0) 45f7010770SYonghong Song return -errno; 46f7010770SYonghong Song 47f7010770SYonghong Song if (setsockopt(sock, SOL_NETLINK, NETLINK_EXT_ACK, 48f7010770SYonghong Song &one, sizeof(one)) < 0) { 49b6e99b01SToke Høiland-Jørgensen pr_warn("Netlink error reporting not supported\n"); 50f7010770SYonghong Song } 51f7010770SYonghong Song 52f7010770SYonghong Song if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) { 53f7010770SYonghong Song ret = -errno; 54f7010770SYonghong Song goto cleanup; 55f7010770SYonghong Song } 56f7010770SYonghong Song 57f7010770SYonghong Song addrlen = sizeof(sa); 58f7010770SYonghong Song if (getsockname(sock, (struct sockaddr *)&sa, &addrlen) < 0) { 59f7010770SYonghong Song ret = -errno; 60f7010770SYonghong Song goto cleanup; 61f7010770SYonghong Song } 62f7010770SYonghong Song 63f7010770SYonghong Song if (addrlen != sizeof(sa)) { 64f7010770SYonghong Song ret = -LIBBPF_ERRNO__INTERNAL; 65f7010770SYonghong Song goto cleanup; 66f7010770SYonghong Song } 67f7010770SYonghong Song 68f7010770SYonghong Song *nl_pid = sa.nl_pid; 69f7010770SYonghong Song return sock; 70f7010770SYonghong Song 71f7010770SYonghong Song cleanup: 72f7010770SYonghong Song close(sock); 73f7010770SYonghong Song return ret; 74f7010770SYonghong Song } 75f7010770SYonghong Song 7636f1678dSYonghong Song static int bpf_netlink_recv(int sock, __u32 nl_pid, int seq, 77aae57780SAndrey Ignatov __dump_nlmsg_t _fn, libbpf_dump_nlmsg_t fn, 7836f1678dSYonghong Song void *cookie) 79f7010770SYonghong Song { 809d0b3c1fSYonghong Song bool multipart = true; 81f7010770SYonghong Song struct nlmsgerr *err; 82f7010770SYonghong Song struct nlmsghdr *nh; 83f7010770SYonghong Song char buf[4096]; 84f7010770SYonghong Song int len, ret; 85f7010770SYonghong Song 869d0b3c1fSYonghong Song while (multipart) { 879d0b3c1fSYonghong Song multipart = false; 88f7010770SYonghong Song len = recv(sock, buf, sizeof(buf), 0); 89f7010770SYonghong Song if (len < 0) { 90f7010770SYonghong Song ret = -errno; 91f7010770SYonghong Song goto done; 92f7010770SYonghong Song } 93f7010770SYonghong Song 949d0b3c1fSYonghong Song if (len == 0) 959d0b3c1fSYonghong Song break; 969d0b3c1fSYonghong Song 97f7010770SYonghong Song for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); 98f7010770SYonghong Song nh = NLMSG_NEXT(nh, len)) { 99f7010770SYonghong Song if (nh->nlmsg_pid != nl_pid) { 100f7010770SYonghong Song ret = -LIBBPF_ERRNO__WRNGPID; 101f7010770SYonghong Song goto done; 102f7010770SYonghong Song } 103f7010770SYonghong Song if (nh->nlmsg_seq != seq) { 104f7010770SYonghong Song ret = -LIBBPF_ERRNO__INVSEQ; 105f7010770SYonghong Song goto done; 106f7010770SYonghong Song } 1079d0b3c1fSYonghong Song if (nh->nlmsg_flags & NLM_F_MULTI) 1089d0b3c1fSYonghong Song multipart = true; 109f7010770SYonghong Song switch (nh->nlmsg_type) { 110f7010770SYonghong Song case NLMSG_ERROR: 111f7010770SYonghong Song err = (struct nlmsgerr *)NLMSG_DATA(nh); 112f7010770SYonghong Song if (!err->error) 113f7010770SYonghong Song continue; 114f7010770SYonghong Song ret = err->error; 115f04bc8a4SAndrey Ignatov libbpf_nla_dump_errormsg(nh); 116f7010770SYonghong Song goto done; 117f7010770SYonghong Song case NLMSG_DONE: 118f7010770SYonghong Song return 0; 119f7010770SYonghong Song default: 120f7010770SYonghong Song break; 121f7010770SYonghong Song } 12236f1678dSYonghong Song if (_fn) { 12336f1678dSYonghong Song ret = _fn(nh, fn, cookie); 12436f1678dSYonghong Song if (ret) 12536f1678dSYonghong Song return ret; 12636f1678dSYonghong Song } 127f7010770SYonghong Song } 128f7010770SYonghong Song } 129f7010770SYonghong Song ret = 0; 130f7010770SYonghong Song done: 131f7010770SYonghong Song return ret; 132f7010770SYonghong Song } 133f7010770SYonghong Song 134bd5ca3efSToke Høiland-Jørgensen static int __bpf_set_link_xdp_fd_replace(int ifindex, int fd, int old_fd, 135bd5ca3efSToke Høiland-Jørgensen __u32 flags) 136f7010770SYonghong Song { 137f7010770SYonghong Song int sock, seq = 0, ret; 138f7010770SYonghong Song struct nlattr *nla, *nla_xdp; 139f7010770SYonghong Song struct { 140f7010770SYonghong Song struct nlmsghdr nh; 141f7010770SYonghong Song struct ifinfomsg ifinfo; 142f7010770SYonghong Song char attrbuf[64]; 143f7010770SYonghong Song } req; 1444734b0feSJeremy Cline __u32 nl_pid = 0; 145f7010770SYonghong Song 146aae57780SAndrey Ignatov sock = libbpf_netlink_open(&nl_pid); 147f7010770SYonghong Song if (sock < 0) 148f7010770SYonghong Song return sock; 149f7010770SYonghong Song 150f7010770SYonghong Song memset(&req, 0, sizeof(req)); 151f7010770SYonghong Song req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); 152f7010770SYonghong Song req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; 153f7010770SYonghong Song req.nh.nlmsg_type = RTM_SETLINK; 154f7010770SYonghong Song req.nh.nlmsg_pid = 0; 155f7010770SYonghong Song req.nh.nlmsg_seq = ++seq; 156f7010770SYonghong Song req.ifinfo.ifi_family = AF_UNSPEC; 157f7010770SYonghong Song req.ifinfo.ifi_index = ifindex; 158f7010770SYonghong Song 159f7010770SYonghong Song /* started nested attribute for XDP */ 160f7010770SYonghong Song nla = (struct nlattr *)(((char *)&req) 161f7010770SYonghong Song + NLMSG_ALIGN(req.nh.nlmsg_len)); 162f7010770SYonghong Song nla->nla_type = NLA_F_NESTED | IFLA_XDP; 163f7010770SYonghong Song nla->nla_len = NLA_HDRLEN; 164f7010770SYonghong Song 165f7010770SYonghong Song /* add XDP fd */ 166f7010770SYonghong Song nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len); 167f7010770SYonghong Song nla_xdp->nla_type = IFLA_XDP_FD; 168f7010770SYonghong Song nla_xdp->nla_len = NLA_HDRLEN + sizeof(int); 169f7010770SYonghong Song memcpy((char *)nla_xdp + NLA_HDRLEN, &fd, sizeof(fd)); 170f7010770SYonghong Song nla->nla_len += nla_xdp->nla_len; 171f7010770SYonghong Song 172f7010770SYonghong Song /* if user passed in any flags, add those too */ 173f7010770SYonghong Song if (flags) { 174f7010770SYonghong Song nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len); 175f7010770SYonghong Song nla_xdp->nla_type = IFLA_XDP_FLAGS; 176f7010770SYonghong Song nla_xdp->nla_len = NLA_HDRLEN + sizeof(flags); 177f7010770SYonghong Song memcpy((char *)nla_xdp + NLA_HDRLEN, &flags, sizeof(flags)); 178f7010770SYonghong Song nla->nla_len += nla_xdp->nla_len; 179f7010770SYonghong Song } 180f7010770SYonghong Song 181bd5ca3efSToke Høiland-Jørgensen if (flags & XDP_FLAGS_REPLACE) { 182bd5ca3efSToke Høiland-Jørgensen nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len); 183bd5ca3efSToke Høiland-Jørgensen nla_xdp->nla_type = IFLA_XDP_EXPECTED_FD; 184bd5ca3efSToke Høiland-Jørgensen nla_xdp->nla_len = NLA_HDRLEN + sizeof(old_fd); 185bd5ca3efSToke Høiland-Jørgensen memcpy((char *)nla_xdp + NLA_HDRLEN, &old_fd, sizeof(old_fd)); 186bd5ca3efSToke Høiland-Jørgensen nla->nla_len += nla_xdp->nla_len; 187bd5ca3efSToke Høiland-Jørgensen } 188bd5ca3efSToke Høiland-Jørgensen 189f7010770SYonghong Song req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len); 190f7010770SYonghong Song 191f7010770SYonghong Song if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) { 192f7010770SYonghong Song ret = -errno; 193f7010770SYonghong Song goto cleanup; 194f7010770SYonghong Song } 19536f1678dSYonghong Song ret = bpf_netlink_recv(sock, nl_pid, seq, NULL, NULL, NULL); 196f7010770SYonghong Song 197f7010770SYonghong Song cleanup: 198f7010770SYonghong Song close(sock); 199f7010770SYonghong Song return ret; 200f7010770SYonghong Song } 20136f1678dSYonghong Song 202bd5ca3efSToke Høiland-Jørgensen int bpf_set_link_xdp_fd_opts(int ifindex, int fd, __u32 flags, 203bd5ca3efSToke Høiland-Jørgensen const struct bpf_xdp_set_link_opts *opts) 204bd5ca3efSToke Høiland-Jørgensen { 205bd5ca3efSToke Høiland-Jørgensen int old_fd = -1; 206bd5ca3efSToke Høiland-Jørgensen 207bd5ca3efSToke Høiland-Jørgensen if (!OPTS_VALID(opts, bpf_xdp_set_link_opts)) 208bd5ca3efSToke Høiland-Jørgensen return -EINVAL; 209bd5ca3efSToke Høiland-Jørgensen 210bd5ca3efSToke Høiland-Jørgensen if (OPTS_HAS(opts, old_fd)) { 211bd5ca3efSToke Høiland-Jørgensen old_fd = OPTS_GET(opts, old_fd, -1); 212bd5ca3efSToke Høiland-Jørgensen flags |= XDP_FLAGS_REPLACE; 213bd5ca3efSToke Høiland-Jørgensen } 214bd5ca3efSToke Høiland-Jørgensen 215bd5ca3efSToke Høiland-Jørgensen return __bpf_set_link_xdp_fd_replace(ifindex, fd, 216bd5ca3efSToke Høiland-Jørgensen old_fd, 217bd5ca3efSToke Høiland-Jørgensen flags); 218bd5ca3efSToke Høiland-Jørgensen } 219bd5ca3efSToke Høiland-Jørgensen 220bd5ca3efSToke Høiland-Jørgensen int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags) 221bd5ca3efSToke Høiland-Jørgensen { 222bd5ca3efSToke Høiland-Jørgensen return __bpf_set_link_xdp_fd_replace(ifindex, fd, 0, flags); 223bd5ca3efSToke Høiland-Jørgensen } 224bd5ca3efSToke Høiland-Jørgensen 225aae57780SAndrey Ignatov static int __dump_link_nlmsg(struct nlmsghdr *nlh, 226aae57780SAndrey Ignatov libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie) 22736f1678dSYonghong Song { 22836f1678dSYonghong Song struct nlattr *tb[IFLA_MAX + 1], *attr; 22936f1678dSYonghong Song struct ifinfomsg *ifi = NLMSG_DATA(nlh); 23036f1678dSYonghong Song int len; 23136f1678dSYonghong Song 23236f1678dSYonghong Song len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi)); 23336f1678dSYonghong Song attr = (struct nlattr *) ((void *) ifi + NLMSG_ALIGN(sizeof(*ifi))); 234f04bc8a4SAndrey Ignatov if (libbpf_nla_parse(tb, IFLA_MAX, attr, len, NULL) != 0) 23536f1678dSYonghong Song return -LIBBPF_ERRNO__NLPARSE; 23636f1678dSYonghong Song 23736f1678dSYonghong Song return dump_link_nlmsg(cookie, ifi, tb); 23836f1678dSYonghong Song } 23936f1678dSYonghong Song 240473f4e13SToke Høiland-Jørgensen static int get_xdp_info(void *cookie, void *msg, struct nlattr **tb) 24150db9f07SMaciej Fijalkowski { 24250db9f07SMaciej Fijalkowski struct nlattr *xdp_tb[IFLA_XDP_MAX + 1]; 24350db9f07SMaciej Fijalkowski struct xdp_id_md *xdp_id = cookie; 24450db9f07SMaciej Fijalkowski struct ifinfomsg *ifinfo = msg; 24550db9f07SMaciej Fijalkowski int ret; 24650db9f07SMaciej Fijalkowski 24750db9f07SMaciej Fijalkowski if (xdp_id->ifindex && xdp_id->ifindex != ifinfo->ifi_index) 24850db9f07SMaciej Fijalkowski return 0; 24950db9f07SMaciej Fijalkowski 25050db9f07SMaciej Fijalkowski if (!tb[IFLA_XDP]) 25150db9f07SMaciej Fijalkowski return 0; 25250db9f07SMaciej Fijalkowski 25350db9f07SMaciej Fijalkowski ret = libbpf_nla_parse_nested(xdp_tb, IFLA_XDP_MAX, tb[IFLA_XDP], NULL); 25450db9f07SMaciej Fijalkowski if (ret) 25550db9f07SMaciej Fijalkowski return ret; 25650db9f07SMaciej Fijalkowski 25750db9f07SMaciej Fijalkowski if (!xdp_tb[IFLA_XDP_ATTACHED]) 25850db9f07SMaciej Fijalkowski return 0; 25950db9f07SMaciej Fijalkowski 260473f4e13SToke Høiland-Jørgensen xdp_id->info.attach_mode = libbpf_nla_getattr_u8( 261473f4e13SToke Høiland-Jørgensen xdp_tb[IFLA_XDP_ATTACHED]); 262473f4e13SToke Høiland-Jørgensen 263473f4e13SToke Høiland-Jørgensen if (xdp_id->info.attach_mode == XDP_ATTACHED_NONE) 26450db9f07SMaciej Fijalkowski return 0; 26550db9f07SMaciej Fijalkowski 266473f4e13SToke Høiland-Jørgensen if (xdp_tb[IFLA_XDP_PROG_ID]) 267473f4e13SToke Høiland-Jørgensen xdp_id->info.prog_id = libbpf_nla_getattr_u32( 268473f4e13SToke Høiland-Jørgensen xdp_tb[IFLA_XDP_PROG_ID]); 26950db9f07SMaciej Fijalkowski 270473f4e13SToke Høiland-Jørgensen if (xdp_tb[IFLA_XDP_SKB_PROG_ID]) 271473f4e13SToke Høiland-Jørgensen xdp_id->info.skb_prog_id = libbpf_nla_getattr_u32( 272473f4e13SToke Høiland-Jørgensen xdp_tb[IFLA_XDP_SKB_PROG_ID]); 273473f4e13SToke Høiland-Jørgensen 274473f4e13SToke Høiland-Jørgensen if (xdp_tb[IFLA_XDP_DRV_PROG_ID]) 275473f4e13SToke Høiland-Jørgensen xdp_id->info.drv_prog_id = libbpf_nla_getattr_u32( 276473f4e13SToke Høiland-Jørgensen xdp_tb[IFLA_XDP_DRV_PROG_ID]); 277473f4e13SToke Høiland-Jørgensen 278473f4e13SToke Høiland-Jørgensen if (xdp_tb[IFLA_XDP_HW_PROG_ID]) 279473f4e13SToke Høiland-Jørgensen xdp_id->info.hw_prog_id = libbpf_nla_getattr_u32( 280473f4e13SToke Høiland-Jørgensen xdp_tb[IFLA_XDP_HW_PROG_ID]); 28150db9f07SMaciej Fijalkowski 28250db9f07SMaciej Fijalkowski return 0; 28350db9f07SMaciej Fijalkowski } 28450db9f07SMaciej Fijalkowski 2857084566aSAndrii Nakryiko static int libbpf_nl_get_link(int sock, unsigned int nl_pid, 2867084566aSAndrii Nakryiko libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie); 2877084566aSAndrii Nakryiko 288473f4e13SToke Høiland-Jørgensen int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info, 289473f4e13SToke Høiland-Jørgensen size_t info_size, __u32 flags) 29050db9f07SMaciej Fijalkowski { 29150db9f07SMaciej Fijalkowski struct xdp_id_md xdp_id = {}; 29250db9f07SMaciej Fijalkowski int sock, ret; 2934734b0feSJeremy Cline __u32 nl_pid = 0; 29450db9f07SMaciej Fijalkowski __u32 mask; 29550db9f07SMaciej Fijalkowski 296473f4e13SToke Høiland-Jørgensen if (flags & ~XDP_FLAGS_MASK || !info_size) 29750db9f07SMaciej Fijalkowski return -EINVAL; 29850db9f07SMaciej Fijalkowski 29950db9f07SMaciej Fijalkowski /* Check whether the single {HW,DRV,SKB} mode is set */ 30050db9f07SMaciej Fijalkowski flags &= (XDP_FLAGS_SKB_MODE | XDP_FLAGS_DRV_MODE | XDP_FLAGS_HW_MODE); 30150db9f07SMaciej Fijalkowski mask = flags - 1; 30250db9f07SMaciej Fijalkowski if (flags && flags & mask) 30350db9f07SMaciej Fijalkowski return -EINVAL; 30450db9f07SMaciej Fijalkowski 30550db9f07SMaciej Fijalkowski sock = libbpf_netlink_open(&nl_pid); 30650db9f07SMaciej Fijalkowski if (sock < 0) 30750db9f07SMaciej Fijalkowski return sock; 30850db9f07SMaciej Fijalkowski 30950db9f07SMaciej Fijalkowski xdp_id.ifindex = ifindex; 31050db9f07SMaciej Fijalkowski xdp_id.flags = flags; 31150db9f07SMaciej Fijalkowski 312473f4e13SToke Høiland-Jørgensen ret = libbpf_nl_get_link(sock, nl_pid, get_xdp_info, &xdp_id); 313473f4e13SToke Høiland-Jørgensen if (!ret) { 314473f4e13SToke Høiland-Jørgensen size_t sz = min(info_size, sizeof(xdp_id.info)); 315473f4e13SToke Høiland-Jørgensen 316473f4e13SToke Høiland-Jørgensen memcpy(info, &xdp_id.info, sz); 317473f4e13SToke Høiland-Jørgensen memset((void *) info + sz, 0, info_size - sz); 318473f4e13SToke Høiland-Jørgensen } 31950db9f07SMaciej Fijalkowski 32050db9f07SMaciej Fijalkowski close(sock); 32150db9f07SMaciej Fijalkowski return ret; 32250db9f07SMaciej Fijalkowski } 32350db9f07SMaciej Fijalkowski 324473f4e13SToke Høiland-Jørgensen static __u32 get_xdp_id(struct xdp_link_info *info, __u32 flags) 325473f4e13SToke Høiland-Jørgensen { 326257d7d4fSDavid Ahern flags &= XDP_FLAGS_MODES; 327257d7d4fSDavid Ahern 328f07cbad2SAndrey Ignatov if (info->attach_mode != XDP_ATTACHED_MULTI && !flags) 329473f4e13SToke Høiland-Jørgensen return info->prog_id; 330473f4e13SToke Høiland-Jørgensen if (flags & XDP_FLAGS_DRV_MODE) 331473f4e13SToke Høiland-Jørgensen return info->drv_prog_id; 332473f4e13SToke Høiland-Jørgensen if (flags & XDP_FLAGS_HW_MODE) 333473f4e13SToke Høiland-Jørgensen return info->hw_prog_id; 334473f4e13SToke Høiland-Jørgensen if (flags & XDP_FLAGS_SKB_MODE) 335473f4e13SToke Høiland-Jørgensen return info->skb_prog_id; 336473f4e13SToke Høiland-Jørgensen 337473f4e13SToke Høiland-Jørgensen return 0; 338473f4e13SToke Høiland-Jørgensen } 339473f4e13SToke Høiland-Jørgensen 340473f4e13SToke Høiland-Jørgensen int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags) 341473f4e13SToke Høiland-Jørgensen { 342473f4e13SToke Høiland-Jørgensen struct xdp_link_info info; 343473f4e13SToke Høiland-Jørgensen int ret; 344473f4e13SToke Høiland-Jørgensen 345473f4e13SToke Høiland-Jørgensen ret = bpf_get_link_xdp_info(ifindex, &info, sizeof(info), flags); 346473f4e13SToke Høiland-Jørgensen if (!ret) 347473f4e13SToke Høiland-Jørgensen *prog_id = get_xdp_id(&info, flags); 348473f4e13SToke Høiland-Jørgensen 349473f4e13SToke Høiland-Jørgensen return ret; 350473f4e13SToke Høiland-Jørgensen } 351473f4e13SToke Høiland-Jørgensen 352aae57780SAndrey Ignatov int libbpf_nl_get_link(int sock, unsigned int nl_pid, 353aae57780SAndrey Ignatov libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie) 35436f1678dSYonghong Song { 35536f1678dSYonghong Song struct { 35636f1678dSYonghong Song struct nlmsghdr nlh; 35736f1678dSYonghong Song struct ifinfomsg ifm; 35836f1678dSYonghong Song } req = { 35936f1678dSYonghong Song .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)), 36036f1678dSYonghong Song .nlh.nlmsg_type = RTM_GETLINK, 36136f1678dSYonghong Song .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, 36236f1678dSYonghong Song .ifm.ifi_family = AF_PACKET, 36336f1678dSYonghong Song }; 36436f1678dSYonghong Song int seq = time(NULL); 36536f1678dSYonghong Song 36636f1678dSYonghong Song req.nlh.nlmsg_seq = seq; 36736f1678dSYonghong Song if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0) 36836f1678dSYonghong Song return -errno; 36936f1678dSYonghong Song 37036f1678dSYonghong Song return bpf_netlink_recv(sock, nl_pid, seq, __dump_link_nlmsg, 37136f1678dSYonghong Song dump_link_nlmsg, cookie); 37236f1678dSYonghong Song } 373