1dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat/* 2dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * libnetlink.c RTnetlink service routines. 3dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 4dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * This program is free software; you can redistribute it and/or 5dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * modify it under the terms of the GNU General Public License 6dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * as published by the Free Software Foundation; either version 7dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 2 of the License, or (at your option) any later version. 8dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 9dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 10dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 11dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat */ 12dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 13dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdio.h> 14dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdlib.h> 15dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <unistd.h> 16dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <syslog.h> 17dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <fcntl.h> 18dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <net/if_arp.h> 19dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/socket.h> 20dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <netinet/in.h> 21dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <string.h> 22dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <errno.h> 23dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <time.h> 24dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/uio.h> 25dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 26dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "libnetlink.h" 27dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 28dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint rcvbuf = 1024 * 1024; 29dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 30dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid rtnl_close(struct rtnl_handle *rth) 31dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 32dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (rth->fd >= 0) { 33dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat close(rth->fd); 34dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat rth->fd = -1; 35dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 36dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 37dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 38dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions, 39dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int protocol) 40dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 41dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat socklen_t addr_len; 42dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int sndbuf = 32768; 43dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 44dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset(rth, 0, sizeof(*rth)); 45dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 46dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat rth->fd = socket(AF_NETLINK, SOCK_RAW, protocol); 47dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (rth->fd < 0) { 48dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat perror("Cannot open netlink socket"); 49dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 50dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 51dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 52dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (setsockopt(rth->fd,SOL_SOCKET,SO_SNDBUF,&sndbuf,sizeof(sndbuf)) < 0) { 53dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat perror("SO_SNDBUF"); 54dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 55dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 56dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 57dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (setsockopt(rth->fd,SOL_SOCKET,SO_RCVBUF,&rcvbuf,sizeof(rcvbuf)) < 0) { 58dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat perror("SO_RCVBUF"); 59dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 60dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 61dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 62dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset(&rth->local, 0, sizeof(rth->local)); 63dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat rth->local.nl_family = AF_NETLINK; 64dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat rth->local.nl_groups = subscriptions; 65dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 66dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) { 67dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat perror("Cannot bind netlink socket"); 68dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 69dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 70dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addr_len = sizeof(rth->local); 71dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) { 72dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat perror("Cannot getsockname"); 73dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 74dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 75dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (addr_len != sizeof(rth->local)) { 76dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Wrong address length %d\n", addr_len); 77dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 78dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 79dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (rth->local.nl_family != AF_NETLINK) { 80dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Wrong address family %d\n", rth->local.nl_family); 81dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 82dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 83dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat rth->seq = time(NULL); 84dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 85dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 86dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 87dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint rtnl_open(struct rtnl_handle *rth, unsigned subscriptions) 88dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 89dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return rtnl_open_byproto(rth, subscriptions, NETLINK_ROUTE); 90dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 91dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 92dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type) 93dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 94dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct { 95dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct nlmsghdr nlh; 96dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct rtgenmsg g; 97dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } req; 98dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 99dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset(&req, 0, sizeof(req)); 100dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat req.nlh.nlmsg_len = sizeof(req); 101dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat req.nlh.nlmsg_type = type; 102dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; 103dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat req.nlh.nlmsg_pid = 0; 104dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat req.nlh.nlmsg_seq = rth->dump = ++rth->seq; 105dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat req.g.rtgen_family = family; 106dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 107dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return send(rth->fd, (void*)&req, sizeof(req), 0); 108dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 109dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 110dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint rtnl_send(struct rtnl_handle *rth, const char *buf, int len) 111dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 112dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return send(rth->fd, buf, len, 0); 113dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 114dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 115dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint rtnl_send_check(struct rtnl_handle *rth, const char *buf, int len) 116dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 117dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct nlmsghdr *h; 118dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int status; 119dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char resp[1024]; 120dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 121dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat status = send(rth->fd, buf, len, 0); 122dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (status < 0) 123dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return status; 124dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 125dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat /* Check for immediate errors */ 126dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat status = recv(rth->fd, resp, sizeof(resp), MSG_DONTWAIT|MSG_PEEK); 127dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (status < 0) { 128dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (errno == EAGAIN) 129dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 130dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 131dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 132dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 133dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat for (h = (struct nlmsghdr *)resp; NLMSG_OK(h, status); 134dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat h = NLMSG_NEXT(h, status)) { 135dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (h->nlmsg_type == NLMSG_ERROR) { 136dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); 137dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) 138dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "ERROR truncated\n"); 139dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else 140dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat errno = -err->error; 141dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 142dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 143dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 144dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 145dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 146dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 147dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 148dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) 149dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 150dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct nlmsghdr nlh; 151dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct sockaddr_nl nladdr; 152dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct iovec iov[2] = { 153dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat { .iov_base = &nlh, .iov_len = sizeof(nlh) }, 154dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat { .iov_base = req, .iov_len = len } 155dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat }; 156dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct msghdr msg = { 157dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .msg_name = &nladdr, 158dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .msg_namelen = sizeof(nladdr), 159dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .msg_iov = iov, 160dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .msg_iovlen = 2, 161dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat }; 162dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 163dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset(&nladdr, 0, sizeof(nladdr)); 164dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat nladdr.nl_family = AF_NETLINK; 165dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 166dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat nlh.nlmsg_len = NLMSG_LENGTH(len); 167dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat nlh.nlmsg_type = type; 168dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; 169dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat nlh.nlmsg_pid = 0; 170dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat nlh.nlmsg_seq = rth->dump = ++rth->seq; 171dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 172dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return sendmsg(rth->fd, &msg, 0); 173dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 174dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 175dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint rtnl_dump_filter_l(struct rtnl_handle *rth, 176dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat const struct rtnl_dump_filter_arg *arg) 177dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 178dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct sockaddr_nl nladdr; 179dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct iovec iov; 180dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct msghdr msg = { 181dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .msg_name = &nladdr, 182dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .msg_namelen = sizeof(nladdr), 183dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .msg_iov = &iov, 184dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .msg_iovlen = 1, 185dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat }; 186dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char buf[16384]; 187dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 188dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat iov.iov_base = buf; 189dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat while (1) { 190dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int status; 191dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat const struct rtnl_dump_filter_arg *a; 192dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 193dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat iov.iov_len = sizeof(buf); 194dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat status = recvmsg(rth->fd, &msg, 0); 195dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 196dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (status < 0) { 197dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (errno == EINTR || errno == EAGAIN) 198dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat continue; 199dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "netlink receive error %s (%d)\n", 200dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strerror(errno), errno); 201dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 202dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 203dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 204dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (status == 0) { 205dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "EOF on netlink\n"); 206dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 207dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 208dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 209dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat for (a = arg; a->filter; a++) { 210dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct nlmsghdr *h = (struct nlmsghdr*)buf; 211dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 212dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat while (NLMSG_OK(h, status)) { 213dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int err; 214dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 215dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (nladdr.nl_pid != 0 || 216dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat h->nlmsg_pid != rth->local.nl_pid || 217dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat h->nlmsg_seq != rth->dump) { 218dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (a->junk) { 219dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat err = a->junk(&nladdr, h, 220dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat a->arg2); 221dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (err < 0) 222dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return err; 223dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 224dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto skip_it; 225dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 226dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 227dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (h->nlmsg_type == NLMSG_DONE) 228dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 229dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (h->nlmsg_type == NLMSG_ERROR) { 230dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); 231dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) { 232dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, 233dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "ERROR truncated\n"); 234dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else { 235dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat errno = -err->error; 236dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat perror("RTNETLINK answers"); 237dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 238dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 239dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 240dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat err = a->filter(&nladdr, h, a->arg1); 241dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (err < 0) 242dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return err; 243dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 244dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatskip_it: 245dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat h = NLMSG_NEXT(h, status); 246dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 247dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } while (0); 248dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (msg.msg_flags & MSG_TRUNC) { 249dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Message truncated\n"); 250dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat continue; 251dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 252dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (status) { 253dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "!!!Remnant of size %d\n", status); 254dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat exit(1); 255dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 256dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 257dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 258dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 259dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint rtnl_dump_filter(struct rtnl_handle *rth, 260dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat rtnl_filter_t filter, 261dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat void *arg1, 262dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat rtnl_filter_t junk, 263dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat void *arg2) 264dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 265dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat const struct rtnl_dump_filter_arg a[2] = { 266dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat { .filter = filter, .arg1 = arg1, .junk = junk, .arg2 = arg2 }, 267dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat { .filter = NULL, .arg1 = NULL, .junk = NULL, .arg2 = NULL } 268dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat }; 269dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 270dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return rtnl_dump_filter_l(rth, a); 271dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 272dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 273dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, 274dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat unsigned groups, struct nlmsghdr *answer, 275dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat rtnl_filter_t junk, 276dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat void *jarg) 277dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 278dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int status; 279dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat unsigned seq; 280dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct nlmsghdr *h; 281dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct sockaddr_nl nladdr; 282dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct iovec iov = { 283dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .iov_base = (void*) n, 284dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .iov_len = n->nlmsg_len 285dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat }; 286dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct msghdr msg = { 287dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .msg_name = &nladdr, 288dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .msg_namelen = sizeof(nladdr), 289dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .msg_iov = &iov, 290dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .msg_iovlen = 1, 291dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat }; 292dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char buf[16384]; 293dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 294dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset(&nladdr, 0, sizeof(nladdr)); 295dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat nladdr.nl_family = AF_NETLINK; 296dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat nladdr.nl_pid = peer; 297dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat nladdr.nl_groups = groups; 298dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 299dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat n->nlmsg_seq = seq = ++rtnl->seq; 300dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 301dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (answer == NULL) 302dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat n->nlmsg_flags |= NLM_F_ACK; 303dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 304dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat status = sendmsg(rtnl->fd, &msg, 0); 305dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 306dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (status < 0) { 307dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat perror("Cannot talk to rtnetlink"); 308dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 309dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 310dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 311dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset(buf,0,sizeof(buf)); 312dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 313dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat iov.iov_base = buf; 314dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 315dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat while (1) { 316dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat iov.iov_len = sizeof(buf); 317dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat status = recvmsg(rtnl->fd, &msg, 0); 318dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 319dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (status < 0) { 320dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (errno == EINTR || errno == EAGAIN) 321dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat continue; 322dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "netlink receive error %s (%d)\n", 323dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strerror(errno), errno); 324dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 325dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 326dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (status == 0) { 327dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "EOF on netlink\n"); 328dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 329dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 330dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (msg.msg_namelen != sizeof(nladdr)) { 331dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "sender address length == %d\n", msg.msg_namelen); 332dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat exit(1); 333dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 334dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) { 335dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int err; 336dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int len = h->nlmsg_len; 337dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int l = len - sizeof(*h); 338dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 339dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (l<0 || len>status) { 340dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (msg.msg_flags & MSG_TRUNC) { 341dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Truncated message\n"); 342dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 343dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 344dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "!!!malformed message: len=%d\n", len); 345dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat exit(1); 346dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 347dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 348dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (nladdr.nl_pid != peer || 349dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat h->nlmsg_pid != rtnl->local.nl_pid || 350dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat h->nlmsg_seq != seq) { 351dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (junk) { 352dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat err = junk(&nladdr, h, jarg); 353dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (err < 0) 354dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return err; 355dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 356dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat /* Don't forget to skip that message. */ 357dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat status -= NLMSG_ALIGN(len); 358dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); 359dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat continue; 360dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 361dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 362dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (h->nlmsg_type == NLMSG_ERROR) { 363dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); 364dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (l < sizeof(struct nlmsgerr)) { 365dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "ERROR truncated\n"); 366dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else { 367dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat errno = -err->error; 368dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (errno == 0) { 369dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (answer) 370dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memcpy(answer, h, h->nlmsg_len); 371dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 372dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 373dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat perror("RTNETLINK answers"); 374dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 375dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 376dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 377dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (answer) { 378dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memcpy(answer, h, h->nlmsg_len); 379dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 380dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 381dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 382dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Unexpected reply!!!\n"); 383dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 384dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat status -= NLMSG_ALIGN(len); 385dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); 386dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 387dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (msg.msg_flags & MSG_TRUNC) { 388dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Message truncated\n"); 389dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat continue; 390dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 391dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (status) { 392dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "!!!Remnant of size %d\n", status); 393dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat exit(1); 394dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 395dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 396dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 397dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 398dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint rtnl_listen(struct rtnl_handle *rtnl, 399dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat rtnl_filter_t handler, 400dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat void *jarg) 401dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 402dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int status; 403dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct nlmsghdr *h; 404dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct sockaddr_nl nladdr; 405dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct iovec iov; 406dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct msghdr msg = { 407dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .msg_name = &nladdr, 408dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .msg_namelen = sizeof(nladdr), 409dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .msg_iov = &iov, 410dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .msg_iovlen = 1, 411dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat }; 412dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char buf[8192]; 413dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 414dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset(&nladdr, 0, sizeof(nladdr)); 415dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat nladdr.nl_family = AF_NETLINK; 416dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat nladdr.nl_pid = 0; 417dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat nladdr.nl_groups = 0; 418dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 419dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat iov.iov_base = buf; 420dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat while (1) { 421dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat iov.iov_len = sizeof(buf); 422dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat status = recvmsg(rtnl->fd, &msg, 0); 423dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 424dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (status < 0) { 425dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (errno == EINTR || errno == EAGAIN) 426dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat continue; 427dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "netlink receive error %s (%d)\n", 428dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strerror(errno), errno); 429dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (errno == ENOBUFS) 430dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat continue; 431dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 432dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 433dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (status == 0) { 434dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "EOF on netlink\n"); 435dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 436dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 437dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (msg.msg_namelen != sizeof(nladdr)) { 438dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Sender address length == %d\n", msg.msg_namelen); 439dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat exit(1); 440dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 441dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) { 442dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int err; 443dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int len = h->nlmsg_len; 444dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int l = len - sizeof(*h); 445dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 446dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (l<0 || len>status) { 447dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (msg.msg_flags & MSG_TRUNC) { 448dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Truncated message\n"); 449dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 450dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 451dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "!!!malformed message: len=%d\n", len); 452dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat exit(1); 453dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 454dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 455dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat err = handler(&nladdr, h, jarg); 456dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (err < 0) 457dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return err; 458dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 459dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat status -= NLMSG_ALIGN(len); 460dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); 461dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 462dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (msg.msg_flags & MSG_TRUNC) { 463dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Message truncated\n"); 464dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat continue; 465dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 466dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (status) { 467dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "!!!Remnant of size %d\n", status); 468dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat exit(1); 469dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 470dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 471dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 472dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 473dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint rtnl_from_file(FILE *rtnl, rtnl_filter_t handler, 474dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat void *jarg) 475dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 476dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int status; 477dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct sockaddr_nl nladdr; 478dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char buf[8192]; 479dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct nlmsghdr *h = (void*)buf; 480dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 481dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset(&nladdr, 0, sizeof(nladdr)); 482dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat nladdr.nl_family = AF_NETLINK; 483dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat nladdr.nl_pid = 0; 484dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat nladdr.nl_groups = 0; 485dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 486dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat while (1) { 487dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int err, len, type; 488dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int l; 489dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 490dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat status = fread(&buf, 1, sizeof(*h), rtnl); 491dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 492dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (status < 0) { 493dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (errno == EINTR) 494dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat continue; 495dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat perror("rtnl_from_file: fread"); 496dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 497dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 498dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (status == 0) 499dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 500dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 501dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat len = h->nlmsg_len; 502dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat type= h->nlmsg_type; 503dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat l = len - sizeof(*h); 504dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 505dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (l<0 || len>sizeof(buf)) { 506dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "!!!malformed message: len=%d @%lu\n", 507dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat len, ftell(rtnl)); 508dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 509dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 510dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 511dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat status = fread(NLMSG_DATA(h), 1, NLMSG_ALIGN(l), rtnl); 512dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 513dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (status < 0) { 514dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat perror("rtnl_from_file: fread"); 515dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 516dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 517dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (status < l) { 518dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "rtnl-from_file: truncated message\n"); 519dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 520dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 521dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 522dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat err = handler(&nladdr, h, jarg); 523dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (err < 0) 524dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return err; 525dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 526dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 527dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 528dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data) 529dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 530dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int len = RTA_LENGTH(4); 531dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct rtattr *rta; 532dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) { 533dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr,"addattr32: Error! max allowed bound %d exceeded\n",maxlen); 534dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 535dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 536dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat rta = NLMSG_TAIL(n); 537dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat rta->rta_type = type; 538dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat rta->rta_len = len; 539dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memcpy(RTA_DATA(rta), &data, 4); 540dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len; 541dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 542dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 543dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 544dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, 545dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int alen) 546dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 547dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int len = RTA_LENGTH(alen); 548dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct rtattr *rta; 549dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 550dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) { 551dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",maxlen); 552dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 553dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 554dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat rta = NLMSG_TAIL(n); 555dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat rta->rta_type = type; 556dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat rta->rta_len = len; 557dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memcpy(RTA_DATA(rta), data, alen); 558dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); 559dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 560dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 561dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 562dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len) 563dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 564dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len) > maxlen) { 565dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "addraw_l ERROR: message exceeded bound of %d\n",maxlen); 566dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 567dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 568dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 569dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memcpy(NLMSG_TAIL(n), data, len); 570dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset((void *) NLMSG_TAIL(n) + len, 0, NLMSG_ALIGN(len) - len); 571dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len); 572dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 573dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 574dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 575dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstruct rtattr *addattr_nest(struct nlmsghdr *n, int maxlen, int type) 576dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 577dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct rtattr *nest = NLMSG_TAIL(n); 578dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 579dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr_l(n, maxlen, type, NULL, 0); 580dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return nest; 581dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 582dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 583dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest) 584dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 585dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat nest->rta_len = (void *)NLMSG_TAIL(n) - (void *)nest; 586dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return n->nlmsg_len; 587dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 588dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 589dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstruct rtattr *addattr_nest_compat(struct nlmsghdr *n, int maxlen, int type, 590dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat const void *data, int len) 591dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 592dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct rtattr *start = NLMSG_TAIL(n); 593dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 594dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr_l(n, maxlen, type, data, len); 595dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr_nest(n, maxlen, type); 596dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return start; 597dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 598dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 599dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint addattr_nest_compat_end(struct nlmsghdr *n, struct rtattr *start) 600dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 601dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct rtattr *nest = (void *)start + NLMSG_ALIGN(start->rta_len); 602dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 603dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat start->rta_len = (void *)NLMSG_TAIL(n) - (void *)start; 604dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr_nest_end(n, nest); 605dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return n->nlmsg_len; 606dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 607dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 608dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data) 609dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 610dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int len = RTA_LENGTH(4); 611dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct rtattr *subrta; 612dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 613dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (RTA_ALIGN(rta->rta_len) + len > maxlen) { 614dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr,"rta_addattr32: Error! max allowed bound %d exceeded\n",maxlen); 615dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 616dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 617dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len)); 618dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat subrta->rta_type = type; 619dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat subrta->rta_len = len; 620dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memcpy(RTA_DATA(subrta), &data, 4); 621dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len; 622dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 623dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 624dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 625dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint rta_addattr_l(struct rtattr *rta, int maxlen, int type, 626dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat const void *data, int alen) 627dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 628dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct rtattr *subrta; 629dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int len = RTA_LENGTH(alen); 630dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 631dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (RTA_ALIGN(rta->rta_len) + RTA_ALIGN(len) > maxlen) { 632dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr,"rta_addattr_l: Error! max allowed bound %d exceeded\n",maxlen); 633dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 634dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 635dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len)); 636dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat subrta->rta_type = type; 637dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat subrta->rta_len = len; 638dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memcpy(RTA_DATA(subrta), data, alen); 639dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat rta->rta_len = NLMSG_ALIGN(rta->rta_len) + RTA_ALIGN(len); 640dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 641dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 642dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 643dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) 644dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 645dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); 646dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat while (RTA_OK(rta, len)) { 6471a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt if ((rta->rta_type <= max) && (!tb[rta->rta_type])) 648dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tb[rta->rta_type] = rta; 649dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat rta = RTA_NEXT(rta,len); 650dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 651dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (len) 652dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len); 653dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 654dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 655dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 656dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len) 657dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 658dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int i = 0; 659dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 660dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset(tb, 0, sizeof(struct rtattr *) * max); 661dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat while (RTA_OK(rta, len)) { 662dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (rta->rta_type <= max && i < max) 663dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tb[i++] = rta; 664dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat rta = RTA_NEXT(rta,len); 665dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 666dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (len) 667dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len); 668dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return i; 669dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 670dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 671dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rta, 672dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int len) 673dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 674dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (RTA_PAYLOAD(rta) < len) 675dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 676dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (RTA_PAYLOAD(rta) >= RTA_ALIGN(len) + sizeof(struct rtattr)) { 677dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat rta = RTA_DATA(rta) + RTA_ALIGN(len); 678dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return parse_rtattr_nested(tb, max, rta); 679dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 680dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); 681dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 682dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 683