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