}
#define DEFINE_CALL_TRANSFORM(fwdrev) \
-static int call_transform_##fwdrev(struct site *st, \
+static transform_apply_return \
+call_transform_##fwdrev(struct site *st, \
struct transform_inst_if *transform, \
struct buffer_if *buf, \
const char **errmsg) \
{ \
if (!is_transform_valid(transform)) { \
*errmsg="transform not set up"; \
- return 1; \
+ return transform_apply_err; \
} \
return transform->fwdrev(transform->st,buf,errmsg); \
}
/* Give the netlink code an opportunity to put its own stuff in the
message (configuration information, etc.) */
buf_prepend_uint32(&st->buffer,LABEL_MSG6);
- int problem = call_transform_forwards(st,transform,
- &st->buffer,&transform_err);
+ transform_apply_return problem =
+ call_transform_forwards(st,transform,
+ &st->buffer,&transform_err);
assert(!problem);
buf_prepend_uint32(&st->buffer,LABEL_MSG6);
buf_prepend_uint32(&st->buffer,st->index);
return True;
}
-static bool_t decrypt_msg0(struct site *st, struct buffer_if *msg0,
+static transform_apply_return
+decrypt_msg0(struct site *st, struct buffer_if *msg0,
const struct comm_addr *src)
{
cstring_t transform_err, auxkey_err, newkey_err="n/a";
struct msg0 m;
- uint32_t problem;
+ transform_apply_return problem;
if (!unpick_msg0(st,msg0,&m)) return False;
if (!st->auxiliary_is_new)
delete_one_key(st,&st->auxiliary_key,
"peer has used new key","auxiliary key",LOG_SEC);
- return True;
+ return 0;
}
- if (problem==2)
- goto skew;
+ if (transform_apply_return_badseq(problem))
+ goto badseq;
buffer_copy(msg0, &st->scratch);
problem = call_transform_reverse(st,st->auxiliary_key.transform,
msg0,&auxkey_err);
- if (problem==0) {
+ if (!problem) {
slog(st,LOG_DROP,"processing packet which uses auxiliary key");
if (st->auxiliary_is_new) {
/* We previously timed out in state SENTMSG5 but it turns
st->auxiliary_is_new=0;
st->renegotiate_key_time=st->auxiliary_renegotiate_key_time;
}
- return True;
+ return 0;
}
- if (problem==2)
- goto skew;
+ if (transform_apply_return_badseq(problem))
+ goto badseq;
if (st->state==SITE_SENTMSG5) {
buffer_copy(msg0, &st->scratch);
BUF_FREE(&st->buffer);
st->timeout=0;
activate_new_key(st);
- return True; /* do process the data in this packet */
+ return 0; /* do process the data in this packet */
}
- if (problem==2)
- goto skew;
+ if (transform_apply_return_badseq(problem))
+ goto badseq;
}
slog(st,LOG_SEC,"transform: %s (aux: %s, new: %s)",
transform_err,auxkey_err,newkey_err);
initiate_key_setup(st,"incoming message would not decrypt",0);
send_nak(src,m.dest,m.source,m.type,msg0,"message would not decrypt");
- return False;
+ assert(problem);
+ return problem;
- skew:
- slog(st,LOG_DROP,"transform: %s (merely skew)",transform_err);
+ badseq:
+ slog(st,LOG_DROP,"transform: %s (bad seq.)",transform_err);
assert(problem);
return problem;
}
const struct comm_addr *src)
{
uint32_t type;
-
- if (!decrypt_msg0(st,msg0,src))
+ transform_apply_return problem;
+
+ problem = decrypt_msg0(st,msg0,src);
+ if (problem==transform_apply_seqdupe) {
+ /* We recently received another copy of this packet, maybe due
+ * to polypath. That's not a problem; indeed, for the
+ * purposes of transport address management it is a success.
+ * But we don't want to process the packet. */
+ transport_data_msgok(st,src);
+ return False;
+ }
+ if (problem)
return False;
CHECK_AVAIL(msg0,4);