Annotation of embedaddon/strongswan/src/libcharon/tests/suites/test_ike_mid_sync.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2016 Tobias Brunner
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify it
                      6:  * under the terms of the GNU General Public License as published by the
                      7:  * Free Software Foundation; either version 2 of the License, or (at your
                      8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful, but
                     11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     13:  * for more details.
                     14:  */
                     15: 
                     16: #include "test_suite.h"
                     17: 
                     18: #include <tests/utils/exchange_test_helper.h>
                     19: #include <tests/utils/exchange_test_asserts.h>
                     20: #include <tests/utils/sa_asserts.h>
                     21: #include <bio/bio_reader.h>
                     22: #include <bio/bio_writer.h>
                     23: 
                     24: /**
                     25:  * FIXME: Since we don't have the server side yet, this is kind of a hack!!!
                     26:  */
                     27: 
                     28: /**
                     29:  * Add the IKEV2_MESSAGE_ID_SYNC_SUPPORTED notify to the IKE_AUTH response
                     30:  */
                     31: static bool add_notify(listener_t *listener, ike_sa_t *ike_sa,
                     32:                                           message_t *message, bool incoming, bool plain)
                     33: {
                     34:        if (plain && !incoming && message->get_exchange_type(message) == IKE_AUTH &&
                     35:                !message->get_request(message))
                     36:        {
                     37:                message->add_notify(message, FALSE, IKEV2_MESSAGE_ID_SYNC_SUPPORTED,
                     38:                                                        chunk_empty);
                     39:                return FALSE;
                     40:        }
                     41:        return TRUE;
                     42: }
                     43: #define add_notify_to_ike_auth() ({ \
                     44:        listener_t _notify_listener = { \
                     45:                .message = add_notify, \
                     46:        }; \
                     47:        exchange_test_helper->add_listener(exchange_test_helper, &_notify_listener); \
                     48: })
                     49: 
                     50: /**
                     51:  * Handle IKEV2_MESSAGE_ID_SYNC notifies
                     52:  */
                     53: typedef struct {
                     54:        listener_t listener;
                     55:        struct {
                     56:                chunk_t nonce;
                     57:                uint32_t send;
                     58:                uint32_t recv;
                     59:        } init, resp;
                     60: } mid_sync_listener_t;
                     61: 
                     62: static bool handle_mid(listener_t *listener,
                     63:                                ike_sa_t *ike_sa, message_t *message, bool incoming, bool plain)
                     64: {
                     65:        mid_sync_listener_t *this = (mid_sync_listener_t*)listener;
                     66: 
                     67:        if (!plain || incoming)
                     68:        {
                     69:                return TRUE;
                     70:        }
                     71: 
                     72:        if (message->get_exchange_type(message) == INFORMATIONAL)
                     73:        {
                     74:                if (streq("resp", ike_sa->get_name(ike_sa)))
                     75:                {
                     76:                        bio_writer_t *writer;
                     77:                        rng_t *rng;
                     78: 
                     79:                        rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
                     80:                        ignore_result(rng->allocate_bytes(rng, 4, &this->init.nonce));
                     81:                        rng->destroy(rng);
                     82:                        writer = bio_writer_create(12);
                     83:                        writer->write_data(writer, this->init.nonce);
                     84:                        writer->write_uint32(writer, this->init.send);
                     85:                        writer->write_uint32(writer, this->init.recv);
                     86:                        message->set_message_id(message, 0);
                     87:                        message->add_notify(message, FALSE, IKEV2_MESSAGE_ID_SYNC,
                     88:                                                                writer->get_buf(writer));
                     89:                        writer->destroy(writer);
                     90:                }
                     91:                else
                     92:                {
                     93:                        notify_payload_t *notify;
                     94:                        bio_reader_t *reader;
                     95: 
                     96:                        notify = message->get_notify(message, IKEV2_MESSAGE_ID_SYNC);
                     97:                        reader = bio_reader_create(notify->get_notification_data(notify));
                     98:                        chunk_clear(&this->resp.nonce);
                     99:                        reader->read_data(reader, 4, &this->resp.nonce);
                    100:                        this->resp.nonce = chunk_clone(this->resp.nonce);
                    101:                        reader->read_uint32(reader, &this->resp.send);
                    102:                        reader->read_uint32(reader, &this->resp.recv);
                    103:                        reader->destroy(reader);
                    104:                }
                    105:        }
                    106:        return TRUE;
                    107: }
                    108: 
                    109: /**
                    110:  * Send a MESSAGE_ID_SYNC notify in an INFORMATIONAL.  We reset the state
                    111:  * afterwards so this seems as if nothing happened.
                    112:  */
                    113: static void send_mid_sync(ike_sa_t *sa, uint32_t send, uint32_t recv)
                    114: {
                    115:        call_ikesa(sa, send_dpd);
                    116:        sa->set_message_id(sa, TRUE, send);
                    117:        sa->set_message_id(sa, FALSE, recv);
                    118:        sa->flush_queue(sa, TASK_QUEUE_QUEUED);
                    119: }
                    120: 
                    121: /**
                    122:  * Send a regular DPD from one IKE_SA to another
                    123:  */
                    124: static void send_dpd(ike_sa_t *from, ike_sa_t *to)
                    125: {
                    126:        uint32_t send, recv;
                    127: 
                    128:        send = from->get_message_id(from, TRUE);
                    129:        recv = to->get_message_id(to, FALSE);
                    130:        call_ikesa(from, send_dpd);
                    131:        exchange_test_helper->process_message(exchange_test_helper, to, NULL);
                    132:        exchange_test_helper->process_message(exchange_test_helper, from, NULL);
                    133:        ck_assert_int_eq(send + 1, from->get_message_id(from, TRUE));
                    134:        ck_assert_int_eq(recv + 1, to->get_message_id(to, FALSE));
                    135: }
                    136: 
                    137: /**
                    138:  * Send a number of DPDs from on IKE_SA to the other
                    139:  */
                    140: static void send_dpds(ike_sa_t *from, ike_sa_t *to, int count)
                    141: {
                    142:        while (count--)
                    143:        {
                    144:                send_dpd(from, to);
                    145:        }
                    146: }
                    147: 
                    148: static struct {
                    149:        int dpds_a, dpds_b;
                    150:        uint32_t send, recv;
                    151: } data[] = {
                    152:        { 0, 0, 0, 2 },
                    153:        { 0, 0, 1, 3 },
                    154:        { 1, 0, 0, 3 },
                    155:        { 1, 0, 5, 8 },
                    156:        { 0, 1, 1, 2 },
                    157:        { 0, 1, 2, 2 },
                    158:        { 1, 1, 1, 3 },
                    159:        { 1, 1, 2, 4 },
                    160:        { 1, 2, 2, 4 },
                    161: };
                    162: 
                    163: /**
                    164:  * The responder syncs message IDs with the initiator
                    165:  */
                    166: START_TEST(test_responder)
                    167: {
                    168:        ike_sa_t *a, *b;
                    169:        mid_sync_listener_t mid = {
                    170:                .listener = { .message = (void*)handle_mid, },
                    171:                .init = {
                    172:                        .send = data[_i].send,
                    173:                        .recv = data[_i].recv,
                    174:                },
                    175:        };
                    176: 
                    177:        add_notify_to_ike_auth();
                    178:        exchange_test_helper->establish_sa(exchange_test_helper,
                    179:                                                                           &a, &b, NULL);
                    180: 
                    181:        send_dpds(a, b, data[_i].dpds_a);
                    182:        send_dpds(b, a, data[_i].dpds_b);
                    183: 
                    184:        exchange_test_helper->add_listener(exchange_test_helper, &mid.listener);
                    185:        send_mid_sync(b, data[_i].send, data[_i].recv);
                    186:        exchange_test_helper->process_message(exchange_test_helper, a, NULL);
                    187:        ck_assert_chunk_eq(mid.init.nonce, mid.resp.nonce);
                    188:        ck_assert_int_eq(data[_i].recv, mid.resp.send);
                    189:        ck_assert_int_eq(data[_i].send, mid.resp.recv);
                    190:        ck_assert_int_eq(data[_i].recv, a->get_message_id(a, TRUE));
                    191:        ck_assert_int_eq(data[_i].send, a->get_message_id(a, FALSE));
                    192:        /* this currently won't be handled */
                    193:        exchange_test_helper->process_message(exchange_test_helper, b, NULL);
                    194:        charon->bus->remove_listener(charon->bus, &mid.listener);
                    195: 
                    196:        send_dpd(a, b);
                    197:        send_dpd(b, a);
                    198: 
                    199:        call_ikesa(a, destroy);
                    200:        call_ikesa(b, destroy);
                    201:        chunk_free(&mid.init.nonce);
                    202:        chunk_free(&mid.resp.nonce);
                    203: }
                    204: END_TEST
                    205: 
                    206: /**
                    207:  * Make sure a retransmit is handled properly.
                    208:  */
                    209: START_TEST(test_retransmit)
                    210: {
                    211:        ike_sa_t *a, *b;
                    212:        mid_sync_listener_t mid = {
                    213:                .listener = { .message = (void*)handle_mid, },
                    214:                .init = {
                    215:                        .send = data[_i].send,
                    216:                        .recv = data[_i].recv,
                    217:                },
                    218:        };
                    219:        message_t *msg, *retransmit;
                    220: 
                    221:        add_notify_to_ike_auth();
                    222:        exchange_test_helper->establish_sa(exchange_test_helper,
                    223:                                                                           &a, &b, NULL);
                    224: 
                    225:        send_dpds(a, b, data[_i].dpds_a);
                    226:        send_dpds(b, a, data[_i].dpds_b);
                    227: 
                    228:        exchange_test_helper->add_listener(exchange_test_helper, &mid.listener);
                    229:        send_mid_sync(b, data[_i].send, data[_i].recv);
                    230:        msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
                    231:        retransmit = message_create_from_packet(msg->get_packet(msg));
                    232:        retransmit->parse_header(retransmit);
                    233:        exchange_test_helper->process_message(exchange_test_helper, a, msg);
                    234:        msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
                    235:        msg->destroy(msg);
                    236:        exchange_test_helper->process_message(exchange_test_helper, a, retransmit);
                    237:        exchange_test_helper->process_message(exchange_test_helper, b, NULL);
                    238:        charon->bus->remove_listener(charon->bus, &mid.listener);
                    239: 
                    240:        send_dpd(a, b);
                    241:        send_dpd(b, a);
                    242: 
                    243:        call_ikesa(a, destroy);
                    244:        call_ikesa(b, destroy);
                    245:        chunk_free(&mid.init.nonce);
                    246:        chunk_free(&mid.resp.nonce);
                    247: }
                    248: END_TEST
                    249: 
                    250: /**
                    251:  * Make sure a replayed or delayed notify is ignored.
                    252:  */
                    253: START_TEST(test_replay)
                    254: {
                    255:        ike_sa_t *a, *b;
                    256:        mid_sync_listener_t mid = {
                    257:                .listener = { .message = (void*)handle_mid, },
                    258:                .init = {
                    259:                        .send = data[_i].send,
                    260:                        .recv = data[_i].recv,
                    261:                },
                    262:        };
                    263:        message_t *msg, *replay;
                    264: 
                    265:        add_notify_to_ike_auth();
                    266:        exchange_test_helper->establish_sa(exchange_test_helper,
                    267:                                                                           &a, &b, NULL);
                    268: 
                    269:        send_dpds(a, b, data[_i].dpds_a);
                    270:        send_dpds(b, a, data[_i].dpds_b);
                    271: 
                    272:        exchange_test_helper->add_listener(exchange_test_helper, &mid.listener);
                    273:        send_mid_sync(b, data[_i].send, data[_i].recv);
                    274:        msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
                    275:        replay = message_create_from_packet(msg->get_packet(msg));
                    276:        replay->parse_header(replay);
                    277:        exchange_test_helper->process_message(exchange_test_helper, a, msg);
                    278:        exchange_test_helper->process_message(exchange_test_helper, b, NULL);
                    279:        charon->bus->remove_listener(charon->bus, &mid.listener);
                    280: 
                    281:        send_dpd(a, b);
                    282:        send_dpd(b, a);
                    283: 
                    284:        exchange_test_helper->process_message(exchange_test_helper, a, replay);
                    285:        ck_assert(!exchange_test_helper->sender->dequeue(exchange_test_helper->sender));
                    286: 
                    287:        call_ikesa(a, destroy);
                    288:        call_ikesa(b, destroy);
                    289:        chunk_free(&mid.init.nonce);
                    290:        chunk_free(&mid.resp.nonce);
                    291: }
                    292: END_TEST
                    293: 
                    294: /**
                    295:  * Make sure the notify is ignored if the extension is not enabled.
                    296:  */
                    297: START_TEST(test_disabled)
                    298: {
                    299:        ike_sa_t *a, *b;
                    300:        mid_sync_listener_t mid = {
                    301:                .listener = { .message = (void*)handle_mid, },
                    302:                .init = {
                    303:                        .send = data[_i].send,
                    304:                        .recv = data[_i].recv,
                    305:                },
                    306:        };
                    307: 
                    308:        exchange_test_helper->establish_sa(exchange_test_helper,
                    309:                                                                           &a, &b, NULL);
                    310: 
                    311:        send_dpds(a, b, data[_i].dpds_a);
                    312:        send_dpds(b, a, data[_i].dpds_b);
                    313: 
                    314:        exchange_test_helper->add_listener(exchange_test_helper, &mid.listener);
                    315:        send_mid_sync(b, data[_i].dpds_b, UINT_MAX);
                    316:        exchange_test_helper->process_message(exchange_test_helper, a, NULL);
                    317:        /* we don't expect a response and unchanged MIDs */
                    318:        ck_assert(!exchange_test_helper->sender->dequeue(exchange_test_helper->sender));
                    319:        ck_assert_int_eq(2 + data[_i].dpds_a, a->get_message_id(a, TRUE));
                    320:        ck_assert_int_eq(data[_i].dpds_b, a->get_message_id(a, FALSE));
                    321:        charon->bus->remove_listener(charon->bus, &mid.listener);
                    322: 
                    323:        send_dpd(a, b);
                    324:        send_dpd(b, a);
                    325: 
                    326:        call_ikesa(a, destroy);
                    327:        call_ikesa(b, destroy);
                    328:        chunk_free(&mid.init.nonce);
                    329:        chunk_free(&mid.resp.nonce);
                    330: }
                    331: END_TEST
                    332: 
                    333: static struct {
                    334:        int dpds_a, dpds_b;
                    335:        uint32_t send, recv;
                    336: } data_too_low[] = {
                    337:        { 0, 1, 0, 2 },
                    338:        { 1, 2, 0, 0 },
                    339:        { 1, 2, 1, 3 },
                    340: };
                    341: 
                    342: /**
                    343:  * The responder syncs message IDs with the initiator but uses too low sender
                    344:  * MIDs so the initiator ignores the notify.
                    345:  */
                    346: START_TEST(test_sender_too_low)
                    347: {
                    348:        ike_sa_t *a, *b;
                    349:        mid_sync_listener_t mid = {
                    350:                .listener = { .message = (void*)handle_mid, },
                    351:                .init = {
                    352:                        .send = data_too_low[_i].send,
                    353:                        .recv = data_too_low[_i].recv,
                    354:                },
                    355:        };
                    356: 
                    357:        add_notify_to_ike_auth();
                    358:        exchange_test_helper->establish_sa(exchange_test_helper,
                    359:                                                                           &a, &b, NULL);
                    360: 
                    361:        send_dpds(a, b, data_too_low[_i].dpds_a);
                    362:        send_dpds(b, a, data_too_low[_i].dpds_b);
                    363: 
                    364:        exchange_test_helper->add_listener(exchange_test_helper, &mid.listener);
                    365:        send_mid_sync(b, data_too_low[_i].dpds_b, UINT_MAX);
                    366:        exchange_test_helper->process_message(exchange_test_helper, a, NULL);
                    367:        /* we don't expect a response and unchanged MIDs */
                    368:        ck_assert(!exchange_test_helper->sender->dequeue(exchange_test_helper->sender));
                    369:        ck_assert_int_eq(2 + data_too_low[_i].dpds_a, a->get_message_id(a, TRUE));
                    370:        ck_assert_int_eq(data_too_low[_i].dpds_b, a->get_message_id(a, FALSE));
                    371:        charon->bus->remove_listener(charon->bus, &mid.listener);
                    372: 
                    373:        send_dpd(a, b);
                    374:        send_dpd(b, a);
                    375: 
                    376:        call_ikesa(a, destroy);
                    377:        call_ikesa(b, destroy);
                    378:        chunk_free(&mid.init.nonce);
                    379: }
                    380: END_TEST
                    381: 
                    382: static struct {
                    383:        int dpds_a, dpds_b;
                    384:        uint32_t send, recv;
                    385:        /* reversed so the table below is clearer */
                    386:        uint32_t recv_exp, send_exp;
                    387: } data_recv_update[] = {
                    388:        { 0, 0, 0, 0, 0, 2 },
                    389:        { 0, 0, 0, 1, 0, 2 },
                    390:        { 0, 0, 1, 1, 1, 2 },
                    391:        { 1, 0, 0, 1, 0, 3 },
                    392:        { 1, 0, 5, 2, 5, 3 },
                    393: };
                    394: 
                    395: /**
                    396:  * The responder syncs message IDs with the initiator but uses too low receiver
                    397:  * MID, which is updated by the initiator in the response.
                    398:  */
                    399: START_TEST(test_recv_update)
                    400: {
                    401:        ike_sa_t *a, *b;
                    402:        mid_sync_listener_t mid = {
                    403:                .listener = { .message = (void*)handle_mid, },
                    404:                .init = {
                    405:                        .send = data_recv_update[_i].send,
                    406:                        .recv = data_recv_update[_i].recv,
                    407:                },
                    408:        };
                    409: 
                    410:        add_notify_to_ike_auth();
                    411:        exchange_test_helper->establish_sa(exchange_test_helper,
                    412:                                                                           &a, &b, NULL);
                    413: 
                    414:        send_dpds(a, b, data_recv_update[_i].dpds_a);
                    415:        send_dpds(b, a, data_recv_update[_i].dpds_b);
                    416: 
                    417:        exchange_test_helper->add_listener(exchange_test_helper, &mid.listener);
                    418:        send_mid_sync(b, data_recv_update[_i].send, data_recv_update[_i].recv);
                    419:        exchange_test_helper->process_message(exchange_test_helper, a, NULL);
                    420:        ck_assert_chunk_eq(mid.init.nonce, mid.resp.nonce);
                    421:        ck_assert_int_eq(data_recv_update[_i].send_exp, mid.resp.send);
                    422:        ck_assert_int_eq(data_recv_update[_i].recv_exp, mid.resp.recv);
                    423:        ck_assert_int_eq(data_recv_update[_i].send_exp, a->get_message_id(a, TRUE));
                    424:        ck_assert_int_eq(data_recv_update[_i].recv_exp, a->get_message_id(a, FALSE));
                    425:        exchange_test_helper->process_message(exchange_test_helper, b, NULL);
                    426:        charon->bus->remove_listener(charon->bus, &mid.listener);
                    427:        /* fake the receipt of the notify */
                    428:        b->set_message_id(b, TRUE, data_recv_update[_i].recv_exp);
                    429:        b->set_message_id(b, FALSE, data_recv_update[_i].send_exp);
                    430: 
                    431:        send_dpd(a, b);
                    432:        send_dpd(b, a);
                    433: 
                    434:        call_ikesa(a, destroy);
                    435:        call_ikesa(b, destroy);
                    436:        chunk_free(&mid.init.nonce);
                    437:        chunk_free(&mid.resp.nonce);
                    438: }
                    439: END_TEST
                    440: 
                    441: static struct {
                    442:        int dpds_a, dpds_b;
                    443:        uint32_t send, recv;
                    444:        /* reversed so the table below is clearer */
                    445:        uint32_t recv_exp, send_exp;
                    446: } data_active[] = {
                    447:        { 0, 0, 0, 2, 0, 3 },
                    448:        { 0, 0, 1, 3, 1, 3 },
                    449:        { 1, 0, 0, 3, 0, 4 },
                    450:        { 1, 0, 5, 8, 5, 8 },
                    451:        { 0, 1, 1, 2, 1, 3 },
                    452:        { 0, 1, 2, 2, 2, 2 },
                    453:        { 1, 1, 1, 3, 1, 4 },
                    454:        { 1, 1, 2, 4, 2, 4 },
                    455: };
                    456: 
                    457: /**
                    458:  * The responder syncs message IDs with the initiator that waits for the
                    459:  * response for an active task.
                    460:  */
                    461: START_TEST(test_active)
                    462: {
                    463:        ike_sa_t *a, *b;
                    464:        mid_sync_listener_t mid = {
                    465:                .listener = { .message = (void*)handle_mid, },
                    466:                .init = {
                    467:                        .send = data_active[_i].send,
                    468:                        .recv = data_active[_i].recv,
                    469:                },
                    470:        };
                    471:        message_t *msg;
                    472: 
                    473:        add_notify_to_ike_auth();
                    474:        exchange_test_helper->establish_sa(exchange_test_helper,
                    475:                                                                           &a, &b, NULL);
                    476: 
                    477:        send_dpds(a, b, data_active[_i].dpds_a);
                    478:        send_dpds(b, a, data_active[_i].dpds_b);
                    479: 
                    480:        call_ikesa(a, send_dpd);
                    481:        msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
                    482:        msg->destroy(msg);
                    483: 
                    484:        exchange_test_helper->add_listener(exchange_test_helper, &mid.listener);
                    485:        send_mid_sync(b, data_active[_i].recv_exp, data_active[_i].send_exp);
                    486:        exchange_test_helper->process_message(exchange_test_helper, a, NULL);
                    487:        ck_assert_chunk_eq(mid.init.nonce, mid.resp.nonce);
                    488:        ck_assert_int_eq(data_active[_i].send_exp, mid.resp.send);
                    489:        ck_assert_int_eq(data_active[_i].recv_exp, mid.resp.recv);
                    490:        ck_assert_int_eq(data_active[_i].send_exp, a->get_message_id(a, TRUE));
                    491:        ck_assert_int_eq(data_active[_i].recv_exp, a->get_message_id(a, FALSE));
                    492:        exchange_test_helper->process_message(exchange_test_helper, b, NULL);
                    493:        charon->bus->remove_listener(charon->bus, &mid.listener);
                    494: 
                    495:        /* the active task was queued again */
                    496:        call_ikesa(a, initiate, NULL, 0, NULL, NULL);
                    497:        exchange_test_helper->process_message(exchange_test_helper, b, NULL);
                    498:        exchange_test_helper->process_message(exchange_test_helper, a, NULL);
                    499:        send_dpd(b, a);
                    500: 
                    501:        call_ikesa(a, destroy);
                    502:        call_ikesa(b, destroy);
                    503:        chunk_free(&mid.init.nonce);
                    504:        chunk_free(&mid.resp.nonce);
                    505: }
                    506: END_TEST
                    507: 
                    508: Suite *ike_mid_sync_suite_create()
                    509: {
                    510:        Suite *s;
                    511:        TCase *tc;
                    512: 
                    513:        s = suite_create("ike MID sync");
                    514: 
                    515:        tc = tcase_create("responder");
                    516:        tcase_add_loop_test(tc, test_responder, 0, countof(data));
                    517:        tcase_add_loop_test(tc, test_retransmit, 0, countof(data));
                    518:        tcase_add_loop_test(tc, test_replay, 0, countof(data));
                    519:        tcase_add_loop_test(tc, test_disabled, 0, countof(data));
                    520:        suite_add_tcase(s, tc);
                    521: 
                    522:        tc = tcase_create("sender MID too low");
                    523:        tcase_add_loop_test(tc, test_sender_too_low, 0, countof(data_too_low));
                    524:        suite_add_tcase(s, tc);
                    525: 
                    526:        tc = tcase_create("receiver MID updated");
                    527:        tcase_add_loop_test(tc, test_recv_update, 0, countof(data_recv_update));
                    528:        suite_add_tcase(s, tc);
                    529: 
                    530:        tc = tcase_create("active task");
                    531:        tcase_add_loop_test(tc, test_active, 0, countof(data_active));
                    532:        suite_add_tcase(s, tc);
                    533: 
                    534:        return s;
                    535: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>