static void conn_default(struct starter_conn *conn, struct starter_conn *def) { int i; /* structure copy to start */ *conn = *def; /* unlink it */ conn->link.tqe_next = NULL; conn->link.tqe_prev = NULL; conn->left.iface = clone_str(def->left.iface, "conn default left iface"); conn->left.id = clone_str(def->left.id, "conn default leftid"); conn->left.rsakey1 = clone_thing(def->left.rsakey1, "conn default left rsakey1"); conn->left.rsakey2 = clone_thing(def->left.rsakey2, "conn default left rsakey2"); conn->right.iface = clone_str(def->right.iface, "conn default right iface"); conn->right.id = clone_str(def->right.id, "conn default rightid"); conn->right.rsakey1 = clone_thing(def->right.rsakey1, "conn default right rsakey1"); conn->right.rsakey2 = clone_thing(def->right.rsakey2, "conn default right rsakey2"); for (i = 0; i < KSCF_MAX; i++) { conn->left.strings[i] = clone_str(def->left.strings[i], "conn default left item"); conn->right.strings[i] = clone_str(def->right.strings[i], "conn default right item"); } for (i = 0; i < KNCF_MAX; i++) { conn->left.options[i] = def->left.options[i]; conn->right.options[i] = def->right.options[i]; } for (i = 0; i < KSF_MAX; i++) conn->strings[i] = clone_str(def->strings[i], "conn default string item"); for (i = 0; i < KBF_MAX; i++) conn->options[i] = def->options[i]; conn->esp = clone_str(def->esp, "conn default esp"); conn->ike = clone_str(def->ike, "conn default ike"); conn->modecfg_dns1 = clone_str(def->modecfg_dns1, "conn default dns1"); conn->modecfg_dns2 = clone_str(def->modecfg_dns2, "conn default dns2"); conn->modecfg_domain = clone_str(def->modecfg_domain, "conn default domain"); conn->modecfg_banner = clone_str(def->modecfg_banner, "conn default banner"); #ifdef HAVE_LABELED_IPSEC conn->policy_label = clone_str(def->policy_label, "conn default policy_label"); #endif conn->policy = def->policy; }
/* * this routine takes two proposals and conjoins them (or) */ struct db_sa *sa_merge_proposals(struct db_sa *a, struct db_sa *b) { struct db_sa *n; unsigned int i, j, k; if (a == NULL || a->prop_conj_cnt == 0) return sa_copy_sa(b, 0); if (b == NULL || b->prop_conj_cnt == 0) return sa_copy_sa(a, 0); n = clone_thing(*a, "conjoin sa"); passert(a->prop_conj_cnt == b->prop_conj_cnt); passert(a->prop_conj_cnt == 1); n->prop_conjs = clone_bytes(n->prop_conjs, n->prop_conj_cnt * sizeof(n->prop_conjs[0]), "sa copy prop conj array"); for (i = 0; i < n->prop_conj_cnt; i++) { struct db_prop_conj *pca = &n->prop_conjs[i]; struct db_prop_conj *pcb = &b->prop_conjs[i]; passert(pca->prop_cnt == pcb->prop_cnt); passert(pca->prop_cnt == 1); pca->props = clone_bytes(pca->props, pca->prop_cnt * sizeof(pca->props[0]), "sa copy prop array"); for (j = 0; j < pca->prop_cnt; j++) { struct db_prop *pa = &pca->props[j]; struct db_prop *pb = &pcb->props[j]; struct db_trans *t; int t_cnt = (pa->trans_cnt + pb->trans_cnt); t = alloc_bytes(t_cnt * sizeof(pa->trans[0]), "sa copy trans array"); memcpy(t, pa->trans, (pa->trans_cnt) * sizeof(pa->trans[0])); memcpy(t + (pa->trans_cnt), pb->trans, (pb->trans_cnt) * sizeof(pa->trans[0])); pa->trans = t; pa->trans_cnt = t_cnt; for (k = 0; k < pa->trans_cnt; k++) clone_trans(&pa->trans[k], 0); } } n->parentSA = a->parentSA; return n; }
/* Get a state object. * Caller must schedule an event for this object so that it doesn't leak. * Caller must insert_state(). */ struct state * new_state(void) { static const struct state blank_state; /* initialized all to zero & NULL */ static so_serial_t next_so = SOS_FIRST; struct state *st; st = clone_thing(blank_state, "struct state in new_state()"); st->st_serialno = next_so++; passert(next_so > SOS_FIRST); /* overflow can't happen! */ st->st_whack_sock = NULL_FD; anyaddr(AF_INET, &st->hidden_variables.st_nat_oa); anyaddr(AF_INET, &st->hidden_variables.st_natd); DBG(DBG_CONTROL, DBG_log("creating state object #%lu at %p" , st->st_serialno, (void *) st)); return st; }
struct db_sa *sa_copy_sa(struct db_sa *sa, int extra) { unsigned int i; struct db_sa *nsa; nsa = clone_thing(*sa, "sa copy prop_conj"); nsa->dynamic = TRUE; nsa->parentSA= sa->parentSA; nsa->prop_conjs = clone_bytes(nsa->prop_conjs , (nsa->prop_conj_cnt+extra)*sizeof(nsa->prop_conjs[0]) , "sa copy prop conj array"); for(i=0; i<nsa->prop_conj_cnt; i++) { clone_propconj(&nsa->prop_conjs[i], 0); } return nsa; }
/* * clone the sa, but keep only the first transform (if any) of the first proposal (if any) * ??? does this make sense? */ struct db_sa *sa_copy_sa_first(struct db_sa *sa) { struct db_sa *nsa; struct db_prop_conj *pc; struct db_prop *p; nsa = clone_thing(*sa, "sa copy prop_conj"); nsa->dynamic = TRUE; if (nsa->prop_conj_cnt == 0) return nsa; nsa->prop_conj_cnt = 1; nsa->prop_conjs = clone_bytes(nsa->prop_conjs, sizeof(nsa->prop_conjs[0]), "sa copy 1 prop conj array"); pc = &nsa->prop_conjs[0]; if (pc->prop_cnt == 0) return nsa; pc->prop_cnt = 1; pc->props = clone_bytes(pc->props, sizeof(pc->props[0]), "sa copy 1 prop array"); p = &pc->props[0]; if (p->trans_cnt == 0) return nsa; p->trans_cnt = 1; p->trans = clone_bytes(p->trans, sizeof(p->trans[0]), "sa copy 1 trans array"); clone_trans(&p->trans[0], 0); return nsa; }
/* * stores a chained list of end certs and CA certs * * @verified_ca is a copied list of the verified authcerts that have * been placed in the global authcert chain */ void store_x509certs(x509cert_t **firstcert, x509cert_t **verified_ca, bool strict) { x509cert_t *cacerts = NULL; x509cert_t **pp = firstcert; /* first extract CA certs, discarding root CA certs */ while (*pp != NULL) { x509cert_t *cert = *pp; if (cert->isCA) { *pp = cert->next; /* we don't accept self-signed CA certs */ if (same_dn(cert->issuer, cert->subject)) { libreswan_log("self-signed cacert rejected"); free_x509cert(cert); } else { /* insertion into temporary chain of candidate CA certs */ cert->next = cacerts; cacerts = cert; } } else { pp = &cert->next; } } /* now verify the candidate CA certs */ x509cert_t *ver = NULL; while (cacerts != NULL) { realtime_t valid_until; x509cert_t *cert = cacerts; cacerts = cacerts->next; if (trust_authcert_candidate(cert, cacerts) && verify_x509cert(cert, strict, &valid_until, cacerts)) { add_authcert(cert, AUTH_CA); if (ver == NULL) { ver = clone_thing(*cert, "x509cert_t"); *verified_ca = ver; } else { ver->next = clone_thing(*cert, "x509cert_t"); ver = ver->next; } ver->next = NULL; } else { libreswan_log("intermediate cacert rejected"); free_x509cert(cert); } } /* now verify the end certificates */ pp = firstcert; while (*pp != NULL) { realtime_t valid_until; x509cert_t *cert = *pp; if (verify_x509cert(cert, strict, &valid_until, NULL)) { DBG(DBG_X509 | DBG_PARSING, DBG_log("public key validated")); add_x509_public_key(NULL, cert, valid_until, DAL_SIGNED); } else { libreswan_log("X.509 certificate rejected"); } *pp = cert->next; free_x509cert(cert); } }
struct private_key_stuff *lsw_nss_foreach_private_key_stuff(secret_eval func, void *uservoid, lsw_nss_buf_t err) { /* * So test for error with "if (err[0]) ..." works. */ err[0] = '\0'; PK11SlotInfo *slot = lsw_nss_get_authenticated_slot(err); if (slot == NULL) { return NULL; } SECKEYPrivateKeyList *list = PK11_ListPrivateKeysInSlot(slot); if (list == NULL) { snprintf(err, sizeof(lsw_nss_buf_t), "no list"); PK11_FreeSlot(slot); return NULL; } int line = 1; struct private_key_stuff *result = NULL; SECKEYPrivateKeyListNode *node; for (node = PRIVKEY_LIST_HEAD(list); !PRIVKEY_LIST_END(node, list); node = PRIVKEY_LIST_NEXT(node)) { if (SECKEY_GetPrivateKeyType(node->key) != rsaKey) { /* only rsa for now */ continue; } struct private_key_stuff pks = { .kind = PPK_RSA, .on_heap = TRUE, }; { SECItem *nss_ckaid = PK11_GetLowLevelKeyIDForPrivateKey(node->key); if (nss_ckaid == NULL) { // fprintf(stderr, "ckaid not found\n"); continue; } const char *err = form_ckaid_nss(nss_ckaid, &pks.u.RSA_private_key.pub.ckaid); SECITEM_FreeItem(nss_ckaid, PR_TRUE); if (err) { // fprintf(stderr, "ckaid not found\n"); continue; } } { SECKEYPublicKey *pubkey = SECKEY_ConvertToPublicKey(node->key); if (pubkey != NULL) { fill_RSA_public_key(&pks.u.RSA_private_key.pub, pubkey); SECKEY_DestroyPublicKey(pubkey); } } /* * Only count private keys that get processed. */ pks.line = line++; int ret = func(NULL, &pks, uservoid); if (ret == 0) { /* * save/return the result. * * XXX: Potential Memory leak. * * lsw_foreach_secret() + lsw_get_pks() * returns an object that must not be freed * BUT lsw_nss_foreach_private_key_stuff() * returns an object that must be freed. * * For moment ignore this - as only caller is * showhostkey.c which quickly exits. */ result = clone_thing(pks, "pks"); break; } freeanyckaid(&pks.u.RSA_private_key.pub.ckaid); freeanychunk(pks.u.RSA_private_key.pub.e); freeanychunk(pks.u.RSA_private_key.pub.n); if (ret < 0) { break; } } SECKEY_DestroyPrivateKeyList(list); PK11_FreeSlot(slot); return result; }
struct raw_iface * find_raw_ifaces6(void) { /* Get list of interfaces with IPv6 addresses from system from /proc/net/if_inet6). * * Documentation of format? * RTFS: linux-2.2.16/net/ipv6/addrconf.c:iface_proc_info() * linux-2.4.9-13/net/ipv6/addrconf.c:iface_proc_info() * * Sample from Gerhard's laptop: * 00000000000000000000000000000001 01 80 10 80 lo * 30490009000000000000000000010002 02 40 00 80 ipsec0 * 30490009000000000000000000010002 07 40 00 80 eth0 * fe80000000000000025004fffefd5484 02 0a 20 80 ipsec0 * fe80000000000000025004fffefd5484 07 0a 20 80 eth0 * * Each line contains: * - IPv6 address: 16 bytes, in hex, no punctuation * - ifindex: 1 byte, in hex * - prefix_len: 1 byte, in hex * - scope (e.g. global, link local): 1 byte, in hex * - flags: 1 byte, in hex * - device name: string, followed by '\n' */ struct raw_iface *rifaces = NULL; static const char proc_name[] = "/proc/net/if_inet6"; FILE *proc_sock = fopen(proc_name, "r"); if (proc_sock == NULL) { DBG(DBG_CONTROL, DBG_log("could not open %s", proc_name)); } else { for (;;) { struct raw_iface ri; unsigned short xb[8]; /* IPv6 address as 8 16-bit chunks */ char sb[8*5]; /* IPv6 address as string-with-colons */ unsigned int if_idx; /* proc field, not used */ unsigned int plen; /* proc field, not used */ unsigned int scope; /* proc field, used to exclude link-local */ unsigned int dad_status; /* proc field, not used */ /* ??? I hate and distrust scanf -- DHR */ int r = fscanf(proc_sock , "%4hx%4hx%4hx%4hx%4hx%4hx%4hx%4hx" " %02x %02x %02x %02x %20s\n" , xb+0, xb+1, xb+2, xb+3, xb+4, xb+5, xb+6, xb+7 , &if_idx, &plen, &scope, &dad_status, ri.name); /* ??? we should diagnose any problems */ if (r != 13) break; /* ignore addresses with link local scope. * From linux-2.4.9-13/include/net/ipv6.h: * IPV6_ADDR_LINKLOCAL 0x0020U * IPV6_ADDR_SCOPE_MASK 0x00f0U */ if ((scope & 0x00f0U) == 0x0020U) continue; snprintf(sb, sizeof(sb) , "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" , xb[0], xb[1], xb[2], xb[3], xb[4], xb[5], xb[6], xb[7]); happy(ttoaddr(sb, 0, AF_INET6, &ri.addr)); if (!isunspecaddr(&ri.addr)) { DBG(DBG_CONTROL , DBG_log("found %s with address %s" , ri.name, sb)); ri.next = rifaces; rifaces = clone_thing(ri, "struct raw_iface"); } } fclose(proc_sock); } return rifaces; }
struct raw_iface * find_raw_ifaces4(void) { static const int on = TRUE; /* by-reference parameter; constant, we hope */ int j; /* index into buf */ static int num=64; /* number of interfaces */ struct ifconf ifconf; struct ifreq *buf; /* for list of interfaces -- arbitrary limit */ struct raw_iface *rifaces = NULL; int master_sock = safe_socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); /* Get a UDP socket */ /* get list of interfaces with assigned IPv4 addresses from system */ if (master_sock == -1) exit_log_errno((e, "socket() failed in find_raw_ifaces4()")); if (setsockopt(master_sock, SOL_SOCKET, SO_REUSEADDR , (const void *)&on, sizeof(on)) < 0) exit_log_errno((e, "setsockopt() in find_raw_ifaces4()")); /* bind the socket */ { ip_address any; happy(anyaddr(AF_INET, &any)); setportof(htons(pluto_port), &any); if (bind(master_sock, sockaddrof(&any), sockaddrlenof(&any)) < 0) exit_log_errno((e, "bind() failed in find_raw_ifaces4()")); } buf = NULL; /* a million interfaces is probably the maximum, ever... */ while(num < (1024*1024)) { /* Get local interfaces. See netdevice(7). */ ifconf.ifc_len = num * sizeof(struct ifreq); buf = (void *) realloc(buf, ifconf.ifc_len); if (!buf) exit_log_errno((e, "realloc of %d in find_raw_ifaces4()", ifconf.ifc_len)); memset(buf, 0, num*sizeof(struct ifreq)); ifconf.ifc_buf = (void *) buf; if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1) exit_log_errno((e, "ioctl(SIOCGIFCONF) in find_raw_ifaces4()")); /* if we got back less than we asked for, we have them all */ if (ifconf.ifc_len < (int)(sizeof(struct ifreq) * num)) break; /* try again and ask for more this time */ num *= 2; } /* Add an entry to rifaces for each interesting interface. */ for (j = 0; (j+1) * sizeof(struct ifreq) <= (size_t)ifconf.ifc_len; j++) { struct raw_iface ri; const struct sockaddr_in *rs = (struct sockaddr_in *) &buf[j].ifr_addr; struct ifreq auxinfo; /* ignore all but AF_INET interfaces */ if (rs->sin_family != AF_INET) continue; /* not interesting */ /* build a NUL-terminated copy of the rname field */ memcpy(ri.name, buf[j].ifr_name, IFNAMSIZ); ri.name[IFNAMSIZ] = '\0'; /* ignore if our interface names were specified, and this isn't one */ if (pluto_ifn_roof != 0) { int i; for (i = 0; i != pluto_ifn_roof; i++) if (streq(ri.name, pluto_ifn[i])) break; if (i == pluto_ifn_roof) continue; /* not found -- skip */ } /* Find out stuff about this interface. See netdevice(7). */ zero(&auxinfo); /* paranoia */ memcpy(auxinfo.ifr_name, buf[j].ifr_name, IFNAMSIZ); if (ioctl(master_sock, SIOCGIFFLAGS, &auxinfo) == -1) exit_log_errno((e , "ioctl(SIOCGIFFLAGS) for %s in find_raw_ifaces4()" , ri.name)); if (!(auxinfo.ifr_flags & IFF_UP)) { DBG(DBG_CONTROL, DBG_log("Ignored interface %s - it is not up" , ri.name)); continue; /* ignore an interface that isn't UP */ } if (auxinfo.ifr_flags & IFF_SLAVE) { DBG(DBG_CONTROL, DBG_log("Ignored interface %s - it is a slave interface" , ri.name)); continue; /* ignore slave interfaces; they share IPs with their master */ } /* ignore unconfigured interfaces */ if (rs->sin_addr.s_addr == 0) { DBG(DBG_CONTROL, DBG_log("Ignored interface %s - it is unconfigured" , ri.name)); continue; } happy(initaddr((const void *)&rs->sin_addr, sizeof(struct in_addr) , AF_INET, &ri.addr)); DBG(DBG_CONTROL, DBG_log("found %s with address %s" , ri.name, ip_str(&ri.addr))); ri.next = rifaces; rifaces = clone_thing(ri, "struct raw_iface"); } close(master_sock); return rifaces; }
struct raw_iface *find_raw_ifaces4(void) { static const int on = TRUE; /* by-reference parameter; constant, we hope */ int j; /* index into buf */ struct ifconf ifconf; struct ifreq *buf = NULL; /* for list of interfaces -- arbitrary limit */ struct ifreq *bp; /* cursor into buf */ struct raw_iface *rifaces = NULL; int master_sock = safe_socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); /* Get a UDP socket */ /* * Current upper bound on number of interfaces. * Tricky: because this is a static, we won't have to start from * 64 in subsequent calls. */ static int num = 64; /* number of interfaces */ /* get list of interfaces with assigned IPv4 addresses from system */ if (master_sock == -1) exit_log_errno((e, "socket() failed in find_raw_ifaces4()")); if (setsockopt(master_sock, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on)) < 0) exit_log_errno((e, "setsockopt() in find_raw_ifaces4()")); /* bind the socket */ { ip_address any; happy(anyaddr(AF_INET, &any)); setportof(htons(pluto_port), &any); if (bind(master_sock, sockaddrof(&any), sockaddrlenof(&any)) < 0) exit_log_errno((e, "bind() failed in find_raw_ifaces4()")); } /* a million interfaces is probably the maximum, ever... */ for (; num < (1024 * 1024); num *= 2) { /* Get num local interfaces. See netdevice(7). */ ifconf.ifc_len = num * sizeof(struct ifreq); buf = realloc(buf, ifconf.ifc_len); if (buf == NULL) { exit_log_errno((e, "realloc of %d in find_raw_ifaces4()", ifconf.ifc_len)); } memset(buf, 0xDF, ifconf.ifc_len); /* stomp */ ifconf.ifc_buf = (void *) buf; if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1) exit_log_errno((e, "ioctl(SIOCGIFCONF) in find_raw_ifaces4()")); /* if we got back less than we asked for, we have them all */ if (ifconf.ifc_len < (int)(sizeof(struct ifreq) * num)) break; } /* Add an entry to rifaces for each interesting interface. On Apple, the size of struct ifreq depends on the contents of the union. See if.h */ for (bp = buf, j = 0; bp < (unsigned char *)buf + (size_t)ifconf.ifc_len; bp = (struct ifreq *) ((unsigned char *)bp +_SIZEOF_ADDR_IFREQ(*bp)), j++) { struct raw_iface ri; const struct sockaddr_in *rs = (struct sockaddr_in *) &bp->ifr_addr; struct ifreq auxinfo; /* ignore all but AF_INET interfaces */ if (rs->sin_family != AF_INET) continue; /* not interesting */ /* build a NUL-terminated copy of the rname field */ memcpy(ri.name, bp->ifr_name, IFNAMSIZ); ri.name[IFNAMSIZ] = '\0'; /* ignore if our interface names were specified, and this isn't one */ if (pluto_ifn_roof != 0) { int i; for (i = 0; i != pluto_ifn_roof; i++) if (streq(ri.name, pluto_ifn[i])) break; if (i == pluto_ifn_roof) continue; /* not found -- skip */ } /* Find out stuff about this interface. See netdevice(7). */ zero(&auxinfo); /* paranoia */ memcpy(auxinfo.ifr_name, bp->ifr_name, IFNAMSIZ); if (ioctl(master_sock, SIOCGIFFLAGS, &auxinfo) == -1) { exit_log_errno((e, "ioctl(SIOCGIFFLAGS) for %s in find_raw_ifaces4()", ri.name)); } if (!(auxinfo.ifr_flags & IFF_UP)) continue; /* ignore an interface that isn't UP */ /* ignore unconfigured interfaces */ if (rs->sin_addr.s_addr == 0) continue; happy(initaddr((const void *)&rs->sin_addr, sizeof(struct in_addr), AF_INET, &ri.addr)); DBG(DBG_CONTROL, { ipstr_buf b; DBG_log("found %s with address %s", ri.name, ipstr(&ri.addr, &b)); }); ri.next = rifaces; rifaces = clone_thing(ri, "struct raw_iface"); }
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); } }