kernel.c
来自「ipsec vpn」· C语言 代码 · 共 2,050 行 · 第 1/5 页
C
2,050 行
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, narrow_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, narrow_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. * 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 , broad_proto_info , ERO_REPLACE , "replace %trap with broad %hold") : !eroute_connection(sr, htonl(SPI_HOLD), SA_INT, SADB_X_SATYPE_INT , broad_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; inner_proto = 0; inner_satype= 0; inner_spi = 0; 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, broad_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 , broad_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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?