unsigned int noinject;
unsigned int dropepoch;
int droprec;
+ int duprec;
} MEMPACKET_TEST_CTX;
static int mempacket_test_new(BIO *bi);
int type)
{
MEMPACKET_TEST_CTX *ctx = BIO_get_data(bio);
- MEMPACKET *thispkt, *looppkt, *nextpkt;
- int i;
+ MEMPACKET *thispkt = NULL, *looppkt, *nextpkt, *allpkts[3];
+ int i, duprec = ctx->duprec > 0;
+ const unsigned char *inu = (const unsigned char *)in;
+ size_t len = ((inu[RECORD_LEN_HI] << 8) | inu[RECORD_LEN_LO])
+ + DTLS1_RT_HEADER_LENGTH;
if (ctx == NULL)
return -1;
+ if ((size_t)inl < len)
+ return -1;
+
+ if ((size_t)inl == len)
+ duprec = 0;
+
+ /* We don't support arbitrary injection when duplicating records */
+ if (duprec && pktnum != -1)
+ return -1;
+
/* We only allow injection before we've started writing any data */
if (pktnum >= 0) {
if (ctx->noinject)
ctx->noinject = 1;
}
- if (!TEST_ptr(thispkt = OPENSSL_malloc(sizeof(*thispkt))))
- return -1;
- if (!TEST_ptr(thispkt->data = OPENSSL_malloc(inl))) {
- mempacket_free(thispkt);
- return -1;
- }
+ for (i = 0; i < (duprec ? 3 : 1); i++) {
+ if (!TEST_ptr(allpkts[i] = OPENSSL_malloc(sizeof(*thispkt))))
+ goto err;
+ thispkt = allpkts[i];
- memcpy(thispkt->data, in, inl);
- thispkt->len = inl;
- thispkt->num = (pktnum >= 0) ? (unsigned int)pktnum : ctx->lastpkt;
- thispkt->type = type;
+ if (!TEST_ptr(thispkt->data = OPENSSL_malloc(inl)))
+ goto err;
+ /*
+ * If we are duplicating the packet, we duplicate it three times. The
+ * first two times we drop the first record if there are more than one.
+ * In this way we know that libssl will not be able to make progress
+ * until it receives the last packet, and hence will be forced to
+ * buffer these records.
+ */
+ if (duprec && i != 2) {
+ memcpy(thispkt->data, in + len, inl - len);
+ thispkt->len = inl - len;
+ } else {
+ memcpy(thispkt->data, in, inl);
+ thispkt->len = inl;
+ }
+ thispkt->num = (pktnum >= 0) ? (unsigned int)pktnum : ctx->lastpkt + i;
+ thispkt->type = type;
+ }
for(i = 0; (looppkt = sk_MEMPACKET_value(ctx->pkts, i)) != NULL; i++) {
/* Check if we found the right place to insert this packet */
if (looppkt->num > thispkt->num) {
- if (sk_MEMPACKET_insert(ctx->pkts, thispkt, i) == 0) {
- mempacket_free(thispkt);
- return -1;
- }
+ if (sk_MEMPACKET_insert(ctx->pkts, thispkt, i) == 0)
+ goto err;
/* If we're doing up front injection then we're done */
if (pktnum >= 0)
return inl;
} else if (looppkt->num == thispkt->num) {
if (!ctx->noinject) {
/* We injected two packets with the same packet number! */
- return -1;
+ goto err;
}
ctx->lastpkt++;
thispkt->num++;
* We didn't find any packets with a packet number equal to or greater than
* this one, so we just add it onto the end
*/
- if (!sk_MEMPACKET_push(ctx->pkts, thispkt)) {
- mempacket_free(thispkt);
- return -1;
- }
+ for (i = 0; i < (duprec ? 3 : 1); i++) {
+ thispkt = allpkts[i];
+ if (!sk_MEMPACKET_push(ctx->pkts, thispkt))
+ goto err;
- if (pktnum < 0)
- ctx->lastpkt++;
+ if (pktnum < 0)
+ ctx->lastpkt++;
+ }
return inl;
+
+ err:
+ for (i = 0; i < (ctx->duprec > 0 ? 3 : 1); i++)
+ mempacket_free(allpkts[i]);
+ return -1;
}
static int mempacket_test_write(BIO *bio, const char *in, int inl)
case MEMPACKET_CTRL_GET_DROP_REC:
ret = ctx->droprec;
break;
+ case MEMPACKET_CTRL_SET_DUPLICATE_REC:
+ ctx->duprec = (int)num;
+ break;
case BIO_CTRL_RESET:
case BIO_CTRL_DUP:
case BIO_CTRL_PUSH: