libnetlink.c revision aba5acdfdb347d2c21fc67d613d83d4430ca3937
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 33aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rtnl_open(struct rtnl_handle *rth, unsigned subscriptions) 34aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 35aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int addr_len; 36aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 37aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(rth, 0, sizeof(rth)); 38aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 39aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rth->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 40aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (rth->fd < 0) { 41aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("Cannot open netlink socket"); 42aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 43aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 44aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 45aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&rth->local, 0, sizeof(rth->local)); 46aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rth->local.nl_family = AF_NETLINK; 47aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rth->local.nl_groups = subscriptions; 48aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 49aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) { 50aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("Cannot bind netlink socket"); 51aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 52aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 53aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger addr_len = sizeof(rth->local); 54aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) { 55aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("Cannot getsockname"); 56aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 57aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 58aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (addr_len != sizeof(rth->local)) { 59aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Wrong address length %d\n", addr_len); 60aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 61aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 62aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (rth->local.nl_family != AF_NETLINK) { 63aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Wrong address family %d\n", rth->local.nl_family); 64aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 65aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 66aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rth->seq = time(NULL); 67aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 68aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 69aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 70aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type) 71aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 72aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct { 73aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr nlh; 74aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct rtgenmsg g; 75aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } req; 76aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 77aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 78aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&nladdr, 0, sizeof(nladdr)); 79aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_family = AF_NETLINK; 80aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 81aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger req.nlh.nlmsg_len = sizeof(req); 82aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger req.nlh.nlmsg_type = type; 83aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; 84aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger req.nlh.nlmsg_pid = 0; 85aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger req.nlh.nlmsg_seq = rth->dump = ++rth->seq; 86aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger req.g.rtgen_family = family; 87aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 88aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return sendto(rth->fd, (void*)&req, sizeof(req), 0, (struct sockaddr*)&nladdr, sizeof(nladdr)); 89aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 90aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 91aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rtnl_send(struct rtnl_handle *rth, char *buf, int len) 92aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 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 return sendto(rth->fd, buf, len, 0, (struct sockaddr*)&nladdr, sizeof(nladdr)); 99aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 100aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 101aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) 102aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 103aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr nlh; 104aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 105aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct iovec iov[2] = { { &nlh, sizeof(nlh) }, { req, len } }; 106aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct msghdr msg = { 107aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger (void*)&nladdr, sizeof(nladdr), 108aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger iov, 2, 109aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger NULL, 0, 110aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 0 111aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger }; 112aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 113aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&nladdr, 0, sizeof(nladdr)); 114aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_family = AF_NETLINK; 115aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 116aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nlh.nlmsg_len = NLMSG_LENGTH(len); 117aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nlh.nlmsg_type = type; 118aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; 119aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nlh.nlmsg_pid = 0; 120aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nlh.nlmsg_seq = rth->dump = ++rth->seq; 121aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 122aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return sendmsg(rth->fd, &msg, 0); 123aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 124aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 125aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rtnl_dump_filter(struct rtnl_handle *rth, 126aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int (*filter)(struct sockaddr_nl *, struct nlmsghdr *n, void *), 127aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger void *arg1, 128aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int (*junk)(struct sockaddr_nl *,struct nlmsghdr *n, void *), 129aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger void *arg2) 130aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 131aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger char buf[8192]; 132aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 133aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct iovec iov = { buf, sizeof(buf) }; 134aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 135aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (1) { 136aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int status; 137aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr *h; 138aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 139aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct msghdr msg = { 140aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger (void*)&nladdr, sizeof(nladdr), 141aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger &iov, 1, 142aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger NULL, 0, 143aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 0 144aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger }; 145aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 146aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = recvmsg(rth->fd, &msg, 0); 147aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 148aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 149aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (errno == EINTR) 150aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 151aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("OVERRUN"); 152aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 153aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 154aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status == 0) { 155aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "EOF on netlink\n"); 156aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 157aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 158aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_namelen != sizeof(nladdr)) { 159aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "sender address length == %d\n", msg.msg_namelen); 160aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 161aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 162aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 163aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger h = (struct nlmsghdr*)buf; 164aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (NLMSG_OK(h, status)) { 165aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int err; 166aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 167aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (h->nlmsg_pid != rth->local.nl_pid || 168aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger h->nlmsg_seq != rth->dump) { 169aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (junk) { 170aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger err = junk(&nladdr, h, arg2); 171aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (err < 0) 172aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return err; 173aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 174aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger goto skip_it; 175aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 176aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 177aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (h->nlmsg_type == NLMSG_DONE) 178aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 179aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (h->nlmsg_type == NLMSG_ERROR) { 180aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); 181aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) { 182aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "ERROR truncated\n"); 183aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } else { 184aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger errno = -err->error; 185aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("RTNETLINK answers"); 186aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 187aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 188aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 189aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger err = filter(&nladdr, h, arg1); 190aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (err < 0) 191aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return err; 192aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 193aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerskip_it: 194aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger h = NLMSG_NEXT(h, status); 195aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 196aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_flags & MSG_TRUNC) { 197aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Message truncated\n"); 198aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 199aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 200aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status) { 201aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!Remnant of size %d\n", status); 202aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 203aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 204aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 205aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 206aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 207aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, 208aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger unsigned groups, struct nlmsghdr *answer, 209aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int (*junk)(struct sockaddr_nl *,struct nlmsghdr *n, void *), 210aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger void *jarg) 211aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 212aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int status; 213aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger unsigned seq; 214aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr *h; 215aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 216aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct iovec iov = { (void*)n, n->nlmsg_len }; 217aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger char buf[8192]; 218aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct msghdr msg = { 219aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger (void*)&nladdr, sizeof(nladdr), 220aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger &iov, 1, 221aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger NULL, 0, 222aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 0 223aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger }; 224aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 225aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&nladdr, 0, sizeof(nladdr)); 226aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_family = AF_NETLINK; 227aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_pid = peer; 228aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_groups = groups; 229aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 230aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger n->nlmsg_seq = seq = ++rtnl->seq; 231aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (answer == NULL) 232aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger n->nlmsg_flags |= NLM_F_ACK; 233aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 234aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = sendmsg(rtnl->fd, &msg, 0); 235aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 236aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 237aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("Cannot talk to rtnetlink"); 238aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 239aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 240aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 241aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger iov.iov_base = buf; 242aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 243aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (1) { 244aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger iov.iov_len = sizeof(buf); 245aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = recvmsg(rtnl->fd, &msg, 0); 246aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 247aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 248aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (errno == EINTR) 249aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 250aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("OVERRUN"); 251aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 252aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 253aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status == 0) { 254aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "EOF on netlink\n"); 255aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 256aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 257aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_namelen != sizeof(nladdr)) { 258aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "sender address length == %d\n", msg.msg_namelen); 259aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 260aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 261aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) { 262aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int err; 263aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = h->nlmsg_len; 264aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int l = len - sizeof(*h); 265aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 266aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (l<0 || len>status) { 267aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_flags & MSG_TRUNC) { 268aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Truncated message\n"); 269aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 270aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 271aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!malformed message: len=%d\n", len); 272aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 273aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 274aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 275aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (h->nlmsg_pid != rtnl->local.nl_pid || 276aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger h->nlmsg_seq != seq) { 277aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (junk) { 278aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger err = junk(&nladdr, h, jarg); 279aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (err < 0) 280aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return err; 281aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 282aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 283aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 284aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 285aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (h->nlmsg_type == NLMSG_ERROR) { 286aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); 287aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (l < sizeof(struct nlmsgerr)) { 288aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "ERROR truncated\n"); 289aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } else { 290aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger errno = -err->error; 291aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (errno == 0) { 292aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (answer) 293aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memcpy(answer, h, h->nlmsg_len); 294aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 295aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 296aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("RTNETLINK answers"); 297aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 298aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 299aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 300aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (answer) { 301aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memcpy(answer, h, h->nlmsg_len); 302aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 303aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 304aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 305aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Unexpected reply!!!\n"); 306aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 307aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status -= NLMSG_ALIGN(len); 308aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); 309aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 310aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_flags & MSG_TRUNC) { 311aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Message truncated\n"); 312aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 313aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 314aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status) { 315aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!Remnant of size %d\n", status); 316aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 317aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 318aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 319aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 320aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 321aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rtnl_listen(struct rtnl_handle *rtnl, 322aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int (*handler)(struct sockaddr_nl *,struct nlmsghdr *n, void *), 323aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger void *jarg) 324aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 325aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int status; 326aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr *h; 327aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 328aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct iovec iov; 329aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger char buf[8192]; 330aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct msghdr msg = { 331aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger (void*)&nladdr, sizeof(nladdr), 332aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger &iov, 1, 333aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger NULL, 0, 334aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 0 335aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger }; 336aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 337aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&nladdr, 0, sizeof(nladdr)); 338aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_family = AF_NETLINK; 339aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_pid = 0; 340aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_groups = 0; 341aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 342aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 343aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger iov.iov_base = buf; 344aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 345aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (1) { 346aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger iov.iov_len = sizeof(buf); 347aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = recvmsg(rtnl->fd, &msg, 0); 348aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 349aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 350aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (errno == EINTR) 351aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 352aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("OVERRUN"); 353aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 354aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 355aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status == 0) { 356aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "EOF on netlink\n"); 357aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 358aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 359aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_namelen != sizeof(nladdr)) { 360aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Sender address length == %d\n", msg.msg_namelen); 361aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 362aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 363aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) { 364aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int err; 365aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = h->nlmsg_len; 366aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int l = len - sizeof(*h); 367aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 368aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (l<0 || len>status) { 369aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_flags & MSG_TRUNC) { 370aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Truncated message\n"); 371aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 372aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 373aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!malformed message: len=%d\n", len); 374aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 375aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 376aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 377aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger err = handler(&nladdr, h, jarg); 378aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (err < 0) 379aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return err; 380aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 381aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status -= NLMSG_ALIGN(len); 382aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); 383aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 384aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_flags & MSG_TRUNC) { 385aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Message truncated\n"); 386aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 387aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 388aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status) { 389aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!Remnant of size %d\n", status); 390aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 391aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 392aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 393aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 394aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 395aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rtnl_from_file(FILE *rtnl, 396aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int (*handler)(struct sockaddr_nl *,struct nlmsghdr *n, void *), 397aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger void *jarg) 398aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 399aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int status; 400aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 401aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger char buf[8192]; 402aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr *h = (void*)buf; 403aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 404aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&nladdr, 0, sizeof(nladdr)); 405aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_family = AF_NETLINK; 406aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_pid = 0; 407aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_groups = 0; 408aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 409aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (1) { 410aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int err, len, type; 411aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int l; 412aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 413aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = fread(&buf, 1, sizeof(*h), rtnl); 414aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 415aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 416aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (errno == EINTR) 417aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 418aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("rtnl_from_file: fread"); 419aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 420aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 421aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status == 0) 422aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 423aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 424aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger len = h->nlmsg_len; 425aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger type= h->nlmsg_type; 426aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger l = len - sizeof(*h); 427aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 428aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (l<0 || len>sizeof(buf)) { 429aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!malformed message: len=%d @%lu\n", 430aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger len, ftell(rtnl)); 431aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 432aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 433aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 434aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = fread(NLMSG_DATA(h), 1, NLMSG_ALIGN(l), rtnl); 435aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 436aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 437aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("rtnl_from_file: fread"); 438aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 439aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 440aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < l) { 441aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "rtnl-from_file: truncated message\n"); 442aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 443aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 444aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 445aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger err = handler(&nladdr, h, jarg); 446aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (err < 0) 447aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return err; 448aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 449aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 450aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 451aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data) 452aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 453aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = RTA_LENGTH(4); 454aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct rtattr *rta; 455aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) 456aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 457aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len)); 458aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta->rta_type = type; 459aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta->rta_len = len; 460aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memcpy(RTA_DATA(rta), &data, 4); 461aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len; 462aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 463aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 464aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 465aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen) 466aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 467aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = RTA_LENGTH(alen); 468aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct rtattr *rta; 469aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 470aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) 471aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 472aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len)); 473aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta->rta_type = type; 474aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta->rta_len = len; 475aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memcpy(RTA_DATA(rta), data, alen); 476aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len; 477aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 478aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 479aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 480aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data) 481aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 482aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = RTA_LENGTH(4); 483aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct rtattr *subrta; 484aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 485aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (RTA_ALIGN(rta->rta_len) + len > maxlen) 486aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 487aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len)); 488aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger subrta->rta_type = type; 489aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger subrta->rta_len = len; 490aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memcpy(RTA_DATA(subrta), &data, 4); 491aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len; 492aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 493aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 494aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 495aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rta_addattr_l(struct rtattr *rta, int maxlen, int type, void *data, int alen) 496aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 497aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct rtattr *subrta; 498aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = RTA_LENGTH(alen); 499aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 500aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (RTA_ALIGN(rta->rta_len) + len > maxlen) 501aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 502aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len)); 503aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger subrta->rta_type = type; 504aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger subrta->rta_len = len; 505aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memcpy(RTA_DATA(subrta), data, alen); 506aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len; 507aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 508aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 509aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 510aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 511aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) 512aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 513aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (RTA_OK(rta, len)) { 514aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (rta->rta_type <= max) 515aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger tb[rta->rta_type] = rta; 516aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta = RTA_NEXT(rta,len); 517aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 518aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (len) 519aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len); 520aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 521aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 522