📄 kernel.c
字号:
/* 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] = ""; 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)); 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 " /* PLUTO_MY_SRCIP */ "%s" /* actual script */ , verb, verb_suffix , c->name , nexthop_str , c->interface->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) , 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));#ifdef KLIPS if (!no_klips) { /* 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. */ FILE *f = popen(cmd, "r"); if (f == NULL) { loglog(RC_LOG_SERIOUS, "unable to popen %s%s command", verb, verb_suffix); 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)); 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); 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; } } }#endif /* KLIPS */ return TRUE;}/* Check that we can route (and eroute). Diagnose if we cannot. */enum routability { route_impossible = 0, route_easy = 1, route_nearconflict = 2, route_farconflict = 3};static enum routabilitycould_route(struct connection *c){ struct spd_route *esr, *rosr; struct connection *ero /* who, if anyone, owns our eroute? */ , *ro = route_owner(c, &rosr, &ero, &esr); /* who owns our route? */ DBG(DBG_CONTROL, DBG_log("could_route called for %s (kind=%s)" , c->name , enum_show(&connection_kind_names, c->kind))); /* it makes no sense to route a connection that is ISAKMP-only */ if (!NEVER_NEGOTIATE(c->policy) && !HAS_IPSEC_POLICY(c->policy)) { loglog(RC_ROUTE, "cannot route an ISAKMP-only connection"); return route_impossible; } /* if this is a Road Warrior template, we cannot route. * Opportunistic template is OK. */ if (!c->spd.that.has_client && c->kind == CK_TEMPLATE && !(c->policy & POLICY_OPPO)) { loglog(RC_ROUTE, "cannot route template policy of %s", prettypolicy(c->policy)); return route_impossible; } /* if we don't know nexthop, we cannot route */ if (isanyaddr(&c->spd.this.host_nexthop)) { loglog(RC_ROUTE, "cannot route connection without knowing our nexthop"); return route_impossible; } /* if routing would affect IKE messages, reject */ if (!no_klips#ifdef NAT_TRAVERSAL && c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT#endif && c->spd.this.host_port != IKE_UDP_PORT && addrinsubnet(&c->spd.that.host_addr, &c->spd.that.client)) { loglog(RC_LOG_SERIOUS, "cannot install route: peer is within its client"); return route_impossible; } /* If there is already a route for peer's client subnet * and it disagrees about interface or nexthop, we cannot steal it. * Note: if this connection is already routed (perhaps for another * state object), the route will agree. * This is as it should be -- it will arise during rekeying. */ if (ro != NULL && !routes_agree(ro, c)) { loglog(RC_LOG_SERIOUS, "cannot route -- route already in use for \"%s\"" , ro->name); return route_impossible; /* another connection already using the eroute */ }#ifdef KLIPS /* if there is an eroute for another connection, there is a problem */ if (ero != NULL && ero != c) { struct connection *ero2, *ero_top; struct connection *inside, *outside; /* * note, wavesec (PERMANENT) goes *outside* and * OE goes *inside* (TEMPLATE) */ inside = NULL; outside= NULL; if (ero->kind == CK_PERMANENT && c->kind == CK_TEMPLATE) { outside = ero; inside = c; } else if (c->kind == CK_PERMANENT && ero->kind == CK_TEMPLATE) { outside = c; inside = ero; } /* okay, check again, with correct order */ if (outside && outside->kind == CK_PERMANENT && inside && inside->kind == CK_TEMPLATE) { char inst[CONN_INST_BUF]; /* this is a co-terminal attempt of the "near" kind. */ /* when chaining, we chain from inside to outside */ /* XXX permit multiple deep connections? */ passert(inside->policy_next == NULL); inside->policy_next = outside; /* since we are going to steal the eroute from the secondary * policy, we need to make sure that it no longer thinks that * it owns the eroute. */ outside->spd.eroute_owner = SOS_NOBODY; outside->spd.routing = RT_UNROUTED_KEYED; /* set the priority of the new eroute owner to be higher * than that of the current eroute owner */ inside->prio = outside->prio + 1; fmt_conn_instance(inside, inst); loglog(RC_LOG_SERIOUS , "conflict on eroute (%s), switching eroute to %s and linking %s" , inst, inside->name, outside->name); return route_nearconflict; } /* look along the chain of policies for one with the same name */ ero_top = ero; for (ero2 = ero; ero2 != NULL; ero2 = ero->policy_next) { if (ero2->kind == CK_TEMPLATE && streq(ero2->name, c->name)) break; } /* If we fell of the end of the list, then we found no TEMPLATE * so there must be a conflict that we can't resolve. * As the names are not equal, then we aren't replacing/rekeying. */ if (ero2 == NULL) { char inst[CONN_INST_BUF]; fmt_conn_instance(ero, inst); loglog(RC_LOG_SERIOUS , "cannot install eroute -- it is in use for \"%s\"%s #%lu" , ero->name, inst, esr->eroute_owner); return FALSE; /* another connection already using the eroute */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -