1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2022 Felix Fietkau <nbd@nbd.name>
7 #include <sys/socket.h>
8 #include <netlink/msg.h>
9 #include <netlink/attr.h>
10 #include <netlink/socket.h>
11 #include <linux/rtnetlink.h>
14 static struct nl_sock
*rtnl
;
15 bool rtnl_ignore_errors
;
18 unetd_nl_error_cb(struct sockaddr_nl
*nla
, struct nlmsgerr
*err
,
21 struct nlmsghdr
*nlh
= (struct nlmsghdr
*) err
- 1;
22 struct nlattr
*tb
[NLMSGERR_ATTR_MAX
+ 1];
24 int ack_len
= sizeof(*nlh
) + sizeof(int) + sizeof(*nlh
);
25 int len
= nlh
->nlmsg_len
;
26 const char *errstr
= "(unknown)";
28 if (rtnl_ignore_errors
)
31 if (!(nlh
->nlmsg_flags
& NLM_F_ACK_TLVS
))
34 if (!(nlh
->nlmsg_flags
& NLM_F_CAPPED
))
35 ack_len
+= err
->msg
.nlmsg_len
- sizeof(*nlh
);
37 attrs
= (void *) ((unsigned char *) nlh
+ ack_len
);
40 nla_parse(tb
, NLMSGERR_ATTR_MAX
, attrs
, len
, NULL
);
41 if (tb
[NLMSGERR_ATTR_MSG
])
42 errstr
= nla_data(tb
[NLMSGERR_ATTR_MSG
]);
44 D("Netlink error(%d): %s\n", err
->error
, errstr
);
49 int rtnl_call(struct nl_msg
*msg
)
53 ret
= nl_send_auto_complete(rtnl
, msg
);
59 return nl_wait_for_ack(rtnl
);
69 rtnl
= nl_socket_alloc();
73 if (nl_connect(rtnl
, NETLINK_ROUTE
))
76 nl_socket_disable_seq_check(rtnl
);
77 nl_socket_set_buffer_size(rtnl
, 65536, 0);
78 nl_cb_err(nl_socket_get_cb(rtnl
), NL_CB_CUSTOM
, unetd_nl_error_cb
, NULL
);
80 fd
= nl_socket_get_fd(rtnl
);
83 setsockopt(fd
, SOL_NETLINK
, NETLINK_EXT_ACK
, &opt
, sizeof(opt
));
86 setsockopt(fd
, SOL_NETLINK
, NETLINK_CAP_ACK
, &opt
, sizeof(opt
));