linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Mike Jagdis <jaggy@purplet.demon.co.uk>
To: Wietse Venema <wietse@porcupine.org>
Cc: linux-kernel@vger.kernel.org
Subject: Re: notion of a local address [was: Re: ioctl SIOCGIFNETMASK: ip alias bug 2.4.9 and 2.2.19]
Date: Fri, 07 Sep 2001 11:30:24 +0100	[thread overview]
Message-ID: <3B98A1C0.6010200@purplet.demon.co.uk> (raw)
In-Reply-To: <20010906173948.502BFBC06C@spike.porcupine.org>

[-- Attachment #1: Type: text/plain, Size: 1404 bytes --]

Wietse Venema wrote:
> The SMTP RFC requires that user@[ip.address] is correctly recognized
> as a final destination.  This requires that Linux provides the MTA
> with information about IP addresses that correspond with INADDR_ANY.
> 
> I am susprised that it is not possible to ask such information up
> front (same with netmasks), and that an application has to actually
> query a complex oracle, again and again, for every IP address.

If I understand correctly you want to get a full list of addresses
and netmasks that have been assigned to interfaces?

   Use netlink. I'm sure someone else has said that but I haven't
read the entire thread, just scanned for the almost certainly
required example attachment (netlink is only straight forward once
you have an example :-( ). Attached is something that simply
asks for the current addresses (and "aliases"). It should be fairly
easy to use.

   The advantage with netlink is that you can just add the socket to
your select/poll list and listen for address changes as they happen
(useful for DHCP clients, maybe fail over scenarios etc.?). This code
doesn't do that. But if you add "while (1) netlink_read(s);" at the
bottom it will merrily report address changes - probably while sucking
CPU time, I suddenly have the feeling I left the set non-blocking
line in there!

				Mike
P.S. It's IPv4. Adding IPv6 is left as an exercise for the reader :-)

[-- Attachment #2: netlink.c --]
[-- Type: text/plain, Size: 4184 bytes --]

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/syslog.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <asm/types.h>
#include <linux/rtnetlink.h>


static int netlink_seq = 0;


static void
netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, int len)
{
	while (RTA_OK(rta, len)) {
		if (rta->rta_type <= max)
			tb[rta->rta_type] = rta;
		rta = RTA_NEXT(rta,len);
	}
}


static int
netlink_ifaddr(struct sockaddr_nl *snl, struct nlmsghdr *h)
{
	int len;
	struct ifaddrmsg *ifa;
	struct rtattr *tb[IFA_MAX + 1];
	struct in_addr *addr = NULL;

	ifa = NLMSG_DATA(h);

	len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg));
	if (len < 0)
		return -1;

	memset(tb, '\0', sizeof(tb));
	netlink_parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), len);

	if (tb[IFA_LOCAL])
		addr = RTA_DATA(tb[IFA_LOCAL]);
  	else if (tb[IFA_ADDRESS])
    		addr = RTA_DATA(tb[IFA_ADDRESS]);
	else
		return -1;

	fprintf(stderr,
		"Netlink %s: iface index %d, IPv4 address: %s/%d\n",
		h->nlmsg_type == RTM_NEWADDR ? "add" : "del",
		ifa->ifa_index, inet_ntoa(*addr), ifa->ifa_prefixlen);
	return 0;
}


int
netlink_open()
{
	int s;
	struct sockaddr_nl snl;

	s = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
	if (s < 0) {
		fprintf(stderr, "Can't open netlink socket: %s\n", strerror(errno));
		return -1;
	}

	fcntl(s, F_SETFL, O_NONBLOCK);
  
	memset(&snl, '\0', sizeof(snl));
	snl.nl_family = AF_NETLINK;
	snl.nl_groups = RTMGRP_IPV4_IFADDR;
  
	if (bind(s, (struct sockaddr *)&snl, sizeof(snl)) < 0) {
		fprintf(stderr, "Can't bind netlink socket: %s\n", strerror(errno));
		close(s);
		return -1;
	}

	return s;
}


int
netlink_request(int s, int family, int type)
{
	struct sockaddr_nl snl;

	struct {
		struct nlmsghdr nlh;
		struct rtgenmsg g;
	} req;

	memset(&snl, '\0', sizeof(snl));
	snl.nl_family = AF_NETLINK;

	req.nlh.nlmsg_len = sizeof(req);
	req.nlh.nlmsg_type = type;
	req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
	req.nlh.nlmsg_pid = 0;
	req.nlh.nlmsg_seq = ++netlink_seq;
	req.g.rtgen_family = family;
  
	if (sendto(s, (void *)&req, sizeof(req), 0, 
		(struct sockaddr *)&snl, sizeof(snl)) < 0)
	{
		fprintf(stderr, "netlink sendto failed: %s\n", strerror (errno));
		return -1;
	}

	return 0;
}


int
netlink_read(int s)
{
	int status;
	int seq = 0;

	while (1) {
		char buf[4096];
		struct iovec iov = { buf, sizeof(buf) };
		struct sockaddr_nl snl;
		struct msghdr msg = {
			(void *)&snl, sizeof(snl), &iov, 1, NULL, 0, 0
		};
		struct nlmsghdr *h;

		status = recvmsg(s, &msg, 0);
		if (status < 0) {
			if (errno == EINTR)
				continue;
			if (errno == EWOULDBLOCK)
				return 0;
			fprintf(stderr, "netlink recvmsg: %s\n", strerror(errno));
	  		continue;
		}

		if (status == 0) {
			fprintf(stderr, "netlink EOF\n");
			return -1;
		}

		if (msg.msg_namelen != sizeof(snl)) {
			fprintf(stderr, "netlink length error: %d != %d\n",
				msg.msg_namelen, sizeof(snl));
			return -1;
		}

		for (h = (struct nlmsghdr *) buf;
			NLMSG_OK(h, status); 
			h = NLMSG_NEXT(h, status))
		{
			seq = h->nlmsg_seq;
			if (h->nlmsg_type == NLMSG_DONE)
				return 0;

			if (h->nlmsg_type == NLMSG_ERROR) {
				struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(h);
				if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
					fprintf(stderr, "netlink: message truncated\n");
				else
					fprintf(stderr, "netlink: %s\n", strerror(-err->error));
				return -1;
			}

			switch (h->nlmsg_type) {
				case RTM_NEWADDR:
				case RTM_DELADDR:
					netlink_ifaddr(&snl, h);
					break;
			}
		}

		if (msg.msg_flags & MSG_TRUNC) {
			fprintf(stderr, "netlink: message truncated\n");
			continue;
		}

		if (status) {
			fprintf(stderr, "netlink: excess data, size %d\n", status);
			return -1;
		}

		/* This message is in reply to a user request. */
		if (seq == 0)
			return 0;
	}

	return 0;
}


int
main(int argc, char *argv[])
{
	int s;

	s = netlink_open();
	if (s >= 0) {
		netlink_request(s, AF_INET, RTM_GETADDR);
		netlink_read(s);
	}
}

  parent reply	other threads:[~2001-09-07 10:31 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20010905170037.A6473@emma1.emma.line.org.suse.lists.linux.kernel>
     [not found] ` <20010905152738.C5912BC06D@spike.porcupine.org.suse.lists.linux.kernel>
     [not found]   ` <20010905182033.D3926@emma1.emma.line.org.suse.lists.linux.kernel>
2001-09-05 19:26     ` ioctl SIOCGIFNETMASK: ip alias bug 2.4.9 and 2.2.19 Andi Kleen
2001-09-06 13:11       ` Matthias Andree
2001-09-06 13:35       ` Andrey Savochkin
2001-09-06 14:04         ` Wietse Venema
2001-09-06 14:21           ` Matthias Andree
2001-09-06 15:37             ` notion of a local address [was: Re: ioctl SIOCGIFNETMASK: ip alias bug 2.4.9 and 2.2.19] Andrey Savochkin
2001-09-06 15:58               ` Wietse Venema
2001-09-06 16:39                 ` notion of a local address [was: Re: ioctl SIOCGIFNETMASK: ip alias Alan Cox
2001-09-06 16:45                   ` Wietse Venema
2001-09-06 16:44                 ` notion of a local address [was: Re: ioctl SIOCGIFNETMASK: ip alias bug 2.4.9 and 2.2.19] Andrey Savochkin
2001-09-06 16:47                   ` Andi Kleen
2001-09-06 17:04                     ` Andrey Savochkin
2001-09-06 16:50                   ` Wietse Venema
2001-09-06 17:01                     ` notion of a local address [was: Re: ioctl SIOCGIFNETMASK: ip alias Alan Cox
2001-09-06 17:23                       ` Wietse Venema
2001-09-06 17:45                         ` Charles Cazabon
2001-09-06 19:34                         ` Alan Cox
2001-09-06 19:41                           ` Wietse Venema
2001-09-06 20:18                             ` Alan Cox
2001-09-06 20:11                           ` Matthias Andree
2001-09-06 20:23                             ` Alan Cox
2001-09-06 20:31                               ` Andi Kleen
2001-09-06 20:52                                 ` Matthias Andree
2001-09-07  9:06                             ` Henning P. Schmiedehausen
2001-09-07  8:52                         ` Matthew Kirkwood
2001-09-08 16:31                           ` Wietse Venema
2001-09-06 18:11                       ` Steve VanDevender
2001-09-06 18:25                         ` Wietse Venema
2001-09-06 19:47                           ` Alan Cox
2001-09-06 20:16                             ` Wietse Venema
2001-09-06 19:10                         ` Steve VanDevender
2001-09-13 14:35                       ` Pavel Machek
2001-09-06 17:03                     ` notion of a local address [was: Re: ioctl SIOCGIFNETMASK: ip alias bug 2.4.9 and 2.2.19] Andi Kleen
2001-09-06 17:23                     ` Andrey Savochkin
2001-09-06 17:39                       ` Wietse Venema
2001-09-06 18:23                         ` H. Peter Anvin
2001-09-07  1:47                           ` Jamie Lokier
2001-09-07  5:48                           ` notion of a local address [was: Re: ioctl SIOCGIFNETMASK: ip aliasbug " Ben Greear
2001-09-07  5:50                             ` H. Peter Anvin
2001-09-17 21:39                               ` Ben Greear
2001-09-07  6:26                             ` Andrey Savochkin
2001-09-07  6:21                               ` H. Peter Anvin
2001-09-06 19:15                         ` notion of a local address [was: Re: ioctl SIOCGIFNETMASK: ip alias bug " dean gaudet
2001-09-06 19:33                           ` Wietse Venema
2001-09-06 20:51                         ` Matti Aarnio
2001-09-07  7:29                           ` Andrey Savochkin
2001-09-07  7:35                             ` Matthias Andree
2001-09-07 10:30                         ` Mike Jagdis [this message]
2001-09-07 11:04                           ` Matthias Andree
2001-09-07 15:34                         ` Kurt Roeckx
2001-09-08 13:16                         ` notion of a local address [was: Re: ioctl SIOCGIFNETMASK: ip alias Kai Henningsen
2001-09-06 18:20                 ` notion of a local address [was: Re: ioctl SIOCGIFNETMASK: ip alias bug 2.4.9 and 2.2.19] H. Peter Anvin
2001-09-06 16:01               ` Matthias Andree
2001-09-06 16:38                 ` Andrey Savochkin
2001-09-06 16:43                   ` Wietse Venema
2001-09-06 17:03                     ` Charles Cazabon
2001-09-06 17:05                   ` Alex Bligh - linux-kernel
2001-09-06 17:37                     ` Andrey Savochkin
2001-09-06 17:55               ` kuznet
2001-09-06 14:51           ` ioctl SIOCGIFNETMASK: ip alias bug 2.4.9 and 2.2.19 Alan Cox
2001-09-06 14:17         ` Matthias Andree
2001-09-08 12:42     ` Kai Henningsen
2001-09-09  0:37       ` Matthias Andree

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3B98A1C0.6010200@purplet.demon.co.uk \
    --to=jaggy@purplet.demon.co.uk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=wietse@porcupine.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).