Re: netlink tester program

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Randy.Dunlap <rddunlap@osdl.org> wrote:
 
> I think it should be possible in around 100 lines of code.
> I don't want to use iproute2 and libnetlink -- they are much larger
> and more complex than a syscall interface test program should be.

Here's my code for traceroute.

Oh yes, if linux/rtnetlink.h is meant to be used directly from userspace,
can we replace these __u?? types with something a little more standard
please?
-- 
Debian GNU/Linux 3.0 is out! ( http://www.debian.org/ )
Email:  Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
/*
 * Copyright (c) 2000
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the Computer Systems
 *	Engineering Group at Lawrence Berkeley Laboratory.
 * 4. Neither the name of the University nor of the Laboratory may be used
 *    to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef lint
static const char rcsid[] =
    "@(#) $Id: findsaddr-linux.c,v 1.1 2000/11/23 20:17:12 leres Exp $ (LBL)";
#endif

/* XXX linux is different (as usual) */

#include <netinet/in.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

typedef uint32_t __u32;
typedef uint16_t __u16;
typedef uint8_t __u8;
typedef int32_t __s32;
#include <linux/rtnetlink.h>

#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif

#include "findsaddr.h"
#include "ifaddrlist.h"
#include "traceroute.h"

/*
 * Return the source address for the given destination address
 */
const char *
findsaddr(const struct sockaddr_in *to, struct sockaddr_in *from)
{
	static char errbuf[256];
	int fd;
	struct {
		struct nlmsghdr n;
		struct rtmsg r;
		char data[1024];
	} req;
	struct rtattr *attr;
	int len;

	fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
	if (fd < 0) {
		sprintf(
			errbuf, "cannot open netlink socket: %.128s",
			strerror(errno)
		);
		return errbuf;
	}

	memset(&req, 0, sizeof(req));
	req.n.nlmsg_len =
		NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.r))) +
		RTA_LENGTH(sizeof(to->sin_addr));
	req.n.nlmsg_flags = NLM_F_REQUEST;
	req.n.nlmsg_type = RTM_GETROUTE;
	req.r.rtm_family = AF_INET;
	req.r.rtm_dst_len = 32;
	attr = (void *) (
		((char *) &req) + NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.r)))
	);
	attr->rta_type = RTA_DST;
	attr->rta_len = RTA_LENGTH(sizeof(to->sin_addr));
	memcpy(RTA_DATA(attr), &to->sin_addr, sizeof(to->sin_addr));

	if (send(fd, &req, req.n.nlmsg_len, 0) < 0) {
		sprintf(
			errbuf, "error sending netlink message: %.128s",
			strerror(errno)
		);
err:
		close(fd);
		return errbuf;
	}

	len = TEMP_FAILURE_RETRY(recv(fd, &req, sizeof(req), 0));
	if (len < 0) {
		sprintf(
			errbuf, "error receiving netlink message: %.128s",
			strerror(errno)
		);
		goto err;
	}

	close(fd);

	if (len < sizeof(struct nlmsghdr)) {
		sprintf(errbuf, "received short netlink message: %d", len);
		return errbuf;
	}
	if (len < req.n.nlmsg_len) {
		sprintf(
			errbuf, "netlink message size error: %d < %d",
			len, req.n.nlmsg_len
		);
		return errbuf;
	}
	if (req.n.nlmsg_type == NLMSG_ERROR) {
		struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA(&req.n);
		sprintf(
			errbuf, "netlink error: %.128s",
			strerror(-err->error)
		);
		return errbuf;
	}

	len -= NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.r)));
	while (len > sizeof(*attr) && len > attr->rta_len) {
		uint32_t addr;

		if (
			attr->rta_type == RTA_PREFSRC &&
			RTA_PAYLOAD(attr) == sizeof(addr)
		) {
			memcpy(&addr, RTA_DATA(attr), sizeof(attr));
			setsin(from, addr);
			return 0;
		}
		len -= attr->rta_len;
		attr = (void *) (((char *) attr) + attr->rta_len);
	}

	strcpy(errbuf, "netlink did not return a source address");
	return errbuf;
}
-
: send the line "unsubscribe linux-net" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux