1c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh/* $NetBSD: sockmisc.c,v 1.8.6.1 2007/08/01 11:52:22 vanhu Exp $ */ 20a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 30a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/* Id: sockmisc.c,v 1.24 2006/05/07 21:32:59 manubsd Exp */ 40a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 50a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/* 60a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 70a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * All rights reserved. 80a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 90a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * Redistribution and use in source and binary forms, with or without 100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * modification, are permitted provided that the following conditions 110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * are met: 120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 1. Redistributions of source code must retain the above copyright 130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * notice, this list of conditions and the following disclaimer. 140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 2. Redistributions in binary form must reproduce the above copyright 150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * notice, this list of conditions and the following disclaimer in the 160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * documentation and/or other materials provided with the distribution. 170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 3. Neither the name of the project nor the names of its contributors 180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * may be used to endorse or promote products derived from this software 190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * without specific prior written permission. 200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * SUCH DAMAGE. 320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */ 330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "config.h" 350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <sys/types.h> 370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <sys/param.h> 380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <sys/socket.h> 390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <sys/uio.h> 400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <netinet/in.h> 420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include PATH_IPSEC_H 430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#if defined(INET6) && !defined(INET6_ADVAPI) && \ 450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang defined(IP_RECVDSTADDR) && !defined(IPV6_RECVDSTADDR) 460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#define IPV6_RECVDSTADDR IP_RECVDSTADDR 470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif 480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <stdlib.h> 500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <stdio.h> 510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <string.h> 520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <errno.h> 530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef HAVE_UNISTD_H 540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <unistd.h> 550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif 560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "var.h" 580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "misc.h" 590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "plog.h" 600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "sockmisc.h" 610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "debug.h" 620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "gcmalloc.h" 630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "debugrm.h" 640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "libpfkey.h" 650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 66c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#ifndef IP_IPSEC_POLICY 67c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#define IP_IPSEC_POLICY 16 /* XXX: from linux/in.h */ 68c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#endif 69c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh 70c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#ifndef IPV6_IPSEC_POLICY 71c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#define IPV6_IPSEC_POLICY 34 /* XXX: from linux/???.h per 72c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh "Tom Lendacky" <toml@us.ibm.com> */ 730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif 740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 75f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yehconst int niflags = 0; 760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/* 78c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh * compare two sockaddr without port number. 79c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh * OUT: 0: equal. 80c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh * 1: not equal. 81c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh */ 82c91307af2622f6625525f3c1f9c954376df950adChia-chi Yehint 83c91307af2622f6625525f3c1f9c954376df950adChia-chi Yehcmpsaddrwop(addr1, addr2) 84c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh const struct sockaddr *addr1; 85c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh const struct sockaddr *addr2; 86c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh{ 87c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh caddr_t sa1, sa2; 88c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh 89c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (addr1 == 0 && addr2 == 0) 90c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 0; 91c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (addr1 == 0 || addr2 == 0) 92c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 93c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh 94c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#ifdef __linux__ 95c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (addr1->sa_family != addr2->sa_family) 96c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 97c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#else 98c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (addr1->sa_len != addr2->sa_len 99c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh || addr1->sa_family != addr2->sa_family) 100c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 101c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh 102c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#endif /* __linux__ */ 103c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh 104c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh switch (addr1->sa_family) { 105c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh case AF_INET: 106c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr; 107c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr; 108c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0) 109c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 110c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh break; 111c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#ifdef INET6 112c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh case AF_INET6: 113c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr; 114c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr; 115c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0) 116c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 117c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (((struct sockaddr_in6 *)addr1)->sin6_scope_id != 118c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh ((struct sockaddr_in6 *)addr2)->sin6_scope_id) 119c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 120c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh break; 121c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#endif 122c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh default: 123c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 124c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh } 125c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh 126c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 0; 127c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh} 128c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh 129c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh/* 1300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * compare two sockaddr with port, taking care wildcard. 1310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * addr1 is a subject address, addr2 is in a database entry. 1320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * OUT: 0: equal. 1330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 1: not equal. 1340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */ 1350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangint 136c91307af2622f6625525f3c1f9c954376df950adChia-chi Yehcmpsaddrwild(addr1, addr2) 1370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang const struct sockaddr *addr1; 1380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang const struct sockaddr *addr2; 1390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{ 1400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang caddr_t sa1, sa2; 141c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh u_short port1, port2; 1420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 143c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (addr1 == 0 && addr2 == 0) 144c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 0; 145c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (addr1 == 0 || addr2 == 0) 146c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 1470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 148c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#ifdef __linux__ 149c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (addr1->sa_family != addr2->sa_family) 150c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 151c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#else 152c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (addr1->sa_len != addr2->sa_len 153c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh || addr1->sa_family != addr2->sa_family) 154c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 1550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 156c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#endif /* __linux__ */ 1570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 1580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang switch (addr1->sa_family) { 1590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang case AF_INET: 1600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr; 1610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr; 1620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang port1 = ((struct sockaddr_in *)addr1)->sin_port; 1630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang port2 = ((struct sockaddr_in *)addr2)->sin_port; 164c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (!(port1 == IPSEC_PORT_ANY || 165c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh port2 == IPSEC_PORT_ANY || 166c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh port1 == port2)) 167c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 1680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0) 169c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 1700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang break; 1710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef INET6 1720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang case AF_INET6: 1730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr; 1740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr; 1750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang port1 = ((struct sockaddr_in6 *)addr1)->sin6_port; 1760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang port2 = ((struct sockaddr_in6 *)addr2)->sin6_port; 177c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (!(port1 == IPSEC_PORT_ANY || 178c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh port2 == IPSEC_PORT_ANY || 179c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh port1 == port2)) 180c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 1810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0) 182c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 1830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (((struct sockaddr_in6 *)addr1)->sin6_scope_id != 1840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang ((struct sockaddr_in6 *)addr2)->sin6_scope_id) 185c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 1860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang break; 1870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif 1880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang default: 189c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 1900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 1910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 192c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 0; 193c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh} 194c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh 195c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh/* 196c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh * compare two sockaddr with strict match on port. 197c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh * OUT: 0: equal. 198c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh * 1: not equal. 199c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh */ 200c91307af2622f6625525f3c1f9c954376df950adChia-chi Yehint 201c91307af2622f6625525f3c1f9c954376df950adChia-chi Yehcmpsaddrstrict(addr1, addr2) 202c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh const struct sockaddr *addr1; 203c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh const struct sockaddr *addr2; 204c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh{ 205c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh caddr_t sa1, sa2; 206c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh u_short port1, port2; 207c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh 208c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (addr1 == 0 && addr2 == 0) 209c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 0; 210c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (addr1 == 0 || addr2 == 0) 211c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 2120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 213c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#ifdef __linux__ 214c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (addr1->sa_family != addr2->sa_family) 215c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 216c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#else 217c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (addr1->sa_len != addr2->sa_len 218c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh || addr1->sa_family != addr2->sa_family) 219c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 2200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 221c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#endif /* __linux__ */ 222c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh 223c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh switch (addr1->sa_family) { 224c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh case AF_INET: 225c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr; 226c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr; 227c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh port1 = ((struct sockaddr_in *)addr1)->sin_port; 228c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh port2 = ((struct sockaddr_in *)addr2)->sin_port; 229c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (port1 != port2) 230c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 231c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0) 232c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 233c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh break; 234c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#ifdef INET6 235c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh case AF_INET6: 236c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr; 237c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr; 238c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh port1 = ((struct sockaddr_in6 *)addr1)->sin6_port; 239c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh port2 = ((struct sockaddr_in6 *)addr2)->sin6_port; 240c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (port1 != port2) 241c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 242c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0) 243c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 244c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (((struct sockaddr_in6 *)addr1)->sin6_scope_id != 245c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh ((struct sockaddr_in6 *)addr2)->sin6_scope_id) 246c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 247c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh break; 248c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#endif 249c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh default: 250c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 1; 251c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh } 252c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh 253c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh return 0; 2540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang} 2550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 256c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh#ifdef ANDROID_PATCHED 257c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh 258c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yehstruct sockaddr *getlocaladdr(struct sockaddr *remote) 259c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh{ 260c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh struct sockaddr_storage local; 261c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh socklen_t len = sysdep_sa_len(remote); 262c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh int s = socket(remote->sa_family, SOCK_DGRAM, 0); 263c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh if (s == -1 || connect(s, remote, len) == -1 || 264c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh getsockname(s, (struct sockaddr *)&local, &len) == -1) { 265c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh close(s); 266c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh return NULL; 267c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh } 268c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh close(s); 269c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh return dupsaddr((struct sockaddr *)&local); 270c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh} 271c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh 272c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yehint recvfromto(int s, void *buf, size_t len, int flags, struct sockaddr *from, 273c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh socklen_t *fromlen, struct sockaddr *to, unsigned int *tolen) 274c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh{ 275c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh if (getsockname(s, to, (socklen_t *)tolen) == -1) { 276c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh return -1; 277c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh } 278c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh return recvfrom(s, buf, len, flags, from, fromlen); 279c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh} 280c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh 281c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yehint sendfromto(int s, const void *buf, size_t len, struct sockaddr *from, 282c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh struct sockaddr *to, int count) 283c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh{ 284c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh int i; 285c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh for (i = 0; i < count; ++i) { 286a6239141a335940e5f665e3f0dc99c9c5cad8966Chia-chi Yeh if (sendto(s, buf, len, 0, to, sysdep_sa_len(to)) == -1) { 287c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh return -1; 288c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh } 289c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh } 290c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh return len; 291c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh} 292c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh 293c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yehint setsockopt_bypass(int s, int family) 294c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh{ 295c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh struct sadb_x_policy p = { 296c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh .sadb_x_policy_len = PFKEY_UNIT64(sizeof(struct sadb_x_policy)), 297c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh .sadb_x_policy_exttype = SADB_X_EXT_POLICY, 298c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh .sadb_x_policy_type = IPSEC_POLICY_BYPASS, 299c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh .sadb_x_policy_dir = IPSEC_DIR_INBOUND, 300c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh#ifdef HAVE_PFKEY_POLICY_PRIORITY 301c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh .sadb_x_policy_priority = PRIORITY_DEFAULT, 302c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh#endif 303c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh }; 304c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh int level = (family == AF_INET) ? IPPROTO_IP : IPPROTO_IPV6; 305c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh int option = (family == AF_INET) ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY; 306c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh int len = PFKEY_EXTLEN(&p); 307a6239141a335940e5f665e3f0dc99c9c5cad8966Chia-chi Yeh if (setsockopt(s, level, option, &p, len) == -1) { 308a6239141a335940e5f665e3f0dc99c9c5cad8966Chia-chi Yeh plog(LLV_WARNING, LOCATION, NULL, "setsockopt in bypass: %s\n", 309a6239141a335940e5f665e3f0dc99c9c5cad8966Chia-chi Yeh strerror(errno)); 310a6239141a335940e5f665e3f0dc99c9c5cad8966Chia-chi Yeh } 311a6239141a335940e5f665e3f0dc99c9c5cad8966Chia-chi Yeh p.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND; 312a6239141a335940e5f665e3f0dc99c9c5cad8966Chia-chi Yeh if (setsockopt(s, level, option, &p, len) == -1) { 313a6239141a335940e5f665e3f0dc99c9c5cad8966Chia-chi Yeh plog(LLV_WARNING, LOCATION, NULL, "setsockopt out bypass: %s\n", 314a6239141a335940e5f665e3f0dc99c9c5cad8966Chia-chi Yeh strerror(errno)); 315c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh } 316c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh return 0; 317c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh} 318a6239141a335940e5f665e3f0dc99c9c5cad8966Chia-chi Yeh 319c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh#else 320c454954382b81262dc81ac54e147f4dc7fc0af75Chia-chi Yeh 3210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/* get local address against the destination. */ 3220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangstruct sockaddr * 3230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wanggetlocaladdr(remote) 3240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct sockaddr *remote; 3250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{ 3260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct sockaddr *local; 3270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang u_int local_len = sizeof(struct sockaddr_storage); 3280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang int s; /* for dummy connection */ 3290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 3300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang /* allocate buffer */ 3310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if ((local = racoon_calloc(1, local_len)) == NULL) { 3320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 3330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "failed to get address buffer.\n"); 3340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang goto err; 3350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 3360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 3370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang /* get real interface received packet */ 338c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if ((s = socket(remote->sa_family, SOCK_DGRAM, 0)) < 0) { 3390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 3400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "socket (%s)\n", strerror(errno)); 3410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang goto err; 3420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 3430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 3440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang setsockopt_bypass(s, remote->sa_family); 3450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 3460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (connect(s, remote, sysdep_sa_len(remote)) < 0) { 3470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 3480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "connect (%s)\n", strerror(errno)); 3490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang close(s); 3500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang goto err; 3510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 3520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 3530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (getsockname(s, local, &local_len) < 0) { 3540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 3550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "getsockname (%s)\n", strerror(errno)); 3560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang close(s); 3570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return NULL; 3580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 3590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 3600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang close(s); 3610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return local; 3620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 3630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang err: 3640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (local != NULL) 3650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang racoon_free(local); 3660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return NULL; 3670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang} 3680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 3690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/* 3700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * Receive packet, with src/dst information. It is assumed that necessary 3710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * setsockopt() have already performed on socket. 3720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */ 3730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangint 3740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangrecvfromto(s, buf, buflen, flags, from, fromlen, to, tolen) 3750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang int s; 3760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang void *buf; 3770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang size_t buflen; 3780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang int flags; 3790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct sockaddr *from; 3800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang socklen_t *fromlen; 3810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct sockaddr *to; 3820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang u_int *tolen; 3830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{ 3840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang int otolen; 385c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh u_int len; 386c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh struct sockaddr_storage ss; 3870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct msghdr m; 3880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct cmsghdr *cm; 3890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct iovec iov[2]; 3900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang u_char cmsgbuf[256]; 3910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#if defined(INET6) && defined(INET6_ADVAPI) 3920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct in6_pktinfo *pi; 3930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif /*INET6_ADVAPI*/ 3940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct sockaddr_in *sin; 3950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef INET6 3960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct sockaddr_in6 *sin6; 3970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif 3980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 399c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh len = sizeof(ss); 400c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (getsockname(s, (struct sockaddr *)&ss, &len) < 0) { 4010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 4020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "getsockname (%s)\n", strerror(errno)); 4030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return -1; 4040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 4050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 4060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang m.msg_name = (caddr_t)from; 4070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang m.msg_namelen = *fromlen; 4080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang iov[0].iov_base = (caddr_t)buf; 4090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang iov[0].iov_len = buflen; 4100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang m.msg_iov = iov; 4110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang m.msg_iovlen = 1; 4120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memset(cmsgbuf, 0, sizeof(cmsgbuf)); 4130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang cm = (struct cmsghdr *)cmsgbuf; 4140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang m.msg_control = (caddr_t)cm; 4150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang m.msg_controllen = sizeof(cmsgbuf); 4160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if ((len = recvmsg(s, &m, flags)) < 0) { 4170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 4180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "recvmsg (%s)\n", strerror(errno)); 4190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return -1; 4200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 4210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *fromlen = m.msg_namelen; 4220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 4230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang otolen = *tolen; 4240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *tolen = 0; 4250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&m); 4260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang m.msg_controllen != 0 && cm; 4270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang cm = (struct cmsghdr *)CMSG_NXTHDR(&m, cm)) { 4280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#if 0 4290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 4300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "cmsg %d %d\n", cm->cmsg_level, cm->cmsg_type);) 4310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif 4320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#if defined(INET6) && defined(INET6_ADVAPI) 433c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (ss.ss_family == AF_INET6 4340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang && cm->cmsg_level == IPPROTO_IPV6 4350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang && cm->cmsg_type == IPV6_PKTINFO 4360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang && otolen >= sizeof(*sin6)) { 4370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang pi = (struct in6_pktinfo *)(CMSG_DATA(cm)); 4380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *tolen = sizeof(*sin6); 4390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang sin6 = (struct sockaddr_in6 *)to; 4400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memset(sin6, 0, sizeof(*sin6)); 4410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang sin6->sin6_family = AF_INET6; 4420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifndef __linux__ 4430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang sin6->sin6_len = sizeof(*sin6); 4440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif 4450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memcpy(&sin6->sin6_addr, &pi->ipi6_addr, 4460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang sizeof(sin6->sin6_addr)); 4470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang /* XXX other cases, such as site-local? */ 4480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 4490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang sin6->sin6_scope_id = pi->ipi6_ifindex; 4500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang else 4510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang sin6->sin6_scope_id = 0; 452c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh sin6->sin6_port = 453c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh ((struct sockaddr_in6 *)&ss)->sin6_port; 4540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang otolen = -1; /* "to" already set */ 4550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang continue; 4560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 4570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif 4580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef __linux__ 459c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (ss.ss_family == AF_INET 4600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang && cm->cmsg_level == IPPROTO_IP 4610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang && cm->cmsg_type == IP_PKTINFO 4620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang && otolen >= sizeof(sin)) { 4630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct in_pktinfo *pi = (struct in_pktinfo *)(CMSG_DATA(cm)); 4640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *tolen = sizeof(*sin); 4650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang sin = (struct sockaddr_in *)to; 4660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memset(sin, 0, sizeof(*sin)); 4670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang sin->sin_family = AF_INET; 4680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memcpy(&sin->sin_addr, &pi->ipi_addr, 4690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang sizeof(sin->sin_addr)); 470c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh sin->sin_port = 471c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh ((struct sockaddr_in *)&ss)->sin_port; 4720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang otolen = -1; /* "to" already set */ 4730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang continue; 4740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 4750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif 4760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#if defined(INET6) && defined(IPV6_RECVDSTADDR) 477c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (ss.ss_family == AF_INET6 4780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang && cm->cmsg_level == IPPROTO_IPV6 4790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang && cm->cmsg_type == IPV6_RECVDSTADDR 4800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang && otolen >= sizeof(*sin6)) { 4810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *tolen = sizeof(*sin6); 4820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang sin6 = (struct sockaddr_in6 *)to; 4830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memset(sin6, 0, sizeof(*sin6)); 4840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang sin6->sin6_family = AF_INET6; 4850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang sin6->sin6_len = sizeof(*sin6); 4860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memcpy(&sin6->sin6_addr, CMSG_DATA(cm), 4870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang sizeof(sin6->sin6_addr)); 488c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh sin6->sin6_port = 489c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh ((struct sockaddr_in6 *)&ss)->sin6_port; 4900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang otolen = -1; /* "to" already set */ 4910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang continue; 4920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 4930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif 4940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifndef __linux__ 495c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (ss.ss_family == AF_INET 4960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang && cm->cmsg_level == IPPROTO_IP 4970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang && cm->cmsg_type == IP_RECVDSTADDR 4980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang && otolen >= sizeof(*sin)) { 4990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *tolen = sizeof(*sin); 5000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang sin = (struct sockaddr_in *)to; 5010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memset(sin, 0, sizeof(*sin)); 5020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang sin->sin_family = AF_INET; 5030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang sin->sin_len = sizeof(*sin); 5040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memcpy(&sin->sin_addr, CMSG_DATA(cm), 5050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang sizeof(sin->sin_addr)); 506c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh sin->sin_port = ((struct sockaddr_in *)&ss)->sin_port; 5070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang otolen = -1; /* "to" already set */ 5080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang continue; 5090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 5100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif 5110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 5120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 5130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return len; 5140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang} 5150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 5160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/* send packet, with fixing src/dst address pair. */ 5170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangint 5180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangsendfromto(s, buf, buflen, src, dst, cnt) 5190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang int s, cnt; 5200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang const void *buf; 5210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang size_t buflen; 5220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct sockaddr *src; 5230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct sockaddr *dst; 5240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{ 5250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct sockaddr_storage ss; 526c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh u_int len; 5270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang int i; 5280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 5290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (src->sa_family != dst->sa_family) { 5300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 5310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "address family mismatch\n"); 5320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return -1; 5330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 5340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 535c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh len = sizeof(ss); 536c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (getsockname(s, (struct sockaddr *)&ss, &len) < 0) { 5370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 5380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "getsockname (%s)\n", strerror(errno)); 5390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return -1; 5400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 5410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 5420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_DEBUG, LOCATION, NULL, 5430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "sockname %s\n", saddr2str((struct sockaddr *)&ss)); 5440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_DEBUG, LOCATION, NULL, 5450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "send packet from %s\n", saddr2str(src)); 5460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_DEBUG, LOCATION, NULL, 5470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "send packet to %s\n", saddr2str(dst)); 5480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 5490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (src->sa_family != ss.ss_family) { 5500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 5510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "address family mismatch\n"); 5520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return -1; 5530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 5540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 5550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang switch (src->sa_family) { 5560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#if defined(INET6) && defined(INET6_ADVAPI) 5570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang// XXX: This block wasn't compiled on Linux - does it work? 5580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang case AF_INET6: 5590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang { 5600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct msghdr m; 5610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct cmsghdr *cm; 5620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct iovec iov[2]; 5630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang u_char cmsgbuf[256]; 5640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct in6_pktinfo *pi; 5650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang int ifindex; 5660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct sockaddr_in6 src6, dst6; 5670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 5680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memcpy(&src6, src, sizeof(src6)); 5690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memcpy(&dst6, dst, sizeof(dst6)); 5700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 5710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang /* XXX take care of other cases, such as site-local */ 5720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang ifindex = 0; 5730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (IN6_IS_ADDR_LINKLOCAL(&src6.sin6_addr) 5740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang || IN6_IS_ADDR_MULTICAST(&src6.sin6_addr)) { 5750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang ifindex = src6.sin6_scope_id; /*???*/ 5760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 5770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 5780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang /* XXX some sanity check on dst6.sin6_scope_id */ 5790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 5800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang /* flowinfo for IKE? mmm, maybe useful but for now make it 0 */ 5810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang src6.sin6_flowinfo = dst6.sin6_flowinfo = 0; 5820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 5830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memset(&m, 0, sizeof(m)); 5840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang m.msg_name = (caddr_t)&dst6; 5850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang m.msg_namelen = sizeof(dst6); 5860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang iov[0].iov_base = (char *)buf; 5870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang iov[0].iov_len = buflen; 5880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang m.msg_iov = iov; 5890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang m.msg_iovlen = 1; 5900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 5910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memset(cmsgbuf, 0, sizeof(cmsgbuf)); 5920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang cm = (struct cmsghdr *)cmsgbuf; 5930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang m.msg_control = (caddr_t)cm; 5940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang m.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); 5950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 5960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 5970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang cm->cmsg_level = IPPROTO_IPV6; 5980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang cm->cmsg_type = IPV6_PKTINFO; 5990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang pi = (struct in6_pktinfo *)CMSG_DATA(cm); 6000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memcpy(&pi->ipi6_addr, &src6.sin6_addr, sizeof(src6.sin6_addr)); 6010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang pi->ipi6_ifindex = ifindex; 6020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 6030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_DEBUG, LOCATION, NULL, 6040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "src6 %s %d\n", 6050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang saddr2str((struct sockaddr *)&src6), 6060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang src6.sin6_scope_id); 6070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_DEBUG, LOCATION, NULL, 6080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "dst6 %s %d\n", 6090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang saddr2str((struct sockaddr *)&dst6), 6100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang dst6.sin6_scope_id); 6110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 6120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang for (i = 0; i < cnt; i++) { 6130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang len = sendmsg(s, &m, 0 /*MSG_DONTROUTE*/); 6140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (len < 0) { 6150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 6160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "sendmsg (%s)\n", strerror(errno)); 6170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return -1; 6180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 6190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_DEBUG, LOCATION, NULL, 6200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "%d times of %d bytes message will be sent " 6210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "to %s\n", 6220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang i + 1, len, saddr2str(dst)); 6230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 6240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plogdump(LLV_DEBUG, (char *)buf, buflen); 6250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 6260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return len; 6270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 6280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif 6290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef __linux__ 6300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang case AF_INET: 6310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang { 6320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct msghdr m; 6330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct cmsghdr *cm; 6340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct iovec iov[2]; 6350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang u_char cmsgbuf[256]; 6360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct in_pktinfo *pi; 6370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang int ifindex = 0; 6380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct sockaddr_in src6, dst6; 6390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 6400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memcpy(&src6, src, sizeof(src6)); 6410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memcpy(&dst6, dst, sizeof(dst6)); 6420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 6430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memset(&m, 0, sizeof(m)); 6440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang m.msg_name = (caddr_t)&dst6; 6450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang m.msg_namelen = sizeof(dst6); 6460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang iov[0].iov_base = (char *)buf; 6470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang iov[0].iov_len = buflen; 6480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang m.msg_iov = iov; 6490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang m.msg_iovlen = 1; 6500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 6510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memset(cmsgbuf, 0, sizeof(cmsgbuf)); 6520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang cm = (struct cmsghdr *)cmsgbuf; 6530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang m.msg_control = (caddr_t)cm; 6540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang m.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); 6550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 6560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang cm->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); 6570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang cm->cmsg_level = IPPROTO_IP; 6580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang cm->cmsg_type = IP_PKTINFO; 6590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang pi = (struct in_pktinfo *)CMSG_DATA(cm); 6600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memcpy(&pi->ipi_spec_dst, &src6.sin_addr, sizeof(src6.sin_addr)); 6610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang pi->ipi_ifindex = ifindex; 6620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 6630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_DEBUG, LOCATION, NULL, 6640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "src4 %s\n", 6650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang saddr2str((struct sockaddr *)&src6)); 6660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_DEBUG, LOCATION, NULL, 6670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "dst4 %s\n", 6680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang saddr2str((struct sockaddr *)&dst6)); 6690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 6700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang for (i = 0; i < cnt; i++) { 6710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang len = sendmsg(s, &m, 0 /*MSG_DONTROUTE*/); 6720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (len < 0) { 6730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 6740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "sendmsg (%s)\n", strerror(errno)); 6750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return -1; 6760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 6770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_DEBUG, LOCATION, NULL, 6780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "%d times of %d bytes message will be sent " 6790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "to %s\n", 6800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang i + 1, len, saddr2str(dst)); 6810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 6820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plogdump(LLV_DEBUG, (char *)buf, buflen); 6830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 6840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return len; 6850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 6860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif /* __linux__ */ 6870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang default: 6880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang { 6890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang int needclose = 0; 6900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang int sendsock; 6910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 6920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (ss.ss_family == src->sa_family && memcmp(&ss, src, sysdep_sa_len(src)) == 0) { 6930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang sendsock = s; 6940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang needclose = 0; 6950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } else { 6960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang int yes = 1; 6970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang /* 6980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * Use newly opened socket for sending packets. 6990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * NOTE: this is unsafe, because if the peer is quick enough 7000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * the packet from the peer may be queued into sendsock. 7010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * Better approach is to prepare bind'ed udp sockets for 7020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * each of the interface addresses. 7030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */ 704c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh sendsock = socket(src->sa_family, SOCK_DGRAM, 0); 7050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (sendsock < 0) { 7060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 7070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "socket (%s)\n", strerror(errno)); 7080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return -1; 7090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 7100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (setsockopt(sendsock, SOL_SOCKET, 7110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef __linux__ 7120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang SO_REUSEADDR, 7130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#else 7140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang SO_REUSEPORT, 7150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif 7160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang (void *)&yes, sizeof(yes)) < 0) { 7170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 7180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "setsockopt SO_REUSEPORT (%s)\n", 7190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang strerror(errno)); 7200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang close(sendsock); 7210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return -1; 7220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 7230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef IPV6_USE_MIN_MTU 7240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (src->sa_family == AF_INET6 && 7250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang setsockopt(sendsock, IPPROTO_IPV6, IPV6_USE_MIN_MTU, 7260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang (void *)&yes, sizeof(yes)) < 0) { 7270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 7280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "setsockopt IPV6_USE_MIN_MTU (%s)\n", 7290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang strerror(errno)); 7300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang close(sendsock); 7310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return -1; 7320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 7330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif 7340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (setsockopt_bypass(sendsock, src->sa_family) < 0) { 7350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang close(sendsock); 7360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return -1; 7370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 7380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 739c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (bind(sendsock, (struct sockaddr *)src, sysdep_sa_len(src)) < 0) { 7400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 7410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "bind 1 (%s)\n", strerror(errno)); 7420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang close(sendsock); 7430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return -1; 7440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 7450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang needclose = 1; 7460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 7470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 7480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang for (i = 0; i < cnt; i++) { 7490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang len = sendto(sendsock, buf, buflen, 0, dst, sysdep_sa_len(dst)); 7500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (len < 0) { 7510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 7520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "sendto (%s)\n", strerror(errno)); 7530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (needclose) 7540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang close(sendsock); 7550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return len; 7560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 7570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_DEBUG, LOCATION, NULL, 7580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "%d times of %d bytes message will be sent " 7590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "to %s\n", 7600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang i + 1, len, saddr2str(dst)); 7610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 7620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plogdump(LLV_DEBUG, (char *)buf, buflen); 7630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 7640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (needclose) 7650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang close(sendsock); 7660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 7670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return len; 7680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 7690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 7700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang} 7710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 7720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangint 7730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangsetsockopt_bypass(so, family) 7740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang int so, family; 7750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{ 7760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang int level; 7770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang char *buf; 7780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang char *policy; 7790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 7800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang switch (family) { 7810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang case AF_INET: 7820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang level = IPPROTO_IP; 7830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang break; 7840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef INET6 7850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang case AF_INET6: 7860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang level = IPPROTO_IPV6; 7870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang break; 7880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif 7890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang default: 7900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 7910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "unsupported address family %d\n", family); 7920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return -1; 7930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 7940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 7950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang policy = "in bypass"; 7960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang buf = ipsec_set_policy(policy, strlen(policy)); 7970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (buf == NULL) { 7980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 7990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "ipsec_set_policy (%s)\n", 8000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang ipsec_strerror()); 8010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return -1; 8020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 803c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (setsockopt(so, level, 8040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang (level == IPPROTO_IP ? 8050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang IP_IPSEC_POLICY : IPV6_IPSEC_POLICY), 8060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang buf, ipsec_get_policylen(buf)) < 0) { 8070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 8080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "setsockopt IP_IPSEC_POLICY (%s)\n", 8090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang strerror(errno)); 8100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return -1; 8110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 8120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang racoon_free(buf); 8130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 8140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang policy = "out bypass"; 8150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang buf = ipsec_set_policy(policy, strlen(policy)); 8160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (buf == NULL) { 8170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 8180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "ipsec_set_policy (%s)\n", 8190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang ipsec_strerror()); 8200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return -1; 8210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 822c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (setsockopt(so, level, 8230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang (level == IPPROTO_IP ? 8240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang IP_IPSEC_POLICY : IPV6_IPSEC_POLICY), 8250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang buf, ipsec_get_policylen(buf)) < 0) { 8260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 8270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "setsockopt IP_IPSEC_POLICY (%s)\n", 8280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang strerror(errno)); 8290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return -1; 8300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 8310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang racoon_free(buf); 8320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 8330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return 0; 8340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang} 8350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 8360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangstruct sockaddr * 8370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangnewsaddr(len) 8380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang int len; 8390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{ 8400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct sockaddr *new; 8410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 8420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if ((new = racoon_calloc(1, len)) == NULL) { 8430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 8440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "%s\n", strerror(errno)); 8450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang goto out; 8460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 8470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 8480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef __linux__ 8490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (len == sizeof (struct sockaddr_in6)) 8500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang new->sa_family = AF_INET6; 8510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang else 8520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang new->sa_family = AF_INET; 8530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#else 8540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang /* initial */ 8550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang new->sa_len = len; 8560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif 8570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangout: 8580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return new; 8590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang} 8600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 861c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#endif 862c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh 8630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangstruct sockaddr * 8640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangdupsaddr(src) 8650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct sockaddr *src; 8660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{ 8670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct sockaddr *dst; 8680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 8690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang dst = racoon_calloc(1, sysdep_sa_len(src)); 8700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (dst == NULL) { 8710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 8720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "%s\n", strerror(errno)); 8730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return NULL; 8740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 8750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 8760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memcpy(dst, src, sysdep_sa_len(src)); 8770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 8780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return dst; 8790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang} 8800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 8810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangchar * 8820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangsaddr2str(saddr) 8830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang const struct sockaddr *saddr; 8840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{ 8850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang static char buf[NI_MAXHOST + NI_MAXSERV + 10]; 8860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang char addr[NI_MAXHOST], port[NI_MAXSERV]; 8870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 8880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (saddr == NULL) 8890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return NULL; 8900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 8910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (saddr->sa_family == AF_UNSPEC) 8920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang snprintf (buf, sizeof(buf), "%s", "anonymous"); 8930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang else { 8940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang GETNAMEINFO(saddr, addr, port); 8950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang snprintf(buf, sizeof(buf), "%s[%s]", addr, port); 8960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 8970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 8980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return buf; 8990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang} 9000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 9010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangchar * 9020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangsaddrwop2str(saddr) 9030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang const struct sockaddr *saddr; 9040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{ 9050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang static char buf[NI_MAXHOST + NI_MAXSERV + 10]; 9060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang char addr[NI_MAXHOST]; 9070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 9080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (saddr == NULL) 9090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return NULL; 9100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 9110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang GETNAMEINFO_NULL(saddr, addr); 9120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang snprintf(buf, sizeof(buf), "%s", addr); 9130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 9140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return buf; 9150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang} 9160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 9170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangchar * 9180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangnaddrwop2str(const struct netaddr *naddr) 9190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{ 9200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang static char buf[NI_MAXHOST + 10]; 9210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang static const struct sockaddr sa_any; /* this is initialized to all zeros */ 9220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 9230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (naddr == NULL) 9240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return NULL; 9250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 9260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (memcmp(&naddr->sa, &sa_any, sizeof(sa_any)) == 0) 9270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang snprintf(buf, sizeof(buf), "%s", "any"); 9280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang else { 9290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang snprintf(buf, sizeof(buf), "%s", saddrwop2str(&naddr->sa.sa)); 9300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang snprintf(&buf[strlen(buf)], sizeof(buf) - strlen(buf), "/%ld", naddr->prefix); 9310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 9320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return buf; 9330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang} 9340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 9350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangchar * 9360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangnaddrwop2str_fromto(const char *format, const struct netaddr *saddr, 9370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang const struct netaddr *daddr) 9380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{ 9390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang static char buf[2*(NI_MAXHOST + NI_MAXSERV + 10) + 100]; 9400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang char *src, *dst; 9410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 9420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang src = racoon_strdup(naddrwop2str(saddr)); 9430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang dst = racoon_strdup(naddrwop2str(daddr)); 9440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang STRDUP_FATAL(src); 9450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang STRDUP_FATAL(dst); 9460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang /* WARNING: Be careful about the format string! Don't 9470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang ever pass in something that a user can modify!!! */ 9480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang snprintf (buf, sizeof(buf), format, src, dst); 9490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang racoon_free (src); 9500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang racoon_free (dst); 9510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 9520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return buf; 9530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang} 9540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 9550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangchar * 9560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangsaddr2str_fromto(format, saddr, daddr) 9570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang const char *format; 9580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang const struct sockaddr *saddr; 9590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang const struct sockaddr *daddr; 9600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{ 9610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang static char buf[2*(NI_MAXHOST + NI_MAXSERV + 10) + 100]; 9620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang char *src, *dst; 9630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 9640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang src = racoon_strdup(saddr2str(saddr)); 9650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang dst = racoon_strdup(saddr2str(daddr)); 9660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang STRDUP_FATAL(src); 9670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang STRDUP_FATAL(dst); 9680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang /* WARNING: Be careful about the format string! Don't 9690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang ever pass in something that a user can modify!!! */ 9700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang snprintf (buf, sizeof(buf), format, src, dst); 9710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang racoon_free (src); 9720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang racoon_free (dst); 9730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 9740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return buf; 9750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang} 9760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 9770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangstruct sockaddr * 9780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangstr2saddr(host, port) 9790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang char *host; 9800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang char *port; 9810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{ 9820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct addrinfo hints, *res; 9830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct sockaddr *saddr; 9840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang int error; 9850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 9860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memset(&hints, 0, sizeof(hints)); 9870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang hints.ai_family = PF_UNSPEC; 9880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang hints.ai_socktype = SOCK_DGRAM; 9890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang hints.ai_flags = AI_NUMERICHOST; 9900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang error = getaddrinfo(host, port, &hints, &res); 9910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (error != 0) { 9920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 9930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "getaddrinfo(%s%s%s): %s\n", 9940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang host, port ? "," : "", port ? port : "", 9950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang gai_strerror(error)); 9960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return NULL; 9970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 9980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (res->ai_next != NULL) { 9990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_WARNING, LOCATION, NULL, 10000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "getaddrinfo(%s%s%s): " 10010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "resolved to multiple address, " 10020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "taking the first one\n", 10030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang host, port ? "," : "", port ? port : ""); 10040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 10050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang saddr = racoon_malloc(res->ai_addrlen); 10060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (saddr == NULL) { 10070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 10080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "failed to allocate buffer.\n"); 10090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang freeaddrinfo(res); 10100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return NULL; 10110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 10120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memcpy(saddr, res->ai_addr, res->ai_addrlen); 10130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang freeaddrinfo(res); 10140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 10150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return saddr; 10160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang} 10170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 10180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangvoid 10190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangmask_sockaddr(a, b, l) 10200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct sockaddr *a; 10210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang const struct sockaddr *b; 10220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang size_t l; 10230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{ 10240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang size_t i; 10250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang u_int8_t *p, alen; 10260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 10270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang switch (b->sa_family) { 10280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang case AF_INET: 10290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang alen = sizeof(struct in_addr); 10300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang p = (u_int8_t *)&((struct sockaddr_in *)a)->sin_addr; 10310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang break; 10320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef INET6 10330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang case AF_INET6: 10340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang alen = sizeof(struct in6_addr); 10350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang p = (u_int8_t *)&((struct sockaddr_in6 *)a)->sin6_addr; 10360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang break; 10370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif 10380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang default: 10390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 10400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "invalid family: %d\n", b->sa_family); 10410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang exit(1); 10420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 10430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 10440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if ((alen << 3) < l) { 10450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 10460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "unexpected inconsistency: %d %zu\n", b->sa_family, l); 10470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang exit(1); 10480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 10490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 10500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang memcpy(a, b, sysdep_sa_len(b)); 10510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang p[l / 8] &= (0xff00 >> (l % 8)) & 0xff; 10520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang for (i = l / 8 + 1; i < alen; i++) 10530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang p[i] = 0x00; 10540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang} 10550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 10560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/* Compute a score describing how "accurate" a netaddr is for a given sockaddr. 10570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * Examples: 10580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * Return values for address 10.20.30.40 [port 500] and given netaddresses... 10590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 10.10.0.0/16 => -1 ... doesn't match 10600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 0.0.0.0/0 => 0 ... matches, but only 0 bits. 10610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 10.20.0.0/16 => 16 ... 16 bits match 10620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 10.20.30.0/24 => 24 ... guess what ;-) 10630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 10.20.30.40/32 => 32 ... whole address match 10640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 10.20.30.40:500 => 33 ... both address and port match 10650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 10.20.30.40:501 => -1 ... port doesn't match and isn't 0 (=any) 10660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */ 10670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangint 10680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangnaddr_score(const struct netaddr *naddr, const struct sockaddr *saddr) 10690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{ 10700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang static const struct netaddr naddr_any; /* initialized to all-zeros */ 10710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang struct sockaddr sa; 10720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang u_int16_t naddr_port, saddr_port; 10730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang int port_score; 10740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 10750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (!naddr || !saddr) { 10760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, 10770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "Call with null args: naddr=%p, saddr=%p\n", 10780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang naddr, saddr); 10790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return -1; 10800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 10810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 10820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang /* Wildcard address matches, but only 0 bits. */ 10830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (memcmp(naddr, &naddr_any, sizeof(naddr_any)) == 0) 10840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return 0; 10850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 10860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang /* If families don't match we really can't do much... */ 10870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (naddr->sa.sa.sa_family != saddr->sa_family) 10880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return -1; 10890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 10900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang /* If port check fail don't bother to check addresses. */ 10910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang naddr_port = extract_port(&naddr->sa.sa); 10920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang saddr_port = extract_port(saddr); 10930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (naddr_port == 0 || saddr_port == 0) /* wildcard match */ 10940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang port_score = 0; 10950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang else if (naddr_port == saddr_port) /* exact match */ 10960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang port_score = 1; 10970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang else /* mismatch :-) */ 10980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return -1; 10990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 11000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang /* Here it comes - compare network addresses. */ 11010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang mask_sockaddr(&sa, saddr, naddr->prefix); 11020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (loglevel >= LLV_DEBUG) { /* debug only */ 11030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang char *a1, *a2, *a3; 11040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang a1 = racoon_strdup(naddrwop2str(naddr)); 11050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang a2 = racoon_strdup(saddrwop2str(saddr)); 11060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang a3 = racoon_strdup(saddrwop2str(&sa)); 11070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang STRDUP_FATAL(a1); 11080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang STRDUP_FATAL(a2); 11090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang STRDUP_FATAL(a3); 11100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_DEBUG, LOCATION, NULL, 11110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang "naddr=%s, saddr=%s (masked=%s)\n", 11120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang a1, a2, a3); 11130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang free(a1); 11140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang free(a2); 11150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang free(a3); 11160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 1117c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh if (cmpsaddrwop(&sa, &naddr->sa.sa) == 0) 11180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return naddr->prefix + port_score; 11190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 11200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return -1; 11210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang} 11220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 1123c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh/* Some usefull functions for sockaddr port manipulations. */ 11240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangu_int16_t 11250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangextract_port (const struct sockaddr *addr) 11260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{ 11270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang u_int16_t port = 0; 11280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 11290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (!addr) 11300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return port; 11310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 11320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang switch (addr->sa_family) { 11330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang case AF_INET: 11340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang port = ((struct sockaddr_in *)addr)->sin_port; 11350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang break; 11360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang case AF_INET6: 11370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang port = ((struct sockaddr_in6 *)addr)->sin6_port; 11380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang break; 11390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang default: 11400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, "unknown AF: %u\n", addr->sa_family); 11410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang break; 11420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 11430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 11440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return ntohs(port); 11450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang} 11460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 11470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangu_int16_t * 11480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangget_port_ptr (struct sockaddr *addr) 11490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{ 11500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang u_int16_t *port_ptr; 11510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 11520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (!addr) 11530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return NULL; 11540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 11550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang switch (addr->sa_family) { 11560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang case AF_INET: 11570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang port_ptr = &(((struct sockaddr_in *)addr)->sin_port); 11580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang break; 11590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang case AF_INET6: 11600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang port_ptr = &(((struct sockaddr_in6 *)addr)->sin6_port); 11610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang break; 11620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang default: 11630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang plog(LLV_ERROR, LOCATION, NULL, "unknown AF: %u\n", addr->sa_family); 11640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return NULL; 11650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang break; 11660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang } 11670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 11680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return port_ptr; 11690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang} 11700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 11710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangu_int16_t * 11720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangset_port (struct sockaddr *addr, u_int16_t new_port) 11730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{ 11740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang u_int16_t *port_ptr; 11750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 11760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang port_ptr = get_port_ptr (addr); 11770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 11780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang if (port_ptr) 11790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *port_ptr = htons(new_port); 11800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang 11810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang return port_ptr; 11820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang} 1183