rtsock.c revision 124524
178064Sume/* $KAME: rtsock.c,v 1.3 2000/10/10 08:46:45 itojun Exp $ */ 278064Sume/* $FreeBSD: head/usr.sbin/rtsold/rtsock.c 124524 2004-01-14 17:16:19Z ume $ */ 378064Sume 478064Sume/* 578064Sume * Copyright (C) 2000 WIDE Project. 678064Sume * All rights reserved. 778064Sume * 878064Sume * Redistribution and use in source and binary forms, with or without 978064Sume * modification, are permitted provided that the following conditions 1078064Sume * are met: 1178064Sume * 1. Redistributions of source code must retain the above copyright 1278064Sume * notice, this list of conditions and the following disclaimer. 1378064Sume * 2. Redistributions in binary form must reproduce the above copyright 1478064Sume * notice, this list of conditions and the following disclaimer in the 1578064Sume * documentation and/or other materials provided with the distribution. 1678064Sume * 3. Neither the name of the project nor the names of its contributors 1778064Sume * may be used to endorse or promote products derived from this software 1878064Sume * without specific prior written permission. 1978064Sume * 2078064Sume * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 2178064Sume * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2278064Sume * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2378064Sume * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 2478064Sume * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2578064Sume * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2678064Sume * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2778064Sume * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2878064Sume * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2978064Sume * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3078064Sume * SUCH DAMAGE. 3178064Sume */ 3278064Sume 3378064Sume#include <sys/param.h> 3478064Sume#include <sys/socket.h> 3578064Sume#include <sys/uio.h> 3678064Sume#include <sys/time.h> 3778064Sume#include <sys/queue.h> 3878064Sume 3978064Sume#include <net/if.h> 4078064Sume#include <net/route.h> 4178064Sume#include <net/if_dl.h> 4278064Sume 4378064Sume#include <netinet/in.h> 4478064Sume#include <netinet/ip6.h> 4578064Sume#include <netinet/icmp6.h> 4678064Sume 4778064Sume#include <time.h> 4878064Sume#include <unistd.h> 4978064Sume#include <stdio.h> 5078064Sume#include <stddef.h> 5178064Sume#include <err.h> 5278064Sume#include <errno.h> 5378064Sume#include <string.h> 5478064Sume#include <stdlib.h> 5578064Sume#include <syslog.h> 5678064Sume#include "rtsold.h" 5778064Sume 5878064Sume#define ROUNDUP(a, size) \ 5978064Sume (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a)) 6078064Sume 6178064Sume#define NEXT_SA(ap) (ap) = (struct sockaddr *) \ 6278064Sume ((caddr_t)(ap) + \ 6378064Sume ((ap)->sa_len ? ROUNDUP((ap)->sa_len, sizeof(u_long)) \ 6478064Sume : sizeof(u_long))) 6578064Sume 6678064Sume#ifdef RTM_IFANNOUNCE /*NetBSD 1.5 or later*/ 6778064Sumestatic int rtsock_input_ifannounce __P((int, struct rt_msghdr *, char *)); 6878064Sume#endif 6978064Sume 7078064Sumestatic struct { 7178064Sume u_char type; 7278064Sume size_t minlen; 7378064Sume int (*func) __P((int, struct rt_msghdr *, char *)); 7478064Sume} rtsock_dispatch[] = { 7578064Sume#ifdef RTM_IFANNOUNCE /*NetBSD 1.5 or later*/ 7678064Sume { RTM_IFANNOUNCE, sizeof(struct if_announcemsghdr), 7778064Sume rtsock_input_ifannounce }, 7878064Sume#endif 7978064Sume { 0, NULL }, 8078064Sume}; 8178064Sume 8278064Sumeint 83124524Sumertsock_open(void) 8478064Sume{ 8578064Sume 8678064Sume return socket(PF_ROUTE, SOCK_RAW, 0); 8778064Sume} 8878064Sume 8978064Sumeint 90124524Sumertsock_input(int s) 9178064Sume{ 9278064Sume ssize_t n; 9378064Sume char msg[2048]; 9478064Sume char *lim, *next; 9578064Sume struct rt_msghdr *rtm; 9678064Sume int idx; 9778064Sume size_t len; 9878064Sume int ret = 0; 9978064Sume const size_t lenlim = 10078064Sume offsetof(struct rt_msghdr, rtm_msglen) + sizeof(rtm->rtm_msglen); 10178064Sume 10278064Sume n = read(s, msg, sizeof(msg)); 10378064Sume 10478064Sume lim = msg + n; 10578064Sume for (next = msg; next < lim; next += len) { 10678064Sume rtm = (struct rt_msghdr *)next; 10778064Sume if (lim - next < lenlim) 10878064Sume break; 10978064Sume len = rtm->rtm_msglen; 11078064Sume if (len < lenlim) 11178064Sume break; 11278064Sume 11378064Sume if (dflag > 1) { 114118660Sume warnmsg(LOG_INFO, __func__, 11578064Sume "rtmsg type %d, len=%lu", rtm->rtm_type, 11678064Sume (u_long)len); 11778064Sume } 11878064Sume 11978064Sume for (idx = 0; rtsock_dispatch[idx].func; idx++) { 12078064Sume if (rtm->rtm_type != rtsock_dispatch[idx].type) 12178064Sume continue; 12278064Sume if (rtm->rtm_msglen < rtsock_dispatch[idx].minlen) { 123118660Sume warnmsg(LOG_INFO, __func__, 12478064Sume "rtmsg type %d too short!", rtm->rtm_type); 12578064Sume continue; 12678064Sume } 12778064Sume 12878064Sume ret = (*rtsock_dispatch[idx].func)(s, rtm, lim); 12978064Sume break; 13078064Sume } 13178064Sume } 13278064Sume 13378064Sume return ret; 13478064Sume} 13578064Sume 13678064Sume#ifdef RTM_IFANNOUNCE /*NetBSD 1.5 or later*/ 13778064Sumestatic int 138124524Sumertsock_input_ifannounce(int s, struct rt_msghdr *rtm, char *lim) 13978064Sume{ 14078064Sume struct if_announcemsghdr *ifan; 14178064Sume struct ifinfo *ifinfo; 14278064Sume 14378064Sume ifan = (struct if_announcemsghdr *)rtm; 14478064Sume if ((char *)(ifan + 1) > lim) 14578064Sume return -1; 14678064Sume 14778064Sume switch (ifan->ifan_what) { 14878064Sume case IFAN_ARRIVAL: 14978064Sume /* 15078064Sume * XXX for NetBSD 1.5, interface index will monotonically be 15178064Sume * increased as new pcmcia card gets inserted. 15278064Sume * we may be able to do a name-based interface match, 15378064Sume * and call ifreconfig() to enable the interface again. 15478064Sume */ 155118660Sume warnmsg(LOG_INFO, __func__, 15678064Sume "interface %s inserted", ifan->ifan_name); 15778064Sume break; 15878064Sume case IFAN_DEPARTURE: 159118660Sume warnmsg(LOG_WARNING, __func__, 16078064Sume "interface %s removed", ifan->ifan_name); 16178064Sume ifinfo = find_ifinfo(ifan->ifan_index); 16278064Sume if (ifinfo) { 16378064Sume if (dflag > 1) { 164118660Sume warnmsg(LOG_INFO, __func__, 16578064Sume "bring interface %s to DOWN state", 16678064Sume ifan->ifan_name); 16778064Sume } 16878064Sume ifinfo->state = IFS_DOWN; 16978064Sume } 17078064Sume break; 17178064Sume } 17278064Sume 17378064Sume return 0; 17478064Sume} 17578064Sume#endif 176