When updating the IP and broadcast addresses, clear out any old IP and
broadcast addresses that may be still bound to the interface.
This commit is contained in:
parent
4d1cfe8586
commit
19d009891a
289
ndhc/ifset.c
289
ndhc/ifset.c
@ -55,6 +55,8 @@
|
|||||||
#include "strl.h"
|
#include "strl.h"
|
||||||
#include "nl.h"
|
#include "nl.h"
|
||||||
|
|
||||||
|
static uint32_t ifset_nl_seq;
|
||||||
|
|
||||||
static int set_if_flag(short flag)
|
static int set_if_flag(short flag)
|
||||||
{
|
{
|
||||||
int fd, ret = -1;
|
int fd, ret = -1;
|
||||||
@ -106,19 +108,212 @@ static inline int subnet4_to_prefixlen(uint32_t sn)
|
|||||||
return 32 - trailz(ntohl(sn));
|
return 32 - trailz(ntohl(sn));
|
||||||
}
|
}
|
||||||
|
|
||||||
// str_bcast is optional.
|
struct ipbcpfx {
|
||||||
void perform_ip_subnet_bcast(const char *str_ipaddr,
|
int fd;
|
||||||
const char *str_subnet, const char *str_bcast)
|
uint32_t ipaddr;
|
||||||
|
uint32_t bcast;
|
||||||
|
uint8_t prefixlen;
|
||||||
|
bool already_ok;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int rtattr_assign(struct rtattr *attr, int type, void *data)
|
||||||
|
{
|
||||||
|
struct rtattr **tb = data;
|
||||||
|
if (type >= IFA_MAX)
|
||||||
|
return 0;
|
||||||
|
tb[type] = attr;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t rtnl_addr_broadcast_send(int fd, int type, int ifa_flags,
|
||||||
|
int ifa_scope, struct in_addr *ipaddr,
|
||||||
|
struct in_addr *bcast,
|
||||||
|
uint8_t prefixlen)
|
||||||
{
|
{
|
||||||
uint8_t request[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
|
uint8_t request[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
|
||||||
NLMSG_ALIGN(sizeof(struct ifaddrmsg)) +
|
NLMSG_ALIGN(sizeof(struct ifaddrmsg)) +
|
||||||
RTA_LENGTH(sizeof(struct in6_addr))];
|
RTA_LENGTH(sizeof(struct in6_addr))];
|
||||||
uint8_t response[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + 64];
|
uint8_t response[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + 64];
|
||||||
struct in_addr ipaddr, subnet, bcast;
|
|
||||||
struct sockaddr_nl nl_addr;
|
|
||||||
struct nlmsghdr *header;
|
struct nlmsghdr *header;
|
||||||
struct ifaddrmsg *ifaddrmsg;
|
struct ifaddrmsg *ifaddrmsg;
|
||||||
int nls, r;
|
struct sockaddr_nl nl_addr;
|
||||||
|
ssize_t r;
|
||||||
|
|
||||||
|
if (!ipaddr && !bcast) {
|
||||||
|
log_warning("%s: (%s) no ipaddr or bcast!",
|
||||||
|
client_config.interface, __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&request, 0, sizeof request);
|
||||||
|
header = (struct nlmsghdr *)request;
|
||||||
|
header->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
|
||||||
|
header->nlmsg_type = type;
|
||||||
|
header->nlmsg_flags = NLM_F_REPLACE | NLM_F_ACK | NLM_F_REQUEST;
|
||||||
|
header->nlmsg_seq = ifset_nl_seq++;
|
||||||
|
|
||||||
|
ifaddrmsg = NLMSG_DATA(header);
|
||||||
|
ifaddrmsg->ifa_family = AF_INET;
|
||||||
|
ifaddrmsg->ifa_prefixlen = prefixlen;
|
||||||
|
ifaddrmsg->ifa_flags = ifa_flags;
|
||||||
|
ifaddrmsg->ifa_scope = ifa_scope;
|
||||||
|
ifaddrmsg->ifa_index = client_config.ifindex;
|
||||||
|
|
||||||
|
if (ipaddr) {
|
||||||
|
if (nl_add_rtattr(header, sizeof request, IFA_LOCAL,
|
||||||
|
&ipaddr, sizeof ipaddr) < 0) {
|
||||||
|
log_line("%s: (%s) couldn't add IFA_LOCAL to nlmsg",
|
||||||
|
client_config.interface, __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bcast) {
|
||||||
|
if (nl_add_rtattr(header, sizeof request, IFA_BROADCAST,
|
||||||
|
&bcast, sizeof bcast) < 0) {
|
||||||
|
log_line("%s: (%s) couldn't add IFA_BROADCAST to nlmsg",
|
||||||
|
client_config.interface, __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&nl_addr, 0, sizeof nl_addr);
|
||||||
|
nl_addr.nl_family = AF_NETLINK;
|
||||||
|
|
||||||
|
retry_sendto:
|
||||||
|
r = sendto(fd, request, header->nlmsg_len, 0,
|
||||||
|
(struct sockaddr *)&nl_addr, sizeof nl_addr);
|
||||||
|
if (r < 0) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
goto retry_sendto;
|
||||||
|
else {
|
||||||
|
log_line("%s: (%s) netlink sendto failed: %s",
|
||||||
|
client_config.interface, __func__, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retry_recv:
|
||||||
|
r = recv(fd, response, sizeof response, 0);
|
||||||
|
if (r < 0) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
goto retry_recv;
|
||||||
|
else {
|
||||||
|
log_line("%s: (%s) netlink recv failed: %s",
|
||||||
|
client_config.interface, __func__, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((size_t)r < sizeof(struct nlmsghdr)) {
|
||||||
|
log_line("%s: (%s) netlink recv returned a headerless response",
|
||||||
|
client_config.interface, __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
uint32_t nr_type;
|
||||||
|
memcpy(&nr_type, response + 4, 2);
|
||||||
|
if (nr_type == NLMSG_ERROR) {
|
||||||
|
log_line("%s: (%s) netlink sendto returned NLMSG_ERROR",
|
||||||
|
client_config.interface, __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ipbcpfx_clear_others_do(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
struct rtattr *tb[IFA_MAX] = {0};
|
||||||
|
struct ifaddrmsg *ifm = nlmsg_get_data(nlh);
|
||||||
|
struct ipbcpfx *ipx = data;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
switch(nlh->nlmsg_type) {
|
||||||
|
case RTM_NEWADDR:
|
||||||
|
if (ifm->ifa_index != (unsigned)client_config.ifindex) {
|
||||||
|
printf("not correct ifindex\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ifm->ifa_family != AF_INET) {
|
||||||
|
printf("not AF_INET\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(ifm->ifa_flags & IFA_F_PERMANENT)) {
|
||||||
|
printf("not F_PERMANENT\n");
|
||||||
|
goto erase;
|
||||||
|
}
|
||||||
|
if (!(ifm->ifa_scope & RT_SCOPE_UNIVERSE)) {
|
||||||
|
printf("not SCOPE_UNIVERSE\n");
|
||||||
|
goto erase;
|
||||||
|
}
|
||||||
|
if (ifm->ifa_prefixlen != ipx->prefixlen) {
|
||||||
|
printf("different prefixlen (%u)\n", ifm->ifa_prefixlen);
|
||||||
|
goto erase;
|
||||||
|
}
|
||||||
|
nl_rtattr_parse(nlh, sizeof *ifm, rtattr_assign, tb);
|
||||||
|
if (!tb[IFA_ADDRESS]) {
|
||||||
|
printf("no IFA_ADDRESS\n");
|
||||||
|
goto erase;
|
||||||
|
}
|
||||||
|
if (memcmp(rtattr_get_data(tb[IFA_ADDRESS]), &ipx->ipaddr,
|
||||||
|
sizeof ipx->ipaddr)) {
|
||||||
|
printf("different IFA_ADDRESS\n");
|
||||||
|
goto erase;
|
||||||
|
}
|
||||||
|
if (!tb[IFA_BROADCAST]) {
|
||||||
|
printf("no IFA_BROADCAST\n");
|
||||||
|
goto erase;
|
||||||
|
}
|
||||||
|
if (memcmp(rtattr_get_data(tb[IFA_BROADCAST]), &ipx->ipaddr,
|
||||||
|
sizeof ipx->ipaddr)) {
|
||||||
|
printf("different IFA_BROADCAST\n");
|
||||||
|
goto erase;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// We already have the proper IP+broadcast+prefix.
|
||||||
|
ipx->already_ok = true;
|
||||||
|
return;
|
||||||
|
|
||||||
|
erase:
|
||||||
|
r = rtnl_addr_broadcast_send(ipx->fd, RTM_DELADDR, ifm->ifa_flags,
|
||||||
|
ifm->ifa_scope,
|
||||||
|
rtattr_get_data(tb[IFA_ADDRESS]),
|
||||||
|
rtattr_get_data(tb[IFA_BROADCAST]),
|
||||||
|
ifm->ifa_prefixlen);
|
||||||
|
if (r < 0) {
|
||||||
|
log_warning("%s: (%s) Failed to delete IP and broadcast addresses.",
|
||||||
|
client_config.interface, __func__);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ipbcpfx_clear_others(int fd, uint32_t ipaddr, uint32_t bcast,
|
||||||
|
uint8_t prefixlen)
|
||||||
|
{
|
||||||
|
char nlbuf[8192];
|
||||||
|
struct ipbcpfx ipx = { .fd = fd, .ipaddr = ipaddr, .bcast = bcast,
|
||||||
|
.prefixlen = prefixlen, .already_ok = false };
|
||||||
|
ssize_t ret;
|
||||||
|
ret = nl_sendgetaddr(fd, ifset_nl_seq++, client_config.ifindex);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = nl_recv_buf(fd, nlbuf, sizeof nlbuf);
|
||||||
|
if (ret == -1)
|
||||||
|
break;
|
||||||
|
if (nl_foreach_nlmsg(nlbuf, ret, 0,
|
||||||
|
ipbcpfx_clear_others_do, &ipx) == -1)
|
||||||
|
break;
|
||||||
|
} while (ret > 0);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// str_bcast is optional.
|
||||||
|
void perform_ip_subnet_bcast(const char *str_ipaddr,
|
||||||
|
const char *str_subnet, const char *str_bcast)
|
||||||
|
{
|
||||||
|
struct in_addr ipaddr, subnet, bcast;
|
||||||
|
int fd, r;
|
||||||
uint8_t prefixlen;
|
uint8_t prefixlen;
|
||||||
|
|
||||||
if (!str_ipaddr) {
|
if (!str_ipaddr) {
|
||||||
@ -156,81 +351,27 @@ void perform_ip_subnet_bcast(const char *str_ipaddr,
|
|||||||
bcast.s_addr = ipaddr.s_addr | htonl(0xfffffffflu >> prefixlen);
|
bcast.s_addr = ipaddr.s_addr | htonl(0xfffffffflu >> prefixlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&request, 0, sizeof request);
|
fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
|
||||||
header = (struct nlmsghdr *)request;
|
if (fd < 0) {
|
||||||
header->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
|
|
||||||
header->nlmsg_type = RTM_NEWADDR;
|
|
||||||
header->nlmsg_flags = NLM_F_REPLACE | NLM_F_ACK | NLM_F_REQUEST;
|
|
||||||
header->nlmsg_seq = 1;
|
|
||||||
|
|
||||||
ifaddrmsg = NLMSG_DATA(header);
|
|
||||||
ifaddrmsg->ifa_family = AF_INET;
|
|
||||||
ifaddrmsg->ifa_prefixlen = prefixlen;
|
|
||||||
ifaddrmsg->ifa_flags = IFA_F_PERMANENT;
|
|
||||||
ifaddrmsg->ifa_scope = RT_SCOPE_UNIVERSE;
|
|
||||||
ifaddrmsg->ifa_index = client_config.ifindex;
|
|
||||||
|
|
||||||
if (nl_add_rtattr(header, sizeof request, IFA_LOCAL,
|
|
||||||
&ipaddr, sizeof ipaddr) < 0) {
|
|
||||||
log_line("%s: (%s) couldn't add IFA_LOCAL to nlmsg",
|
|
||||||
client_config.interface, __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (nl_add_rtattr(header, sizeof request, IFA_BROADCAST,
|
|
||||||
&bcast, sizeof bcast) < 0) {
|
|
||||||
log_line("%s: (%s) couldn't add IFA_BROADCAST to nlmsg",
|
|
||||||
client_config.interface, __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nls = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
|
|
||||||
if (nls < 0) {
|
|
||||||
log_line("%s: (%s) netlink socket open failed: %s",
|
log_line("%s: (%s) netlink socket open failed: %s",
|
||||||
client_config.interface, __func__, strerror(errno));
|
client_config.interface, __func__, strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&nl_addr, 0, sizeof nl_addr);
|
r = ipbcpfx_clear_others(fd, ipaddr.s_addr, bcast.s_addr, prefixlen);
|
||||||
nl_addr.nl_family = AF_NETLINK;
|
if (r < 0) {
|
||||||
|
close(fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
retry_sendto:
|
r = rtnl_addr_broadcast_send(fd, RTM_NEWADDR, IFA_F_PERMANENT,
|
||||||
r = sendto(nls, request, header->nlmsg_len, 0,
|
RT_SCOPE_UNIVERSE, &ipaddr, &bcast,
|
||||||
(struct sockaddr *)&nl_addr, sizeof nl_addr);
|
prefixlen);
|
||||||
if (r < 0) {
|
|
||||||
if (errno == EINTR)
|
close(fd); // XXX: Move this when we also set the link flags.
|
||||||
goto retry_sendto;
|
if (r < 0)
|
||||||
else {
|
|
||||||
log_line("%s: (%s) netlink sendto failed: %s",
|
|
||||||
client_config.interface, __func__, strerror(errno));
|
|
||||||
close(nls);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
retry_recv:
|
|
||||||
r = recv(nls, response, sizeof response, 0);
|
|
||||||
if (r < 0) {
|
|
||||||
if (errno == EINTR)
|
|
||||||
goto retry_recv;
|
|
||||||
else {
|
|
||||||
log_line("%s: (%s) netlink recv failed: %s",
|
|
||||||
client_config.interface, __func__, strerror(errno));
|
|
||||||
close(nls);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close(nls);
|
|
||||||
if ((size_t)r < sizeof(struct nlmsghdr)) {
|
|
||||||
log_line("%s: (%s) netlink recv returned a headerless response",
|
|
||||||
client_config.interface, __func__);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
uint32_t nr_type;
|
|
||||||
memcpy(&nr_type, response + 4, 2);
|
|
||||||
if (nr_type == NLMSG_ERROR) {
|
|
||||||
log_line("%s: (%s) netlink sendto returned NLMSG_ERROR",
|
|
||||||
client_config.interface, __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
log_line("Interface IP set to: '%s'", str_ipaddr);
|
log_line("Interface IP set to: '%s'", str_ipaddr);
|
||||||
log_line("Interface subnet set to: '%s'", str_subnet);
|
log_line("Interface subnet set to: '%s'", str_subnet);
|
||||||
if (str_bcast)
|
if (str_bcast)
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
#include "nl.h"
|
#include "nl.h"
|
||||||
#include "state.h"
|
#include "state.h"
|
||||||
|
|
||||||
static int nlrtattr_assign(struct nlattr *attr, int type, void *data)
|
static int nlattr_assign(struct nlattr *attr, int type, void *data)
|
||||||
{
|
{
|
||||||
struct nlattr **tb = data;
|
struct nlattr **tb = data;
|
||||||
if (type >= IFLA_MAX)
|
if (type >= IFLA_MAX)
|
||||||
@ -55,7 +55,7 @@ static void get_if_index_and_mac(const struct nlmsghdr *nlh,
|
|||||||
struct ifinfomsg *ifm)
|
struct ifinfomsg *ifm)
|
||||||
{
|
{
|
||||||
struct nlattr *tb[IFLA_MAX] = {0};
|
struct nlattr *tb[IFLA_MAX] = {0};
|
||||||
nl_attr_parse(nlh, sizeof *ifm, nlrtattr_assign, tb);
|
nl_attr_parse(nlh, sizeof *ifm, nlattr_assign, tb);
|
||||||
if (!tb[IFLA_IFNAME])
|
if (!tb[IFLA_IFNAME])
|
||||||
return;
|
return;
|
||||||
if (!strncmp(client_config.interface,
|
if (!strncmp(client_config.interface,
|
||||||
@ -78,7 +78,7 @@ static void get_if_index_and_mac(const struct nlmsghdr *nlh,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nl_process_msgs(const struct nlmsghdr *nlh, void *data)
|
static void nl_process_msgs(const struct nlmsghdr *nlh, void *data)
|
||||||
{
|
{
|
||||||
struct ifinfomsg *ifm = nlmsg_get_data(nlh);
|
struct ifinfomsg *ifm = nlmsg_get_data(nlh);
|
||||||
struct client_state_t *cs = data;
|
struct client_state_t *cs = data;
|
||||||
@ -120,7 +120,6 @@ static int nl_process_msgs(const struct nlmsghdr *nlh, void *data)
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_nl_message(struct client_state_t *cs)
|
void handle_nl_message(struct client_state_t *cs)
|
||||||
|
22
ndhc/nl.c
22
ndhc/nl.c
@ -78,6 +78,21 @@ void nl_attr_parse(const struct nlmsghdr *nlh, size_t offset,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nl_rtattr_parse(const struct nlmsghdr *nlh, size_t offset,
|
||||||
|
nl_rtattr_parse_fn workfn, void *data)
|
||||||
|
{
|
||||||
|
struct rtattr *attr;
|
||||||
|
for (attr = (struct rtattr *)
|
||||||
|
((char *)nlh + NLMSG_HDRLEN + NLMSG_ALIGN(offset));
|
||||||
|
rtattr_ok(attr, (char *)nlh + NLMSG_ALIGN(nlh->nlmsg_len) -
|
||||||
|
(char *)attr);
|
||||||
|
attr = (struct rtattr *)((char *)attr + NLMSG_ALIGN(attr->rta_len)))
|
||||||
|
{
|
||||||
|
if (workfn(attr, attr->rta_type, data) < 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ssize_t nl_recv_buf(int fd, char *buf, size_t blen)
|
ssize_t nl_recv_buf(int fd, char *buf, size_t blen)
|
||||||
{
|
{
|
||||||
struct sockaddr_nl addr;
|
struct sockaddr_nl addr;
|
||||||
@ -172,10 +187,11 @@ retry_sendto:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nl_sendgetaddr(int fd, int seq)
|
int nl_sendgetaddr(int fd, int seq, int ifindex)
|
||||||
{
|
{
|
||||||
char nlbuf[512];
|
char nlbuf[512];
|
||||||
struct nlmsghdr *nlh = (struct nlmsghdr *)nlbuf;
|
struct nlmsghdr *nlh = (struct nlmsghdr *)nlbuf;
|
||||||
|
struct ifaddrmsg *ifaddrmsg;
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
|
|
||||||
memset(nlbuf, 0, sizeof nlbuf);
|
memset(nlbuf, 0, sizeof nlbuf);
|
||||||
@ -184,6 +200,10 @@ int nl_sendgetaddr(int fd, int seq)
|
|||||||
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
|
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
|
||||||
nlh->nlmsg_seq = seq;
|
nlh->nlmsg_seq = seq;
|
||||||
|
|
||||||
|
ifaddrmsg = NLMSG_DATA(nlh);
|
||||||
|
ifaddrmsg->ifa_family = AF_INET;
|
||||||
|
ifaddrmsg->ifa_index = ifindex;
|
||||||
|
|
||||||
struct sockaddr_nl addr = {
|
struct sockaddr_nl addr = {
|
||||||
.nl_family = AF_NETLINK,
|
.nl_family = AF_NETLINK,
|
||||||
};
|
};
|
||||||
|
18
ndhc/nl.h
18
ndhc/nl.h
@ -31,6 +31,7 @@
|
|||||||
// Limited netlink code. The horrors...
|
// Limited netlink code. The horrors...
|
||||||
|
|
||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
static inline int nl_attr_ok(const struct nlattr *attr, size_t len)
|
static inline int nl_attr_ok(const struct nlattr *attr, size_t len)
|
||||||
{
|
{
|
||||||
@ -43,6 +44,11 @@ static inline int nl_attr_ok(const struct nlattr *attr, size_t len)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int rtattr_ok(const struct rtattr *attr, size_t len)
|
||||||
|
{
|
||||||
|
return RTA_OK(attr, len);
|
||||||
|
}
|
||||||
|
|
||||||
static inline size_t nlattr_get_len(const struct nlattr *attr)
|
static inline size_t nlattr_get_len(const struct nlattr *attr)
|
||||||
{
|
{
|
||||||
return attr->nla_len;
|
return attr->nla_len;
|
||||||
@ -53,6 +59,11 @@ static inline void *nlattr_get_data(const struct nlattr *attr)
|
|||||||
return (char *)attr + NLA_HDRLEN;
|
return (char *)attr + NLA_HDRLEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void *rtattr_get_data(const struct rtattr *attr)
|
||||||
|
{
|
||||||
|
return (char *)RTA_DATA(attr);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void *nlmsg_get_data(const struct nlmsghdr *nlh)
|
static inline void *nlmsg_get_data(const struct nlmsghdr *nlh)
|
||||||
{
|
{
|
||||||
return (char *)nlh + NLMSG_HDRLEN;
|
return (char *)nlh + NLMSG_HDRLEN;
|
||||||
@ -71,14 +82,17 @@ extern int nl_add_rtattr(struct nlmsghdr *n, size_t max_length, int type,
|
|||||||
typedef int (*nl_attr_parse_fn)(struct nlattr *attr, int type, void *data);
|
typedef int (*nl_attr_parse_fn)(struct nlattr *attr, int type, void *data);
|
||||||
extern void nl_attr_parse(const struct nlmsghdr *nlh, size_t offset,
|
extern void nl_attr_parse(const struct nlmsghdr *nlh, size_t offset,
|
||||||
nl_attr_parse_fn workfn, void *data);
|
nl_attr_parse_fn workfn, void *data);
|
||||||
|
typedef int (*nl_rtattr_parse_fn)(struct rtattr *attr, int type, void *data);
|
||||||
|
extern void nl_rtattr_parse(const struct nlmsghdr *nlh, size_t offset,
|
||||||
|
nl_rtattr_parse_fn workfn, void *data);
|
||||||
|
|
||||||
extern ssize_t nl_recv_buf(int fd, char *buf, size_t blen);
|
extern ssize_t nl_recv_buf(int fd, char *buf, size_t blen);
|
||||||
|
|
||||||
typedef int (*nlmsg_foreach_fn)(const struct nlmsghdr *, void *);
|
typedef void (*nlmsg_foreach_fn)(const struct nlmsghdr *, void *);
|
||||||
extern int nl_foreach_nlmsg(char *buf, size_t blen, uint32_t portid,
|
extern int nl_foreach_nlmsg(char *buf, size_t blen, uint32_t portid,
|
||||||
nlmsg_foreach_fn pfn, void *fnarg);
|
nlmsg_foreach_fn pfn, void *fnarg);
|
||||||
extern int nl_sendgetlink(int fd, int seq);
|
extern int nl_sendgetlink(int fd, int seq);
|
||||||
extern int nl_sendgetaddr(int fd, int seq);
|
extern int nl_sendgetaddr(int fd, int seq, int ifindex);
|
||||||
|
|
||||||
extern int nl_open(int nltype, int nlgroup, int *nlportid);
|
extern int nl_open(int nltype, int nlgroup, int *nlportid);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user