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

📄 kernel.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 5 页
字号:
    }#endif /* KLIPS */    return route_easy;}booltrap_connection(struct connection *c){    switch (could_route(c))    {    case route_impossible:        return FALSE;    case route_nearconflict:    case route_easy:        /* RT_ROUTED_TUNNEL is treated specially: we don't override         * because we don't want to lose track of the IPSEC_SAs etc.         */        if (c->spd.routing < RT_ROUTED_TUNNEL)        {            return route_and_eroute(c, &c->spd, NULL);        }        return TRUE;    case route_farconflict:        return FALSE;    }    return FALSE;}/* delete any eroute for a connection and unroute it if route isn't shared */voidunroute_connection(struct connection *c){    struct spd_route *sr;    enum routing_t cr;    for (sr = &c->spd; sr; sr = sr->next)    {        cr = sr->routing;        if (erouted(cr))        {            /* cannot handle a live one */            passert(sr->routing != RT_ROUTED_TUNNEL);#ifdef KLIPS            shunt_eroute(c, sr, RT_UNROUTED, ERO_DELETE, "delete");#endif        }        sr->routing = RT_UNROUTED;  /* do now so route_owner won't find us */        /* only unroute if no other connection shares it */        if (routed(cr) && route_owner(c, NULL, NULL, NULL) == NULL)            (void) do_command(c, sr, "unroute");    }}#include "alg_info.h"#include "kernel_alg.h"#ifdef KLIPSstatic voidset_text_said(char *text_said, const ip_address *dst, ipsec_spi_t spi, int proto){    ip_said said;    initsaid(dst, spi, proto, &said);    satot(&said, 0, text_said, SATOT_BUF);}/* find an entry in the bare_shunt table. * Trick: return a pointer to the pointer to the entry; * this allows the entry to be deleted. */static struct bare_shunt **bare_shunt_ptr(const ip_subnet *ours, const ip_subnet *his, int transport_proto){    struct bare_shunt *p, **pp;    for (pp = &bare_shunts; (p = *pp) != NULL; pp = &p->next)    {        if (samesubnet(ours, &p->ours)        && samesubnet(his, &p->his)        && transport_proto == p->transport_proto        && portof(&ours->addr) == portof(&p->ours.addr)        && portof(&his->addr) == portof(&p->his.addr))            return pp;    }    return NULL;}/* free a bare_shunt entry, given a pointer to the pointer */static voidfree_bare_shunt(struct bare_shunt **pp){    if (pp == NULL)    {        DBG(DBG_CONTROL,            DBG_log("delete bare shunt: null pointer")        )    }    else    {        struct bare_shunt *p = *pp;        *pp = p->next;        DBG_bare_shunt("delete", p);        pfree(p->why);        pfree(p);    }}voidshow_shunt_status(void){    struct bare_shunt *bs;    for (bs = bare_shunts; bs != NULL; bs = bs->next)    {        /* Print interesting fields.  Ignore count and last_active. */        int ourport = ntohs(portof(&bs->ours.addr));        int hisport = ntohs(portof(&bs->his.addr));        char ourst[SUBNETTOT_BUF];        char hist[SUBNETTOT_BUF];        char sat[SATOT_BUF];        char prio[POLICY_PRIO_BUF];        subnettot(&(bs)->ours, 0, ourst, sizeof(ourst));        subnettot(&(bs)->his, 0, hist, sizeof(hist));        satot(&(bs)->said, 0, sat, sizeof(sat));        fmt_policy_prio(bs->policy_prio, prio);        whack_log(RC_COMMENT, "%s:%d -%d-> %s:%d => %s %s    %s"            , ourst, ourport, bs->transport_proto, hist, hisport, sat            , prio, bs->why);    }}/* Setup an IPsec route entry. * op is one of the ERO_* operators. */static boolraw_eroute(const ip_address *this_host           , const ip_subnet *this_client           , const ip_address *that_host           , const ip_subnet *that_client           , ipsec_spi_t spi           , unsigned int proto           , unsigned int transport_proto           , unsigned int satype           , const struct pfkey_proto_info *proto_info           , time_t use_lifetime           , unsigned int op           , const char *opname USED_BY_DEBUG){    char text_said[SATOT_BUF];    int sport = ntohs(portof(&this_client->addr));    int dport = ntohs(portof(&that_client->addr));    set_text_said(text_said, that_host, spi, proto);    DBG(DBG_CONTROL | DBG_KLIPS,        {            char mybuf[SUBNETTOT_BUF];            char peerbuf[SUBNETTOT_BUF];            subnettot(this_client, 0, mybuf, sizeof(mybuf));            subnettot(that_client, 0, peerbuf, sizeof(peerbuf));            DBG_log("%s eroute %s:%d --%d-> %s:%d => %s (raw_eroute)"                    , opname, mybuf, sport, transport_proto, peerbuf, dport                    , text_said);        });    return kernel_ops->raw_eroute(this_host, this_client                                  , that_host, that_client                                  , spi, proto                                  , transport_proto                                  , satype, proto_info                                  , use_lifetime, op, text_said);}/* test to see if %hold remains */boolhas_bare_hold(const ip_address *src, const ip_address *dst, int transport_proto){    ip_subnet this_client, that_client;    struct bare_shunt **bspp;    passert(addrtypeof(src) == addrtypeof(dst));    happy(addrtosubnet(src, &this_client));    happy(addrtosubnet(dst, &that_client));    bspp = bare_shunt_ptr(&this_client, &that_client, transport_proto);    return bspp != NULL        && (*bspp)->said.proto == SA_INT && (*bspp)->said.spi == htonl(SPI_HOLD);}/* Replace (or delete) a shunt that is in the bare_shunts table. * Issues the PF_KEY commands and updates the bare_shunts table. */boolreplace_bare_shunt(const ip_address *src, const ip_address *dst                   , policy_prio_t policy_prio                   , ipsec_spi_t shunt_spi      /* in host order! */                   , bool repl  /* if TRUE, replace; if FALSE, delete */                   , int transport_proto                   , const char *why){    ip_subnet this_client, that_client;    const ip_address *null_host = aftoinfo(addrtypeof(src))->any;    passert(addrtypeof(src) == addrtypeof(dst));    happy(addrtosubnet(src, &this_client));    happy(addrtosubnet(dst, &that_client));    /*     * if the transport protocol is not the wildcard, then we need     * to look for a host<->host shunt, and replace that with the     * shunt spi, and then we add a %HOLD for what was there before.     *     * this is at ods with repl == 0, which should delete things.     *      */    if(transport_proto != 0) {        ip_subnet this_broad_client, that_broad_client;        this_broad_client = this_client;        that_broad_client = that_client;        setportof(0, &this_broad_client.addr);        setportof(0, &that_broad_client.addr);                if (repl)            {                struct bare_shunt **bs_pp = bare_shunt_ptr(&this_broad_client                                                           , &that_broad_client, 0);                                /* is there already a broad host-to-host bare shunt? */                if (bs_pp == NULL)                    {                        if (raw_eroute(null_host, &this_broad_client                                       , null_host, &that_broad_client                                       , htonl(shunt_spi), SA_INT                                       , transport_proto                                       , SADB_X_SATYPE_INT, null_proto_info                                       , SHUNT_PATIENCE, ERO_REPLACE, why))                            {                                struct bare_shunt *bs = alloc_thing(struct bare_shunt, "bare shunt");                                                                bs->ours = this_broad_client;                                bs->his =  that_broad_client;                                bs->transport_proto = 0;                                bs->said.proto = SA_INT;                                bs->why = clone_str(why, "bare shunt story");                                bs->policy_prio = policy_prio;                                bs->said.spi = htonl(shunt_spi);                                bs->said.dst = *null_host;                                bs->count = 0;                                bs->last_activity = now();                                bs->next = bare_shunts;                                bare_shunts = bs;                                DBG_bare_shunt("add", bs);                            }                    }                shunt_spi = SPI_HOLD;            }                if (raw_eroute(null_host, &this_client, null_host, &that_client                       , htonl(shunt_spi)                       , SA_INT                       , transport_proto                       , SADB_X_SATYPE_INT, null_proto_info                       , SHUNT_PATIENCE, ERO_ADD, why))            {                struct bare_shunt **bs_pp = bare_shunt_ptr(&this_client, &that_client                                                           , transport_proto);                                /* delete bare eroute */                free_bare_shunt(bs_pp);                                return TRUE;            }        else            {                return FALSE;            }    }    else {        unsigned int op = repl? ERO_REPLACE : ERO_DELETE;                if (raw_eroute(null_host, &this_client, null_host, &that_client                       , htonl(shunt_spi), SA_INT                       , 0 /* transport_proto */                       , SADB_X_SATYPE_INT, null_proto_info                       , SHUNT_PATIENCE, op, why))            {                struct bare_shunt **bs_pp = bare_shunt_ptr(&this_client                                                           , &that_client, 0);                                if (repl)                    {                        /* change over to new bare eroute */                        struct bare_shunt *bs = *bs_pp;                                                pfree(bs->why);                        bs->why = clone_str(why, "bare shunt story");                        bs->policy_prio = policy_prio;                        bs->said.spi = htonl(shunt_spi);                        bs->said.proto = SA_INT;                        bs->said.dst = *null_host;                        bs->count = 0;                        bs->last_activity = now();                        DBG_bare_shunt("change", bs);                    }                else                    {                        /* delete bare eroute */                        free_bare_shunt(bs_pp);                    }                return TRUE;            }        else            {                return FALSE;            }    }        }static booleroute_connection(struct spd_route *sr, ipsec_spi_t spi, unsigned int proto, unsigned int satype, const struct pfkey_proto_info *proto_info, unsigned int op, const char *opname){    const ip_address *peer = &sr->that.host_addr;    char buf2[256];    snprintf(buf2, sizeof(buf2)             , "eroute_connection %s", opname);    if (proto == SA_INT)        peer = aftoinfo(addrtypeof(peer))->any;    return raw_eroute(&sr->this.host_addr, &sr->this.client                      , peer                      , &sr->that.client                      , spi                      , proto                      , sr->this.protocol                      , satype                      , proto_info, 0, op, buf2);}/* assign a bare hold to a connection */boolassign_hold(struct connection *c USED_BY_DEBUG            , struct spd_route *sr            , int transport_proto            , const ip_address *src, const ip_address *dst){    /* either the automatically installed %hold eroute is broad enough     * or we try to add a broader one and delete the automatic one.     * Beware: this %hold might be already handled, but still squeak     * through because of a race.     */    enum routing_t ro = sr->routing     /* routing, old */        , rn = ro;                      /* routing, new */    passert(LHAS(LELEM(CK_PERMANENT) | LELEM(CK_INSTANCE), c->kind));    /* figure out what routing should become */    switch (ro)    {    case RT_UNROUTED:        rn = RT_UNROUTED_HOLD;        break;    case RT_ROUTED_PROSPECTIVE:        rn = RT_ROUTED_HOLD;        break;    default:        /* no change: this %hold is old news and should just be deleted */        break;    }    DBG(DBG_CONTROL,        DBG_log("assign hold, routing was %s, needs to be %s"                , enum_name(&routing_story, ro)                , enum_name(&routing_story, rn)));    if (eclipsable(sr))    {        /* although %hold is appropriately broad, it will no longer be bare         * so we must ditch it from the bare table.         */        free_bare_shunt(bare_shunt_ptr(&sr->this.client, &sr->that.client, sr->this.protocol));    }    else    {        /* we need a broad %hold, not the narrow one.         * First we ensure that there is a broad %hold.         * There may already be one (race condition): no need to create one.

⌨️ 快捷键说明

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