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

📄 kernel.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 5 页
字号:
         * There may already be a %trap: replace it.         * There may not be any broad eroute: add %hold.         * Once the broad %hold is in place, delete the narrow one.         */        if (rn != ro)        {            if (erouted(ro)            ? !eroute_connection(sr, htonl(SPI_HOLD), SA_INT, SADB_X_SATYPE_INT                                 , null_proto_info                                 , ERO_REPLACE                                 , "replace %trap with broad %hold")            : !eroute_connection(sr, htonl(SPI_HOLD), SA_INT, SADB_X_SATYPE_INT                                 , null_proto_info                , ERO_ADD, "add broad %hold"))            {                return FALSE;            }        }        if (!replace_bare_shunt(src, dst                                , BOTTOM_PRIO                                , SPI_HOLD                                , FALSE                                , transport_proto                                , "delete narrow %hold"))            return FALSE;    }    sr->routing = rn;    return TRUE;}/* install or remove eroute for SA Group */static boolsag_eroute(struct state *st, struct spd_route *sr           , unsigned op, const char *opname){    unsigned int        inner_proto,        inner_satype;    ipsec_spi_t inner_spi;    struct pfkey_proto_info proto_info[4];    int i;    bool tunnel;    /* figure out the SPI and protocol (in two forms)     * for the innermost transformation.     */    i = sizeof(proto_info) / sizeof(proto_info[0]) - 1;    proto_info[i].proto = 0;    tunnel = FALSE;    if (st->st_ah.present)    {        inner_spi = st->st_ah.attrs.spi;        inner_proto = SA_AH;        inner_satype = SADB_SATYPE_AH;        i--;        proto_info[i].proto = IPPROTO_AH;        proto_info[i].encapsulation = st->st_ah.attrs.encapsulation;        tunnel |= proto_info[i].encapsulation == ENCAPSULATION_MODE_TUNNEL;        proto_info[i].reqid = sr->reqid;    }    if (st->st_esp.present)    {        inner_spi = st->st_esp.attrs.spi;        inner_proto = SA_ESP;        inner_satype = SADB_SATYPE_ESP;        i--;        proto_info[i].proto = IPPROTO_ESP;        proto_info[i].encapsulation = st->st_esp.attrs.encapsulation;        tunnel |= proto_info[i].encapsulation == ENCAPSULATION_MODE_TUNNEL;        proto_info[i].reqid = sr->reqid + 1;    }    if (st->st_ipcomp.present)    {        inner_spi = st->st_ipcomp.attrs.spi;        inner_proto = SA_COMP;        inner_satype = SADB_X_SATYPE_COMP;        i--;        proto_info[i].proto = IPPROTO_COMP;        proto_info[i].encapsulation = st->st_ipcomp.attrs.encapsulation;        tunnel |= proto_info[i].encapsulation == ENCAPSULATION_MODE_TUNNEL;        proto_info[i].reqid = sr->reqid + 2;    }    if (i == sizeof(proto_info) / sizeof(proto_info[0]) - 1)    {        impossible();   /* no transform at all! */    }    if (tunnel)    {        int j;        inner_spi = st->st_tunnel_out_spi;        inner_proto = SA_IPIP;        inner_satype = SADB_X_SATYPE_IPIP;        proto_info[i].encapsulation = ENCAPSULATION_MODE_TUNNEL;        for (j = i + 1; proto_info[j].proto; j++)        {            proto_info[j].encapsulation = ENCAPSULATION_MODE_TRANSPORT;        }    }    return eroute_connection(sr        , inner_spi, inner_proto, inner_satype, proto_info + i        , op, opname);}/* compute a (host-order!) SPI to implement the policy in connection c */ipsec_spi_tshunt_policy_spi(struct connection *c, bool prospective){    /* note: these are in host order :-( */    static const ipsec_spi_t shunt_spi[] =    {        SPI_TRAP,       /* --initiateontraffic */        SPI_PASS,       /* --pass */        SPI_DROP,       /* --drop */        SPI_REJECT,     /* --reject */    };    static const ipsec_spi_t fail_spi[] =    {        0,      /* --none*/        SPI_PASS,       /* --failpass */        SPI_DROP,       /* --faildrop */        SPI_REJECT,     /* --failreject */    };    return prospective        ? shunt_spi[(c->policy & POLICY_SHUNT_MASK) >> POLICY_SHUNT_SHIFT]        : fail_spi[(c->policy & POLICY_FAIL_MASK) >> POLICY_FAIL_SHIFT];}/* Add/replace/delete a shunt eroute. * Such an eroute determines the fate of packets without the use * of any SAs.  These are defaults, in effect. * If a negotiation has not been attempted, use %trap. * If negotiation has failed, the choice between %trap/%pass/%drop/%reject * is specified in the policy of connection c. */static boolshunt_eroute(struct connection *c             , struct spd_route *sr             , enum routing_t rt_kind             , unsigned int op, const char *opname){    /* We are constructing a special SAID for the eroute.     * The destination doesn't seem to matter, but the family does.     * The protocol is SA_INT -- mark this as shunt.     * The satype has no meaning, but is required for PF_KEY header!     * The SPI signifies the kind of shunt.     */    ipsec_spi_t spi = shunt_policy_spi(c, rt_kind == RT_ROUTED_PROSPECTIVE);    bool ok;    if (spi == 0)    {        /* we're supposed to end up with no eroute: rejig op and opname */        switch (op)        {        case ERO_REPLACE:            /* replace with nothing == delete */            op = ERO_DELETE;            opname = "delete";            break;        case ERO_ADD:            /* add nothing == do nothing */            return TRUE;        case ERO_DELETE:            /* delete remains delete */            break;        default:            bad_case(op);        }    }    if (sr->routing == RT_ROUTED_ECLIPSED && c->kind == CK_TEMPLATE)    {        /* We think that we have an eroute, but we don't.         * Adjust the request and account for eclipses.         */        passert(eclipsable(sr));        switch (op)        {        case ERO_REPLACE:            /* really an add */            op = ERO_ADD;            opname = "replace eclipsed";            eclipse_count--;            break;        case ERO_DELETE:            /* delete unnecessary: we don't actually have an eroute */            eclipse_count--;            return TRUE;        case ERO_ADD:        default:            bad_case(op);        }    }    else if (eclipse_count > 0 && op == ERO_DELETE && eclipsable(sr))    {        /* maybe we are uneclipsing something */        struct spd_route *esr;        struct connection *ue = eclipsed(c, &esr);        if (ue != NULL)        {            esr->routing = RT_ROUTED_PROSPECTIVE;            return shunt_eroute(ue, esr                                , RT_ROUTED_PROSPECTIVE, ERO_REPLACE, "restoring eclipsed");        }    }    ok = TRUE;    if (kernel_ops->inbound_eroute)    {        ok = raw_eroute(&c->spd.that.host_addr, &c->spd.that.client                        , &c->spd.this.host_addr, &c->spd.this.client                        , htonl(spi)                        , SA_INT                        , 0 /* transport_proto is not relevant */                        , SADB_X_SATYPE_INT, null_proto_info                        , 0      /* use lifetime */                        , op | (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT)                        , opname);    }    return eroute_connection(sr, htonl(spi), SA_INT, SADB_X_SATYPE_INT        , null_proto_info, op, opname) && ok;}/* * This is only called when s is a likely SAID with  trailing protocol i.e. * it has the form :- * *   %<keyword>:p *   <ip-proto><spi>@a.b.c.d:p * * The task here is to remove the ":p" part so that the rest can be read * by another routine. */static const char *read_proto(const char * s, size_t * len, int * transport_proto){    const char * p;    const char * ugh;    unsigned long proto;    size_t l;    l = *len;    p = memchr(s, ':', l);    if (p == 0) {        *transport_proto = 0;        return 0;    }    ugh = ttoul(p+1, l-((p-s)+1), 10, &proto);    if (ugh != 0)        return ugh;    if (proto > 65535)        return "protocol number is too large, legal range is 0-65535";    *len = p-s;    *transport_proto = proto;    return 0;}/* scan /proc/net/ipsec_eroute every once in a while, looking for: * * - %hold shunts of which Pluto isn't aware.  This situation could *   be caused by lost ACQUIRE messages.  When found, they will *   added to orphan_holds.  This in turn will lead to Opportunistic *   initiation. * * - other kinds of shunts that haven't been used recently.  These will be *   deleted.  They represent OE failures. * * - recording recent uses of tunnel eroutes so that rekeying decisions *   can be made for OE connections. * * Here are some sample lines: * 10         10.3.2.1.0/24    -> 0.0.0.0/0          => %trap * 259        10.3.2.1.115/32  -> 10.19.75.161/32    => tun0x1002@10.19.75.145 * 71         10.44.73.97/32   -> 0.0.0.0/0          => %trap * 4119       10.44.73.97/32   -> 10.114.121.41/32   => %pass * Newer versions of KLIPS start each line with a 32-bit packet count. * If available, the count is used to detect whether a %pass shunt is in use. * * NOTE: execution time is quadratic in the number of eroutes since the * searching for each is sequential.  If this becomes a problem, faster * searches could be implemented (hash or radix tree, for example). */voidscan_proc_shunts(void){    static const char procname[] = "/proc/net/ipsec_eroute";    FILE *f;    time_t nw = now();    int lino;    struct eroute_info *expired = NULL;    event_schedule(EVENT_SHUNT_SCAN, SHUNT_SCAN_INTERVAL, NULL);    DBG(DBG_CONTROL,        DBG_log("scanning for shunt eroutes")    )    /* free any leftover entries: they will be refreshed if still current */    while (orphaned_holds != NULL)    {        struct eroute_info *p = orphaned_holds;        orphaned_holds = p->next;        pfree(orphaned_holds);    }    /* decode the /proc file.  Don't do anything strenuous to it     * (certainly no PF_KEY stuff) to minimize the chance that it     * might change underfoot.     */    f = fopen(procname, "r");    if (f == NULL)        return;    /* for each line... */    for (lino = 1; ; lino++)    {        unsigned char buf[1024];        /* should be big enough */        chunk_t field[10];      /* 10 is loose upper bound */        chunk_t *ff;    /* fixed fields (excluding optional count) */        int fi;        struct eroute_info eri;        char *cp;        err_t context = ""            , ugh = NULL;        cp = fgets(buf, sizeof(buf), f);        if (cp == NULL)            break;        /* break out each field         * Note: if there are too many fields, just stop;         * it will be diagnosed a little later.         */        for (fi = 0; fi < (int)elemsof(field); fi++)        {            static const char sep[] = " \t\n";  /* field-separating whitespace */            size_t w;            cp += strspn(cp, sep);      /* find start of field */            w = strcspn(cp, sep);       /* find width of field */            setchunk(field[fi], cp, w);            cp += w;            if (w == 0)                break;        }        /* This odd do-hickey is to share error reporting code.         * A break will get to that common code.  The setting         * of "ugh" and "context" parameterize it.         */        do {            /* Old entries have no packet count; new ones do.             * check if things are as they should be.             */            if (fi == 5)                ff = &field[0]; /* old form, with no count */            else if (fi == 6)                ff = &field[1]; /* new form, with count */            else            {                ugh = "has wrong number of fields";                break;            }            if (ff[1].len != 2            || strncmp(ff[1].ptr, "->", 2) != 0            || ff[3].len != 2            || strncmp(ff[3].ptr, "=>", 2) != 0)            {                ugh = "is missing -> or =>";                break;            }            /* actually digest fields of interest */            /* packet count */            eri.count = 0;            if (ff != field)            {                context = "count field is malformed: ";                ugh = ttoul(field[0].ptr, field[0].len, 10, &eri.count);                if (ugh != NULL)                    break;            }            /* our client */            context = "source subnet field malformed: ";            ugh = ttosubnet(ff[0].ptr, ff[0].len, AF_INET, &eri.ours);

⌨️ 快捷键说明

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