/* create new sadb_msg to reply. */
len = sizeof(struct sadb_msg)
+#ifdef __APPLE__
+ + sizeof(struct sadb_sa_2)
+#else
+ sizeof(struct sadb_sa)
+#endif
+ sizeof(struct sadb_address)
+ PFKEY_ALIGN8(sysdep_sa_len(src))
+ sizeof(struct sadb_address)
#ifdef ENABLE_HYBRID
case ADMIN_LOGOUT_USER: {
struct ph1handle *iph1;
- char *user;
- int found = 0;
+ char user[LOGINLEN+1];
+ int found = 0, len = com->ac_len - sizeof(com);
- if (com->ac_len > sizeof(com) + LOGINLEN + 1) {
+ if (len > LOGINLEN) {
plog(LLV_ERROR, LOCATION, NULL,
"malformed message (login too long)\n");
break;
}
- user = (char *)(com + 1);
+ memcpy(user, (char *)(com + 1), len);
+ user[len] = 0;
+
found = purgeph1bylogin(user);
plog(LLV_INFO, LOCATION, NULL,
"deleted %d SA for user \"%s\"\n", found, user);
X509_STORE_CTX_set_flags (csc, X509_V_FLAG_CRL_CHECK_ALL);
#endif
error = X509_verify_cert(csc);
- X509_STORE_CTX_cleanup(csc);
+ X509_STORE_CTX_free(csc);
/*
* if x509_verify_cert() is successful then the value of error is
unlink_sainfo_from_ph2(iph2->sainfo);
iph2->sainfo = NULL;
}
+ if (iph2->ext_nat_id) {
+ vfree(iph2->ext_nat_id);
+ iph2->ext_nat_id = NULL;
+ }
+ if (iph2->ext_nat_id_p) {
+ vfree(iph2->ext_nat_id_p);
+ iph2->ext_nat_id_p = NULL;
+ }
#endif
racoon_free(iph2);
}
}
- sched_new(lt, sweep_recvdpkt, NULL);
+ sched_new(lt, sweep_recvdpkt, &rcptree);
}
void
rem_recvdpkt(r);
del_recvdpkt(r);
}
+ sched_scrub_param(&rcptree);
}
void
LIST_INIT(&rcptree);
- sched_new(lt, sweep_recvdpkt, NULL);
+ sched_new(lt, sweep_recvdpkt, &rcptree);
}
#ifdef ENABLE_HYBRID
int is_dying:1;
ike_session_t *parent_session;
LIST_ENTRY(ph2handle) ph2ofsession_chain;
+ vchar_t *ext_nat_id;
+ vchar_t *ext_nat_id_p;
#endif
LIST_ENTRY(ph2handle) chain;
#include "localconf.h"
#include "remoteconf.h"
#include "vpn_control.h"
+#include "proposal.h"
+#include "sainfo.h"
const char *ike_session_stopped_by_vpn_disconnect = "Stopped by VPN disconnect";
const char *ike_session_stopped_by_flush = "Stopped by Flush";
const char *ike_session_stopped_by_idle = "Stopped by Idle";
const char *ike_session_stopped_by_xauth_timeout = "Stopped by XAUTH timeout";
-static LIST_HEAD(_ike_session_tree_, ike_session) ike_session_tree;
+static LIST_HEAD(_ike_session_tree_, ike_session) ike_session_tree = { NULL };
static ike_session_t *
new_ike_session (ike_session_id_t *id)
SCHED_KILL(session->traffic_monitor.sc_idle);
SCHED_KILL(session->sc_xauth);
if (session->start_timestamp.tv_sec || session->start_timestamp.tv_usec) {
- if (!(session->stop_timestamp.tv_sec || session->start_timestamp.tv_usec)) {
+ if (!(session->stop_timestamp.tv_sec || session->stop_timestamp.tv_usec)) {
gettimeofday(&session->stop_timestamp, NULL);
}
if (session->term_reason != ike_session_stopped_by_vpn_disconnect ||
min_period = MIN(iph1->rmconf->dpd_interval, iph1->rmconf->idle_timeout);
max_period = MAX(iph1->rmconf->dpd_interval, iph1->rmconf->idle_timeout);
} else if (iph1->rmconf->idle_timeout) {
- min_period = max_period = MIN(0, iph1->rmconf->idle_timeout);
+ min_period = max_period = iph1->rmconf->idle_timeout;
} else {
// DPD_ALGO_DEFAULT is configured and there's no idle timeout... we don't need to monitor traffic
return;
}
if (min_period) {
- sample_period = min_period >> 1;
+ sample_period = min_period / 20;
if (!sample_period)
sample_period = 1; // bad
} else {
- sample_period = max_period >> 1;
+ sample_period = max_period / 20;
if (!sample_period)
sample_period = 1; // bad
}
static void
ike_session_cleanup_idle (void *arg)
{
- ike_session_t *session = (ike_session_t *)arg;
+ ike_session_cleanup((ike_session_t *)arg, ike_session_stopped_by_idle);
+}
+
+static void
+ike_session_monitor_idle (ike_session_t *session)
+{
+ if (!session)
+ return;
if (session->traffic_monitor.dir_idle == IPSEC_DIR_INBOUND ||
session->traffic_monitor.dir_idle == IPSEC_DIR_ANY) {
if (session->peer_sent_data_sc_idle) {
SCHED_KILL(session->traffic_monitor.sc_idle);
- session->traffic_monitor.sc_idle = sched_new(session->traffic_monitor.interv_idle,
- ike_session_cleanup_idle,
- session);
+ if (session->traffic_monitor.interv_idle) {
+ session->traffic_monitor.sc_idle = sched_new(session->traffic_monitor.interv_idle,
+ ike_session_cleanup_idle,
+ session);
+ }
session->peer_sent_data_sc_idle = 0;
session->i_sent_data_sc_idle = 0;
return;
session->traffic_monitor.dir_idle == IPSEC_DIR_ANY) {
if (session->i_sent_data_sc_idle) {
SCHED_KILL(session->traffic_monitor.sc_idle);
- session->traffic_monitor.sc_idle = sched_new(session->traffic_monitor.interv_idle,
- ike_session_cleanup_idle,
- session);
+ if (session->traffic_monitor.interv_idle) {
+ session->traffic_monitor.sc_idle = sched_new(session->traffic_monitor.interv_idle,
+ ike_session_cleanup_idle,
+ session);
+ }
session->peer_sent_data_sc_idle = 0;
session->i_sent_data_sc_idle = 0;
return;
}
}
-
- ike_session_cleanup((ike_session_t *)arg, ike_session_stopped_by_idle);
}
void
return;
}
+ if (!session->established || session->stopped_by_vpn_controller || session->stop_timestamp.tv_sec || session->stop_timestamp.tv_usec) {
+ plog(LLV_DEBUG2, LOCATION, NULL, "dropping update on invalid session.\n", __FUNCTION__);
+ return;
+ }
+
for (i = 0; i < max_stats; i++) {
if (dir == IPSEC_DIR_INBOUND) {
for (j = 0; j < session->traffic_monitor.num_in_last_poll; j++) {
session->i_sent_data_sc_idle = 1;
}
}
+
+ ike_session_monitor_idle(session);
}
void
if (!session)
return;
+ SCHED_KILL(session->traffic_monitor.sc_idle);
// do ph2's first... we need the ph1s for notifications
for (iph2 = LIST_FIRST(&session->ikev1_state.ph2tree); iph2; iph2 = LIST_NEXT(iph2, ph2ofsession_chain)) {
if (iph2->status == PHASE2ST_ESTABLISHED) {
if (iph1->parent_session) {
SCHED_KILL(iph1->parent_session->sc_xauth);
}
+}
+
+static int
+ike_session_is_id_ipany (vchar_t *ext_id)
+{
+ struct id {
+ u_int8_t type; /* ID Type */
+ u_int8_t proto_id; /* Protocol ID */
+ u_int16_t port; /* Port */
+ u_int32_t addr; /* IPv4 address */
+ u_int32_t mask;
+ } *id_ptr;
+
+ /* ignore protocol and port */
+ id_ptr = (struct id *)ext_id->v;
+ if (id_ptr->type == IPSECDOI_ID_IPV4_ADDR &&
+ id_ptr->addr == 0) {
+ return 1;
+ } else if (id_ptr->type == IPSECDOI_ID_IPV4_ADDR_SUBNET &&
+ id_ptr->mask == 0 &&
+ id_ptr->addr == 0) {
+ return 1;
+ }
+ plog(LLV_DEBUG2, LOCATION, NULL, "not ipany_ids in %s: type %d, addr %x, mask %x.\n",
+ __FUNCTION__, id_ptr->type, id_ptr->addr, id_ptr->mask);
+ return 0;
+}
+
+static int
+ike_session_cmp_ph2_ids_ipany (vchar_t *ext_id,
+ vchar_t *ext_id_p)
+{
+ if (ike_session_is_id_ipany(ext_id) &&
+ ike_session_is_id_ipany(ext_id_p)) {
+ return 1;
+ }
+ return 0;
+}
+
+static int
+ike_session_cmp_ph2_ids (struct ph2handle *iph2,
+ struct ph2handle *older_ph2)
+{
+ if (iph2->id && older_ph2->id &&
+ iph2->id->l == older_ph2->id->l &&
+ memcmp(iph2->id->v, older_ph2->id->v, iph2->id->l) == 0 &&
+ iph2->id_p && older_ph2->id_p &&
+ iph2->id_p->l == older_ph2->id_p->l &&
+ memcmp(iph2->id_p->v, older_ph2->id_p->v, iph2->id_p->l) == 0) {
+ return 0;
+ }
+ if (iph2->ext_nat_id && older_ph2->ext_nat_id &&
+ iph2->ext_nat_id->l == older_ph2->ext_nat_id->l &&
+ memcmp(iph2->ext_nat_id->v, older_ph2->ext_nat_id->v, iph2->ext_nat_id->l) == 0 &&
+ iph2->ext_nat_id_p && older_ph2->ext_nat_id_p &&
+ iph2->ext_nat_id_p->l == older_ph2->ext_nat_id_p->l &&
+ memcmp(iph2->ext_nat_id_p->v, older_ph2->ext_nat_id_p->v, iph2->ext_nat_id_p->l) == 0) {
+ return 0;
+ }
+ if (iph2->id && older_ph2->ext_nat_id &&
+ iph2->id->l == older_ph2->ext_nat_id->l &&
+ memcmp(iph2->id->v, older_ph2->ext_nat_id->v, iph2->id->l) == 0 &&
+ iph2->id_p && older_ph2->ext_nat_id_p &&
+ iph2->id_p->l == older_ph2->ext_nat_id_p->l &&
+ memcmp(iph2->id_p->v, older_ph2->ext_nat_id_p->v, iph2->id_p->l) == 0) {
+ return 0;
+ }
+ return -1;
+}
+
+int
+ike_session_get_sainfo_r (struct ph2handle *iph2)
+{
+ if (iph2->parent_session &&
+ iph2->parent_session->is_client &&
+ iph2->id && iph2->id_p) {
+ struct ph2handle *p;
+ int ipany_ids = ike_session_cmp_ph2_ids_ipany(iph2->id, iph2->id_p);
+ plog(LLV_DEBUG2, LOCATION, NULL, "ipany_ids %d in %s.\n", ipany_ids, __FUNCTION__);
+
+ for (p = LIST_FIRST(&iph2->parent_session->ikev1_state.ph2tree); p; p = LIST_NEXT(p, ph2ofsession_chain)) {
+ if (iph2 != p && !p->is_dying && p->status >= PHASE2ST_ESTABLISHED &&
+ p->sainfo && !p->sainfo->to_delete && !p->sainfo->to_remove) {
+ plog(LLV_DEBUG2, LOCATION, NULL, "candidate ph2 found in %s.\n", __FUNCTION__);
+ if (ipany_ids ||
+ ike_session_cmp_ph2_ids(iph2, p) == 0) {
+ plog(LLV_DEBUG2, LOCATION, NULL, "candidate ph2 matched in %s.\n", __FUNCTION__);
+ iph2->sainfo = p->sainfo;
+ return 0;
+ }
+ }
+ }
+ }
+ return -1;
}
\ No newline at end of file
extern int ike_session_is_client_ph1_rekey __P((struct ph1handle *));
extern void ike_session_start_xauth_timer __P((struct ph1handle *));
extern void ike_session_stop_xauth_timer __P((struct ph1handle *));
+extern int ike_session_get_sainfo_r __P((struct ph2handle *));
#endif /* _IKE_SESSION_H */
((struct sockaddr_in6 *)&saddr)->sin6_port = IPSEC_PORT_ANY;
memcpy(&((struct sockaddr_in6 *)&saddr)->sin6_addr,
id->v + sizeof(*id_b), sizeof(struct in6_addr));
+ ((struct sockaddr_in6 *)&saddr)->sin6_scope_id =
+ (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)&saddr)->sin6_addr)
+ ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
+ : 0);
break;
#endif
}
memcpy(&((struct sockaddr_in6 *)&saddr)->sin6_addr,
id->v + sizeof(*id_b) + sizeof(struct in6_addr),
sizeof(struct in6_addr));
+ ((struct sockaddr_in6 *)&saddr)->sin6_scope_id =
+ (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)&saddr)->sin6_addr)
+ ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
+ : 0);
if (len >= 0) {
len += snprintf( buf + len, sizeof(buf) - len, "%s", saddrwop2str((struct sockaddr *)&saddr));
if (ISSET(isakmp->flags, ISAKMP_FLAG_C))
iph2->flags |= ISAKMP_FLAG_C;
+ if (ISSET(isakmp->flags, ISAKMP_FLAG_E) &&
+ (iph2->ph1 == NULL || iph2->ph1->approval == NULL)) {
+ IPSECSESSIONTRACEREVENT(iph2->parent_session,
+ IPSECSESSIONEVENTCODE_IKEV1_PH2_INIT_DROP,
+ CONSTSTR("can't continue phase2 without valid phase1"),
+ CONSTSTR("Failed to continue phase2 resonder (invalid linked phase1"));
+ plog(LLV_ERROR, LOCATION, remote,
+ "can't start the quick mode, "
+ "invalid linked ISAKMP-SA\n");
+ return -1;
+ }
+
/* call main process of quick mode */
if (quick_main(iph2, msg) < 0) {
plog(LLV_ERROR, LOCATION, iph1->remote,
/* XXX copy remote address */
if (copy_ph1addresses(iph1, rmconf, remote, local) < 0) {
/* don't call remph1(iph1) until after insph1(iph1) is called */
- delph1(iph1);
+ iph1 = NULL; /* deleted in copy_ph1addresses */
return -1;
}
/* copy remote address */
if (copy_ph1addresses(iph1, rmconf, remote, local) < 0) {
/* don't call remph1(iph1) until after insph1(iph1) is called */
- delph1(iph1);
+ iph1 = NULL; /* deleted in copy_ph1addresses */
return -1;
}
(void)insph1(iph1);
initph2tree();
initctdtree();
init_recvdpkt();
- ike_session_init();
if (isakmp_open() < 0)
goto err;
"failed to bind to address %s (%s).\n",
saddr2str(p->addr), strerror(errno));
close(p->sock);
+ p->sock = -1;
goto err_and_next;
}
default:
plog(LLV_ERROR, LOCATION, NULL,
"invalid family: %d\n", iph1->remote->sa_family);
+ delph1(iph1);
return -1;
}
if (iph1->mode_cfg->flags & ISAKMP_CFG_DELETE_PH1) {
if (iph1->status == PHASE1ST_ESTABLISHED)
isakmp_info_send_d1(iph1);
- remph1(iph1);
- delph1(iph1);
+ isakmp_ph1expire(iph1);
iph1 = NULL;
}
vfree(payload);
/* If a pool already exists, check if we can shrink it */
if ((isakmp_cfg_config.port_pool != NULL) &&
(size < isakmp_cfg_config.pool_size)) {
- for (i = isakmp_cfg_config.pool_size; i >= size; --i) {
+ for (i = isakmp_cfg_config.pool_size-1; i >= size; --i) {
if (isakmp_cfg_config.port_pool[i].used) {
plog(LLV_ERROR, LOCATION, NULL,
"resize pool from %zu to %d impossible "
isakmp_cfg_config.splitdns_list = NULL;
isakmp_cfg_config.splitdns_len = 0;
+#if 0
if (cold == ISAKMP_CFG_INIT_COLD) {
if ((error = isakmp_cfg_resize_pool(ISAKMP_CFG_MAX_CNX)) != 0)
return error;
}
+#endif
return 0;
}
* frag->len is the frag payload data plus the frag payload header,
* whose size is sizeof(*frag)
*/
- if (msg->l < sizeof(*isakmp) + ntohs(frag->len)) {
+ if (msg->l < sizeof(*isakmp) + ntohs(frag->len) ||
+ ntohs(frag->len) < sizeof(*frag) + 1) {
plog(LLV_ERROR, LOCATION, NULL, "Fragment too short\n");
return -1;
}
plog(LLV_ERROR, LOCATION, NULL,
"failed to copy ph1 addresses");
error = -1;
+ iph1 = NULL; /* deleted in copy_ph1addresses */
goto end;
}
if (f_id == 0 && (iph2->ph1->natt_flags & NAT_DETECTED_ME)) {
if (lcconf->ext_nat_id)
vfree(lcconf->ext_nat_id);
- lcconf->ext_nat_id = vmalloc(idp_ptr->h.len - sizeof(struct isakmp_gen));
+ lcconf->ext_nat_id = vmalloc(ntohs(idp_ptr->h.len) - sizeof(struct isakmp_gen));
if (lcconf->ext_nat_id == NULL) {
plog(LLV_ERROR, LOCATION, NULL, "memory error while allocating external nat id.\n");
goto end;
}
memcpy(lcconf->ext_nat_id->v, &(idp_ptr->b), lcconf->ext_nat_id->l);
+ if (iph2->ext_nat_id)
+ vfree(iph2->ext_nat_id);
+ iph2->ext_nat_id = vdup(lcconf->ext_nat_id);
+ if (iph2->ext_nat_id == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "memory error while allocating ph2's external nat id.\n");
+ goto end;
+ }
plog(LLV_DEBUG, LOCATION, NULL, "external nat address saved.\n");
+ } else if (f_id && (iph2->ph1->natt_flags & NAT_DETECTED_PEER)) {
+ if (iph2->ext_nat_id_p)
+ vfree(iph2->ext_nat_id_p);
+ iph2->ext_nat_id_p = vmalloc(ntohs(idp_ptr->h.len) - sizeof(struct isakmp_gen));
+ if (iph2->ext_nat_id_p == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "memory error while allocating peers ph2's external nat id.\n");
+ goto end;
+ }
+ memcpy(iph2->ext_nat_id_p->v, &(idp_ptr->b), iph2->ext_nat_id_p->l);
+ plog(LLV_DEBUG, LOCATION, NULL, "peer's external nat address saved.\n");
}
} else {
plog(LLV_ERROR, LOCATION, NULL, "mismatched ID was returned.\n");
/* check the existence of ID payload and create responder's proposal */
error = get_proposal_r(iph2, 0);
- if (error != -2 && error != 0 && (iph2->ph1->natt_flags & NAT_DETECTED_ME) && (lcconf->ext_nat_id != NULL || ike_session_is_client_ph2_rekey(iph2)))
+ if (error != -2 && error != 0 &&
+ (((iph2->ph1->natt_flags & NAT_DETECTED_ME) && lcconf->ext_nat_id != NULL) ||
+ (iph2->parent_session && iph2->parent_session->is_client)))
error = get_proposal_r(iph2, 1);
switch (error) {
vchar_t *idsrc = NULL, *iddst = NULL;
int prefixlen;
int error = ISAKMP_INTERNAL_ERROR;
- int remoteid = 0;
+ struct sainfo *anonymous = NULL;
- if (iph2->id == NULL ||
- ((iph2->ph1->natt_flags & NAT_DETECTED_ME) && ike_session_is_client_ph2_rekey(iph2))) {
+ if (iph2->id == NULL) {
switch (iph2->src->sa_family) {
case AF_INET:
prefixlen = sizeof(struct in_addr) << 3;
goto end;
}
- if (iph2->id_p == NULL ||
- ((iph2->ph1->natt_flags & NAT_DETECTED_PEER) && ike_session_is_client_ph2_rekey(iph2))) {
+ if (iph2->id_p == NULL) {
switch (iph2->dst->sa_family) {
case AF_INET:
prefixlen = sizeof(struct in_addr) << 3;
}
iph2->sainfo = getsainfo(idsrc, iddst, iph2->ph1->id_p, 0);
- if (iph2->sainfo == NULL)
+ // track anonymous sainfo, because we'll try to find a better sainfo if this is a client
+ if (iph2->sainfo && iph2->sainfo->idsrc == NULL)
+ anonymous = iph2->sainfo;
+
+ if (iph2->sainfo == NULL ||
+ (anonymous && iph2->parent_session && iph2->parent_session->is_client)) {
if ((iph2->ph1->natt_flags & NAT_DETECTED_ME) && lcconf->ext_nat_id != NULL)
iph2->sainfo = getsainfo(idsrc, iddst, iph2->ph1->id_p, 1);
+ if (iph2->sainfo) {
+ plog(LLV_DEBUG2, LOCATION, NULL,
+ "get_sainfo_r case 1.\n");
+ }
+ // still no sainfo (or anonymous): for client, fallback to sainfo used by a previous established phase2
+ if (iph2->sainfo == NULL ||
+ (iph2->sainfo->idsrc == NULL && iph2->parent_session && iph2->parent_session->is_client)) {
+ ike_session_get_sainfo_r(iph2);
+ if (iph2->sainfo) {
+ plog(LLV_DEBUG2, LOCATION, NULL,
+ "get_sainfo_r case 2.\n");
+ }
+ }
+ }
if (iph2->sainfo == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
- "failed to get sainfo.\n");
- goto end;
+ if (anonymous == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to get sainfo.\n");
+ goto end;
+ }
+ iph2->sainfo = anonymous;
}
#ifdef __APPLE__
if (link_sainfo_to_ph2(iph2->sainfo) != 0) {
/* Delete Phase 1 SA */
if (iph1->status == PHASE1ST_ESTABLISHED)
isakmp_info_send_d1(iph1);
- remph1(iph1);
- delph1(iph1);
+ isakmp_ph1expire(iph1);
return -1;
}
}
#endif
+#ifdef ENABLE_HYBRID
+ if(isakmp_cfg_config.network4 && isakmp_cfg_config.pool_size == 0)
+ if ((error = isakmp_cfg_resize_pool(ISAKMP_CFG_MAX_CNX)) != 0)
+ return error;
+#endif
+
if (dump_config)
dumprmconf ();
natt_float_ports (struct ph1handle *iph1)
{
- if (! (iph1->natt_flags && NAT_DETECTED) )
+ if (! (iph1->natt_flags & NAT_DETECTED) )
return;
if (! iph1->natt_options->float_port){
/* Drafts 00 / 01, just schedule keepalive */
/* do decrypt */
new = alg_oakley_encdef_decrypt(iph1->approval->enctype,
buf, iph1->key, ivdp);
- if (new == NULL) {
+ if (new == NULL || new->v == NULL || new->l == 0) {
plog(LLV_ERROR, LOCATION, NULL,
"decryption %d failed.\n", iph1->approval->enctype);
goto end;
int allow_anon;
{
struct remoteconf *p;
+ struct remoteconf *p_withport_besteffort = NULL;
struct remoteconf *anon = NULL;
int withport;
char buf[NI_MAXHOST + NI_MAXSERV + 10];
withport = 0;
-#ifndef ENABLE_NATT
/*
* We never have ports set in our remote configurations, but when
* NAT-T is enabled, the kernel can have policies with ports and
* send us an acquire message for a destination that has a port set.
- * If we do this port check here, we don't find the remote config.
+ * If we do this port check here, we have to fallback to a best-effort result (without the port).
*
* In an ideal world, we would be able to have remote conf with
* port, and the port could be a wildcard. That test could be used.
default:
plog(LLV_ERROR2, LOCATION, NULL,
"invalid ip address family: %d\n", remote->sa_family);
- exit(1);
+ return NULL;
}
-#endif /* ENABLE_NATT */
if (remote->sa_family == AF_UNSPEC)
snprintf (buf, sizeof(buf), "%s", "anonymous");
plog(LLV_DEBUG, LOCATION, NULL,
"configuration found for %s.\n", buf);
return p;
+ } else if (withport && cmpsaddrwop(remote, p->remote) == 0) {
+ // for withport: save the pointer for the best-effort search
+ p_withport_besteffort = p;
}
/* save the pointer to the anonymous configuration */
anon = p;
}
+ if (p_withport_besteffort) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "configuration found for %s.\n", buf);
+ return p_withport_besteffort;
+ }
+
if (allow_anon && anon != NULL) {
plog(LLV_DEBUG, LOCATION, NULL,
"anonymous configuration selected for %s.\n", buf);
#else
char rbuf[1024];
rbuf[0] = '\0';
- fgets (rbuf, sizeof(rbuf), stdin);
- if (!rbuf[0])
+ if (fgets(rbuf, sizeof(rbuf), stdin) == NULL)
break;
if (rbuf[strlen(rbuf)-1] == '\n')
rbuf[strlen(rbuf)-1] = '\0';