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