File:  [DragonFly] / src / libexec / bootpd / rtmsg.c
Revision 1.2: download - view: text, annotated - select for diffs
Tue Jun 17 04:27:07 2003 UTC (10 years, 10 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids.  Most
ids have been removed from !lint sections and moved into comment sections.

    1: /*
    2:  * Copyright (c) 1984, 1993
    3:  *	The Regents of the University of California.  All rights reserved.
    4:  * Copyright (c) 1994
    5:  *	Geoffrey M. Rehmet, All rights reserved.
    6:  *
    7:  * This code is derived from software which forms part of the 4.4-Lite
    8:  * Berkeley software distribution, which was in derived from software
    9:  * contributed to Berkeley by Sun Microsystems, Inc.
   10:  *
   11:  * Redistribution and use in source and binary forms, with or without
   12:  * modification, are permitted provided that the following conditions
   13:  * are met:
   14:  * 1. Redistributions of source code must retain the above copyright
   15:  *    notice, this list of conditions and the following disclaimer.
   16:  * 2. Redistributions in binary form must reproduce the above copyright
   17:  *    notice, this list of conditions and the following disclaimer in the
   18:  *    documentation and/or other materials provided with the distribution.
   19:  * 3. All advertising materials mentioning features or use of this software
   20:  *    must display the following acknowledgement:
   21:  *	This product includes software developed by the University of
   22:  *	California, Berkeley and its contributors.
   23:  * 4. Neither the name of the University nor the names of its contributors
   24:  *    may be used to endorse or promote products derived from this software
   25:  *    without specific prior written permission.
   26:  *
   27:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   28:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   29:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   30:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   31:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   32:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   33:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   34:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   35:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   36:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   37:  * SUCH DAMAGE.
   38:  */
   39: 
   40: /*
   41:  * from arp.c	8.2 (Berkeley) 1/2/94
   42:  * $FreeBSD: src/libexec/bootpd/rtmsg.c,v 1.10 1999/08/28 00:09:19 peter Exp $
   43:  * $DragonFly: src/libexec/bootpd/rtmsg.c,v 1.2 2003/06/17 04:27:07 dillon Exp $
   44:  */
   45: 
   46: #include <sys/param.h>
   47: /*
   48:  * Verify that we are at least 4.4 BSD
   49:  */
   50: #if defined(BSD)
   51: #if BSD >= 199306
   52: 
   53: #include <sys/socket.h>
   54: #include <sys/filio.h>
   55: #include <sys/time.h>
   56: 
   57: #include <net/if.h>
   58: #include <net/if_dl.h>
   59: #include <net/if_types.h>
   60: #include <net/route.h>
   61: 
   62: #include <netinet/in.h>
   63: #include <netinet/if_ether.h>
   64: 
   65: #include <arpa/inet.h>
   66: 
   67: #include <errno.h>
   68: #include <stdio.h>
   69: #include <string.h>
   70: #include <syslog.h>
   71: #include <unistd.h>
   72: 
   73: #include "report.h"
   74: 
   75: 
   76: static int rtmsg __P((int));
   77: 
   78: static int s = -1; 	/* routing socket */
   79: 
   80: 
   81: /*
   82:  * Open the routing socket
   83:  */
   84: static void getsocket () {
   85: 	if (s < 0) {
   86: 		s = socket(PF_ROUTE, SOCK_RAW, 0);
   87: 		if (s < 0) {
   88: 			report(LOG_ERR, "socket %s", strerror(errno));
   89: 			exit(1);
   90: 		}
   91: 	} else {
   92: 		/*
   93: 		 * Drain the socket of any unwanted routing messages.
   94: 		 */
   95: 		int n;
   96: 		char buf[512];
   97: 
   98: 		ioctl(s, FIONREAD, &n);
   99: 		while (n > 0) {
  100: 			read(s, buf, sizeof buf);
  101: 			ioctl(s, FIONREAD, &n);
  102: 		}
  103: 	}
  104: }
  105: 
  106: static struct	sockaddr_in so_mask = {8, 0, 0, { 0xffffffff}};
  107: static struct	sockaddr_inarp blank_sin = {sizeof(blank_sin), AF_INET }, sin_m;
  108: static struct	sockaddr_dl blank_sdl = {sizeof(blank_sdl), AF_LINK }, sdl_m;
  109: static int	expire_time, flags, export_only, doing_proxy;
  110: static struct	{
  111: 	struct	rt_msghdr m_rtm;
  112: 	char	m_space[512];
  113: }	m_rtmsg;
  114: 
  115: /*
  116:  * Set an individual arp entry
  117:  */
  118: int bsd_arp_set(ia, eaddr, len)
  119: 	struct in_addr *ia;
  120: 	char *eaddr;
  121: 	int len;
  122: {
  123: 	register struct sockaddr_inarp *sin = &sin_m;
  124: 	register struct sockaddr_dl *sdl;
  125: 	register struct rt_msghdr *rtm = &(m_rtmsg.m_rtm);
  126: 	u_char *ea;
  127: 	struct timeval time;
  128: 	int op = RTM_ADD;
  129: 
  130: 	getsocket();
  131: 	sdl_m = blank_sdl;
  132: 	sin_m = blank_sin;
  133: 	sin->sin_addr = *ia;
  134: 
  135: 	ea = (u_char *)LLADDR(&sdl_m);
  136: 	bcopy(eaddr, ea, len);
  137: 	sdl_m.sdl_alen = len;
  138: 	doing_proxy = flags = export_only = expire_time = 0;
  139: 
  140: 	/* make arp entry temporary */
  141: 	gettimeofday(&time, 0);
  142: 	expire_time = time.tv_sec + 20 * 60;
  143: 
  144: tryagain:
  145: 	if (rtmsg(RTM_GET) < 0) {
  146: 		report(LOG_WARNING, "rtmget: %s", strerror(errno));
  147: 		return (1);
  148: 	}
  149: 	sin = (struct sockaddr_inarp *)(rtm + 1);
  150: 	sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin);
  151: 	if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) {
  152: 		if (sdl->sdl_family == AF_LINK &&
  153: 		    (rtm->rtm_flags & RTF_LLINFO) &&
  154: 		    !(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) {
  155: 		case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023:
  156: 		case IFT_ISO88024: case IFT_ISO88025:
  157: 			op = RTM_CHANGE;
  158: 			goto overwrite;
  159: 		}
  160: 		if (doing_proxy == 0) {
  161: 			report(LOG_WARNING, "set: can only proxy for %s\n",
  162: 				inet_ntoa(sin->sin_addr));
  163: 			return (1);
  164: 		}
  165: 		if (sin_m.sin_other & SIN_PROXY) {
  166: 			report(LOG_WARNING,
  167: 				"set: proxy entry exists for non 802 device\n");
  168: 			return(1);
  169: 		}
  170: 		sin_m.sin_other = SIN_PROXY;
  171: 		export_only = 1;
  172: 		goto tryagain;
  173: 	}
  174: overwrite:
  175: 	if (sdl->sdl_family != AF_LINK) {
  176: 		report(LOG_WARNING,
  177: 			"cannot intuit interface index and type for %s\n",
  178: 			inet_ntoa(sin->sin_addr));
  179: 		return (1);
  180: 	}
  181: 	sdl_m.sdl_type = sdl->sdl_type;
  182: 	sdl_m.sdl_index = sdl->sdl_index;
  183: 	return (rtmsg(op));
  184: }
  185: 
  186: 
  187: static int rtmsg(cmd)
  188: 	int cmd;
  189: {
  190: 	static int seq;
  191: 	int rlen;
  192: 	register struct rt_msghdr *rtm = &m_rtmsg.m_rtm;
  193: 	register char *cp = m_rtmsg.m_space;
  194: 	register int l;
  195: 
  196: 	errno = 0;
  197: 	bzero((char *)&m_rtmsg, sizeof(m_rtmsg));
  198: 	rtm->rtm_flags = flags;
  199: 	rtm->rtm_version = RTM_VERSION;
  200: 
  201: 	switch (cmd) {
  202: 	default:
  203: 		report(LOG_ERR, "set_arp: internal wrong cmd - exiting");
  204: 		exit(1);
  205: 	case RTM_ADD:
  206: 	case RTM_CHANGE:
  207: 		rtm->rtm_addrs |= RTA_GATEWAY;
  208: 		rtm->rtm_rmx.rmx_expire = expire_time;
  209: 		rtm->rtm_inits = RTV_EXPIRE;
  210: 		rtm->rtm_flags |= (RTF_HOST | RTF_STATIC);
  211: 		sin_m.sin_other = 0;
  212: 		if (doing_proxy) {
  213: 			if (export_only)
  214: 				sin_m.sin_other = SIN_PROXY;
  215: 			else {
  216: 				rtm->rtm_addrs |= RTA_NETMASK;
  217: 				rtm->rtm_flags &= ~RTF_HOST;
  218: 			}
  219: 		}
  220: 		/* FALLTHROUGH */
  221: 	case RTM_GET:
  222: 		rtm->rtm_addrs |= RTA_DST;
  223: 	}
  224: #define NEXTADDR(w, s) \
  225: 	if (rtm->rtm_addrs & (w)) { \
  226: 		bcopy((char *)&s, cp, sizeof(s)); cp += sizeof(s);}
  227: 
  228: 	NEXTADDR(RTA_DST, sin_m);
  229: 	NEXTADDR(RTA_GATEWAY, sdl_m);
  230: 	NEXTADDR(RTA_NETMASK, so_mask);
  231: 
  232: 	rtm->rtm_msglen = cp - (char *)&m_rtmsg;
  233: 
  234: 	l = rtm->rtm_msglen;
  235: 	rtm->rtm_seq = ++seq;
  236: 	rtm->rtm_type = cmd;
  237: 	if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) {
  238: 		if ((errno != ESRCH) && !(errno == EEXIST && cmd == RTM_ADD)){
  239: 			report(LOG_WARNING, "writing to routing socket: %s",
  240: 				strerror(errno));
  241: 			return (-1);
  242: 		}
  243: 	}
  244: 	do {
  245: 		l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
  246: 	} while (l > 0 && (rtm->rtm_type != cmd || rtm->rtm_seq != seq || rtm->rtm_pid != getpid()));
  247: 	if (l < 0)
  248: 		report(LOG_WARNING, "arp: read from routing socket: %s\n",
  249: 		    strerror(errno));
  250: 	return (0);
  251: }
  252: 
  253: #endif /* BSD */
  254: #endif /* BSD >= 199306 */