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

📄 sysdep_linux.c

📁 ipsec vpn
💻 C
字号:
/* * routines that are Linux specific * * Copyright (C) 2005 Michael Richardson <mcr@xelerance.com> * 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: sysdep_linux.c,v 1.2 2005/07/19 20:34:15 ken Exp $ */#include <stddef.h>#include <string.h>#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <wait.h>#include <unistd.h>#include <fcntl.h>#include <sys/utsname.h>#include <sys/queue.h>#include <sys/stat.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <openswan.h>#include <openswan/ipsec_policy.h>#include "constants.h"#include "oswlog.h"#include "defs.h"#include "rnd.h"#include "id.h"#include "connections.h"        /* needs id.h */#include "state.h"#include "timer.h"#include "kernel.h"#include "kernel_netlink.h"#include "kernel_pfkey.h"#include "kernel_noklips.h"#include "packet.h"#include "x509.h"#include "log.h"#include "server.h"#include "whack.h"      /* for RC_LOG_SERIOUS */#include "keys.h"/* invoke the updown script to do the routing and firewall commands required * * The user-specified updown script is run.  Parameters are fed to it in * the form of environment variables.  All such environment variables * have names starting with "PLUTO_". * * The operation to be performed is specified by PLUTO_VERB.  This * verb has a suffix "-host" if the client on this end is just the * host; otherwise the suffix is "-client".  If the address family * of the host is IPv6, an extra suffix of "-v6" is added. * * "prepare-host" and "prepare-client" are used to delete a route * that may exist (due to forces outside of Pluto).  It is used to * prepare for pluto creating a route. * * "route-host" and "route-client" are used to install a route. * Since routing is based only on destination, the PLUTO_MY_CLIENT_* * values are probably of no use (using them may signify a bug). * * "unroute-host" and "unroute-client" are used to delete a route. * Since routing is based only on destination, the PLUTO_MY_CLIENT_* * values are probably of no use (using them may signify a bug). * * "up-host" and "up-client" are run when an eroute is added (not replaced). * They are useful for adjusting a firewall: usually for adding a rule * to let processed packets flow between clients.  Note that only * one eroute may exist for a pair of client subnets but inbound * IPsec SAs may persist without an eroute. * * "down-host" and "down-client" are run when an eroute is deleted. * They are useful for adjusting a firewall. */#ifndef DEFAULT_UPDOWN# define DEFAULT_UPDOWN "ipsec _updown"#endifbooldo_command_linux(struct connection *c, struct spd_route *sr		 , const char *verb, struct state *st){    char cmd[1536];     /* arbitrary limit on shell command length */    const char *verb_suffix;    /* figure out which verb suffix applies */    {        const char *hs, *cs;        switch (addrtypeof(&sr->this.host_addr))        {            case AF_INET:                hs = "-host";                cs = "-client";                break;            case AF_INET6:                hs = "-host-v6";                cs = "-client-v6";                break;            default:                loglog(RC_LOG_SERIOUS, "unknown address family");                return FALSE;        }        verb_suffix = subnetisaddr(&sr->this.client, &sr->this.host_addr)            ? hs : cs;    }    /* form the command string */    {        char            nexthop_str[sizeof("PLUTO_NEXT_HOP='' ")+ADDRTOT_BUF],            me_str[ADDRTOT_BUF],            myid_str[IDTOA_BUF],            srcip_str[ADDRTOT_BUF+sizeof("PLUTO_MY_SOURCEIP=")+4],            myclient_str[SUBNETTOT_BUF],            myclientnet_str[ADDRTOT_BUF],            myclientmask_str[ADDRTOT_BUF],            peer_str[ADDRTOT_BUF],            peerid_str[IDTOA_BUF],            peerclient_str[SUBNETTOT_BUF],            peerclientnet_str[ADDRTOT_BUF],            peerclientmask_str[ADDRTOT_BUF],            secure_myid_str[IDTOA_BUF] = "",            secure_peerid_str[IDTOA_BUF] = "",            secure_peerca_str[IDTOA_BUF] = "",            secure_xauth_username_str[IDTOA_BUF] = "";	            ip_address ta;	nexthop_str[0]='\0';	if(addrbytesptr(&sr->this.host_nexthop, NULL)	   && !isanyaddr(&sr->this.host_nexthop))	{	    char *n;	    strcpy(nexthop_str, "PLUTO_NEXT_HOP='");	    n = nexthop_str + strlen(nexthop_str);	    addrtot(&sr->this.host_nexthop, 0,		    n, sizeof(nexthop_str)-strlen(nexthop_str));	    strncat(nexthop_str, "' ", sizeof(nexthop_str));	}        addrtot(&sr->this.host_addr, 0, me_str, sizeof(me_str));        idtoa(&sr->this.id, myid_str, sizeof(myid_str));        escape_metachar(myid_str, secure_myid_str, sizeof(secure_myid_str));        subnettot(&sr->this.client, 0, myclient_str, sizeof(myclientnet_str));        networkof(&sr->this.client, &ta);        addrtot(&ta, 0, myclientnet_str, sizeof(myclientnet_str));        maskof(&sr->this.client, &ta);        addrtot(&ta, 0, myclientmask_str, sizeof(myclientmask_str));        addrtot(&sr->that.host_addr, 0, peer_str, sizeof(peer_str));        idtoa(&sr->that.id, peerid_str, sizeof(peerid_str));        escape_metachar(peerid_str, secure_peerid_str, sizeof(secure_peerid_str));        subnettot(&sr->that.client, 0, peerclient_str, sizeof(peerclientnet_str));        networkof(&sr->that.client, &ta);        addrtot(&ta, 0, peerclientnet_str, sizeof(peerclientnet_str));        maskof(&sr->that.client, &ta);        addrtot(&ta, 0, peerclientmask_str, sizeof(peerclientmask_str));		secure_xauth_username_str[0]='\0';	if (st != NULL && st->st_xauth_username) {		size_t len;	 	strcpy(secure_xauth_username_str, "PLUTO_XAUTH_USERNAME='");		len = strlen(secure_xauth_username_str);		remove_metachar(st->st_xauth_username				,secure_xauth_username_str+len				,sizeof(secure_xauth_username_str)-(len+2));		strncat(secure_xauth_username_str, "'", sizeof(secure_xauth_username_str)-1);	}        srcip_str[0]='\0';        if(addrbytesptr(&sr->this.host_srcip, NULL) != 0           && !isanyaddr(&sr->this.host_srcip))        {            char *p;            int   l;            strncat(srcip_str, "PLUTO_MY_SOURCEIP=", sizeof(srcip_str));            strncat(srcip_str, "'", sizeof(srcip_str));            l = strlen(srcip_str);            p = srcip_str + l;                        addrtot(&sr->this.host_srcip, 0, p, sizeof(srcip_str));            strncat(srcip_str, "'", sizeof(srcip_str));        }        {            struct pubkey_list *p;            char peerca_str[IDTOA_BUF];            for (p = pubkeys; p != NULL; p = p->next)                {                    struct pubkey *key = p->key;                    int pathlen;                                        if (key->alg == PUBKEY_ALG_RSA && same_id(&sr->that.id, &key->id)                        && trusted_ca(key->issuer, sr->that.ca, &pathlen))                        {                            dntoa_or_null(peerca_str, IDTOA_BUF, key->issuer, "");                            escape_metachar(peerca_str, secure_peerca_str, sizeof(secure_peerca_str));                            break;                        }                }        }        if (-1 == snprintf(cmd, sizeof(cmd)			   , "2>&1 "   /* capture stderr along with stdout */			   "PLUTO_VERSION='1.1' "    /* change VERSION when interface spec changes */			   "PLUTO_VERB='%s%s' "			   "PLUTO_CONNECTION='%s' "			   "%s"      /* possible PLUTO_NEXT_HOP */			   "PLUTO_INTERFACE='%s' "			   "PLUTO_ME='%s' "			   "PLUTO_MY_ID='%s' "			   "PLUTO_MY_CLIENT='%s' "			   "PLUTO_MY_CLIENT_NET='%s' "			   "PLUTO_MY_CLIENT_MASK='%s' "			   "PLUTO_MY_PORT='%u' "			   "PLUTO_MY_PROTOCOL='%u' "			   "PLUTO_PEER='%s' "			   "PLUTO_PEER_ID='%s' "			   "PLUTO_PEER_CLIENT='%s' "			   "PLUTO_PEER_CLIENT_NET='%s' "			   "PLUTO_PEER_CLIENT_MASK='%s' "			   "PLUTO_PEER_PORT='%u' "			   "PLUTO_PEER_PROTOCOL='%u' "			   "PLUTO_PEER_CA='%s' "			   "PLUTO_CONN_POLICY='%s' "			   "%s "			   "%s "       /* PLUTO_MY_SRCIP */                    			   "%s"        /* actual script */			   , verb, verb_suffix			   , c->name			   , nexthop_str			   , c->interface->ip_dev->id_vname			   , me_str			   , secure_myid_str			   , myclient_str			   , myclientnet_str			   , myclientmask_str			   , sr->this.port			   , sr->this.protocol			   , peer_str			   , secure_peerid_str			   , peerclient_str			   , peerclientnet_str			   , peerclientmask_str			   , sr->that.port			   , sr->that.protocol			   , secure_peerca_str			   , prettypolicy(c->policy)			   , secure_xauth_username_str			   , srcip_str			   , sr->this.updown == NULL? DEFAULT_UPDOWN : sr->this.updown))        {            loglog(RC_LOG_SERIOUS, "%s%s command too long!", verb, verb_suffix);            return FALSE;        }    }    DBG(DBG_CONTROL, DBG_log("executing %s%s: %s"        , verb, verb_suffix, cmd));    {        /* invoke the script, catching stderr and stdout         * It may be of concern that some file descriptors will         * be inherited.  For the ones under our control, we         * have done fcntl(fd, F_SETFD, FD_CLOEXEC) to prevent this.         * Any used by library routines (perhaps the resolver or syslog)         * will remain.         */	__sighandler_t savesig;        FILE *f;	savesig = signal(SIGCHLD, SIG_DFL);        f = popen(cmd, "r");        if (f == NULL)        {            loglog(RC_LOG_SERIOUS, "unable to popen %s%s command", verb, verb_suffix);	    signal(SIGCHLD, savesig);            return FALSE;        }        /* log any output */        for (;;)        {            /* if response doesn't fit in this buffer, it will be folded */            char resp[256];            if (fgets(resp, sizeof(resp), f) == NULL)            {                if (ferror(f))                {                    log_errno((e, "fgets failed on output of %s%s command"                        , verb, verb_suffix));		    signal(SIGCHLD, savesig);                    return FALSE;                }                else                {                    passert(feof(f));                    break;                }            }            else            {                char *e = resp + strlen(resp);                if (e > resp && e[-1] == '\n')                    e[-1] = '\0';       /* trim trailing '\n' */                openswan_log("%s%s output: %s", verb, verb_suffix, resp);            }        }        /* report on and react to return code */        {            int r = pclose(f);	    signal(SIGCHLD, savesig);            if (r == -1)            {                log_errno((e, "pclose failed for %s%s command"                    , verb, verb_suffix));                return FALSE;            }            else if (WIFEXITED(r))            {                if (WEXITSTATUS(r) != 0)                {                    loglog(RC_LOG_SERIOUS, "%s%s command exited with status %d"                        , verb, verb_suffix, WEXITSTATUS(r));                    return FALSE;                }            }            else if (WIFSIGNALED(r))            {                loglog(RC_LOG_SERIOUS, "%s%s command exited with signal %d"                    , verb, verb_suffix, WTERMSIG(r));                return FALSE;            }            else            {                loglog(RC_LOG_SERIOUS, "%s%s command exited with unknown status %d"                    , verb, verb_suffix, r);                return FALSE;            }        }    }    return TRUE;}

⌨️ 快捷键说明

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