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 287f03191fda39ff09640f093b7ad84f461ffd65b2Patrick McHardyint rcvbuf = 1024 * 1024; 297f03191fda39ff09640f093b7ad84f461ffd65b2Patrick McHardy 30aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingervoid rtnl_close(struct rtnl_handle *rth) 31aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 323bfa73ff99291d872f6d0e0284ee416e880088b6Stephen Hemminger if (rth->fd >= 0) { 333bfa73ff99291d872f6d0e0284ee416e880088b6Stephen Hemminger close(rth->fd); 343bfa73ff99291d872f6d0e0284ee416e880088b6Stephen Hemminger rth->fd = -1; 353bfa73ff99291d872f6d0e0284ee416e880088b6Stephen Hemminger } 36aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 37aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 388ed63ab1f1283b2c63355fb7c1e80abead4b9399shemmingerint rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions, 398ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger int protocol) 40aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 41f332d169246447bd5e258ac03d5ee840a70adb1eshemminger socklen_t addr_len; 42007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger int sndbuf = 32768; 43aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 44b16621cafd599499fdbaa79236266d72a53106bbStephen Hemminger memset(rth, 0, sizeof(*rth)); 45aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 46c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger rth->fd = socket(AF_NETLINK, SOCK_RAW, protocol); 47aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (rth->fd < 0) { 48aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("Cannot open netlink socket"); 49aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 50aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 51aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 52007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger if (setsockopt(rth->fd,SOL_SOCKET,SO_SNDBUF,&sndbuf,sizeof(sndbuf)) < 0) { 53007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger perror("SO_SNDBUF"); 54007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger return -1; 55007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger } 56007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger 57007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger if (setsockopt(rth->fd,SOL_SOCKET,SO_RCVBUF,&rcvbuf,sizeof(rcvbuf)) < 0) { 58007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger perror("SO_RCVBUF"); 59007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger return -1; 60007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger } 61007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger 62aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&rth->local, 0, sizeof(rth->local)); 63aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rth->local.nl_family = AF_NETLINK; 64aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rth->local.nl_groups = subscriptions; 65aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 66aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) { 67aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("Cannot bind netlink socket"); 68aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 69aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 70aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger addr_len = sizeof(rth->local); 71aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) { 72aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("Cannot getsockname"); 73aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 74aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 75aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (addr_len != sizeof(rth->local)) { 76aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Wrong address length %d\n", addr_len); 77aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 78aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 79aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (rth->local.nl_family != AF_NETLINK) { 80aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Wrong address family %d\n", rth->local.nl_family); 81aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 82aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 83aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rth->seq = time(NULL); 84aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 85aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 86aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 87c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemmingerint rtnl_open(struct rtnl_handle *rth, unsigned subscriptions) 88c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger{ 89c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger return rtnl_open_byproto(rth, subscriptions, NETLINK_ROUTE); 90c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger} 91c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger 92aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type) 93aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 94aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct { 95aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr nlh; 96aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct rtgenmsg g; 97bd886ebb1ffd84301caa2341b671df9a9e2db4c9Rose, Gregory V __u16 align_rta; /* attribute has to be 32bit aligned */ 98bd886ebb1ffd84301caa2341b671df9a9e2db4c9Rose, Gregory V struct rtattr ext_req; 99bd886ebb1ffd84301caa2341b671df9a9e2db4c9Rose, Gregory V __u32 ext_filter_mask; 100aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } req; 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; 105aa38c3eefaf6c6f4fd0a8858f6b771b6c8f84129Masatake YAMATO req.nlh.nlmsg_flags = NLM_F_DUMP|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 110bd886ebb1ffd84301caa2341b671df9a9e2db4c9Rose, Gregory V req.ext_req.rta_type = IFLA_EXT_MASK; 111bd886ebb1ffd84301caa2341b671df9a9e2db4c9Rose, Gregory V req.ext_req.rta_len = RTA_LENGTH(sizeof(__u32)); 112bd886ebb1ffd84301caa2341b671df9a9e2db4c9Rose, Gregory V req.ext_filter_mask = RTEXT_FILTER_VF; 113bd886ebb1ffd84301caa2341b671df9a9e2db4c9Rose, Gregory V 114f31a37f79d1f33d4d0d6a18f3768bfee27e8b6ccStephen Hemminger return send(rth->fd, (void*)&req, sizeof(req), 0); 115aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 116aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 1176cf8398f5f487762586801c25539d8fe5bb33b39Stephen Hemmingerint rtnl_send(struct rtnl_handle *rth, const void *buf, int len) 118aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 119f31a37f79d1f33d4d0d6a18f3768bfee27e8b6ccStephen Hemminger return send(rth->fd, buf, len, 0); 120f31a37f79d1f33d4d0d6a18f3768bfee27e8b6ccStephen Hemminger} 121f31a37f79d1f33d4d0d6a18f3768bfee27e8b6ccStephen Hemminger 1226cf8398f5f487762586801c25539d8fe5bb33b39Stephen Hemmingerint rtnl_send_check(struct rtnl_handle *rth, const void *buf, int len) 123f31a37f79d1f33d4d0d6a18f3768bfee27e8b6ccStephen Hemminger{ 12454bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger struct nlmsghdr *h; 12554bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger int status; 12654bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger char resp[1024]; 127aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 128f31a37f79d1f33d4d0d6a18f3768bfee27e8b6ccStephen Hemminger status = send(rth->fd, buf, len, 0); 12954bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger if (status < 0) 13054bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger return status; 13154bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger 1322d8240f8d95dfdc276dcf447623129fb5ccedcd6Stephen Hemminger /* Check for immediate errors */ 1332d8240f8d95dfdc276dcf447623129fb5ccedcd6Stephen Hemminger status = recv(rth->fd, resp, sizeof(resp), MSG_DONTWAIT|MSG_PEEK); 13454bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger if (status < 0) { 13554bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger if (errno == EAGAIN) 13654bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger return 0; 13754bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger return -1; 13854bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger } 13954bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger 14054bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger for (h = (struct nlmsghdr *)resp; NLMSG_OK(h, status); 14154bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger h = NLMSG_NEXT(h, status)) { 14254bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger if (h->nlmsg_type == NLMSG_ERROR) { 14354bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); 14454bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) 14554bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger fprintf(stderr, "ERROR truncated\n"); 14654bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger else 14754bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger errno = -err->error; 14824f38182441868f27aec03e82105eb008127e879Sven Anders return -1; 14954bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger } 15054bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger } 15154bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger 15254bb35c69cec6c730a4ac95530a1d2ca6670f73bStephen Hemminger return 0; 153aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 154aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 155aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) 156aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 157aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr nlh; 1586cf8398f5f487762586801c25539d8fe5bb33b39Stephen Hemminger struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK }; 1598ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger struct iovec iov[2] = { 1608ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger { .iov_base = &nlh, .iov_len = sizeof(nlh) }, 1618ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger { .iov_base = req, .iov_len = len } 1628ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger }; 163aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct msghdr msg = { 1648ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_name = &nladdr, 1658ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_namelen = sizeof(nladdr), 1668ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_iov = iov, 1678ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_iovlen = 2, 168aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger }; 169aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 170aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nlh.nlmsg_len = NLMSG_LENGTH(len); 171aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nlh.nlmsg_type = type; 172aa38c3eefaf6c6f4fd0a8858f6b771b6c8f84129Masatake YAMATO nlh.nlmsg_flags = NLM_F_DUMP|NLM_F_REQUEST; 173aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nlh.nlmsg_pid = 0; 174aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nlh.nlmsg_seq = rth->dump = ++rth->seq; 175aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 176aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return sendmsg(rth->fd, &msg, 0); 177aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 178aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 179b49240ec7eab91418d2f090536bf8cd2205988d6Simon Hormanint rtnl_dump_filter_l(struct rtnl_handle *rth, 180b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman const struct rtnl_dump_filter_arg *arg) 181aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 182aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 1838ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger struct iovec iov; 1848ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger struct msghdr msg = { 1858ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_name = &nladdr, 1868ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_namelen = sizeof(nladdr), 1878ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_iov = &iov, 1888ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_iovlen = 1, 1898ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger }; 1908ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger char buf[16384]; 191aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 1928ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger iov.iov_base = buf; 193aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (1) { 194aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int status; 195b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman const struct rtnl_dump_filter_arg *a; 1963bc1c4f29777171b484d36abf673667e3729202bBen Greear int found_done = 0; 1973bc1c4f29777171b484d36abf673667e3729202bBen Greear int msglen = 0; 198aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 1998ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger iov.iov_len = sizeof(buf); 200aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = recvmsg(rth->fd, &msg, 0); 201aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 202aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 203aa8032e628405c1318271fc928babbc06ab12d62Stephen Hemminger if (errno == EINTR || errno == EAGAIN) 204aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 205aa8032e628405c1318271fc928babbc06ab12d62Stephen Hemminger fprintf(stderr, "netlink receive error %s (%d)\n", 206aa8032e628405c1318271fc928babbc06ab12d62Stephen Hemminger strerror(errno), errno); 207aa8032e628405c1318271fc928babbc06ab12d62Stephen Hemminger return -1; 208aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 2098ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger 210aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status == 0) { 211aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "EOF on netlink\n"); 212aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 213aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 214aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 215b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman for (a = arg; a->filter; a++) { 216b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman struct nlmsghdr *h = (struct nlmsghdr*)buf; 2173bc1c4f29777171b484d36abf673667e3729202bBen Greear msglen = status; 218b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman 2193bc1c4f29777171b484d36abf673667e3729202bBen Greear while (NLMSG_OK(h, msglen)) { 220b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman int err; 221b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman 222b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman if (nladdr.nl_pid != 0 || 223b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman h->nlmsg_pid != rth->local.nl_pid || 224cd70f3f522e04b4d2fa80ae10292379bf223a53bStephen Hemminger h->nlmsg_seq != rth->dump) 225b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman goto skip_it; 226aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 2273bc1c4f29777171b484d36abf673667e3729202bBen Greear if (h->nlmsg_type == NLMSG_DONE) { 2283bc1c4f29777171b484d36abf673667e3729202bBen Greear found_done = 1; 2293bc1c4f29777171b484d36abf673667e3729202bBen Greear break; /* process next filter */ 2303bc1c4f29777171b484d36abf673667e3729202bBen Greear } 231b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman if (h->nlmsg_type == NLMSG_ERROR) { 232b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); 233b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) { 234b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman fprintf(stderr, 235b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman "ERROR truncated\n"); 236b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman } else { 237b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman errno = -err->error; 238b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman perror("RTNETLINK answers"); 239b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman } 240b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman return -1; 241aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 242b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman err = a->filter(&nladdr, h, a->arg1); 243b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman if (err < 0) 244b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman return err; 245aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 246aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerskip_it: 2473bc1c4f29777171b484d36abf673667e3729202bBen Greear h = NLMSG_NEXT(h, msglen); 248b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman } 2493bc1c4f29777171b484d36abf673667e3729202bBen Greear } 2503bc1c4f29777171b484d36abf673667e3729202bBen Greear 2513bc1c4f29777171b484d36abf673667e3729202bBen Greear if (found_done) 2523bc1c4f29777171b484d36abf673667e3729202bBen Greear return 0; 2533bc1c4f29777171b484d36abf673667e3729202bBen Greear 254aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_flags & MSG_TRUNC) { 255aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Message truncated\n"); 256aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 257aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 2583bc1c4f29777171b484d36abf673667e3729202bBen Greear if (msglen) { 2593bc1c4f29777171b484d36abf673667e3729202bBen Greear fprintf(stderr, "!!!Remnant of size %d\n", msglen); 260aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 261aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 262aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 263aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 264aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 265b49240ec7eab91418d2f090536bf8cd2205988d6Simon Hormanint rtnl_dump_filter(struct rtnl_handle *rth, 266b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman rtnl_filter_t filter, 267cd70f3f522e04b4d2fa80ae10292379bf223a53bStephen Hemminger void *arg1) 268b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman{ 269b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman const struct rtnl_dump_filter_arg a[2] = { 270cd70f3f522e04b4d2fa80ae10292379bf223a53bStephen Hemminger { .filter = filter, .arg1 = arg1, }, 271cd70f3f522e04b4d2fa80ae10292379bf223a53bStephen Hemminger { .filter = NULL, .arg1 = NULL, }, 272b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman }; 273b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman 274b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman return rtnl_dump_filter_l(rth, a); 275b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman} 276b49240ec7eab91418d2f090536bf8cd2205988d6Simon Horman 277aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, 278cd70f3f522e04b4d2fa80ae10292379bf223a53bStephen Hemminger unsigned groups, struct nlmsghdr *answer) 279aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 280aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int status; 281aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger unsigned seq; 282aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr *h; 283aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 284fb2297599de1fb7447a050e16e0179f739460473shemminger struct iovec iov = { 285fb2297599de1fb7447a050e16e0179f739460473shemminger .iov_base = (void*) n, 286fb2297599de1fb7447a050e16e0179f739460473shemminger .iov_len = n->nlmsg_len 287fb2297599de1fb7447a050e16e0179f739460473shemminger }; 288aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct msghdr msg = { 2898ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_name = &nladdr, 2908ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_namelen = sizeof(nladdr), 2918ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_iov = &iov, 2928ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_iovlen = 1, 293aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger }; 2948ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger char buf[16384]; 295aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 296aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&nladdr, 0, sizeof(nladdr)); 297aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_family = AF_NETLINK; 298aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_pid = peer; 299aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_groups = groups; 300aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 301aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger n->nlmsg_seq = seq = ++rtnl->seq; 302007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger 303aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (answer == NULL) 304aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger n->nlmsg_flags |= NLM_F_ACK; 305aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 306aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = sendmsg(rtnl->fd, &msg, 0); 307aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 308aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 309aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("Cannot talk to rtnetlink"); 310aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 311aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 312aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 313007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger memset(buf,0,sizeof(buf)); 314007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger 315aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger iov.iov_base = buf; 316aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 317aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (1) { 318aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger iov.iov_len = sizeof(buf); 319aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = recvmsg(rtnl->fd, &msg, 0); 320aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 321aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 322aa8032e628405c1318271fc928babbc06ab12d62Stephen Hemminger if (errno == EINTR || errno == EAGAIN) 323aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 324aa8032e628405c1318271fc928babbc06ab12d62Stephen Hemminger fprintf(stderr, "netlink receive error %s (%d)\n", 325aa8032e628405c1318271fc928babbc06ab12d62Stephen Hemminger strerror(errno), errno); 326aa8032e628405c1318271fc928babbc06ab12d62Stephen Hemminger return -1; 327aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 328aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status == 0) { 329aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "EOF on netlink\n"); 330aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 331aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 332aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_namelen != sizeof(nladdr)) { 333aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "sender address length == %d\n", msg.msg_namelen); 334aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 335aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 336aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) { 337aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = h->nlmsg_len; 338aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int l = len - sizeof(*h); 339aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 340cd70f3f522e04b4d2fa80ae10292379bf223a53bStephen Hemminger if (l < 0 || len>status) { 341aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_flags & MSG_TRUNC) { 342aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Truncated message\n"); 343aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 344aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 345aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!malformed message: len=%d\n", len); 346aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 347aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 348aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 34910f57ef1ab9b4fca639cb2383bc04616fafba5eforg[shemminger]!shemminger if (nladdr.nl_pid != peer || 35010f57ef1ab9b4fca639cb2383bc04616fafba5eforg[shemminger]!shemminger h->nlmsg_pid != rtnl->local.nl_pid || 351aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger h->nlmsg_seq != seq) { 3524cca16f20e92a97399d5814fc810af66ce0581d8shemminger /* Don't forget to skip that message. */ 3534cca16f20e92a97399d5814fc810af66ce0581d8shemminger status -= NLMSG_ALIGN(len); 3544cca16f20e92a97399d5814fc810af66ce0581d8shemminger h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); 355aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 356aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 357aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 358aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (h->nlmsg_type == NLMSG_ERROR) { 359aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); 360aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (l < sizeof(struct nlmsgerr)) { 361aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "ERROR truncated\n"); 362aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } else { 363aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger errno = -err->error; 364aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (errno == 0) { 365aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (answer) 366aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memcpy(answer, h, h->nlmsg_len); 367aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 368aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 369aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("RTNETLINK answers"); 370aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 371aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 372aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 373aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (answer) { 374aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memcpy(answer, h, h->nlmsg_len); 375aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 376aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 377aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 378aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Unexpected reply!!!\n"); 379aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 380aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status -= NLMSG_ALIGN(len); 381aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); 382aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 383aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_flags & MSG_TRUNC) { 384aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Message truncated\n"); 385aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 386aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 387aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status) { 388aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!Remnant of size %d\n", status); 389aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 390aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 391aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 392aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 393aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 3948ed63ab1f1283b2c63355fb7c1e80abead4b9399shemmingerint rtnl_listen(struct rtnl_handle *rtnl, 3956dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemminger rtnl_filter_t handler, 3966dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemminger void *jarg) 397aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 398aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int status; 399aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr *h; 400aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 401aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct iovec iov; 402aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct msghdr msg = { 4038ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_name = &nladdr, 4048ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_namelen = sizeof(nladdr), 4058ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_iov = &iov, 4068ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger .msg_iovlen = 1, 407aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger }; 4088ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger char buf[8192]; 409aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 410aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&nladdr, 0, sizeof(nladdr)); 411aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_family = AF_NETLINK; 412aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_pid = 0; 413aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_groups = 0; 414aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 415aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger iov.iov_base = buf; 416aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (1) { 417aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger iov.iov_len = sizeof(buf); 418aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = recvmsg(rtnl->fd, &msg, 0); 419aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 420aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 421aa8032e628405c1318271fc928babbc06ab12d62Stephen Hemminger if (errno == EINTR || errno == EAGAIN) 422aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 423aa8032e628405c1318271fc928babbc06ab12d62Stephen Hemminger fprintf(stderr, "netlink receive error %s (%d)\n", 424aa8032e628405c1318271fc928babbc06ab12d62Stephen Hemminger strerror(errno), errno); 4257f03191fda39ff09640f093b7ad84f461ffd65b2Patrick McHardy if (errno == ENOBUFS) 4267f03191fda39ff09640f093b7ad84f461ffd65b2Patrick McHardy continue; 427aa8032e628405c1318271fc928babbc06ab12d62Stephen Hemminger return -1; 428aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 429aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status == 0) { 430aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "EOF on netlink\n"); 431aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 432aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 433aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_namelen != sizeof(nladdr)) { 434aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Sender address length == %d\n", msg.msg_namelen); 435aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 436aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 437aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) { 438aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int err; 439aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = h->nlmsg_len; 440aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int l = len - sizeof(*h); 441aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 442aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (l<0 || len>status) { 443aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_flags & MSG_TRUNC) { 444aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Truncated message\n"); 445aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 446aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 447aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!malformed message: len=%d\n", len); 448aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 449aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 450aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 451aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger err = handler(&nladdr, h, jarg); 452aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (err < 0) 453aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return err; 454aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 455aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status -= NLMSG_ALIGN(len); 456aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); 457aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 458aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (msg.msg_flags & MSG_TRUNC) { 459aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "Message truncated\n"); 460aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 461aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 462aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status) { 463aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!Remnant of size %d\n", status); 464aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger exit(1); 465aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 466aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 467aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 468aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 4696dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemmingerint rtnl_from_file(FILE *rtnl, rtnl_filter_t handler, 4706dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemminger void *jarg) 471aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 472aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int status; 473aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct sockaddr_nl nladdr; 474aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger char buf[8192]; 475aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nlmsghdr *h = (void*)buf; 476aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 477aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(&nladdr, 0, sizeof(nladdr)); 478aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_family = AF_NETLINK; 479aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_pid = 0; 480aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger nladdr.nl_groups = 0; 481aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 482aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (1) { 4832dd9f8e073717aed2b624d1e9e325487260b57ebStephen Hemminger int err, len; 484aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int l; 485aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 486aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = fread(&buf, 1, sizeof(*h), rtnl); 487aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 488aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 489aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (errno == EINTR) 490aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger continue; 491aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("rtnl_from_file: fread"); 492aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 493aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 494aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status == 0) 495aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 496aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 497aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger len = h->nlmsg_len; 498aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger l = len - sizeof(*h); 499aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 500aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (l<0 || len>sizeof(buf)) { 501aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "!!!malformed message: len=%d @%lu\n", 502aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger len, ftell(rtnl)); 503aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 504aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 505aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 506aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger status = fread(NLMSG_DATA(h), 1, NLMSG_ALIGN(l), rtnl); 507aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 508aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < 0) { 509aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger perror("rtnl_from_file: fread"); 510aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 511aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 512aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (status < l) { 513aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr, "rtnl-from_file: truncated message\n"); 514aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 515aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 516aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 517aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger err = handler(&nladdr, h, jarg); 518aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (err < 0) 519aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return err; 520aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 521aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 522aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 5232aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemmingerint addattr(struct nlmsghdr *n, int maxlen, int type) 5242aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemminger{ 5252aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemminger return addattr_l(n, maxlen, type, NULL, 0); 5262aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemminger} 5272aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemminger 5282aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemmingerint addattr8(struct nlmsghdr *n, int maxlen, int type, __u8 data) 5292aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemminger{ 5302aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemminger return addattr_l(n, maxlen, type, &data, sizeof(__u8)); 5312aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemminger} 5322aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemminger 5332aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemmingerint addattr16(struct nlmsghdr *n, int maxlen, int type, __u16 data) 5342aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemminger{ 5352aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemminger return addattr_l(n, maxlen, type, &data, sizeof(__u16)); 5362aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemminger} 5372aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemminger 538aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data) 539aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 5402aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemminger return addattr_l(n, maxlen, type, &data, sizeof(__u32)); 5412aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemminger} 5422aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemminger 5432aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemmingerint addattr64(struct nlmsghdr *n, int maxlen, int type, __u64 data) 5442aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemminger{ 5452aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemminger return addattr_l(n, maxlen, type, &data, sizeof(__u64)); 5462aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemminger} 5472aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemminger 5482aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemmingerint addattrstrz(struct nlmsghdr *n, int maxlen, int type, const char *str) 5492aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemminger{ 5502aa3dd29a75c494bf969586da5489d4dc7d07839Stephen Hemminger return addattr_l(n, maxlen, type, str, strlen(str)+1); 551aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 552aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 5538ed63ab1f1283b2c63355fb7c1e80abead4b9399shemmingerint addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, 5546dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemminger int alen) 555aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 556aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = RTA_LENGTH(alen); 557aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct rtattr *rta; 558aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 5593dabdbb3da5ab7e9df8bf561602d681db26d8982net[shemminger]!shemminger if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) { 560007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",maxlen); 561aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 562007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger } 56307f9436201eba2f75e6c480f5b16316b3bf977fcn); rta = NLMSG_TAIL(n); 564aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta->rta_type = type; 565aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta->rta_len = len; 566aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memcpy(RTA_DATA(rta), data, alen); 5673dabdbb3da5ab7e9df8bf561602d681db26d8982net[shemminger]!shemminger n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); 568aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 569aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 570aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 57107f9436201eba2f75e6c480f5b16316b3bf977fcstruct nlmsghdr *n, int maxlen, const void *data, int len)int addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len) 57207f9436201eba2f75e6c480f5b16316b3bf977fcNLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len) > maxlen) {{ 57307f9436201eba2f75e6c480f5b16316b3bf977fcstderr, "addraw_l ERROR: message exceeded bound of %d\n",maxlen); if (NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len) > maxlen) { 57407f9436201eba2f75e6c480f5b16316b3bf977fcNLMSG_TAIL(n), data, len); fprintf(stderr, "addraw_l ERROR: message exceeded bound of %d\n",maxlen); 57507f9436201eba2f75e6c480f5b16316b3bf977fc(void *) NLMSG_TAIL(n) + len, return -1; 57607f9436201eba2f75e6c480f5b16316b3bf977fcn->nlmsg_len) + NLMSG_ALIGN(len); } 5772f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy 5782f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy memcpy(NLMSG_TAIL(n), data, len); 5792f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy memset((void *) NLMSG_TAIL(n) + len, 0, NLMSG_ALIGN(len) - len); 5802f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len); 5812f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy return 0; 5822f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy} 5832f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy 5842f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardystruct rtattr *addattr_nest(struct nlmsghdr *n, int maxlen, int type) 5852f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy{ 5862f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy struct rtattr *nest = NLMSG_TAIL(n); 5872f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy 5882f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy addattr_l(n, maxlen, type, NULL, 0); 5892f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy return nest; 5902f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy} 5912f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy 5922f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardyint addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest) 5932f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy{ 5942f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy nest->rta_len = (void *)NLMSG_TAIL(n) - (void *)nest; 5952f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy return n->nlmsg_len; 5962f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy} 5972f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy 5982f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardystruct rtattr *addattr_nest_compat(struct nlmsghdr *n, int maxlen, int type, 5992f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy const void *data, int len) 6002f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy{ 6012f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy struct rtattr *start = NLMSG_TAIL(n); 6022f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy 6032f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy addattr_l(n, maxlen, type, data, len); 6042f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy addattr_nest(n, maxlen, type); 6052f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy return start; 6062f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy} 6072f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy 6082f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardyint addattr_nest_compat_end(struct nlmsghdr *n, struct rtattr *start) 6092f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy{ 610aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct rtattr *nest = (void *)start + NLMSG_ALIGN(start->rta_len); 611aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 612aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger start->rta_len = (void *)NLMSG_TAIL(n) - (void *)start; 613aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger addattr_nest_end(n, nest); 614aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return n->nlmsg_len; 615007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger} 616007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger 617aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data) 618007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger{ 619aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = RTA_LENGTH(4); 620aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct rtattr *subrta; 621aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 622aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (RTA_ALIGN(rta->rta_len) + len > maxlen) { 623aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger fprintf(stderr,"rta_addattr32: Error! max allowed bound %d exceeded\n",maxlen); 624aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 625aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 626aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len)); 6278ed63ab1f1283b2c63355fb7c1e80abead4b9399shemminger subrta->rta_type = type; 6286dc9f016347441fbf94cf851c054b0f45ba32c1cosdl.net!shemminger subrta->rta_len = len; 629aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memcpy(RTA_DATA(subrta), &data, 4); 630aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len; 631aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return 0; 632aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 6333dabdbb3da5ab7e9df8bf561602d681db26d8982net[shemminger]!shemminger 634007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemmingerint rta_addattr_l(struct rtattr *rta, int maxlen, int type, 635aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger const void *data, int alen) 636007d3a3e9f0747039a772198293fd7f45a025f80osdl.net!shemminger{ 637aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct rtattr *subrta; 638aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int len = RTA_LENGTH(alen); 639aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 640aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (RTA_ALIGN(rta->rta_len) + RTA_ALIGN(len) > maxlen) { 6413dabdbb3da5ab7e9df8bf561602d681db26d8982net[shemminger]!shemminger fprintf(stderr,"rta_addattr_l: Error! max allowed bound %d exceeded\n",maxlen); 642aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return -1; 643aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 644aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len)); 645aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger subrta->rta_type = type; 646aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger subrta->rta_len = len; 647175e2440df5be09b0a4c134cad958a49f7bfb9d9osdl.net!shemminger memcpy(RTA_DATA(subrta), data, alen); 648aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger rta->rta_len = NLMSG_ALIGN(rta->rta_len) + RTA_ALIGN(len); 6496e46ec813b7f06a85acb5a348dfc1a25ea488024Williams, Mitch A return 0; 650aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 651aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 652aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) 653aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 654aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); 655aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger while (RTA_OK(rta, len)) { 656aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if ((rta->rta_type <= max) && (!tb[rta->rta_type])) 657c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger tb[rta->rta_type] = rta; 658c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger rta = RTA_NEXT(rta,len); 659c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger } 660c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger if (len) 661175e2440df5be09b0a4c134cad958a49f7bfb9d9osdl.net!shemminger fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len); 662175e2440df5be09b0a4c134cad958a49f7bfb9d9osdl.net!shemminger return 0; 663c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger} 664175e2440df5be09b0a4c134cad958a49f7bfb9d9osdl.net!shemminger 665c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemmingerint parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len) 666c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger{ 667c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger int i = 0; 668c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger 669c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger memset(tb, 0, sizeof(struct rtattr *) * max); 670c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger while (RTA_OK(rta, len)) { 671c7699875bee00fbcd057fc62c30d6560b044e007net[shemminger]!shemminger if (rta->rta_type <= max && i < max) 6722f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy tb[i++] = rta; 6732f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy rta = RTA_NEXT(rta,len); 6742f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy } 6752f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy if (len) 6762f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len); 6772f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy return i; 6782f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy} 6792f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy 6802f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardyint __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rta, 6812f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy int len) 682037c635eee994f6b29fc82931490e831d4a2ead2Stephen Hemminger{ 6832f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy if (RTA_PAYLOAD(rta) < len) 6842f90c9c0bb0d8ed4841cb4c77c2d707ec07f20bfPatrick McHardy return -1; 685 if (RTA_PAYLOAD(rta) >= RTA_ALIGN(len) + sizeof(struct rtattr)) { 686 rta = RTA_DATA(rta) + RTA_ALIGN(len); 687 return parse_rtattr_nested(tb, max, rta); 688 } 689 memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); 690 return 0; 691} 692