/* * Iterate through the allowed_targets_list, and if none of the * specified addresses matches the one from REDIRECT * payload, return FALSE */ static bool allow_to_be_redirected(const char *allowed_targets_list, ip_address *dest_ip) { if (allowed_targets_list == NULL || streq(allowed_targets_list, "%any")) return TRUE; ip_address ip_addr; for (const char *t = allowed_targets_list;; ) { t += strspn(t, ", "); /* skip leading separator */ int len = strcspn(t, ", "); /* length of name */ if (len == 0) break; /* no more */ err_t ugh = ttoaddr_num(t, len, AF_UNSPEC, &ip_addr); if (ugh != NULL) { DBGF(DBG_CONTROLMORE, "address %.*s isn't a valid address", len, t); } else if (sameaddr(dest_ip, &ip_addr)) { DBGF(DBG_CONTROLMORE, "address %.*s is a match to received GW identity", len, t); return TRUE; } else { DBGF(DBG_CONTROLMORE, "address %.*s is not a match to received GW identity", len, t); } t += len; /* skip name */ } DBGF(DBG_CONTROLMORE, "we did not find suitable address in the list specified by accept-redirect-to option"); return FALSE; }
void block_peer_add(ip_address *ip) { block_peer **cur = &block_peer_head, *tmp; if (!block_ip_reject_num) return; for (; *cur; cur = &(*cur)->next) { if (!sameaddr(&(*cur)->ip, ip)) continue; (*cur)->reject_num++; (*cur)->last_reject_time = now(); goto Exit; } tmp = (block_peer *)malloc(sizeof(block_peer)); if (!tmp) return; tmp->reject_num = 1; tmp->ip = *ip; tmp->start_time = 0; tmp->last_reject_time = now(); tmp->next = NULL; *cur = tmp; block_peer_log("IP address %s was added to block-IP list", tmp); Exit: block_peer_start_block(*cur); }
void restart_connections_by_peer(struct connection *c) { struct connection *d; if (c->host_pair == NULL) return; d = c->host_pair->connections; for (; d != NULL; d = d->hp_next) { if ( #ifdef DYNAMICDNS (c->dnshostname && d->dnshostname && (strcmp(c->dnshostname, d->dnshostname) == 0)) || (c->dnshostname == NULL && d->dnshostname == NULL && #endif /* DYNAMICDNS */ sameaddr(&d->spd.that.host_addr, &c->spd.that.host_addr) #ifdef DYNAMICDNS ) #endif /* DYNAMICDNS */ ) terminate_connection(d->name); } #ifdef DYNAMICDNS update_host_pairs(c); #endif /* DYNAMICDNS */ if (c->host_pair == NULL) return; d = c->host_pair->connections; for (; d != NULL; d = d->hp_next) { if ( #ifdef DYNAMICDNS (c->dnshostname && d->dnshostname && (strcmp(c->dnshostname, d->dnshostname) == 0)) || (c->dnshostname == NULL && d->dnshostname == NULL && #endif /* DYNAMICDNS */ sameaddr(&d->spd.that.host_addr, &c->spd.that.host_addr) #ifdef DYNAMICDNS ) #endif /* DYNAMICDNS */ ) initiate_connection(d->name, NULL_FD, 0, pcim_demand_crypto); } }
/* compare two struct id values */ bool same_id(const struct id *a, const struct id *b) { a = resolve_myid(a); b = resolve_myid(b); if(b->kind == ID_NONE || a->kind==ID_NONE) { return TRUE; /* it's the wildcard */ } if (a->kind != b->kind) return FALSE; switch (a->kind) { case ID_NONE: return TRUE; /* repeat of above for completeness */ case ID_IPV4_ADDR: case ID_IPV6_ADDR: return sameaddr(&a->ip_addr, &b->ip_addr); case ID_FQDN: case ID_USER_FQDN: /* assumptions: * - case should be ignored * - trailing "." should be ignored (even if the only character?) */ { size_t al = a->name.len , bl = b->name.len; while (al > 0 && a->name.ptr[al - 1] == '.') al--; while (bl > 0 && b->name.ptr[bl - 1] == '.') bl--; return al == bl && strncasecmp((char *)a->name.ptr , (char *)b->name.ptr, al) == 0; } case ID_DER_ASN1_DN: return same_dn(a->name, b->name); case ID_KEY_ID: return a->name.len == b->name.len && memcmp(a->name.ptr, b->name.ptr, a->name.len) == 0; default: bad_case(a->kind); } /* NOTREACHED */ return FALSE; }
block_peer *block_peer_get_by_ip(ip_address *ip) { block_peer *peer = block_peer_head; for (; peer; peer=peer->next) { if (sameaddr(ip, &peer->ip)) return peer; } return NULL; }
/* ipcmp compares the two ip_address values a and b. * It returns -1, 0, or +1 if a is, respectively, * less than, equal to, or greater than b. */ static int ipcmp(ip_address *a, ip_address *b) { if (addrtypeof(a) != addrtypeof(b)) { return addrtypeof(a) < addrtypeof(b) ? -1 : 1; } else if (sameaddr(a, b)) { return 0; } else { const struct sockaddr *sa = sockaddrof(a), *sb = sockaddrof(b); passert(addrtypeof(a) == AF_INET); /* not yet implemented IPv6 version :-( */ return (ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr) < ntohl(((const struct sockaddr_in *)sb)->sin_addr.s_addr)) ? -1 : 1; } }
void subrange(unsigned char *sin, unsigned char *ein) // recursive function to divide ip range { unsigned char nets[4], nete[4]; int bitlen, nextlen; bitlen = count_bits(sin, ein); if (bitlen == 32) { sprintf(range_buf + strlen(range_buf), "%u.%u.%u.%u/32 ", sin[0], sin[1], sin[2], sin[3]); cprintf("%u.%u.%u.%u/32\n", sin[0], sin[1], sin[2], sin[3]); return; } else if (bitlen == 31) { sprintf(range_buf + strlen(range_buf), "%u.%u.%u.%u/31 ", sin[0], sin[1], sin[2], sin[3]); cprintf("%u.%u.%u.%u/31\n", sin[0], sin[1], sin[2], sin[3]); return; } nextlen = bitlen + 1; getse(sin, nets, nete, bitlen); if (sameaddr(sin, nets) && sameaddr(ein, nete)) { sprintf(range_buf + strlen(range_buf), "%u.%u.%u.%u/%d ", nets[0], nets[1], nets[2], nets[3], bitlen); cprintf("%u.%u.%u.%u/%d\n", nets[0], nets[1], nets[2], nets[3], bitlen); return; } getse(sin, nets, nete, nextlen); if (sameaddr(sin, nete)) { sprintf(range_buf + strlen(range_buf), "%u.%u.%u.%u/32 ", sin[0], sin[1], sin[2], sin[3]); cprintf("%u.%u.%u.%u/32\n", sin[0], sin[1], sin[2], sin[3]); } else if (sameaddr(sin, nets)) { sprintf(range_buf + strlen(range_buf), "%u.%u.%u.%u/%d ", nets[0], nets[1], nets[2], nets[3], nextlen); cprintf("%u.%u.%u.%u/%d\n", nets[0], nets[1], nets[2], nets[3], nextlen); } else // continue check subrange(sin, nete); getse(ein, nets, nete, nextlen); if (sameaddr(ein, nets)) { sprintf(range_buf + strlen(range_buf), "%u.%u.%u.%u/32 ", ein[0], ein[1], ein[2], ein[3]); cprintf("%u.%u.%u.%u/32\n", ein[0], ein[1], ein[2], ein[3]); } else if (sameaddr(ein, nete)) { sprintf(range_buf + strlen(range_buf), "%u.%u.%u.%u/%d ", nets[0], nets[1], nets[2], nets[3], nextlen); cprintf("%u.%u.%u.%u/%d\n", nets[0], nets[1], nets[2], nets[3], nextlen); } else // continue check subrange(nets, ein); }
void block_peer_del(ip_address *ip) { block_peer **peer = &block_peer_head, *tmp; while (*peer) { if (ip && !sameaddr(ip, &(*peer)->ip)) { peer=&(*peer)->next; continue; } tmp = *peer; *peer = tmp->next; block_peer_log("IP address %s was removed from block-IP list", tmp); block_peer_free(tmp); if (ip) return; } }
static void nilwalkfwd(NilFlow *rcheck) { NilFlow *r; Prog *p; ProgInfo info; // If the path down from rcheck dereferences the address // (possibly with a small offset) before writing to memory // and before any subsequent checks, it's okay to wait for // that implicit check. Only consider this basic block to // avoid problems like: // _ = *x // should panic // for {} // no writes but infinite loop may be considered visible for(r = (NilFlow*)uniqs(&rcheck->f); r != nil; r = (NilFlow*)uniqs(&r->f)) { p = r->f.prog; proginfo(&info, p); if((info.flags & LeftRead) && smallindir(&p->from, &rcheck->f.prog->from)) { rcheck->kill = 1; return; } if((info.flags & (RightRead|RightWrite)) && smallindir(&p->to, &rcheck->f.prog->from)) { rcheck->kill = 1; return; } // Stop if another nil check happens. if(p->as == ACHECKNIL) return; // Stop if value is lost. if((info.flags & RightWrite) && sameaddr(&p->to, &rcheck->f.prog->from)) return; // Stop if memory write. if((info.flags & RightWrite) && !regtyp(&p->to)) return; } }
static void bsdkame_process_raw_ifaces(struct raw_iface *rifaces) { struct raw_iface *ifp; /* * There are no virtual interfaces, so all interfaces are valid */ for (ifp = rifaces; ifp != NULL; ifp = ifp->next) { bool after = FALSE; /* has vfp passed ifp on the list? */ bool bad = FALSE; struct raw_iface *vfp; for (vfp = rifaces; vfp != NULL; vfp = vfp->next) { if (vfp == ifp) { after = TRUE; } else if (sameaddr(&ifp->addr, &vfp->addr)) { if (after) { loglog(RC_LOG_SERIOUS , "IP interfaces %s and %s share address %s!" , ifp->name, vfp->name, ip_str(&ifp->addr)); } bad = TRUE; } } if (bad) continue; /* We've got all we need; see if this is a new thing: * search old interfaces list. */ { struct iface_port **p = &interfaces; for (;;) { struct iface_port *q = *p; struct iface_dev *id = NULL; /* search is over if at end of list */ if (q == NULL) { /* matches nothing -- create a new entry */ int fd = create_socket(ifp, ifp->name, pluto_port); if (fd < 0) break; #ifdef NAT_TRAVERSAL if (nat_traversal_support_non_ike && addrtypeof(&ifp->addr) == AF_INET) { nat_traversal_espinudp_socket(fd, "IPv4", ESPINUDP_WITH_NON_IKE); } #endif q = alloc_thing(struct iface_port, "struct iface_port"); id = alloc_thing(struct iface_dev, "struct iface_dev"); LIST_INSERT_HEAD(&interface_dev, id, id_entry); q->ip_dev = id; id->id_rname = clone_str(ifp->name, "real device name"); id->id_vname = clone_str(ifp->name, "virtual device name"); id->id_count++; q->ip_addr = ifp->addr; q->fd = fd; q->next = interfaces; q->change = IFN_ADD; q->port = pluto_port; q->ike_float = FALSE; interfaces = q; openswan_log("adding interface %s/%s %s:%d" , q->ip_dev->id_vname , q->ip_dev->id_rname , ip_str(&q->ip_addr) , q->port); #ifdef NAT_TRAVERSAL /* * right now, we do not support NAT-T on IPv6, because * the kernel did not support it, and gave an error * it one tried to turn it on. */ if (nat_traversal_support_port_floating && addrtypeof(&ifp->addr) == AF_INET) { fd = create_socket(ifp, id->id_vname, NAT_T_IKE_FLOAT_PORT); if (fd < 0) break; nat_traversal_espinudp_socket(fd, "IPv4" , ESPINUDP_WITH_NON_ESP); q = alloc_thing(struct iface_port, "struct iface_port"); q->ip_dev = id; id->id_count++; q->ip_addr = ifp->addr; setportof(htons(NAT_T_IKE_FLOAT_PORT), &q->ip_addr); q->port = NAT_T_IKE_FLOAT_PORT; q->fd = fd; q->next = interfaces; q->change = IFN_ADD; q->ike_float = TRUE; interfaces = q; openswan_log("adding interface %s/%s %s:%d" , q->ip_dev->id_vname, q->ip_dev->id_rname , ip_str(&q->ip_addr) , q->port); } #endif break; } /* search over if matching old entry found */ if (streq(q->ip_dev->id_rname, ifp->name) && streq(q->ip_dev->id_vname, ifp->name) && sameaddr(&q->ip_addr, &ifp->addr)) { /* matches -- rejuvinate old entry */ q->change = IFN_KEEP; #ifdef NAT_TRAVERSAL /* look for other interfaces to keep (due to NAT-T) */ for (q = q->next ; q ; q = q->next) { if (streq(q->ip_dev->id_rname, ifp->name) && streq(q->ip_dev->id_vname, ifp->name) && sameaddr(&q->ip_addr, &ifp->addr)) { q->change = IFN_KEEP; } } #endif break; } /* try again */ p = &q->next; } /* for (;;) */ }
static void klips_process_raw_ifaces(struct raw_iface *rifaces) { struct raw_iface *ifp; /* Find all virtual/real interface pairs. * For each real interface... */ for (ifp = rifaces; ifp != NULL; ifp = ifp->next) { struct raw_iface *v = NULL; /* matching ipsecX interface */ struct raw_iface fake_v; bool after = FALSE; /* has vfp passed ifp on the list? */ bool bad = FALSE; struct raw_iface *vfp; ip_address lip; if (pluto_listen) { err_t e; e = ttoaddr(pluto_listen, 0, 0, &lip); if (e) { DBG_log("invalid listen= option ignored: %s\n", e); pluto_listen = NULL; } } /* ignore if virtual (ipsec*) interface */ if (strncmp(ifp->name, IPSECDEVPREFIX, sizeof(IPSECDEVPREFIX) - 1) == 0) continue; /* ignore if virtual (mast*) interface */ if (strncmp(ifp->name, MASTDEVPREFIX, sizeof(MASTDEVPREFIX) - 1) == 0) continue; for (vfp = rifaces; vfp != NULL; vfp = vfp->next) { if (vfp == ifp) { after = TRUE; } else if (sameaddr(&ifp->addr, &vfp->addr)) { /* Different entries with matching IP addresses. * Many interesting cases. */ if (strncmp(vfp->name, IPSECDEVPREFIX, sizeof(IPSECDEVPREFIX) - 1) == 0) { if (v != NULL) { loglog(RC_LOG_SERIOUS, "ipsec interfaces %s and %s share same address %s", v->name, vfp->name, ip_str(&ifp->addr)); bad = TRUE; } else { v = vfp; /* current winner */ } } else { /* ugh: a second real interface with the same IP address * "after" allows us to avoid double reporting. */ #if defined(linux) && defined(NETKEY_SUPPORT) if (kern_interface == USE_NETKEY) { if (after) { bad = TRUE; break; } continue; } #endif if (after) { loglog(RC_LOG_SERIOUS, "IP interfaces %s and %s share address %s!", ifp->name, vfp->name, ip_str(&ifp->addr)); } bad = TRUE; } } } if (bad) continue; #if defined(linux) && defined(NETKEY_SUPPORT) if (kern_interface == USE_NETKEY) { v = ifp; goto add_entry; } #endif /* what if we didn't find a virtual interface? */ if (v == NULL) { if (kern_interface == NO_KERNEL) { /* kludge for testing: invent a virtual device */ static const char fvp[] = "virtual"; fake_v = *ifp; passert(sizeof(fake_v.name) > sizeof(fvp)); strcpy(fake_v.name, fvp); addrtot(&ifp->addr, 0, fake_v.name + sizeof(fvp) - 1, sizeof(fake_v.name) - (sizeof(fvp) - 1)); v = &fake_v; } else { DBG(DBG_CONTROL, DBG_log( "IP interface %s %s has no matching ipsec* interface -- ignored", ifp->name, ip_str(&ifp->addr))); continue; } } /* ignore if --listen is specified and we do not match */ if (pluto_listen != NULL) { if (!sameaddr(&lip, &ifp->addr)) { libreswan_log("skipping interface %s with %s", ifp->name, ip_str(&ifp->addr)); continue; } } /* We've got all we need; see if this is a new thing: * search old interfaces list. */ #if defined(linux) && defined(NETKEY_SUPPORT) add_entry: #endif { struct iface_port **p = &interfaces; for (;; ) { struct iface_port *q = *p; struct iface_dev *id = NULL; /* search is over if at end of list */ if (q == NULL) { /* matches nothing -- create a new entry */ int fd = create_socket(ifp, v->name, pluto_port); if (fd < 0) break; DBG(DBG_NATT, DBG_log( "NAT-T KLIPS: checking for nat_traversal_support_non_ike for IPv4")); if (nat_traversal_support_non_ike && addrtypeof(&ifp->addr) == AF_INET) { DBG(DBG_NATT, DBG_log( "NAT-T KLIPS: found, calling nat_traversal_espinudp_socket")); nat_traversal_espinudp_socket( fd, "IPv4", ESPINUDP_WITH_NON_IKE); } else { DBG(DBG_NATT, DBG_log( "NAT-T KLIPS: support not found, nat_traversal_support_non_ike = %s", nat_traversal_support_non_ike ? "TRUE" : "FALSE")); } q = alloc_thing(struct iface_port, "struct iface_port"); id = alloc_thing(struct iface_dev, "struct iface_dev"); LIST_INSERT_HEAD(&interface_dev, id, id_entry); q->ip_dev = id; id->id_rname = clone_str(ifp->name, "real device name"); id->id_vname = clone_str(v->name, "virtual device name klips"); id->id_count++; q->ip_addr = ifp->addr; q->fd = fd; q->next = interfaces; q->change = IFN_ADD; q->port = pluto_port; q->ike_float = FALSE; interfaces = q; libreswan_log( "adding interface %s/%s %s:%d", q->ip_dev->id_vname, q->ip_dev->id_rname, ip_str(&q->ip_addr), q->port); /* * right now, we do not support NAT-T on IPv6, because * the kernel did not support it, and gave an error * it one tried to turn it on. */ if (nat_traversal_support_port_floating && addrtypeof(&ifp->addr) == AF_INET) { DBG(DBG_NATT, DBG_log( "NAT-T KLIPS: found floating port, calling nat_traversal_espinudp_socket")); fd = create_socket(ifp, v->name, pluto_natt_float_port); if (fd < 0) break; nat_traversal_espinudp_socket( fd, "IPv4", ESPINUDP_WITH_NON_ESP); q = alloc_thing( struct iface_port, "struct iface_port"); q->ip_dev = id; id->id_count++; q->ip_addr = ifp->addr; setportof(htons( pluto_natt_float_port), &q->ip_addr); q->port = pluto_natt_float_port; q->fd = fd; q->next = interfaces; q->change = IFN_ADD; q->ike_float = TRUE; interfaces = q; libreswan_log( "adding interface %s/%s %s:%d", q->ip_dev->id_vname, q->ip_dev->id_rname, ip_str(&q-> ip_addr), q->port); } break; } /* search over if matching old entry found */ if (streq(q->ip_dev->id_rname, ifp->name) && streq(q->ip_dev->id_vname, v->name) && sameaddr(&q->ip_addr, &ifp->addr)) { /* matches -- rejuvinate old entry */ q->change = IFN_KEEP; /* look for other interfaces to keep (due to NAT-T) */ for (q = q->next; q; q = q->next) { if (streq(q->ip_dev->id_rname, ifp->name) && streq(q->ip_dev->id_vname, v->name) && sameaddr(&q->ip_addr, &ifp->addr)) q->change = IFN_KEEP; } break; } /* try again */ p = &q->next; } /* for (;;) */ }
/* compare two struct id values */ bool same_id(const struct id *a, const struct id *b) { a = resolve_myid(a); b = resolve_myid(b); if (b->kind == ID_NONE || a->kind == ID_NONE) { DBG(DBG_PARSING, DBG_log("id type with ID_NONE means wildcard match")); return TRUE; /* it's the wildcard */ } if (a->kind != b->kind) { return FALSE; } switch (a->kind) { case ID_NONE: return TRUE; /* repeat of above for completeness */ case ID_NULL: if (a->kind == b->kind) { DBG(DBG_PARSING, DBG_log("ID_NULL: id kind matches")); return TRUE; } return FALSE; case ID_IPV4_ADDR: case ID_IPV6_ADDR: return sameaddr(&a->ip_addr, &b->ip_addr); case ID_FQDN: case ID_USER_FQDN: /* * assumptions: * - case should be ignored * - trailing "." should be ignored * (even if the only character?) */ { size_t al = a->name.len, bl = b->name.len; while (al > 0 && a->name.ptr[al - 1] == '.') al--; while (bl > 0 && b->name.ptr[bl - 1] == '.') bl--; return al == bl && strncaseeq((char *)a->name.ptr, (char *)b->name.ptr, al); } case ID_FROMCERT: DBG(DBG_CONTROL, DBG_log("same_id() received ID_FROMCERT - unexpected")); /* FALLTHROUGH */ case ID_DER_ASN1_DN: return same_dn(a->name, b->name); case ID_KEY_ID: return a->name.len == b->name.len && memeq(a->name.ptr, b->name.ptr, a->name.len); default: bad_case(a->kind); /* NOTREACHED */ return FALSE; } }
/** returns a host pair based upon addresses. * * find_host_pair is given a pair of addresses, plus UDP ports, and * returns a host_pair entry that covers it. It also moves the relevant * pair description to the beginning of the list, so that it can be * found faster next time. */ struct host_pair *find_host_pair(const ip_address *myaddr, u_int16_t myport, const ip_address *hisaddr, u_int16_t hisport) { struct host_pair *p, *prev; /* default hisaddr to an appropriate any */ if (hisaddr == NULL) { #if 0 /* broken */ const struct af_info *af = aftoinfo(addrtypeof(myaddr)); if (af == NULL) af = aftoinfo(AF_INET); if (af) hisaddr = af->any; #else hisaddr = aftoinfo(addrtypeof(myaddr))->any; #endif } /* * look for a host-pair that has the right set of ports/address. * */ /* * for the purposes of comparison, port 500 and 4500 are identical, * but other ports are not. * So if any port==4500, then set it to 500. * But we can also have non-RFC values for pluto_port and pluto_nat_port */ if (myport == pluto_nat_port) myport = pluto_port; if (hisport == pluto_nat_port) hisport = pluto_port; for (prev = NULL, p = host_pairs; p != NULL; prev = p, p = p->next) { DBG(DBG_CONTROLMORE, { ipstr_buf b1; ipstr_buf b2; DBG_log("find_host_pair: comparing %s:%d to %s:%d", ipstr(&p->me.addr, &b1), p->me.host_port, ipstr(&p->him.addr, &b2), p->him.host_port); }); if (sameaddr(&p->me.addr, myaddr) && (!p->me.host_port_specific || p->me.host_port == myport) && sameaddr(&p->him.addr, hisaddr) && (!p->him.host_port_specific || p->him.host_port == hisport) ) { if (prev != NULL) { prev->next = p->next; /* remove p from list */ p->next = host_pairs; /* and stick it on front */ host_pairs = p; } break; } }
static void nilwalkback(NilFlow *rcheck) { Prog *p; ProgInfo info; NilFlow *r; for(r = rcheck; r != nil; r = (NilFlow*)uniqp(&r->f)) { p = r->f.prog; proginfo(&info, p); if((info.flags & RightWrite) && sameaddr(&p->to, &rcheck->f.prog->from)) { // Found initialization of value we're checking for nil. // without first finding the check, so this one is unchecked. return; } if(r != rcheck && p->as == ACHECKNIL && sameaddr(&p->from, &rcheck->f.prog->from)) { rcheck->kill = 1; return; } } // Here is a more complex version that scans backward across branches. // It assumes rcheck->kill = 1 has been set on entry, and its job is to find a reason // to keep the check (setting rcheck->kill = 0). // It doesn't handle copying of aggregates as well as I would like, // nor variables with their address taken, // and it's too subtle to turn on this late in Go 1.2. Perhaps for Go 1.3. /* for(r1 = r0; r1 != nil; r1 = (NilFlow*)r1->f.p1) { if(r1->f.active == gen) break; r1->f.active = gen; p = r1->f.prog; // If same check, stop this loop but still check // alternate predecessors up to this point. if(r1 != rcheck && p->as == ACHECKNIL && sameaddr(&p->from, &rcheck->f.prog->from)) break; proginfo(&info, p); if((info.flags & RightWrite) && sameaddr(&p->to, &rcheck->f.prog->from)) { // Found initialization of value we're checking for nil. // without first finding the check, so this one is unchecked. rcheck->kill = 0; return; } if(r1->f.p1 == nil && r1->f.p2 == nil) { print("lost pred for %P\n", rcheck->f.prog); for(r1=r0; r1!=nil; r1=(NilFlow*)r1->f.p1) { proginfo(&info, r1->f.prog); print("\t%P %d %d %D %D\n", r1->f.prog, info.flags&RightWrite, sameaddr(&r1->f.prog->to, &rcheck->f.prog->from), &r1->f.prog->to, &rcheck->f.prog->from); } fatal("lost pred trail"); } } for(r = r0; r != r1; r = (NilFlow*)r->f.p1) for(r2 = (NilFlow*)r->f.p2; r2 != nil; r2 = (NilFlow*)r2->f.p2link) nilwalkback(rcheck, r2, gen); */ }
static void cannot_oppo(struct connection *c , struct find_oppo_bundle *b , err_t ughmsg) { char pcb[ADDRTOT_BUF]; char ocb[ADDRTOT_BUF]; addrtot(&b->peer_client, 0, pcb, sizeof(pcb)); addrtot(&b->our_client, 0, ocb, sizeof(ocb)); DBG(DBG_OPPO, openswan_log("Can not opportunistically initiate for %s to %s: %s" , ocb, pcb, ughmsg)); whack_log(RC_OPPOFAILURE , "Can not opportunistically initiate for %s to %s: %s" , ocb, pcb, ughmsg); if (c != NULL && c->policy_next != NULL) { /* there is some policy that comes afterwards */ struct spd_route *shunt_spd; struct connection *nc = c->policy_next; struct state *st; passert(c->kind == CK_TEMPLATE); passert(nc->kind == CK_PERMANENT); DBG(DBG_OPPO, DBG_log("OE failed for %s to %s, but %s overrides shunt" , ocb, pcb, nc->name)); /* * okay, here we need add to the "next" policy, which is ought * to be an instance. * We will add another entry to the spd_route list for the specific * situation that we have. */ shunt_spd = clone_thing(nc->spd, "shunt eroute policy"); shunt_spd->next = nc->spd.next; nc->spd.next = shunt_spd; happy(addrtosubnet(&b->peer_client, &shunt_spd->that.client)); if (sameaddr(&b->peer_client, &shunt_spd->that.host_addr)) shunt_spd->that.has_client = FALSE; /* * override the tunnel destination with the one from the secondaried * policy */ shunt_spd->that.host_addr = nc->spd.that.host_addr; /* now, lookup the state, and poke it up. */ st = state_with_serialno(nc->newest_ipsec_sa); /* XXX what to do if the IPSEC SA has died? */ passert(st != NULL); /* link the new connection instance to the state's list of * connections */ DBG(DBG_OPPO, DBG_log("installing state: %ld for %s to %s" , nc->newest_ipsec_sa , ocb, pcb)); #ifdef DEBUG if (DBGP(DBG_OPPO | DBG_CONTROLMORE)) { char state_buf[LOG_WIDTH]; char state_buf2[LOG_WIDTH]; const time_t n = now(); fmt_state(st, n, state_buf, sizeof(state_buf) , state_buf2, sizeof(state_buf2)); DBG_log("cannot_oppo, failure SA1: %s", state_buf); DBG_log("cannot_oppo, failure SA2: %s", state_buf2); } #endif /* DEBUG */ if (!route_and_eroute(c, shunt_spd, st)) { whack_log(RC_OPPOFAILURE , "failed to instantiate shunt policy %s for %s to %s" , c->name , ocb, pcb); } return; } /* * NETKEY default for level param in tmpl is required, so no traffic will * transmitted until an SA is fully up */ if (b->held && kern_interface != USE_NETKEY) { int failure_shunt = b->failure_shunt; /* Replace HOLD with b->failure_shunt. * If no failure_shunt specified, use SPI_PASS -- THIS MAY CHANGE. */ if (failure_shunt == 0) { DBG(DBG_OPPO, DBG_log("no explicit failure shunt for %s to %s; removing spurious hold shunt" , ocb, pcb)); } (void) replace_bare_shunt(&b->our_client, &b->peer_client , b->policy_prio , failure_shunt , failure_shunt != 0 , b->transport_proto , ughmsg); } }