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