libnetlink.c revision b16621cafd599499fdbaa79236266d72a53106bb
1aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger/* 2aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger * libnetlink.c RTnetlink service routines. 3aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger * 4aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger * This program is free software; you can redistribute it and/or 5aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger * modify it under the terms of the GNU General Public License 6aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger * as published by the Free Software Foundation; either version 7aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger * 2 of the License, or (at your option) any later version. 8aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger * 9aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 10aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger * 11aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger */ 12aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 13aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <stdio.h> 14aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <stdlib.h> 15aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <unistd.h> 16aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <syslog.h> 17aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <fcntl.h> 18aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <net/if_arp.h> 19aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <sys/socket.h> 20aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <netinet/in.h> 21aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <string.h> 22aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <errno.h> 23aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <time.h> 24aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <sys/uio.h> 25aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 26aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include "libnetlink.h" 27aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 28aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingervoid rtnl_close(struct rtnl_handle *rth) 29aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 303bfa73ff99291d872f6d0e0284ee416e880088b6Stephen Hemminger if (rth->fd >= 0) { 313bfa73ff99291d872f6d0e0284ee416e880088b6Stephen Hemminger close(rth->fd); 323bfa73ff99291d872f6d0e0284ee416e880088b6Stephen Hemminger rth->fd = -1; 333bfa73ff99291d872f6d0e0284ee416e880088b6Stephen Hemminger } 34aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 35aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 368ed63ab1f1283b2c63355fb7c1e80abead4b9399shemmingerint rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions, 378ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger int protocol) 38aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 39f332d169246447bd5e258ac03d5ee840a70adb1eshemminger socklen_t addr_len; 40007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger int sndbuf = 32768; 41007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger int rcvbuf = 32768; 42aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 43b16621cafd599499fdbaa79236266d72a53106bbStephen Hemminger memset(rth, 0, sizeof(*rth)); 44aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 45c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger rth->fd = socket(AF_NETLINK, SOCK_RAW, protocol); 46aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (rth->fd < 0) { 47aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("Cannot open netlink socket"); 48aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 49aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 50aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 51007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger if (setsockopt(rth->fd,SOL_SOCKET,SO_SNDBUF,&sndbuf,sizeof(sndbuf)) < 0) { 52007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger perror("SO_SNDBUF"); 53007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger return -1; 54007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger } 55007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger 56007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger if (setsockopt(rth->fd,SOL_SOCKET,SO_RCVBUF,&rcvbuf,sizeof(rcvbuf)) < 0) { 57007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger perror("SO_RCVBUF"); 58007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger return -1; 59007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger } 60007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger 61aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&rth->local, 0, sizeof(rth->local)); 62aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rth->local.nl_family = AF_NETLINK; 63aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rth->local.nl_groups = subscriptions; 64aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 65aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) { 66aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("Cannot bind netlink socket"); 67aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 68aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 69aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger addr_len = sizeof(rth->local); 70aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) { 71aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("Cannot getsockname"); 72aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 73aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 74aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (addr_len != sizeof(rth->local)) { 75aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Wrong address length %d\n", addr_len); 76aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 77aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 78aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (rth->local.nl_family != AF_NETLINK) { 79aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Wrong address family %d\n", rth->local.nl_family); 80aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 81aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 82aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rth->seq = time(NULL); 83aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 84aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 85aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 86c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemmingerint rtnl_open(struct rtnl_handle *rth, unsigned subscriptions) 87c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger{ 88c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger return rtnl_open_byproto(rth, subscriptions, NETLINK_ROUTE); 89c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger} 90c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger 91aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type) 92aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 93aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct { 94aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr nlh; 95aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct rtgenmsg g; 96aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } req; 97aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 98aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 99aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&nladdr, 0, sizeof(nladdr)); 100aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_family = AF_NETLINK; 101aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 1028ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger memset(&req, 0, sizeof(req)); 103aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger req.nlh.nlmsg_len = sizeof(req); 104aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger req.nlh.nlmsg_type = type; 105aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; 106aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger req.nlh.nlmsg_pid = 0; 107aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger req.nlh.nlmsg_seq = rth->dump = ++rth->seq; 108aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger req.g.rtgen_family = family; 109aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 1108ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger return sendto(rth->fd, (void*)&req, sizeof(req), 0, 1118ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger (struct sockaddr*)&nladdr, sizeof(nladdr)); 112aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 113aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 1146dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemmingerint rtnl_send(struct rtnl_handle *rth, const char *buf, int len) 115aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 116aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 117aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 118aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&nladdr, 0, sizeof(nladdr)); 119aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_family = AF_NETLINK; 120aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 121aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return sendto(rth->fd, buf, len, 0, (struct sockaddr*)&nladdr, sizeof(nladdr)); 122aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 123aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 124aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) 125aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 126aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr nlh; 127aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 1288ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger struct iovec iov[2] = { 1298ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger { .iov_base = &nlh, .iov_len = sizeof(nlh) }, 1308ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger { .iov_base = req, .iov_len = len } 1318ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger }; 132aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct msghdr msg = { 1338ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_name = &nladdr, 1348ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_namelen = sizeof(nladdr), 1358ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_iov = iov, 1368ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_iovlen = 2, 137aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger }; 138aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 139aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&nladdr, 0, sizeof(nladdr)); 140aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_family = AF_NETLINK; 141aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 142aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nlh.nlmsg_len = NLMSG_LENGTH(len); 143aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nlh.nlmsg_type = type; 144aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; 145aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nlh.nlmsg_pid = 0; 146aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nlh.nlmsg_seq = rth->dump = ++rth->seq; 147aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 148aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return sendmsg(rth->fd, &msg, 0); 149aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 150aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 151aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rtnl_dump_filter(struct rtnl_handle *rth, 1526dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemminger rtnl_filter_t filter, 153aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger void *arg1, 1546dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemminger rtnl_filter_t junk, 155aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger void *arg2) 156aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 157aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 1588ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger struct iovec iov; 1598ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger struct msghdr msg = { 1608ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_name = &nladdr, 1618ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_namelen = sizeof(nladdr), 1628ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_iov = &iov, 1638ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_iovlen = 1, 1648ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger }; 1658ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger char buf[16384]; 166aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 1678ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger iov.iov_base = buf; 168aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (1) { 169aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int status; 170aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr *h; 171aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 1728ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger iov.iov_len = sizeof(buf); 173aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = recvmsg(rth->fd, &msg, 0); 174aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 175aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 176aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (errno == EINTR) 177aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 178aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("OVERRUN"); 179aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 180aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 1818ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger 182aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status == 0) { 183aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "EOF on netlink\n"); 184aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 185aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 186aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 187aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger h = (struct nlmsghdr*)buf; 188aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (NLMSG_OK(h, status)) { 189aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int err; 190aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 19110f57ef1ab9b4fca639cb2383bc04616fafba5eforg[shemminger]!shemminger if (nladdr.nl_pid != 0 || 19210f57ef1ab9b4fca639cb2383bc04616fafba5eforg[shemminger]!shemminger h->nlmsg_pid != rth->local.nl_pid || 193aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger h->nlmsg_seq != rth->dump) { 194aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (junk) { 195aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger err = junk(&nladdr, h, arg2); 196aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (err < 0) 197aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return err; 198aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 199aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger goto skip_it; 200aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 201aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 202aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (h->nlmsg_type == NLMSG_DONE) 203aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 204aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (h->nlmsg_type == NLMSG_ERROR) { 205aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); 206aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) { 207aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "ERROR truncated\n"); 208aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } else { 209aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger errno = -err->error; 210aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("RTNETLINK answers"); 211aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 212aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 213aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 214aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger err = filter(&nladdr, h, arg1); 215aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (err < 0) 216aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return err; 217aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 218aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerskip_it: 219aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger h = NLMSG_NEXT(h, status); 220aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 221aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_flags & MSG_TRUNC) { 222aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Message truncated\n"); 223aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 224aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 225aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status) { 226aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!Remnant of size %d\n", status); 227aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 228aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 229aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 230aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 231aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 232aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, 233aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger unsigned groups, struct nlmsghdr *answer, 2346dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemminger rtnl_filter_t junk, 235aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger void *jarg) 236aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 237aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int status; 238aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger unsigned seq; 239aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr *h; 240aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 241fb2297599de1fb7447a050e16e0179f739460473shemminger struct iovec iov = { 242fb2297599de1fb7447a050e16e0179f739460473shemminger .iov_base = (void*) n, 243fb2297599de1fb7447a050e16e0179f739460473shemminger .iov_len = n->nlmsg_len 244fb2297599de1fb7447a050e16e0179f739460473shemminger }; 245aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct msghdr msg = { 2468ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_name = &nladdr, 2478ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_namelen = sizeof(nladdr), 2488ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_iov = &iov, 2498ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_iovlen = 1, 250aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger }; 2518ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger char buf[16384]; 252aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 253aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&nladdr, 0, sizeof(nladdr)); 254aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_family = AF_NETLINK; 255aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_pid = peer; 256aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_groups = groups; 257aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 258aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger n->nlmsg_seq = seq = ++rtnl->seq; 259007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger 260aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (answer == NULL) 261aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger n->nlmsg_flags |= NLM_F_ACK; 262aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 263aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = sendmsg(rtnl->fd, &msg, 0); 264aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 265aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 266aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("Cannot talk to rtnetlink"); 267aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 268aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 269aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 270007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger memset(buf,0,sizeof(buf)); 271007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger 272aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger iov.iov_base = buf; 273aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 274aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (1) { 275aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger iov.iov_len = sizeof(buf); 276aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = recvmsg(rtnl->fd, &msg, 0); 277aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 278aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 279aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (errno == EINTR) 280aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 281aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("OVERRUN"); 282aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 283aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 284aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status == 0) { 285aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "EOF on netlink\n"); 286aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 287aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 288aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_namelen != sizeof(nladdr)) { 289aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "sender address length == %d\n", msg.msg_namelen); 290aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 291aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 292aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) { 293aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int err; 294aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = h->nlmsg_len; 295aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int l = len - sizeof(*h); 296aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 297aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (l<0 || len>status) { 298aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_flags & MSG_TRUNC) { 299aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Truncated message\n"); 300aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 301aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 302aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!malformed message: len=%d\n", len); 303aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 304aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 305aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 30610f57ef1ab9b4fca639cb2383bc04616fafba5eforg[shemminger]!shemminger if (nladdr.nl_pid != peer || 30710f57ef1ab9b4fca639cb2383bc04616fafba5eforg[shemminger]!shemminger h->nlmsg_pid != rtnl->local.nl_pid || 308aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger h->nlmsg_seq != seq) { 309aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (junk) { 310aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger err = junk(&nladdr, h, jarg); 311aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (err < 0) 312aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return err; 313aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 3144cca16f20e92a97399d5814fc810af66ce0581d8shemminger /* Don't forget to skip that message. */ 3154cca16f20e92a97399d5814fc810af66ce0581d8shemminger status -= NLMSG_ALIGN(len); 3164cca16f20e92a97399d5814fc810af66ce0581d8shemminger h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); 317aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 318aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 319aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 320aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (h->nlmsg_type == NLMSG_ERROR) { 321aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); 322aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (l < sizeof(struct nlmsgerr)) { 323aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "ERROR truncated\n"); 324aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } else { 325aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger errno = -err->error; 326aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (errno == 0) { 327aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (answer) 328aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memcpy(answer, h, h->nlmsg_len); 329aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 330aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 331aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("RTNETLINK answers"); 332aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 333aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 334aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 335aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (answer) { 336aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memcpy(answer, h, h->nlmsg_len); 337aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 338aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 339aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 340aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Unexpected reply!!!\n"); 341aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 342aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status -= NLMSG_ALIGN(len); 343aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); 344aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 345aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_flags & MSG_TRUNC) { 346aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Message truncated\n"); 347aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 348aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 349aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status) { 350aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!Remnant of size %d\n", status); 351aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 352aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 353aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 354aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 355aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 3568ed63ab1f1283b2c63355fb7c1e80abead4b9399shemmingerint rtnl_listen(struct rtnl_handle *rtnl, 3576dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemminger rtnl_filter_t handler, 3586dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemminger void *jarg) 359aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 360aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int status; 361aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr *h; 362aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 363aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct iovec iov; 364aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct msghdr msg = { 3658ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_name = &nladdr, 3668ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_namelen = sizeof(nladdr), 3678ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_iov = &iov, 3688ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_iovlen = 1, 369aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger }; 3708ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger char buf[8192]; 371aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 372aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&nladdr, 0, sizeof(nladdr)); 373aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_family = AF_NETLINK; 374aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_pid = 0; 375aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_groups = 0; 376aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 377aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger iov.iov_base = buf; 378aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (1) { 379aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger iov.iov_len = sizeof(buf); 380aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = recvmsg(rtnl->fd, &msg, 0); 381aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 382aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 383aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (errno == EINTR) 384aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 385aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("OVERRUN"); 386aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 387aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 388aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status == 0) { 389aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "EOF on netlink\n"); 390aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 391aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 392aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_namelen != sizeof(nladdr)) { 393aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Sender address length == %d\n", msg.msg_namelen); 394aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 395aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 396aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) { 397aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int err; 398aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = h->nlmsg_len; 399aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int l = len - sizeof(*h); 400aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 401aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (l<0 || len>status) { 402aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_flags & MSG_TRUNC) { 403aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Truncated message\n"); 404aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 405aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 406aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!malformed message: len=%d\n", len); 407aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 408aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 409aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 410aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger err = handler(&nladdr, h, jarg); 411aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (err < 0) 412aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return err; 413aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 414aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status -= NLMSG_ALIGN(len); 415aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); 416aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 417aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_flags & MSG_TRUNC) { 418aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Message truncated\n"); 419aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 420aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 421aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status) { 422aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!Remnant of size %d\n", status); 423aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 424aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 425aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 426aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 427aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 4286dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemmingerint rtnl_from_file(FILE *rtnl, rtnl_filter_t handler, 4296dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemminger void *jarg) 430aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 431aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int status; 432aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 433aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger char buf[8192]; 434aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr *h = (void*)buf; 435aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 436aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&nladdr, 0, sizeof(nladdr)); 437aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_family = AF_NETLINK; 438aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_pid = 0; 439aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_groups = 0; 440aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 441aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (1) { 442aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int err, len, type; 443aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int l; 444aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 445aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = fread(&buf, 1, sizeof(*h), rtnl); 446aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 447aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 448aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (errno == EINTR) 449aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 450aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("rtnl_from_file: fread"); 451aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 452aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 453aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status == 0) 454aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 455aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 456aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger len = h->nlmsg_len; 457aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger type= h->nlmsg_type; 458aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger l = len - sizeof(*h); 459aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 460aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (l<0 || len>sizeof(buf)) { 461aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!malformed message: len=%d @%lu\n", 462aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger len, ftell(rtnl)); 463aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 464aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 465aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 466aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = fread(NLMSG_DATA(h), 1, NLMSG_ALIGN(l), rtnl); 467aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 468aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 469aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("rtnl_from_file: fread"); 470aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 471aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 472aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < l) { 473aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "rtnl-from_file: truncated message\n"); 474aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 475aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 476aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 477aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger err = handler(&nladdr, h, jarg); 478aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (err < 0) 479aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return err; 480aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 481aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 482aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 483aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data) 484aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 485aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = RTA_LENGTH(4); 486aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct rtattr *rta; 487007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) { 488007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger fprintf(stderr,"addattr32: Error! max allowed bound %d exceeded\n",maxlen); 489aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 490007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger } 49107f9436201eba2f75e6c480f5b16316b3bf977fcn); rta = NLMSG_TAIL(n); 492aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta->rta_type = type; 493aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta->rta_len = len; 494aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memcpy(RTA_DATA(rta), &data, 4); 495aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len; 496aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 497aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 498aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 4998ed63ab1f1283b2c63355fb7c1e80abead4b9399shemmingerint addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, 5006dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemminger int alen) 501aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 502aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = RTA_LENGTH(alen); 503aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct rtattr *rta; 504aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 5053dabdbb3da5ab7e9df8bf561602d681db26d8982net[shemminger]!shemminger if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) { 506007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",maxlen); 507aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 508007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger } 50907f9436201eba2f75e6c480f5b16316b3bf977fcn); rta = NLMSG_TAIL(n); 510aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta->rta_type = type; 511aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta->rta_len = len; 512aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memcpy(RTA_DATA(rta), data, alen); 5133dabdbb3da5ab7e9df8bf561602d681db26d8982net[shemminger]!shemminger n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); 514aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 515aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 516aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 51707f9436201eba2f75e6c480f5b16316b3bf977fcstruct nlmsghdr *n, int maxlen, const void *data, int len)int addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len) 51807f9436201eba2f75e6c480f5b16316b3bf977fcNLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len) > maxlen) {{ 51907f9436201eba2f75e6c480f5b16316b3bf977fcstderr, "addraw_l ERROR: message exceeded bound of %d\n",maxlen); if (NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len) > maxlen) { 52007f9436201eba2f75e6c480f5b16316b3bf977fcNLMSG_TAIL(n), data, len); fprintf(stderr, "addraw_l ERROR: message exceeded bound of %d\n",maxlen); 52107f9436201eba2f75e6c480f5b16316b3bf977fc(void *) NLMSG_TAIL(n) + len, return -1; 52207f9436201eba2f75e6c480f5b16316b3bf977fcn->nlmsg_len) + NLMSG_ALIGN(len); } 523aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 524aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memcpy(NLMSG_TAIL(n), data, len); 525aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset((void *) NLMSG_TAIL(n) + len, 0, NLMSG_ALIGN(len) - len); 526aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len); 527aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 528007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger} 529007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger 530aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data) 531007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger{ 532aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = RTA_LENGTH(4); 533aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct rtattr *subrta; 534aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 535aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (RTA_ALIGN(rta->rta_len) + len > maxlen) { 536aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr,"rta_addattr32: Error! max allowed bound %d exceeded\n",maxlen); 537aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 538aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 539aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len)); 5408ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger subrta->rta_type = type; 5416dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemminger subrta->rta_len = len; 542aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memcpy(RTA_DATA(subrta), &data, 4); 543aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len; 544aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 545aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 5463dabdbb3da5ab7e9df8bf561602d681db26d8982net[shemminger]!shemminger 547007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemmingerint rta_addattr_l(struct rtattr *rta, int maxlen, int type, 548aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger const void *data, int alen) 549007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger{ 550aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct rtattr *subrta; 551aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = RTA_LENGTH(alen); 552aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 553aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (RTA_ALIGN(rta->rta_len) + RTA_ALIGN(len) > maxlen) { 5543dabdbb3da5ab7e9df8bf561602d681db26d8982net[shemminger]!shemminger fprintf(stderr,"rta_addattr_l: Error! max allowed bound %d exceeded\n",maxlen); 555aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 556aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 557aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len)); 558aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger subrta->rta_type = type; 559aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger subrta->rta_len = len; 560175e2440df5be09b0a4c134cad958a49f7bfb9d9osdl.net!shemminger memcpy(RTA_DATA(subrta), data, alen); 561aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta->rta_len = NLMSG_ALIGN(rta->rta_len) + RTA_ALIGN(len); 562aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 563aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 564aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 565aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) 566aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 567aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); 568aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (RTA_OK(rta, len)) { 569aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (rta->rta_type <= max) 570c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger tb[rta->rta_type] = rta; 571c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger rta = RTA_NEXT(rta,len); 572c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger } 573c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger if (len) 574175e2440df5be09b0a4c134cad958a49f7bfb9d9osdl.net!shemminger fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len); 575175e2440df5be09b0a4c134cad958a49f7bfb9d9osdl.net!shemminger return 0; 576c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger} 577175e2440df5be09b0a4c134cad958a49f7bfb9d9osdl.net!shemminger 578c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemmingerint parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len) 579c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger{ 580c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger int i = 0; 581c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger 582c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger memset(tb, 0, sizeof(struct rtattr *) * max); 583c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger while (RTA_OK(rta, len)) { 584c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger if (rta->rta_type <= max && i < max) 585 tb[i++] = rta; 586 rta = RTA_NEXT(rta,len); 587 } 588 if (len) 589 fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len); 590 return i; 591} 592