⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 server.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 2 页
字号:
/* get-next-event loop * Copyright (C) 1997 Angelos D. Keromytis. * Copyright (C) 1998-2002  D. Hugh Redelmeier. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * for more details. * * RCSID $Id: server.c,v 1.103 2004/11/30 02:28:07 mcr Exp $ */#include <stdio.h>#include <stdlib.h>#include <stddef.h>#include <string.h>#include <errno.h>#include <signal.h>#include <ctype.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/socket.h>#include <sys/un.h>#ifdef SOLARIS# include <sys/sockio.h>	/* for Solaris 2.6: defines SIOCGIFCONF */#endif#include <netinet/in.h>#include <arpa/inet.h>#include <sys/time.h>#include <netdb.h>#include <unistd.h>#include <fcntl.h>#include <net/if.h>#include <sys/ioctl.h>#include <resolv.h>#include <arpa/nameser.h>	/* missing from <resolv.h> on old systems */#include <sys/queue.h>#include <sys/resource.h>#include <sys/wait.h>#include <openswan.h>#include "constants.h"#include "defs.h"#include "state.h"#include "id.h"#include "x509.h"#include "pgp.h"#include "certs.h"#include "smartcard.h"#ifdef XAUTH_USEPAM#include <security/pam_appl.h>#endif#include "connections.h"	/* needs id.h */#include "kernel.h"  /* for no_klips; needs connections.h */#include "log.h"#include "server.h"#include "timer.h"#include "packet.h"#include "demux.h"  /* needs packet.h */#include "rcv_whack.h"#include "rcv_info.h"#include "keys.h"#include "adns.h"	/* needs <resolv.h> */#include "dnskey.h"	/* needs keys.h and adns.h */#include "whack.h"	/* for RC_LOG_SERIOUS */#include "pluto_crypt.h" /* cryptographic helper functions */#include <pfkeyv2.h>#include <pfkey.h>#include "kameipsec.h"#ifdef NAT_TRAVERSAL#include "nat_traversal.h"#endif/* *  Server main loop and socket initialization routines. */static const int on = TRUE;	/* by-reference parameter; constant, we hope */bool no_retransmits = FALSE;/* control (whack) socket */int ctl_fd = NULL_FD;	/* file descriptor of control (whack) socket */struct sockaddr_un ctl_addr = { AF_UNIX, DEFAULT_CTLBASE CTL_SUFFIX };/* info (showpolicy) socket */int policy_fd = NULL_FD;struct sockaddr_un info_addr= { AF_UNIX, DEFAULT_CTLBASE INFO_SUFFIX };/* Initialize the control socket. * Note: this is called very early, so little infrastructure is available. * It is important that the socket is created before the original * Pluto process returns. */err_tinit_ctl_socket(void){    err_t failed = NULL;    delete_ctl_socket();	/* preventative medicine */    ctl_fd = socket(AF_UNIX, SOCK_STREAM, 0);    if (ctl_fd == -1)	failed = "create";    else if (fcntl(ctl_fd, F_SETFD, FD_CLOEXEC) == -1)	failed = "fcntl FD+CLOEXEC";    else if (setsockopt(ctl_fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on)) < 0)	failed = "setsockopt";    else    {	/* to keep control socket secure, use umask */	mode_t ou = umask(~S_IRWXU);	if (bind(ctl_fd, (struct sockaddr *)&ctl_addr	, offsetof(struct sockaddr_un, sun_path) + strlen(ctl_addr.sun_path)) < 0)	    failed = "bind";	umask(ou);    }    /* 5 is a haphazardly chosen limit for the backlog.     * Rumour has it that this is the max on BSD systems.     */    if (failed == NULL && listen(ctl_fd, 5) < 0)	failed = "listen() on";    return failed == NULL? NULL : builddiag("could not %s control socket: %d %s"	    , failed, errno, strerror(errno));}voiddelete_ctl_socket(void){    /* Is noting failure useful?  Not when used as preventative medicine. */    unlink(ctl_addr.sun_path);}#ifdef IPSECPOLICY/* Initialize the info socket. */err_tinit_info_socket(void){    err_t failed = NULL;    delete_info_socket();	/* preventative medicine */    info_fd = socket(AF_UNIX, SOCK_STREAM, 0);    if (info_fd == -1)	failed = "create";    else if (fcntl(info_fd, F_SETFD, FD_CLOEXEC) == -1)	failed = "fcntl FD+CLOEXEC";    else if (setsockopt(info_fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on)) < 0)	failed = "setsockopt";    else    {	/* this socket should be openable by all proceses */	mode_t ou = umask(0);	if (bind(info_fd, (struct sockaddr *)&info_addr	, offsetof(struct sockaddr_un, sun_path) + strlen(info_addr.sun_path)) < 0)	    failed = "bind";	umask(ou);    }    /* 64 might be big enough, and the system may limit us anyway.     */    if (failed == NULL && listen(info_fd, 64) < 0)	failed = "listen() on";    return failed == NULL? NULL : builddiag("could not %s info socket: %d %s"	    , failed, errno, strerror(errno));}voiddelete_info_socket(void){    unlink(info_addr.sun_path);}#endif /* IPSECPOLICY */bool listening = FALSE;	/* should we pay attention to IKE messages? */struct iface *interfaces = NULL;	/* public interfaces *//* Initialize the interface sockets. */static voidmark_ifaces_dead(void){    struct iface *p;    for (p = interfaces; p != NULL; p = p->next)	p->change = IFN_DELETE;}static voidfree_dead_ifaces(void){    struct iface *p;    bool some_dead = FALSE	, some_new = FALSE;    for (p = interfaces; p != NULL; p = p->next)    {	if (p->change == IFN_DELETE)	{	    openswan_log("shutting down interface %s/%s %s"		, p->vname, p->rname, ip_str(&p->addr));	    some_dead = TRUE;	}	else if (p->change == IFN_ADD)	{	    some_new = TRUE;	}    }    if (some_dead)    {	struct iface **pp;	release_dead_interfaces();	for (pp = &interfaces; (p = *pp) != NULL; )	{	    if (p->change == IFN_DELETE)	    {		*pp = p->next;	/* advance *pp */		pfree(p->vname);		pfree(p->rname);		close(p->fd);		pfree(p);	    }	    else	    {		pp = &p->next;	/* advance pp */	    }	}    }    /* this must be done after the release_dead_interfaces     * in case some to the newly unoriented connections can     * become oriented here.     */    if (some_dead || some_new)	check_orientations();}voidfree_ifaces(void){    mark_ifaces_dead();    free_dead_ifaces();}struct raw_iface {    ip_address addr;    char name[IFNAMSIZ + 20];	/* what would be a safe size? */    struct raw_iface *next;};/* Called to handle --interface <ifname> * Semantics: if specified, only these (real) interfaces are considered. */static const char *pluto_ifn[10];static int pluto_ifn_roof = 0;booluse_interface(const char *rifn){    if(pluto_ifn_inst[0]=='\0') {	pluto_ifn_inst = clone_str(rifn, "genifn");    }    if (pluto_ifn_roof >= (int)elemsof(pluto_ifn))    {	return FALSE;    }    else    {	pluto_ifn[pluto_ifn_roof++] = rifn;	return TRUE;    }}#ifndef IPSECDEVPREFIX# define IPSECDEVPREFIX "ipsec"#endifstatic struct raw_iface *find_raw_ifaces4(void){    int j;	/* index into buf */    struct ifconf ifconf;    struct ifreq buf[300];	/* for list of interfaces -- arbitrary limit */    struct raw_iface *rifaces = NULL;    int master_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);    /* Get a UDP socket */    /* get list of interfaces with assigned IPv4 addresses from system */    if (master_sock == -1)	exit_log_errno((e, "socket() failed in find_raw_ifaces4()"));    if (setsockopt(master_sock, SOL_SOCKET, SO_REUSEADDR    , (const void *)&on, sizeof(on)) < 0)	exit_log_errno((e, "setsockopt() in find_raw_ifaces4()"));    /* bind the socket */    {	ip_address any;	happy(anyaddr(AF_INET, &any));	setportof(htons(pluto_port), &any);	if (bind(master_sock, sockaddrof(&any), sockaddrlenof(&any)) < 0)	    exit_log_errno((e, "bind() failed in find_raw_ifaces4()"));    }    /* Get local interfaces.  See netdevice(7). */    ifconf.ifc_len = sizeof(buf);    ifconf.ifc_buf = (void *) buf;    zero(buf);    if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1)	exit_log_errno((e, "ioctl(SIOCGIFCONF) in find_raw_ifaces4()"));    /* Add an entry to rifaces for each interesting interface. */    for (j = 0; (j+1) * sizeof(*buf) <= (size_t)ifconf.ifc_len; j++)    {	struct raw_iface ri;	const struct sockaddr_in *rs = (struct sockaddr_in *) &buf[j].ifr_addr;	struct ifreq auxinfo;	/* ignore all but AF_INET interfaces */	if (rs->sin_family != AF_INET)	    continue;	/* not interesting */	/* build a NUL-terminated copy of the rname field */	memcpy(ri.name, buf[j].ifr_name, IFNAMSIZ);	ri.name[IFNAMSIZ] = '\0';	/* ignore if our interface names were specified, and this isn't one */	if (pluto_ifn_roof != 0)	{	    int i;	    for (i = 0; i != pluto_ifn_roof; i++)		if (streq(ri.name, pluto_ifn[i]))		    break;	    if (i == pluto_ifn_roof)		continue;	/* not found -- skip */	}	/* Find out stuff about this interface.  See netdevice(7). */	zero(&auxinfo);	/* paranoia */	memcpy(auxinfo.ifr_name, buf[j].ifr_name, IFNAMSIZ);	if (ioctl(master_sock, SIOCGIFFLAGS, &auxinfo) == -1)	    exit_log_errno((e		, "ioctl(SIOCGIFFLAGS) for %s in find_raw_ifaces4()"		, ri.name));	if (!(auxinfo.ifr_flags & IFF_UP))	    continue;	/* ignore an interface that isn't UP */	/* ignore unconfigured interfaces */	if (rs->sin_addr.s_addr == 0)	    continue;	happy(initaddr((const void *)&rs->sin_addr, sizeof(struct in_addr)	    , AF_INET, &ri.addr));	DBG(DBG_CONTROL, DBG_log("found %s with address %s"	    , ri.name, ip_str(&ri.addr)));	ri.next = rifaces;	rifaces = clone_thing(ri, "struct raw_iface");    }    close(master_sock);    return rifaces;}static struct raw_iface *find_raw_ifaces6(void){    /* Get list of interfaces with IPv6 addresses from system from /proc/net/if_inet6).     *     * Documentation of format?     * RTFS: linux-2.2.16/net/ipv6/addrconf.c:iface_proc_info()     *       linux-2.4.9-13/net/ipv6/addrconf.c:iface_proc_info()     *     * Sample from Gerhard's laptop:     *	00000000000000000000000000000001 01 80 10 80       lo     *	30490009000000000000000000010002 02 40 00 80   ipsec0     *	30490009000000000000000000010002 07 40 00 80     eth0     *	fe80000000000000025004fffefd5484 02 0a 20 80   ipsec0     *	fe80000000000000025004fffefd5484 07 0a 20 80     eth0     *     * Each line contains:     * - IPv6 address: 16 bytes, in hex, no punctuation     * - ifindex: 1 byte, in hex     * - prefix_len: 1 byte, in hex     * - scope (e.g. global, link local): 1 byte, in hex     * - flags: 1 byte, in hex     * - device name: string, followed by '\n'     */    struct raw_iface *rifaces = NULL;    static const char proc_name[] = "/proc/net/if_inet6";    FILE *proc_sock = fopen(proc_name, "r");    if (proc_sock == NULL)    {	DBG(DBG_CONTROL, DBG_log("could not open %s", proc_name));    }    else    {	for (;;)	{	    struct raw_iface ri;	    unsigned short xb[8];	/* IPv6 address as 8 16-bit chunks */	    char sb[8*5];	/* IPv6 address as string-with-colons */	    unsigned int if_idx;	/* proc field, not used */	    unsigned int plen;	/* proc field, not used */	    unsigned int scope;	/* proc field, used to exclude link-local */	    unsigned int dad_status;	/* proc field, not used */	    /* ??? I hate and distrust scanf -- DHR */	    int r = fscanf(proc_sock		, "%4hx%4hx%4hx%4hx%4hx%4hx%4hx%4hx"		  " %02x %02x %02x %02x %20s\n"		, xb+0, xb+1, xb+2, xb+3, xb+4, xb+5, xb+6, xb+7		, &if_idx, &plen, &scope, &dad_status, ri.name);	    /* ??? we should diagnose any problems */	    if (r != 13)		break;	    /* ignore addresses with link local scope.	     * From linux-2.4.9-13/include/net/ipv6.h:	     * IPV6_ADDR_LINKLOCAL	0x0020U	     * IPV6_ADDR_SCOPE_MASK	0x00f0U	     */	    if ((scope & 0x00f0U) == 0x0020U)		continue;	    snprintf(sb, sizeof(sb)		, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"		, xb[0], xb[1], xb[2], xb[3], xb[4], xb[5], xb[6], xb[7]);	    happy(ttoaddr(sb, 0, AF_INET6, &ri.addr));	    if (!isunspecaddr(&ri.addr))	    {		DBG(DBG_CONTROL		    , DBG_log("found %s with address %s"			, ri.name, sb));		ri.next = rifaces;		rifaces = clone_thing(ri, "struct raw_iface");	    }	}	fclose(proc_sock);    }    return rifaces;}static intcreate_socket(struct raw_iface *ifp, const char *v_name, int port){    int fd = socket(addrtypeof(&ifp->addr), SOCK_DGRAM, IPPROTO_UDP);    int fcntl_flags;    if (fd < 0)    {	log_errno((e, "socket() in process_raw_ifaces()"));	return -1;    }    /* Set socket Nonblocking */    if ((fcntl_flags=fcntl(fd, F_GETFL)) >= 0) {	if (!(fcntl_flags & O_NONBLOCK)) {	    fcntl_flags |= O_NONBLOCK;	    fcntl(fd, F_SETFL, fcntl_flags);	}    }    if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)    {	log_errno((e, "fcntl(,, FD_CLOEXEC) in process_raw_ifaces()"));	close(fd);	return -1;    }    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR    , (const void *)&on, sizeof(on)) < 0)    {	log_errno((e, "setsockopt SO_REUSEADDR in process_raw_ifaces()"));	close(fd);	return -1;    }    /* To improve error reporting.  See ip(7). */#if defined(IP_RECVERR) && defined(MSG_ERRQUEUE)    if (setsockopt(fd, SOL_IP, IP_RECVERR    , (const void *)&on, sizeof(on)) < 0)    {	log_errno((e, "setsockopt IP_RECVERR in process_raw_ifaces()"));	close(fd);	return -1;    }#endif    /* With IPv6, there is no fragmentation after     * it leaves our interface.  PMTU discovery     * is mandatory but doesn't work well with IKE (why?).     * So we must set the IPV6_USE_MIN_MTU option.     * See draft-ietf-ipngwg-rfc2292bis-01.txt 11.1     */#ifdef IPV6_USE_MIN_MTU	/* YUCK: not always defined */    if (addrtypeof(&ifp->addr) == AF_INET6    && setsockopt(fd, SOL_SOCKET, IPV6_USE_MIN_MTU      , (const void *)&on, sizeof(on)) < 0)    {	log_errno((e, "setsockopt IPV6_USE_MIN_MTU in process_raw_ifaces()"));	close(fd);	return -1;    }#endif#if defined(linux) && defined(KERNEL26_SUPPORT)    if (!no_klips && kernel_ops->type == KERNEL_TYPE_LINUX)    {	struct sadb_x_policy policy;	int level, opt;	policy.sadb_x_policy_len = sizeof(policy) / IPSEC_PFKEYv2_ALIGN;	policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY;	policy.sadb_x_policy_type = IPSEC_POLICY_BYPASS;	policy.sadb_x_policy_dir = IPSEC_DIR_INBOUND;	policy.sadb_x_policy_reserved = 0;	policy.sadb_x_policy_id = 0;	policy.sadb_x_policy_reserved2 = 0;	if (addrtypeof(&ifp->addr) == AF_INET6)	{	    level = IPPROTO_IPV6;	    opt = IPV6_IPSEC_POLICY;	}	else	{	    level = IPPROTO_IP;	    opt = IP_IPSEC_POLICY;	}	if (setsockopt(fd, level, opt	  , &policy, sizeof(policy)) < 0)	{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -