📄 kernel.c
字号:
}#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 + -