File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon / sockmisc.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:39:10 2012 UTC (12 years, 4 months ago) by misho
Branches: ipsec-tools, MAIN
CVS tags: v0_8_2p2, v0_8_1p0, v0_8_1, v0_8_0p0, v0_8_0, HEAD
ipsec-tools

    1: /*	$NetBSD: sockmisc.c,v 1.19 2011/03/14 17:18:13 tteras Exp $	*/
    2: 
    3: /* Id: sockmisc.c,v 1.24 2006/05/07 21:32:59 manubsd Exp */
    4: 
    5: /*
    6:  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    7:  * All rights reserved.
    8:  * 
    9:  * Redistribution and use in source and binary forms, with or without
   10:  * modification, are permitted provided that the following conditions
   11:  * are met:
   12:  * 1. Redistributions of source code must retain the above copyright
   13:  *    notice, this list of conditions and the following disclaimer.
   14:  * 2. Redistributions in binary form must reproduce the above copyright
   15:  *    notice, this list of conditions and the following disclaimer in the
   16:  *    documentation and/or other materials provided with the distribution.
   17:  * 3. Neither the name of the project nor the names of its contributors
   18:  *    may be used to endorse or promote products derived from this software
   19:  *    without specific prior written permission.
   20:  * 
   21:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31:  * SUCH DAMAGE.
   32:  */
   33: 
   34: #include "config.h"
   35: 
   36: #include <sys/types.h>
   37: #include <sys/param.h>
   38: #include <sys/socket.h>
   39: #include <sys/uio.h>
   40: 
   41: #include <netinet/in.h>
   42: #include PATH_IPSEC_H
   43: 
   44: #if defined(INET6) && !defined(INET6_ADVAPI) && \
   45: 	defined(IP_RECVDSTADDR) && !defined(IPV6_RECVDSTADDR)
   46: #define IPV6_RECVDSTADDR IP_RECVDSTADDR
   47: #endif
   48: 
   49: #include <stdlib.h>
   50: #include <stdio.h>
   51: #include <string.h>
   52: #include <errno.h>
   53: #ifdef HAVE_UNISTD_H
   54: #include <unistd.h>
   55: #endif
   56: 
   57: #include "var.h"
   58: #include "misc.h"
   59: #include "vmbuf.h"
   60: #include "plog.h"
   61: #include "sockmisc.h"
   62: #include "debug.h"
   63: #include "gcmalloc.h"
   64: #include "debugrm.h"
   65: #include "libpfkey.h"
   66: #include "isakmp_var.h"
   67: 
   68: #ifdef NOUSE_PRIVSEP
   69: #define BIND bind
   70: #define SOCKET socket
   71: #define SETSOCKOPT setsockopt
   72: #else
   73: #include "admin.h"
   74: #include "privsep.h"
   75: #define BIND privsep_bind
   76: #define SOCKET privsep_socket
   77: #define SETSOCKOPT privsep_setsockopt
   78: #endif
   79: 
   80: const int niflags = 0;
   81: 
   82: /*
   83:  * compare two sockaddr with port, taking care wildcard.
   84:  * addr1 is a subject address, addr2 is in a database entry.
   85:  * OUT:	0: equal.
   86:  *	1: not equal.
   87:  */
   88: int
   89: cmpsaddr(addr1, addr2)
   90: 	const struct sockaddr *addr1;
   91: 	const struct sockaddr *addr2;
   92: {
   93: 	caddr_t sa1, sa2;
   94: 	u_short port1 = IPSEC_PORT_ANY;
   95: 	u_short port2 = IPSEC_PORT_ANY;
   96: 
   97: 	if (addr1 == NULL && addr2 == NULL)
   98: 		return CMPSADDR_MATCH;
   99: 
  100: 	if (addr1 == NULL || addr2 == NULL)
  101: 		return CMPSADDR_MISMATCH;
  102: 
  103: 	if (addr1->sa_family != addr2->sa_family ||
  104: 	    sysdep_sa_len(addr1) != sysdep_sa_len(addr2))
  105: 		return CMPSADDR_MISMATCH;
  106: 
  107: 	switch (addr1->sa_family) {
  108: 	case AF_UNSPEC:
  109: 		break;
  110: 	case AF_INET:
  111: 		sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr;
  112: 		sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr;
  113: 		port1 = ((struct sockaddr_in *)addr1)->sin_port;
  114: 		port2 = ((struct sockaddr_in *)addr2)->sin_port;
  115: 		if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0)
  116: 			return CMPSADDR_MISMATCH;
  117: 		break;
  118: #ifdef INET6
  119: 	case AF_INET6:
  120: 		sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr;
  121: 		sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr;
  122: 		port1 = ((struct sockaddr_in6 *)addr1)->sin6_port;
  123: 		port2 = ((struct sockaddr_in6 *)addr2)->sin6_port;
  124: 		if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0)
  125: 			return CMPSADDR_MISMATCH;
  126: 		if (((struct sockaddr_in6 *)addr1)->sin6_scope_id !=
  127: 		    ((struct sockaddr_in6 *)addr2)->sin6_scope_id)
  128: 			return CMPSADDR_MISMATCH;
  129: 		break;
  130: #endif
  131: 	default:
  132: 		return CMPSADDR_MISMATCH;
  133: 	}
  134: 
  135: 	if (port1 == port2)
  136: 		return CMPSADDR_MATCH;
  137: 
  138: 	if (port1 == IPSEC_PORT_ANY ||
  139: 	    port2 == IPSEC_PORT_ANY)
  140: 		return CMPSADDR_WILDPORT_MATCH;
  141: 
  142: 	return CMPSADDR_WOP_MATCH;
  143: }
  144: 
  145: /* get local address against the destination. */
  146: struct sockaddr *
  147: getlocaladdr(remote)
  148: 	struct sockaddr *remote;
  149: {
  150: 	struct sockaddr *local;
  151: 	u_int local_len = sizeof(struct sockaddr_storage);
  152: 	int s;	/* for dummy connection */
  153: 
  154: 	/* allocate buffer */
  155: 	if ((local = racoon_calloc(1, local_len)) == NULL) {
  156: 		plog(LLV_ERROR, LOCATION, NULL,
  157: 			"failed to get address buffer.\n");
  158: 		goto err;
  159: 	}
  160: 	
  161: 	/* get real interface received packet */
  162: 	if ((s = SOCKET(remote->sa_family, SOCK_DGRAM, 0)) < 0) {
  163: 		plog(LLV_ERROR, LOCATION, NULL,
  164: 			"socket (%s)\n", strerror(errno));
  165: 		goto err;
  166: 	}
  167: 
  168: 	setsockopt_bypass(s, remote->sa_family);
  169: 	
  170: 	if (connect(s, remote, sysdep_sa_len(remote)) < 0) {
  171: 		plog(LLV_ERROR, LOCATION, NULL,
  172: 			"connect (%s)\n", strerror(errno));
  173: 		close(s);
  174: 		goto err;
  175: 	}
  176: 
  177: 	if (getsockname(s, local, &local_len) < 0) {
  178: 		plog(LLV_ERROR, LOCATION, NULL,
  179: 			"getsockname (%s)\n", strerror(errno));
  180: 		close(s);
  181: 		return NULL;
  182: 	}
  183: 
  184: 	close(s);
  185: 	return local;
  186: 
  187:     err:
  188: 	if (local != NULL)
  189: 		racoon_free(local);
  190: 	return NULL;
  191: }
  192: 
  193: /*
  194:  * Receive packet, with src/dst information.  It is assumed that necessary
  195:  * setsockopt() have already performed on socket.
  196:  */
  197: int
  198: recvfromto(s, buf, buflen, flags, from, fromlen, to, tolen)
  199: 	int s;
  200: 	void *buf;
  201: 	size_t buflen;
  202: 	int flags;
  203: 	struct sockaddr *from;
  204: 	socklen_t *fromlen;
  205: 	struct sockaddr *to;
  206: 	u_int *tolen;
  207: {
  208: 	int otolen;
  209: 	socklen_t slen;
  210: 	int len;
  211: 	union sockaddr_any sa;
  212: 	struct msghdr m;
  213: 	struct cmsghdr *cm;
  214: 	struct iovec iov[2];
  215: 	u_char cmsgbuf[256];
  216: #if defined(INET6) && defined(INET6_ADVAPI)
  217: 	struct in6_pktinfo *pi;
  218: #endif /*INET6_ADVAPI*/
  219: 	struct sockaddr_in *sin;
  220: #ifdef INET6
  221: 	struct sockaddr_in6 *sin6;
  222: #endif
  223: 
  224: 	slen = sizeof(sa);
  225: 	if (getsockname(s, &sa.sa, &slen) < 0) {
  226: 		plog(LLV_ERROR, LOCATION, NULL,
  227: 			"getsockname (%s)\n", strerror(errno));
  228: 		return -1;
  229: 	}
  230: 
  231: 	m.msg_name = (caddr_t)from;
  232: 	m.msg_namelen = *fromlen;
  233: 	iov[0].iov_base = (caddr_t)buf;
  234: 	iov[0].iov_len = buflen;
  235: 	m.msg_iov = iov;
  236: 	m.msg_iovlen = 1;
  237: 	memset(cmsgbuf, 0, sizeof(cmsgbuf));
  238: 	cm = (struct cmsghdr *)cmsgbuf;
  239: 	m.msg_control = (caddr_t)cm;
  240: 	m.msg_controllen = sizeof(cmsgbuf);
  241: 	if ((len = recvmsg(s, &m, flags)) < 0) {
  242: 		plog(LLV_ERROR, LOCATION, NULL,
  243: 			"recvmsg (%s)\n", strerror(errno));
  244: 		return -1;
  245: 	}
  246: 	*fromlen = m.msg_namelen;
  247: 
  248: 	otolen = *tolen;
  249: 	*tolen = 0;
  250: 	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&m);
  251: 	     m.msg_controllen != 0 && cm;
  252: 	     cm = (struct cmsghdr *)CMSG_NXTHDR(&m, cm)) {
  253: #if 0
  254: 		plog(LLV_ERROR, LOCATION, NULL,
  255: 			"cmsg %d %d\n", cm->cmsg_level, cm->cmsg_type);)
  256: #endif
  257: #if defined(INET6) && defined(INET6_ADVAPI)
  258: 		if (sa.sa.sa_family == AF_INET6
  259: 		 && cm->cmsg_level == IPPROTO_IPV6
  260: 		 && cm->cmsg_type == IPV6_PKTINFO
  261: 		 && otolen >= sizeof(*sin6)) {
  262: 			pi = (struct in6_pktinfo *)(CMSG_DATA(cm));
  263: 			*tolen = sizeof(*sin6);
  264: 			sin6 = (struct sockaddr_in6 *)to;
  265: 			memset(sin6, 0, sizeof(*sin6));
  266: 			sin6->sin6_family = AF_INET6;
  267: #ifndef __linux__
  268: 			sin6->sin6_len = sizeof(*sin6);
  269: #endif
  270: 			memcpy(&sin6->sin6_addr, &pi->ipi6_addr,
  271: 				sizeof(sin6->sin6_addr));
  272: 			/* XXX other cases, such as site-local? */
  273: 			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
  274: 				sin6->sin6_scope_id = pi->ipi6_ifindex;
  275: 			else
  276: 				sin6->sin6_scope_id = 0;
  277: 			sin6->sin6_port = sa.sin6.sin6_port;
  278: 			otolen = -1;	/* "to" already set */
  279: 			continue;
  280: 		}
  281: #endif
  282: #ifdef __linux__
  283: 		if (sa.sa.sa_family == AF_INET
  284: 		 && cm->cmsg_level == IPPROTO_IP
  285: 		 && cm->cmsg_type == IP_PKTINFO
  286: 		 && otolen >= sizeof(sin)) {
  287: 			struct in_pktinfo *pi = (struct in_pktinfo *)(CMSG_DATA(cm));
  288: 			*tolen = sizeof(*sin);
  289: 			sin = (struct sockaddr_in *)to;
  290: 			memset(sin, 0, sizeof(*sin));
  291: 			sin->sin_family = AF_INET;
  292: 			memcpy(&sin->sin_addr, &pi->ipi_addr,
  293: 				sizeof(sin->sin_addr));
  294: 			sin->sin_port = sa.sin.sin_port;
  295: 			otolen = -1;	/* "to" already set */
  296: 			continue;
  297: 		}
  298: #endif
  299: #if defined(INET6) && defined(IPV6_RECVDSTADDR)
  300: 		if (sa.sa.sa_family == AF_INET6
  301: 		      && cm->cmsg_level == IPPROTO_IPV6
  302: 		      && cm->cmsg_type == IPV6_RECVDSTADDR
  303: 		      && otolen >= sizeof(*sin6)) {
  304: 			*tolen = sizeof(*sin6);
  305: 			sin6 = (struct sockaddr_in6 *)to;
  306: 			memset(sin6, 0, sizeof(*sin6));
  307: 			sin6->sin6_family = AF_INET6;
  308: 			sin6->sin6_len = sizeof(*sin6);
  309: 			memcpy(&sin6->sin6_addr, CMSG_DATA(cm),
  310: 				sizeof(sin6->sin6_addr));
  311: 			sin6->sin6_port = sa.sin6.sin6_port;
  312: 			otolen = -1;	/* "to" already set */
  313: 			continue;
  314: 		}
  315: #endif
  316: #ifndef __linux__
  317: 		if (sa.sa.sa_family == AF_INET
  318: 		 && cm->cmsg_level == IPPROTO_IP
  319: 		 && cm->cmsg_type == IP_RECVDSTADDR
  320: 		 && otolen >= sizeof(*sin)) {
  321: 			*tolen = sizeof(*sin);
  322: 			sin = (struct sockaddr_in *)to;
  323: 			memset(sin, 0, sizeof(*sin));
  324: 			sin->sin_family = AF_INET;
  325: 			sin->sin_len = sizeof(*sin);
  326: 			memcpy(&sin->sin_addr, CMSG_DATA(cm),
  327: 				sizeof(sin->sin_addr));
  328: 			sin->sin_port = sa.sin.sin_port;
  329: 			otolen = -1;	/* "to" already set */
  330: 			continue;
  331: 		}
  332: #endif
  333: 	}
  334: 
  335: 	return len;
  336: }
  337: 
  338: /* send packet, with fixing src/dst address pair. */
  339: int
  340: sendfromto(s, buf, buflen, src, dst, cnt)
  341: 	int s, cnt;
  342: 	const void *buf;
  343: 	size_t buflen;
  344: 	struct sockaddr *src;
  345: 	struct sockaddr *dst;
  346: {
  347: 	struct sockaddr_storage ss;
  348: 	socklen_t slen;
  349: 	int len = 0;
  350: 	int i;
  351: 
  352: 	if (src->sa_family != dst->sa_family) {
  353: 		plog(LLV_ERROR, LOCATION, NULL,
  354: 			"address family mismatch\n");
  355: 		return -1;
  356: 	}
  357: 
  358: 	slen = sizeof(ss);
  359: 	if (getsockname(s, (struct sockaddr *)&ss, &slen) < 0) {
  360: 		plog(LLV_ERROR, LOCATION, NULL,
  361: 			"getsockname (%s)\n", strerror(errno));
  362: 		return -1;
  363: 	}
  364: 
  365: 	plog(LLV_DEBUG, LOCATION, NULL,
  366: 		"sockname %s\n", saddr2str((struct sockaddr *)&ss));
  367: 	plog(LLV_DEBUG, LOCATION, NULL,
  368: 		"send packet from %s\n", saddr2str(src));
  369: 	plog(LLV_DEBUG, LOCATION, NULL,
  370: 		"send packet to %s\n", saddr2str(dst));
  371: 
  372: 	if (src->sa_family != ss.ss_family) {
  373: 		plog(LLV_ERROR, LOCATION, NULL,
  374: 			"address family mismatch\n");
  375: 		return -1;
  376: 	}
  377: 
  378: 	switch (src->sa_family) {
  379: #if defined(INET6) && defined(INET6_ADVAPI)
  380: // XXX: This block wasn't compiled on Linux - does it work?
  381: 	case AF_INET6:
  382: 	    {
  383: 		struct msghdr m;
  384: 		struct cmsghdr *cm;
  385: 		struct iovec iov[2];
  386: 		u_char cmsgbuf[256];
  387: 		struct in6_pktinfo *pi;
  388: 		int ifindex;
  389: 		struct sockaddr_in6 src6, dst6;
  390: 
  391: 		memcpy(&src6, src, sizeof(src6));
  392: 		memcpy(&dst6, dst, sizeof(dst6));
  393: 
  394: 		/* XXX take care of other cases, such as site-local */
  395: 		ifindex = 0;
  396: 		if (IN6_IS_ADDR_LINKLOCAL(&src6.sin6_addr)
  397: 		 || IN6_IS_ADDR_MULTICAST(&src6.sin6_addr)) {
  398: 			ifindex = src6.sin6_scope_id;	/*???*/
  399: 		}
  400: 
  401: 		/* XXX some sanity check on dst6.sin6_scope_id */
  402: 
  403: 		/* flowinfo for IKE?  mmm, maybe useful but for now make it 0 */
  404: 		src6.sin6_flowinfo = dst6.sin6_flowinfo = 0;
  405: 
  406: 		memset(&m, 0, sizeof(m));
  407: 		m.msg_name = (caddr_t)&dst6;
  408: 		m.msg_namelen = sizeof(dst6);
  409: 		iov[0].iov_base = (char *)buf;
  410: 		iov[0].iov_len = buflen;
  411: 		m.msg_iov = iov;
  412: 		m.msg_iovlen = 1;
  413: 
  414: 		memset(cmsgbuf, 0, sizeof(cmsgbuf));
  415: 		cm = (struct cmsghdr *)cmsgbuf;
  416: 		m.msg_control = (caddr_t)cm;
  417: 		m.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
  418: 
  419: 		cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
  420: 		cm->cmsg_level = IPPROTO_IPV6;
  421: 		cm->cmsg_type = IPV6_PKTINFO;
  422: 		pi = (struct in6_pktinfo *)CMSG_DATA(cm);
  423: 		memcpy(&pi->ipi6_addr, &src6.sin6_addr, sizeof(src6.sin6_addr));
  424: 		pi->ipi6_ifindex = ifindex;
  425: 
  426: 		plog(LLV_DEBUG, LOCATION, NULL,
  427: 			"src6 %s %d\n",
  428: 			saddr2str((struct sockaddr *)&src6),
  429: 			src6.sin6_scope_id);
  430: 		plog(LLV_DEBUG, LOCATION, NULL,
  431: 			"dst6 %s %d\n",
  432: 			saddr2str((struct sockaddr *)&dst6),
  433: 			dst6.sin6_scope_id);
  434: 
  435: 		for (i = 0; i < cnt; i++) {
  436: 			len = sendmsg(s, &m, 0 /*MSG_DONTROUTE*/);
  437: 			if (len < 0) {
  438: 				plog(LLV_ERROR, LOCATION, NULL,
  439: 					"sendmsg (%s)\n", strerror(errno));
  440: 				return -1;
  441: 			}
  442: 			plog(LLV_DEBUG, LOCATION, NULL,
  443: 				"%d times of %d bytes message will be sent "
  444: 				"to %s\n",
  445: 				i + 1, len, saddr2str(dst));
  446: 		}
  447: 		plogdump(LLV_DEBUG, (char *)buf, buflen);
  448: 
  449: 		return len;
  450: 	    }
  451: #endif
  452: #ifdef __linux__
  453: 	case AF_INET:
  454: 	    {
  455: 		struct msghdr m;
  456: 		struct cmsghdr *cm;
  457: 		struct iovec iov[2];
  458: 		u_char cmsgbuf[256];
  459: 		struct in_pktinfo *pi;
  460: 		int ifindex = 0;
  461: 		struct sockaddr_in src6, dst6;
  462: 
  463: 		memcpy(&src6, src, sizeof(src6));
  464: 		memcpy(&dst6, dst, sizeof(dst6));
  465: 
  466: 		memset(&m, 0, sizeof(m));
  467: 		m.msg_name = (caddr_t)&dst6;
  468: 		m.msg_namelen = sizeof(dst6);
  469: 		iov[0].iov_base = (char *)buf;
  470: 		iov[0].iov_len = buflen;
  471: 		m.msg_iov = iov;
  472: 		m.msg_iovlen = 1;
  473: 
  474: 		memset(cmsgbuf, 0, sizeof(cmsgbuf));
  475: 		cm = (struct cmsghdr *)cmsgbuf;
  476: 		m.msg_control = (caddr_t)cm;
  477: 		m.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
  478: 
  479: 		cm->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
  480: 		cm->cmsg_level = IPPROTO_IP;
  481: 		cm->cmsg_type = IP_PKTINFO;
  482: 		pi = (struct in_pktinfo *)CMSG_DATA(cm);
  483: 		memcpy(&pi->ipi_spec_dst, &src6.sin_addr, sizeof(src6.sin_addr));
  484: 		pi->ipi_ifindex = ifindex;
  485: 
  486: 		plog(LLV_DEBUG, LOCATION, NULL,
  487: 			"src4 %s\n",
  488: 			saddr2str((struct sockaddr *)&src6));
  489: 		plog(LLV_DEBUG, LOCATION, NULL,
  490: 			"dst4 %s\n",
  491: 			saddr2str((struct sockaddr *)&dst6));
  492: 
  493: 		for (i = 0; i < cnt; i++) {
  494: 			len = sendmsg(s, &m, 0 /*MSG_DONTROUTE*/);
  495: 			if (len < 0) {
  496: 				plog(LLV_ERROR, LOCATION, NULL,
  497: 					"sendmsg (%s)\n", strerror(errno));
  498: 				return -1;
  499: 			}
  500: 			plog(LLV_DEBUG, LOCATION, NULL,
  501: 				"%d times of %d bytes message will be sent "
  502: 				"to %s\n",
  503: 				i + 1, len, saddr2str(dst));
  504: 		}
  505: 		plogdump(LLV_DEBUG, (char *)buf, buflen);
  506: 
  507: 		return len;
  508: 	    }
  509: #endif /* __linux__ */
  510: 	default:
  511: 	    {
  512: 		int needclose = 0;
  513: 		int sendsock;
  514: 
  515: 		if (ss.ss_family == src->sa_family && memcmp(&ss, src, sysdep_sa_len(src)) == 0) {
  516: 			sendsock = s;
  517: 			needclose = 0;
  518: 		} else {
  519: 			int yes = 1;
  520: 			/*
  521: 			 * Use newly opened socket for sending packets.
  522: 			 * NOTE: this is unsafe, because if the peer is quick enough
  523: 			 * the packet from the peer may be queued into sendsock.
  524: 			 * Better approach is to prepare bind'ed udp sockets for
  525: 			 * each of the interface addresses.
  526: 			 */
  527: 			sendsock = SOCKET(src->sa_family, SOCK_DGRAM, 0);
  528: 			if (sendsock < 0) {
  529: 				plog(LLV_ERROR, LOCATION, NULL,
  530: 					"socket (%s)\n", strerror(errno));
  531: 				return -1;
  532: 			}
  533: 			if (setsockopt(sendsock, SOL_SOCKET,
  534: #ifdef __linux__
  535: 				       SO_REUSEADDR,
  536: #else
  537: 				       SO_REUSEPORT,
  538: #endif
  539: 				       (void *)&yes, sizeof(yes)) < 0) {
  540: 				plog(LLV_ERROR, LOCATION, NULL,
  541: 					"setsockopt SO_REUSEPORT (%s)\n", 
  542: 					strerror(errno));
  543: 				close(sendsock);
  544: 				return -1;
  545: 			}
  546: #ifdef IPV6_USE_MIN_MTU
  547: 			if (src->sa_family == AF_INET6 &&
  548: 			    setsockopt(sendsock, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
  549: 			    (void *)&yes, sizeof(yes)) < 0) {
  550: 				plog(LLV_ERROR, LOCATION, NULL,
  551: 					"setsockopt IPV6_USE_MIN_MTU (%s)\n", 
  552: 					strerror(errno));
  553: 				close(sendsock);
  554: 				return -1;
  555: 			}
  556: #endif
  557: 			if (setsockopt_bypass(sendsock, src->sa_family) < 0) {
  558: 				close(sendsock);
  559: 				return -1;
  560: 			}
  561: 
  562: 			if (BIND(sendsock, (struct sockaddr *)src,
  563: 				 sysdep_sa_len(src)) < 0) {
  564: 				plog(LLV_ERROR, LOCATION, NULL,
  565: 					"bind 1 (%s)\n", strerror(errno));
  566: 				close(sendsock);
  567: 				return -1;
  568: 			}
  569: 			needclose = 1;
  570: 		}
  571: 
  572: 		for (i = 0; i < cnt; i++) {
  573: 			len = sendto(sendsock, buf, buflen, 0, dst, sysdep_sa_len(dst));
  574: 			if (len < 0) {
  575: 				plog(LLV_ERROR, LOCATION, NULL,
  576: 					"sendto (%s)\n", strerror(errno));
  577: 				if (needclose)
  578: 					close(sendsock);
  579: 				return len;
  580: 			}
  581: 			plog(LLV_DEBUG, LOCATION, NULL,
  582: 				"%d times of %d bytes message will be sent "
  583: 				"to %s\n",
  584: 				i + 1, len, saddr2str(dst));
  585: 		}
  586: 		plogdump(LLV_DEBUG, (char *)buf, buflen);
  587: 
  588: 		if (needclose)
  589: 			close(sendsock);
  590: 
  591: 		return len;
  592: 	    }
  593: 	}
  594: }
  595: 
  596: int
  597: setsockopt_bypass(so, family)
  598: 	int so, family;
  599: {
  600: 	int level;
  601: 	char *buf;
  602: 	char *policy;
  603: 
  604: 	switch (family) {
  605: 	case AF_INET:
  606: 		level = IPPROTO_IP;
  607: 		break;
  608: #ifdef INET6
  609: 	case AF_INET6:
  610: 		level = IPPROTO_IPV6;
  611: 		break;
  612: #endif
  613: 	default:
  614: 		plog(LLV_ERROR, LOCATION, NULL,
  615: 			"unsupported address family %d\n", family);
  616: 		return -1;
  617: 	}
  618: 
  619: 	policy = "in bypass";
  620: 	buf = ipsec_set_policy(policy, strlen(policy));
  621: 	if (buf == NULL) {
  622: 		plog(LLV_ERROR, LOCATION, NULL,
  623: 			"ipsec_set_policy (%s)\n",
  624: 			ipsec_strerror());
  625: 		return -1;
  626: 	}
  627: 	if (SETSOCKOPT(so, level,
  628: 	               (level == IPPROTO_IP ?
  629: 	                         IP_IPSEC_POLICY : IPV6_IPSEC_POLICY),
  630: 	               buf, ipsec_get_policylen(buf)) < 0) {
  631: 		plog(LLV_ERROR, LOCATION, NULL,
  632: 			"setsockopt IP_IPSEC_POLICY (%s)\n",
  633: 			strerror(errno));
  634: 		return -1;
  635: 	}
  636: 	racoon_free(buf);
  637: 
  638: 	policy = "out bypass";
  639: 	buf = ipsec_set_policy(policy, strlen(policy));
  640: 	if (buf == NULL) {
  641: 		plog(LLV_ERROR, LOCATION, NULL,
  642: 			"ipsec_set_policy (%s)\n",
  643: 			ipsec_strerror());
  644: 		return -1;
  645: 	}
  646: 	if (SETSOCKOPT(so, level,
  647: 	               (level == IPPROTO_IP ?
  648: 	                         IP_IPSEC_POLICY : IPV6_IPSEC_POLICY),
  649: 	               buf, ipsec_get_policylen(buf)) < 0) {
  650: 		plog(LLV_ERROR, LOCATION, NULL,
  651: 			"setsockopt IP_IPSEC_POLICY (%s)\n",
  652: 			strerror(errno));
  653: 		return -1;
  654: 	}
  655: 	racoon_free(buf);
  656: 
  657: 	return 0;
  658: }
  659: 
  660: struct sockaddr *
  661: newsaddr(len)
  662: 	int len;
  663: {
  664: 	struct sockaddr *new;
  665: 
  666: 	if ((new = racoon_calloc(1, len)) == NULL) {
  667: 		plog(LLV_ERROR, LOCATION, NULL,
  668: 			"%s\n", strerror(errno)); 
  669: 		goto out;
  670: 	}
  671: 
  672: #ifdef __linux__
  673: 	if (len == sizeof (struct sockaddr_in6))
  674: 		new->sa_family = AF_INET6;
  675: 	else
  676: 		new->sa_family = AF_INET;
  677: #else
  678: 	/* initial */
  679: 	new->sa_len = len;
  680: #endif
  681: out:
  682: 	return new;
  683: }
  684: 
  685: struct sockaddr *
  686: dupsaddr(src)
  687: 	struct sockaddr *src;
  688: {
  689: 	struct sockaddr *dst;
  690: 
  691: 	dst = racoon_calloc(1, sysdep_sa_len(src));
  692: 	if (dst == NULL) {
  693: 		plog(LLV_ERROR, LOCATION, NULL,
  694: 			"%s\n", strerror(errno)); 
  695: 		return NULL;
  696: 	}
  697: 
  698: 	memcpy(dst, src, sysdep_sa_len(src));
  699: 
  700: 	return dst;
  701: }
  702: 
  703: char *
  704: saddr2str(saddr)
  705: 	const struct sockaddr *saddr;
  706: {
  707: 	static char buf[NI_MAXHOST + NI_MAXSERV + 10];
  708: 	char addr[NI_MAXHOST], port[NI_MAXSERV];
  709: 
  710: 	if (saddr == NULL)
  711: 		return NULL;
  712: 
  713: 	if (saddr->sa_family == AF_UNSPEC)
  714: 		snprintf (buf, sizeof(buf), "%s", "anonymous");
  715: 	else {
  716: 		GETNAMEINFO(saddr, addr, port);
  717: 		snprintf(buf, sizeof(buf), "%s[%s]", addr, port);
  718: 	}
  719: 
  720: 	return buf;
  721: }
  722: 
  723: char *
  724: saddrwop2str(saddr)
  725: 	const struct sockaddr *saddr;
  726: {
  727: 	static char buf[NI_MAXHOST + NI_MAXSERV + 10];
  728: 	char addr[NI_MAXHOST];
  729: 
  730: 	if (saddr == NULL)
  731: 		return NULL;
  732: 
  733: 	GETNAMEINFO_NULL(saddr, addr);
  734: 	snprintf(buf, sizeof(buf), "%s", addr);
  735: 
  736: 	return buf;
  737: }
  738: 
  739: char *
  740: naddrwop2str(const struct netaddr *naddr)
  741: {
  742: 	static char buf[NI_MAXHOST + 10];
  743: 	static const struct sockaddr sa_any;	/* this is initialized to all zeros */
  744: 	
  745: 	if (naddr == NULL)
  746: 		return NULL;
  747: 
  748: 	if (memcmp(&naddr->sa, &sa_any, sizeof(sa_any)) == 0)
  749: 		snprintf(buf, sizeof(buf), "%s", "any");
  750: 	else {
  751: 		snprintf(buf, sizeof(buf), "%s", saddrwop2str(&naddr->sa.sa));
  752: 		snprintf(&buf[strlen(buf)], sizeof(buf) - strlen(buf), "/%ld", naddr->prefix);
  753: 	}
  754: 	return buf;
  755: }
  756: 
  757: char *
  758: naddrwop2str_fromto(const char *format, const struct netaddr *saddr,
  759: 		    const struct netaddr *daddr)
  760: {
  761: 	static char buf[2*(NI_MAXHOST + NI_MAXSERV + 10) + 100];
  762: 	char *src, *dst;
  763: 
  764: 	src = racoon_strdup(naddrwop2str(saddr));
  765: 	dst = racoon_strdup(naddrwop2str(daddr));
  766: 	STRDUP_FATAL(src);
  767: 	STRDUP_FATAL(dst);
  768: 	/* WARNING: Be careful about the format string! Don't 
  769: 	   ever pass in something that a user can modify!!! */
  770: 	snprintf (buf, sizeof(buf), format, src, dst);
  771: 	racoon_free (src);
  772: 	racoon_free (dst);
  773: 
  774: 	return buf;
  775: }
  776: 
  777: char *
  778: saddr2str_fromto(format, saddr, daddr)
  779: 	const char *format;
  780: 	const struct sockaddr *saddr;
  781: 	const struct sockaddr *daddr;
  782: {
  783: 	static char buf[2*(NI_MAXHOST + NI_MAXSERV + 10) + 100];
  784: 	char *src, *dst;
  785: 
  786: 	src = racoon_strdup(saddr2str(saddr));
  787: 	dst = racoon_strdup(saddr2str(daddr));
  788: 	STRDUP_FATAL(src);
  789: 	STRDUP_FATAL(dst);
  790: 	/* WARNING: Be careful about the format string! Don't 
  791: 	   ever pass in something that a user can modify!!! */
  792: 	snprintf (buf, sizeof(buf), format, src, dst);
  793: 	racoon_free (src);
  794: 	racoon_free (dst);
  795: 
  796: 	return buf;
  797: }
  798: 
  799: struct sockaddr *
  800: str2saddr(host, port)
  801: 	char *host;
  802: 	char *port;
  803: {
  804: 	struct addrinfo hints, *res;
  805: 	struct sockaddr *saddr;
  806: 	int error;
  807: 
  808: 	memset(&hints, 0, sizeof(hints));
  809: 	hints.ai_family = PF_UNSPEC;
  810: 	hints.ai_socktype = SOCK_DGRAM;
  811: 	hints.ai_flags = AI_NUMERICHOST;
  812: 	error = getaddrinfo(host, port, &hints, &res);
  813: 	if (error != 0) {
  814: 		plog(LLV_ERROR, LOCATION, NULL,
  815: 			"getaddrinfo(%s%s%s): %s\n",
  816: 			host, port ? "," : "", port ? port : "",
  817: 			gai_strerror(error));
  818: 		return NULL;
  819: 	}
  820: 	if (res->ai_next != NULL) {
  821: 		plog(LLV_WARNING, LOCATION, NULL,
  822: 			"getaddrinfo(%s%s%s): "
  823: 			"resolved to multiple address, "
  824: 			"taking the first one\n",
  825: 			host, port ? "," : "", port ? port : "");
  826: 	}
  827: 	saddr = racoon_malloc(res->ai_addrlen);
  828: 	if (saddr == NULL) {
  829: 		plog(LLV_ERROR, LOCATION, NULL,
  830: 			"failed to allocate buffer.\n");
  831: 		freeaddrinfo(res);
  832: 		return NULL;
  833: 	}
  834: 	memcpy(saddr, res->ai_addr, res->ai_addrlen);
  835: 	freeaddrinfo(res);
  836: 
  837: 	return saddr;
  838: }
  839: 
  840: void
  841: mask_sockaddr(a, b, l)
  842: 	struct sockaddr *a;
  843: 	const struct sockaddr *b;
  844: 	size_t l;
  845: {
  846: 	size_t i;
  847: 	u_int8_t *p, alen;
  848: 
  849: 	switch (b->sa_family) {
  850: 	case AF_INET:
  851: 		alen = sizeof(struct in_addr);
  852: 		p = (u_int8_t *)&((struct sockaddr_in *)a)->sin_addr;
  853: 		break;
  854: #ifdef INET6
  855: 	case AF_INET6:
  856: 		alen = sizeof(struct in6_addr);
  857: 		p = (u_int8_t *)&((struct sockaddr_in6 *)a)->sin6_addr;
  858: 		break;
  859: #endif
  860: 	default:
  861: 		plog(LLV_ERROR, LOCATION, NULL,
  862: 			"invalid family: %d\n", b->sa_family);
  863: 		exit(1);
  864: 	}
  865: 
  866: 	if ((alen << 3) < l) {
  867: 		plog(LLV_ERROR, LOCATION, NULL,
  868: 			"unexpected inconsistency: %d %zu\n", b->sa_family, l);
  869: 		exit(1);
  870: 	}
  871: 
  872: 	memcpy(a, b, sysdep_sa_len(b));
  873: 	p[l / 8] &= (0xff00 >> (l % 8)) & 0xff;
  874: 	for (i = l / 8 + 1; i < alen; i++)
  875: 		p[i] = 0x00;
  876: }
  877: 
  878: /* Compute a score describing how "accurate" a netaddr is for a given sockaddr.
  879:  * Examples:
  880:  * 	Return values for address 10.20.30.40 [port 500] and given netaddresses...
  881:  * 		10.10.0.0/16	=> -1	... doesn't match
  882:  * 		0.0.0.0/0	=> 0	... matches, but only 0 bits.
  883:  * 		10.20.0.0/16	=> 16	... 16 bits match
  884:  * 		10.20.30.0/24	=> 24	... guess what ;-)
  885:  * 		10.20.30.40/32	=> 32	... whole address match
  886:  * 		10.20.30.40:500	=> 33	... both address and port match
  887:  * 		10.20.30.40:501	=> -1	... port doesn't match and isn't 0 (=any)
  888:  */
  889: int
  890: naddr_score(const struct netaddr *naddr, const struct sockaddr *saddr)
  891: {
  892: 	static const struct netaddr naddr_any;	/* initialized to all-zeros */
  893: 	struct sockaddr sa;
  894: 	u_int16_t naddr_port, saddr_port;
  895: 	int port_score;
  896: 
  897: 	if (!naddr || !saddr) {
  898: 		plog(LLV_ERROR, LOCATION, NULL,
  899: 		     "Call with null args: naddr=%p, saddr=%p\n",
  900: 		     naddr, saddr);
  901: 		return -1;
  902: 	}
  903: 
  904: 	/* Wildcard address matches, but only 0 bits. */
  905: 	if (memcmp(naddr, &naddr_any, sizeof(naddr_any)) == 0)
  906: 		return 0;
  907: 
  908: 	/* If families don't match we really can't do much... */
  909: 	if (naddr->sa.sa.sa_family != saddr->sa_family)
  910: 		return -1;
  911: 	
  912: 	/* If port check fail don't bother to check addresses. */
  913: 	naddr_port = extract_port(&naddr->sa.sa);
  914: 	saddr_port = extract_port(saddr);
  915: 	if (naddr_port == 0 || saddr_port == 0)	/* wildcard match */
  916: 		port_score = 0;
  917: 	else if (naddr_port == saddr_port)	/* exact match */
  918: 		port_score = 1;
  919: 	else					/* mismatch :-) */
  920: 		return -1;
  921: 
  922: 	/* Here it comes - compare network addresses. */
  923: 	mask_sockaddr(&sa, saddr, naddr->prefix);
  924: 	if (loglevel >= LLV_DEBUG) {	/* debug only */
  925: 		char *a1, *a2, *a3;
  926: 		a1 = racoon_strdup(naddrwop2str(naddr));
  927: 		a2 = racoon_strdup(saddrwop2str(saddr));
  928: 		a3 = racoon_strdup(saddrwop2str(&sa));
  929: 		STRDUP_FATAL(a1);
  930: 		STRDUP_FATAL(a2);
  931: 		STRDUP_FATAL(a3);
  932: 		plog(LLV_DEBUG, LOCATION, NULL,
  933: 		     "naddr=%s, saddr=%s (masked=%s)\n",
  934: 		     a1, a2, a3);
  935: 		free(a1);
  936: 		free(a2);
  937: 		free(a3);
  938: 	}
  939: 	if (cmpsaddr(&sa, &naddr->sa.sa) <= CMPSADDR_WOP_MATCH)
  940: 		return naddr->prefix + port_score;
  941: 
  942: 	return -1;
  943: }
  944: 
  945: /* Some useful functions for sockaddr port manipulations. */
  946: u_int16_t
  947: extract_port (const struct sockaddr *addr)
  948: {
  949:   u_int16_t port = 0;
  950:   
  951:   if (!addr)
  952:     return port;
  953: 
  954:   switch (addr->sa_family) {
  955:     case AF_UNSPEC:
  956:       break;
  957:     case AF_INET:
  958:       port = ((struct sockaddr_in *)addr)->sin_port;
  959:       break;
  960:     case AF_INET6:
  961:       port = ((struct sockaddr_in6 *)addr)->sin6_port;
  962:       break;
  963:     default:
  964:       plog(LLV_ERROR, LOCATION, NULL, "unknown AF: %u\n", addr->sa_family);
  965:       break;
  966:   }
  967: 
  968:   return ntohs(port);
  969: }
  970: 
  971: u_int16_t *
  972: get_port_ptr (struct sockaddr *addr)
  973: {
  974:   u_int16_t *port_ptr;
  975: 
  976:   if (!addr)
  977:     return NULL;
  978: 
  979:   switch (addr->sa_family) {
  980:     case AF_INET:
  981:       port_ptr = &(((struct sockaddr_in *)addr)->sin_port);
  982:       break;
  983:     case AF_INET6:
  984:       port_ptr = &(((struct sockaddr_in6 *)addr)->sin6_port);
  985:       break;
  986:     default:
  987:       plog(LLV_ERROR, LOCATION, NULL, "unknown AF: %u\n", addr->sa_family);
  988:       return NULL;
  989:       break;
  990:   }
  991: 
  992:   return port_ptr;
  993: }
  994: 
  995: u_int16_t *
  996: set_port (struct sockaddr *addr, u_int16_t new_port)
  997: {
  998:   u_int16_t *port_ptr;
  999: 
 1000:   port_ptr = get_port_ptr (addr);
 1001: 
 1002:   if (port_ptr)
 1003:     *port_ptr = htons(new_port);
 1004: 
 1005:   return port_ptr;
 1006: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>