libnetlink.c revision 3dabdbb3da5ab7e9df8bf561602d681db26d8982
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{ 30aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger close(rth->fd); 31aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 32aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 33c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemmingerint rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions, int protocol) 34aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 35aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int addr_len; 36007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger int sndbuf = 32768; 37007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger int rcvbuf = 32768; 38aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 39aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(rth, 0, sizeof(rth)); 40aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 41c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger rth->fd = socket(AF_NETLINK, SOCK_RAW, protocol); 42aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (rth->fd < 0) { 43aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("Cannot open netlink socket"); 44aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 45aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 46aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 47007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger if (setsockopt(rth->fd,SOL_SOCKET,SO_SNDBUF,&sndbuf,sizeof(sndbuf)) < 0) { 48007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger perror("SO_SNDBUF"); 49007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger return -1; 50007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger } 51007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger 52007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger if (setsockopt(rth->fd,SOL_SOCKET,SO_RCVBUF,&rcvbuf,sizeof(rcvbuf)) < 0) { 53007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger perror("SO_RCVBUF"); 54007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger return -1; 55007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger } 56007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger 57aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&rth->local, 0, sizeof(rth->local)); 58aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rth->local.nl_family = AF_NETLINK; 59aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rth->local.nl_groups = subscriptions; 60aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 61aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) { 62aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("Cannot bind netlink socket"); 63aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 64aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 65aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger addr_len = sizeof(rth->local); 66aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) { 67aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("Cannot getsockname"); 68aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 69aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 70aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (addr_len != sizeof(rth->local)) { 71aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Wrong address length %d\n", addr_len); 72aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 73aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 74aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (rth->local.nl_family != AF_NETLINK) { 75aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Wrong address family %d\n", rth->local.nl_family); 76aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 77aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 78aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rth->seq = time(NULL); 79aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 80aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 81aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 82c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemmingerint rtnl_open(struct rtnl_handle *rth, unsigned subscriptions) 83c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger{ 84c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger return rtnl_open_byproto(rth, subscriptions, NETLINK_ROUTE); 85c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger} 86c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger 87aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type) 88aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 89aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct { 90aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr nlh; 91aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct rtgenmsg g; 92aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } req; 93aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 94aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 95aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&nladdr, 0, sizeof(nladdr)); 96aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_family = AF_NETLINK; 97aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 98aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger req.nlh.nlmsg_len = sizeof(req); 99aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger req.nlh.nlmsg_type = type; 100aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; 101aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger req.nlh.nlmsg_pid = 0; 102aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger req.nlh.nlmsg_seq = rth->dump = ++rth->seq; 103aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger req.g.rtgen_family = family; 104aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 105aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return sendto(rth->fd, (void*)&req, sizeof(req), 0, (struct sockaddr*)&nladdr, sizeof(nladdr)); 106aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 107aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 1086dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemmingerint rtnl_send(struct rtnl_handle *rth, const char *buf, int len) 109aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 110aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 111aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 112aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&nladdr, 0, sizeof(nladdr)); 113aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_family = AF_NETLINK; 114aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 115aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return sendto(rth->fd, buf, len, 0, (struct sockaddr*)&nladdr, sizeof(nladdr)); 116aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 117aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 118aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) 119aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 120aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr nlh; 121aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 122aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct iovec iov[2] = { { &nlh, sizeof(nlh) }, { req, len } }; 123aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct msghdr msg = { 124aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger (void*)&nladdr, sizeof(nladdr), 125aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger iov, 2, 126aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger NULL, 0, 127aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 0 128aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger }; 129aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 130aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&nladdr, 0, sizeof(nladdr)); 131aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_family = AF_NETLINK; 132aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 133aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nlh.nlmsg_len = NLMSG_LENGTH(len); 134aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nlh.nlmsg_type = type; 135aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; 136aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nlh.nlmsg_pid = 0; 137aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nlh.nlmsg_seq = rth->dump = ++rth->seq; 138aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 139aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return sendmsg(rth->fd, &msg, 0); 140aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 141aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 142aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rtnl_dump_filter(struct rtnl_handle *rth, 1436dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemminger rtnl_filter_t filter, 144aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger void *arg1, 1456dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemminger rtnl_filter_t junk, 146aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger void *arg2) 147aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 148007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger char buf[16384]; 149aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 150aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct iovec iov = { buf, sizeof(buf) }; 151aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 152aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (1) { 153aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int status; 154aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr *h; 155aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 156aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct msghdr msg = { 157aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger (void*)&nladdr, sizeof(nladdr), 158aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger &iov, 1, 159aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger NULL, 0, 160aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 0 161aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger }; 162aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 163aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = recvmsg(rth->fd, &msg, 0); 164aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 165aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 166aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (errno == EINTR) 167aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 168aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("OVERRUN"); 169aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 170aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 171aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status == 0) { 172aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "EOF on netlink\n"); 173aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 174aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 175aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_namelen != sizeof(nladdr)) { 176aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "sender address length == %d\n", msg.msg_namelen); 177aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 178aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 179aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 180aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger h = (struct nlmsghdr*)buf; 181aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (NLMSG_OK(h, status)) { 182aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int err; 183aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 18410f57ef1ab9b4fca639cb2383bc04616fafba5eforg[shemminger]!shemminger if (nladdr.nl_pid != 0 || 18510f57ef1ab9b4fca639cb2383bc04616fafba5eforg[shemminger]!shemminger h->nlmsg_pid != rth->local.nl_pid || 186aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger h->nlmsg_seq != rth->dump) { 187aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (junk) { 188aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger err = junk(&nladdr, h, arg2); 189aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (err < 0) 190aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return err; 191aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 192aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger goto skip_it; 193aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 194aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 195aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (h->nlmsg_type == NLMSG_DONE) 196aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 197aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (h->nlmsg_type == NLMSG_ERROR) { 198aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); 199aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) { 200aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "ERROR truncated\n"); 201aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } else { 202aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger errno = -err->error; 203aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("RTNETLINK answers"); 204aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 205aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 206aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 207aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger err = filter(&nladdr, h, arg1); 208aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (err < 0) 209aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return err; 210aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 211aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerskip_it: 212aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger h = NLMSG_NEXT(h, status); 213aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 214aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_flags & MSG_TRUNC) { 215aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Message truncated\n"); 216aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 217aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 218aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status) { 219aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!Remnant of size %d\n", status); 220aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 221aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 222aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 223aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 224aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 225aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, 226aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger unsigned groups, struct nlmsghdr *answer, 2276dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemminger rtnl_filter_t junk, 228aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger void *jarg) 229aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 230aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int status; 231aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger unsigned seq; 232aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr *h; 233aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 234aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct iovec iov = { (void*)n, n->nlmsg_len }; 235007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger char buf[16384]; 236aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct msghdr msg = { 237aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger (void*)&nladdr, sizeof(nladdr), 238aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger &iov, 1, 239aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger NULL, 0, 240aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 0 241aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger }; 242aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 243aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&nladdr, 0, sizeof(nladdr)); 244aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_family = AF_NETLINK; 245aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_pid = peer; 246aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_groups = groups; 247aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 248aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger n->nlmsg_seq = seq = ++rtnl->seq; 249007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger 250aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (answer == NULL) 251aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger n->nlmsg_flags |= NLM_F_ACK; 252aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 253aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = sendmsg(rtnl->fd, &msg, 0); 254aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 255aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 256aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("Cannot talk to rtnetlink"); 257aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 258aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 259aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 260007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger memset(buf,0,sizeof(buf)); 261007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger 262aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger iov.iov_base = buf; 263aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 264aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (1) { 265aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger iov.iov_len = sizeof(buf); 266aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = recvmsg(rtnl->fd, &msg, 0); 267aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 268aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 269aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (errno == EINTR) 270aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 271aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("OVERRUN"); 272aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 273aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 274aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status == 0) { 275aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "EOF on netlink\n"); 276aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 277aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 278aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_namelen != sizeof(nladdr)) { 279aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "sender address length == %d\n", msg.msg_namelen); 280aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 281aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 282aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) { 283aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int err; 284aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = h->nlmsg_len; 285aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int l = len - sizeof(*h); 286aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 287aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (l<0 || len>status) { 288aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_flags & MSG_TRUNC) { 289aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Truncated message\n"); 290aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 291aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 292aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!malformed message: len=%d\n", len); 293aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 294aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 295aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 29610f57ef1ab9b4fca639cb2383bc04616fafba5eforg[shemminger]!shemminger if (nladdr.nl_pid != peer || 29710f57ef1ab9b4fca639cb2383bc04616fafba5eforg[shemminger]!shemminger h->nlmsg_pid != rtnl->local.nl_pid || 298aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger h->nlmsg_seq != seq) { 299aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (junk) { 300aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger err = junk(&nladdr, h, jarg); 301aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (err < 0) 302aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return err; 303aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 304aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 305aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 306aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 307aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (h->nlmsg_type == NLMSG_ERROR) { 308aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); 309aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (l < sizeof(struct nlmsgerr)) { 310aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "ERROR truncated\n"); 311aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } else { 312aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger errno = -err->error; 313aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (errno == 0) { 314aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (answer) 315aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memcpy(answer, h, h->nlmsg_len); 316aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 317aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 318aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("RTNETLINK answers"); 319aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 320aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 321aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 322aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (answer) { 323aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memcpy(answer, h, h->nlmsg_len); 324aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 325aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 326aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 327aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Unexpected reply!!!\n"); 328aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 329aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status -= NLMSG_ALIGN(len); 330aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); 331aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 332aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_flags & MSG_TRUNC) { 333aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Message truncated\n"); 334aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 335aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 336aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status) { 337aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!Remnant of size %d\n", status); 338aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 339aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 340aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 341aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 342aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 343aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rtnl_listen(struct rtnl_handle *rtnl, 3446dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemminger rtnl_filter_t handler, 3456dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemminger void *jarg) 346aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 347aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int status; 348aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr *h; 349aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 350aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct iovec iov; 351aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger char buf[8192]; 352aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct msghdr msg = { 353aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger (void*)&nladdr, sizeof(nladdr), 354aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger &iov, 1, 355aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger NULL, 0, 356aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 0 357aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger }; 358aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 359aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&nladdr, 0, sizeof(nladdr)); 360aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_family = AF_NETLINK; 361aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_pid = 0; 362aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_groups = 0; 363aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 364aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 365aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger iov.iov_base = buf; 366aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 367aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (1) { 368aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger iov.iov_len = sizeof(buf); 369aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = recvmsg(rtnl->fd, &msg, 0); 370aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 371aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 372aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (errno == EINTR) 373aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 374aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("OVERRUN"); 375aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 376aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 377aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status == 0) { 378aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "EOF on netlink\n"); 379aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 380aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 381aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_namelen != sizeof(nladdr)) { 382aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Sender address length == %d\n", msg.msg_namelen); 383aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 384aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 385aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) { 386aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int err; 387aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = h->nlmsg_len; 388aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int l = len - sizeof(*h); 389aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 390aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (l<0 || len>status) { 391aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_flags & MSG_TRUNC) { 392aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Truncated message\n"); 393aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 394aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 395aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!malformed message: len=%d\n", len); 396aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 397aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 398aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 399aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger err = handler(&nladdr, h, jarg); 400aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (err < 0) 401aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return err; 402aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 403aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status -= NLMSG_ALIGN(len); 404aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); 405aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 406aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_flags & MSG_TRUNC) { 407aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Message truncated\n"); 408aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 409aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 410aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status) { 411aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!Remnant of size %d\n", status); 412aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 413aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 414aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 415aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 416aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 4176dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemmingerint rtnl_from_file(FILE *rtnl, rtnl_filter_t handler, 4186dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemminger void *jarg) 419aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 420aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int status; 421aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 422aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger char buf[8192]; 423aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr *h = (void*)buf; 424aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 425aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&nladdr, 0, sizeof(nladdr)); 426aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_family = AF_NETLINK; 427aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_pid = 0; 428aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_groups = 0; 429aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 430aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (1) { 431aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int err, len, type; 432aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int l; 433aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 434aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = fread(&buf, 1, sizeof(*h), rtnl); 435aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 436aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 437aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (errno == EINTR) 438aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 439aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("rtnl_from_file: fread"); 440aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 441aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 442aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status == 0) 443aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 444aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 445aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger len = h->nlmsg_len; 446aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger type= h->nlmsg_type; 447aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger l = len - sizeof(*h); 448aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 449aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (l<0 || len>sizeof(buf)) { 450aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!malformed message: len=%d @%lu\n", 451aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger len, ftell(rtnl)); 452aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 453aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 454aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 455aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = fread(NLMSG_DATA(h), 1, NLMSG_ALIGN(l), rtnl); 456aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 457aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 458aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("rtnl_from_file: fread"); 459aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 460aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 461aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < l) { 462aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "rtnl-from_file: truncated message\n"); 463aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 464aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 465aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 466aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger err = handler(&nladdr, h, jarg); 467aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (err < 0) 468aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return err; 469aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 470aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 471aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 472aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data) 473aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 474aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = RTA_LENGTH(4); 475aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct rtattr *rta; 476007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) { 477007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger fprintf(stderr,"addattr32: Error! max allowed bound %d exceeded\n",maxlen); 478aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 479007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger } 48007f9436201eba2f75e6c480f5b16316b3bf977fcn); rta = NLMSG_TAIL(n); 481aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta->rta_type = type; 482aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta->rta_len = len; 483aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memcpy(RTA_DATA(rta), &data, 4); 484aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len; 485aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 486aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 487aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 4886dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemmingerint addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, 4896dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemminger int alen) 490aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 491aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = RTA_LENGTH(alen); 492aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct rtattr *rta; 493aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 4943dabdbb3da5ab7e9df8bf561602d681db26d8982net[shemminger]!shemminger if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) { 495007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",maxlen); 496aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 497007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger } 49807f9436201eba2f75e6c480f5b16316b3bf977fcn); rta = NLMSG_TAIL(n); 499aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta->rta_type = type; 500aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta->rta_len = len; 501aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memcpy(RTA_DATA(rta), data, alen); 5023dabdbb3da5ab7e9df8bf561602d681db26d8982net[shemminger]!shemminger n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); 503aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 504aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 505aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 50607f9436201eba2f75e6c480f5b16316b3bf977fcstruct nlmsghdr *n, int maxlen, const void *data, int len)int addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len) 50707f9436201eba2f75e6c480f5b16316b3bf977fcNLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len) > maxlen) {{ 50807f9436201eba2f75e6c480f5b16316b3bf977fcstderr, "addraw_l ERROR: message exceeded bound of %d\n",maxlen); if (NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len) > maxlen) { 50907f9436201eba2f75e6c480f5b16316b3bf977fcNLMSG_TAIL(n), data, len); fprintf(stderr, "addraw_l ERROR: message exceeded bound of %d\n",maxlen); 51007f9436201eba2f75e6c480f5b16316b3bf977fc(void *) NLMSG_TAIL(n) + len, return -1; 51107f9436201eba2f75e6c480f5b16316b3bf977fcn->nlmsg_len) + NLMSG_ALIGN(len); } 512aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 513aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memcpy(NLMSG_TAIL(n), data, len); 514aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset((void *) NLMSG_TAIL(n) + len, 0, NLMSG_ALIGN(len) - len); 515aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len); 516aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 517007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger} 518007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger 519aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data) 520007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger{ 521aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = RTA_LENGTH(4); 522aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct rtattr *subrta; 523aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 524aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (RTA_ALIGN(rta->rta_len) + len > maxlen) { 525aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr,"rta_addattr32: Error! max allowed bound %d exceeded\n",maxlen); 526aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 527aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 528aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len)); 5296dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemminger subrta->rta_type = type; 5306dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemminger subrta->rta_len = len; 531aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memcpy(RTA_DATA(subrta), &data, 4); 532aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len; 533aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 534aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 5353dabdbb3da5ab7e9df8bf561602d681db26d8982net[shemminger]!shemminger 536007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemmingerint rta_addattr_l(struct rtattr *rta, int maxlen, int type, 537aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger const void *data, int alen) 538007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger{ 539aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct rtattr *subrta; 540aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = RTA_LENGTH(alen); 541aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 542aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (RTA_ALIGN(rta->rta_len) + RTA_ALIGN(len) > maxlen) { 5433dabdbb3da5ab7e9df8bf561602d681db26d8982net[shemminger]!shemminger fprintf(stderr,"rta_addattr_l: Error! max allowed bound %d exceeded\n",maxlen); 544aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 545aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 546aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len)); 547aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger subrta->rta_type = type; 548aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger subrta->rta_len = len; 549175e2440df5be09b0a4c134cad958a49f7bfb9d9osdl.net!shemminger memcpy(RTA_DATA(subrta), data, alen); 550aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta->rta_len = NLMSG_ALIGN(rta->rta_len) + RTA_ALIGN(len); 551aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 552aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 553aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 554aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) 555aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 556aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); 557aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (RTA_OK(rta, len)) { 558aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (rta->rta_type <= max) 559c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger tb[rta->rta_type] = rta; 560c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger rta = RTA_NEXT(rta,len); 561c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger } 562c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger if (len) 563175e2440df5be09b0a4c134cad958a49f7bfb9d9osdl.net!shemminger fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len); 564175e2440df5be09b0a4c134cad958a49f7bfb9d9osdl.net!shemminger return 0; 565c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger} 566175e2440df5be09b0a4c134cad958a49f7bfb9d9osdl.net!shemminger 567c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemmingerint parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len) 568c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger{ 569c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger int i = 0; 570c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger 571c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger memset(tb, 0, sizeof(struct rtattr *) * max); 572c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger while (RTA_OK(rta, len)) { 573c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger if (rta->rta_type <= max && i < max) 574 tb[i++] = rta; 575 rta = RTA_NEXT(rta,len); 576 } 577 if (len) 578 fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len); 579 return i; 580} 581