rtsock.c revision 127141
1327Sjkh/*	$KAME: rtsock.c,v 1.3 2000/10/10 08:46:45 itojun Exp $	*/
2327Sjkh/*	$FreeBSD: head/usr.sbin/rtsold/rtsock.c 127141 2004-03-17 20:10:59Z ru $	*/
3327Sjkh
4327Sjkh/*
5327Sjkh * Copyright (C) 2000 WIDE Project.
6327Sjkh * All rights reserved.
7327Sjkh *
8327Sjkh * Redistribution and use in source and binary forms, with or without
9327Sjkh * modification, are permitted provided that the following conditions
10327Sjkh * are met:
11327Sjkh * 1. Redistributions of source code must retain the above copyright
12327Sjkh *    notice, this list of conditions and the following disclaimer.
13327Sjkh * 2. Redistributions in binary form must reproduce the above copyright
14327Sjkh *    notice, this list of conditions and the following disclaimer in the
15327Sjkh *    documentation and/or other materials provided with the distribution.
16327Sjkh * 3. Neither the name of the project nor the names of its contributors
17327Sjkh *    may be used to endorse or promote products derived from this software
18327Sjkh *    without specific prior written permission.
19327Sjkh *
20327Sjkh * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
2193520Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2293520Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2393520Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2430221Scharnier * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2569793Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26327Sjkh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27327Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28327Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2984670Ssobomax * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30327Sjkh * SUCH DAMAGE.
314996Sjkh */
32327Sjkh
33327Sjkh#include <sys/param.h>
34327Sjkh#include <sys/socket.h>
35327Sjkh#include <sys/uio.h>
3637728Seivind#include <sys/time.h>
37327Sjkh#include <sys/queue.h>
38327Sjkh
39327Sjkh#include <net/if.h>
40327Sjkh#include <net/route.h>
41327Sjkh#include <net/if_dl.h>
42327Sjkh
43327Sjkh#include <netinet/in.h>
44327Sjkh#include <netinet/ip6.h>
45327Sjkh#include <netinet/icmp6.h>
46382Sjkh
47382Sjkh#include <time.h>
48382Sjkh#include <unistd.h>
49382Sjkh#include <stdio.h>
50382Sjkh#include <stddef.h>
51382Sjkh#include <err.h>
52327Sjkh#include <errno.h>
53327Sjkh#include <string.h>
54327Sjkh#include <stdlib.h>
55327Sjkh#include <syslog.h>
5611780Sjkh#include "rtsold.h"
57327Sjkh
588083Sjkh#define ROUNDUP(a, size) \
598083Sjkh	(((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
608083Sjkh
618083Sjkh#define NEXT_SA(ap) (ap) = (struct sockaddr *) \
628083Sjkh	((caddr_t)(ap) + \
63327Sjkh	 ((ap)->sa_len ? ROUNDUP((ap)->sa_len, sizeof(u_long)) \
64327Sjkh		       : sizeof(u_long)))
65327Sjkh
66327Sjkh#ifdef RTM_IFANNOUNCE	/*NetBSD 1.5 or later*/
6711780Sjkhstatic int rtsock_input_ifannounce __P((int, struct rt_msghdr *, char *));
687998Sjkh#endif
6984670Ssobomax
70327Sjkhstatic struct {
7111780Sjkh	u_char type;
721545Sjkh	size_t minlen;
733364Sjkh	int (*func) __P((int, struct rt_msghdr *, char *));
74131280Seik} rtsock_dispatch[] = {
7541866Sjkh#ifdef RTM_IFANNOUNCE	/*NetBSD 1.5 or later*/
7641866Sjkh	{ RTM_IFANNOUNCE, sizeof(struct if_announcemsghdr),
7741866Sjkh	  rtsock_input_ifannounce },
7841866Sjkh#endif
7941866Sjkh	{ 0, 0, NULL },
80113594Skris};
81113594Skris
82327Sjkhint
83113594Skrisrtsock_open(void)
8411780Sjkh{
8537728Seivind
86327Sjkh	return socket(PF_ROUTE, SOCK_RAW, 0);
8711780Sjkh}
8811780Sjkh
898075Sjkhint
908083Sjkhrtsock_input(int s)
9111780Sjkh{
9211780Sjkh	ssize_t n;
9311780Sjkh	char msg[2048];
9411780Sjkh	char *lim, *next;
9530221Scharnier	struct rt_msghdr *rtm;
96382Sjkh	int idx;
97382Sjkh	size_t len;
98382Sjkh	int ret = 0;
9911780Sjkh	const size_t lenlim =
100327Sjkh	    offsetof(struct rt_msghdr, rtm_msglen) + sizeof(rtm->rtm_msglen);
1018083Sjkh
102382Sjkh	n = read(s, msg, sizeof(msg));
103102383Sobrien
1048083Sjkh	lim = msg + n;
105154145Sflz	for (next = msg; next < lim; next += len) {
10681046Ssobomax		rtm = (struct rt_msghdr *)next;
1078083Sjkh		if (lim - next < lenlim)
1088083Sjkh			break;
10911780Sjkh		len = rtm->rtm_msglen;
11011780Sjkh		if (len < lenlim)
11111780Sjkh			break;
11211780Sjkh
11330221Scharnier		if (dflag > 1) {
11481046Ssobomax			warnmsg(LOG_INFO, __func__,
11530221Scharnier			    "rtmsg type %d, len=%lu", rtm->rtm_type,
11611780Sjkh			    (u_long)len);
11711780Sjkh		}
11811780Sjkh
11911780Sjkh		for (idx = 0; rtsock_dispatch[idx].func; idx++) {
120382Sjkh			if (rtm->rtm_type != rtsock_dispatch[idx].type)
1218083Sjkh				continue;
12276739Ssobomax			if (rtm->rtm_msglen < rtsock_dispatch[idx].minlen) {
12376739Ssobomax				warnmsg(LOG_INFO, __func__,
12476739Ssobomax				    "rtmsg type %d too short!", rtm->rtm_type);
12576739Ssobomax				continue;
12614582Sjkh			}
12714582Sjkh
12830221Scharnier			ret = (*rtsock_dispatch[idx].func)(s, rtm, lim);
12914582Sjkh			break;
13014582Sjkh		}
13114582Sjkh	}
13214582Sjkh
13311780Sjkh	return ret;
13422750Sjkh}
13514582Sjkh
13622750Sjkh#ifdef RTM_IFANNOUNCE	/*NetBSD 1.5 or later*/
13722750Sjkhstatic int
13811780Sjkhrtsock_input_ifannounce(int s, struct rt_msghdr *rtm, char *lim)
13911780Sjkh{
140132799Sstefanf	struct if_announcemsghdr *ifan;
14111780Sjkh	struct ifinfo *ifinfo;
14238583Sjkh
14338583Sjkh	ifan = (struct if_announcemsghdr *)rtm;
14438583Sjkh	if ((char *)(ifan + 1) > lim)
14514582Sjkh		return -1;
14630221Scharnier
14781046Ssobomax	switch (ifan->ifan_what) {
14830221Scharnier	case IFAN_ARRIVAL:
14911780Sjkh		/*
15011780Sjkh		 * XXX for NetBSD 1.5, interface index will monotonically be
15111780Sjkh		 * increased as new pcmcia card gets inserted.
15211780Sjkh		 * we may be able to do a name-based interface match,
15330221Scharnier		 * and call ifreconfig() to enable the interface again.
15481046Ssobomax		 */
15530221Scharnier		warnmsg(LOG_INFO, __func__,
15611780Sjkh		    "interface %s inserted", ifan->ifan_name);
15711780Sjkh		break;
15811780Sjkh	case IFAN_DEPARTURE:
15911780Sjkh		warnmsg(LOG_WARNING, __func__,
1607998Sjkh		    "interface %s removed", ifan->ifan_name);
16111780Sjkh		ifinfo = find_ifinfo(ifan->ifan_index);
16211780Sjkh		if (ifinfo) {
16311780Sjkh			if (dflag > 1) {
16411780Sjkh				warnmsg(LOG_INFO, __func__,
16511780Sjkh				    "bring interface %s to DOWN state",
16611780Sjkh				    ifan->ifan_name);
16711780Sjkh			}
16811780Sjkh			ifinfo->state = IFS_DOWN;
16911780Sjkh		}
170131285Seik		break;
17111780Sjkh	}
17281046Ssobomax
17311780Sjkh	return 0;
17411780Sjkh}
1757998Sjkh#endif
17611780Sjkh