Annotation of embedaddon/strongswan/src/libcharon/network/receiver.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2008-2012 Tobias Brunner
        !             3:  * Copyright (C) 2005-2006 Martin Willi
        !             4:  * Copyright (C) 2005 Jan Hutter
        !             5:  * HSR Hochschule fuer Technik Rapperswil
        !             6:  *
        !             7:  * This program is free software; you can redistribute it and/or modify it
        !             8:  * under the terms of the GNU General Public License as published by the
        !             9:  * Free Software Foundation; either version 2 of the License, or (at your
        !            10:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !            11:  *
        !            12:  * This program is distributed in the hope that it will be useful, but
        !            13:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            14:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            15:  * for more details.
        !            16:  */
        !            17: 
        !            18: #include <stdlib.h>
        !            19: #include <unistd.h>
        !            20: 
        !            21: #include "receiver.h"
        !            22: 
        !            23: #include <daemon.h>
        !            24: #include <network/socket.h>
        !            25: #include <processing/jobs/job.h>
        !            26: #include <processing/jobs/process_message_job.h>
        !            27: #include <processing/jobs/callback_job.h>
        !            28: #include <crypto/hashers/hasher.h>
        !            29: #include <threading/mutex.h>
        !            30: #include <networking/packet.h>
        !            31: 
        !            32: /** lifetime of a cookie, in seconds */
        !            33: #define COOKIE_LIFETIME 10
        !            34: /** time we wait before disabling cookies */
        !            35: #define COOKIE_CALMDOWN_DELAY 10
        !            36: /** how many times to reuse the secret */
        !            37: #define COOKIE_REUSE 10000
        !            38: /** default value for private_receiver_t.cookie_threshold */
        !            39: #define COOKIE_THRESHOLD_DEFAULT 10
        !            40: /** default value for private_receiver_t.block_threshold */
        !            41: #define BLOCK_THRESHOLD_DEFAULT 5
        !            42: /** length of the secret to use for cookie calculation */
        !            43: #define SECRET_LENGTH 16
        !            44: /** Length of a notify payload header */
        !            45: #define NOTIFY_PAYLOAD_HEADER_LENGTH 8
        !            46: 
        !            47: typedef struct private_receiver_t private_receiver_t;
        !            48: 
        !            49: /**
        !            50:  * Private data of a receiver_t object.
        !            51:  */
        !            52: struct private_receiver_t {
        !            53:        /**
        !            54:         * Public part of a receiver_t object.
        !            55:         */
        !            56:        receiver_t public;
        !            57: 
        !            58:        /**
        !            59:         * Registered callback for ESP packets
        !            60:         */
        !            61:        struct {
        !            62:                receiver_esp_cb_t cb;
        !            63:                void *data;
        !            64:        } esp_cb;
        !            65: 
        !            66:        /**
        !            67:         * Mutex for ESP callback
        !            68:         */
        !            69:        mutex_t *esp_cb_mutex;
        !            70: 
        !            71:        /**
        !            72:         * current secret to use for cookie calculation
        !            73:         */
        !            74:        char secret[SECRET_LENGTH];
        !            75: 
        !            76:        /**
        !            77:         * previous secret used to verify older cookies
        !            78:         */
        !            79:        char secret_old[SECRET_LENGTH];
        !            80: 
        !            81:        /**
        !            82:         * how many times we have used "secret" so far
        !            83:         */
        !            84:        uint32_t secret_used;
        !            85: 
        !            86:        /**
        !            87:         * time we did the cookie switch
        !            88:         */
        !            89:        uint32_t secret_switch;
        !            90: 
        !            91:        /**
        !            92:         * time offset to use, hides our system time
        !            93:         */
        !            94:        uint32_t secret_offset;
        !            95: 
        !            96:        /**
        !            97:         * the RNG to use for secret generation
        !            98:         */
        !            99:        rng_t *rng;
        !           100: 
        !           101:        /**
        !           102:         * hasher to use for cookie calculation
        !           103:         */
        !           104:        hasher_t *hasher;
        !           105: 
        !           106:        /**
        !           107:         * require cookies after this many half open IKE_SAs
        !           108:         */
        !           109:        uint32_t cookie_threshold;
        !           110: 
        !           111:        /**
        !           112:         * timestamp of last cookie requested
        !           113:         */
        !           114:        time_t last_cookie;
        !           115: 
        !           116:        /**
        !           117:         * how many half open IKE_SAs per peer before blocking
        !           118:         */
        !           119:        uint32_t block_threshold;
        !           120: 
        !           121:        /**
        !           122:         * Drop IKE_SA_INIT requests if processor job load exceeds this limit
        !           123:         */
        !           124:        u_int init_limit_job_load;
        !           125: 
        !           126:        /**
        !           127:         * Drop IKE_SA_INIT requests if half open IKE_SA count exceeds this limit
        !           128:         */
        !           129:        u_int init_limit_half_open;
        !           130: 
        !           131:        /**
        !           132:         * Delay for receiving incoming packets, to simulate larger RTT
        !           133:         */
        !           134:        int receive_delay;
        !           135: 
        !           136:        /**
        !           137:         * Specific message type to delay, 0 for any
        !           138:         */
        !           139:        int receive_delay_type;
        !           140: 
        !           141:        /**
        !           142:         * Delay request messages?
        !           143:         */
        !           144:        bool receive_delay_request;
        !           145: 
        !           146:        /**
        !           147:         * Delay response messages?
        !           148:         */
        !           149:        bool receive_delay_response;
        !           150: 
        !           151:        /**
        !           152:         * Endpoint is allowed to act as an initiator only
        !           153:         */
        !           154:        bool initiator_only;
        !           155: 
        !           156: };
        !           157: 
        !           158: /**
        !           159:  * send a notify back to the sender
        !           160:  */
        !           161: static void send_notify(message_t *request, int major, exchange_type_t exchange,
        !           162:                                                notify_type_t type, chunk_t data)
        !           163: {
        !           164:        ike_sa_id_t *ike_sa_id;
        !           165:        message_t *response;
        !           166:        host_t *src, *dst;
        !           167:        packet_t *packet;
        !           168: 
        !           169:        response = message_create(major, 0);
        !           170:        response->set_exchange_type(response, exchange);
        !           171:        response->add_notify(response, FALSE, type, data);
        !           172:        dst = request->get_source(request);
        !           173:        src = request->get_destination(request);
        !           174:        response->set_source(response, src->clone(src));
        !           175:        response->set_destination(response, dst->clone(dst));
        !           176:        if (major == IKEV2_MAJOR_VERSION)
        !           177:        {
        !           178:                response->set_request(response, FALSE);
        !           179:                response->set_message_id(response, request->get_message_id(request));
        !           180:        }
        !           181:        ike_sa_id = request->get_ike_sa_id(request);
        !           182:        ike_sa_id->switch_initiator(ike_sa_id);
        !           183:        response->set_ike_sa_id(response, ike_sa_id);
        !           184:        if (response->generate(response, NULL, &packet) == SUCCESS)
        !           185:        {
        !           186:                charon->sender->send(charon->sender, packet);
        !           187:        }
        !           188:        response->destroy(response);
        !           189: }
        !           190: 
        !           191: /**
        !           192:  * build a cookie
        !           193:  */
        !           194: static bool cookie_build(private_receiver_t *this, message_t *message,
        !           195:                                                 uint32_t t, chunk_t secret, chunk_t *cookie)
        !           196: {
        !           197:        uint64_t spi = message->get_initiator_spi(message);
        !           198:        host_t *ip = message->get_source(message);
        !           199:        chunk_t input, hash;
        !           200: 
        !           201:        /* COOKIE = t | sha1( IPi | SPIi | t | secret ) */
        !           202:        input = chunk_cata("cccc", ip->get_address(ip), chunk_from_thing(spi),
        !           203:                                          chunk_from_thing(t), secret);
        !           204:        hash = chunk_alloca(this->hasher->get_hash_size(this->hasher));
        !           205:        if (!this->hasher->get_hash(this->hasher, input, hash.ptr))
        !           206:        {
        !           207:                return FALSE;
        !           208:        }
        !           209:        *cookie = chunk_cat("cc", chunk_from_thing(t), hash);
        !           210:        return TRUE;
        !           211: }
        !           212: 
        !           213: /**
        !           214:  * verify a received cookie
        !           215:  */
        !           216: static bool cookie_verify(private_receiver_t *this, message_t *message,
        !           217:                                                  chunk_t cookie)
        !           218: {
        !           219:        uint32_t t, now;
        !           220:        chunk_t reference;
        !           221:        chunk_t secret;
        !           222: 
        !           223:        now = time_monotonic(NULL);
        !           224:        t = *(uint32_t*)cookie.ptr;
        !           225: 
        !           226:        if (cookie.len != sizeof(uint32_t) +
        !           227:                        this->hasher->get_hash_size(this->hasher) ||
        !           228:                t < now - this->secret_offset - COOKIE_LIFETIME)
        !           229:        {
        !           230:                DBG2(DBG_NET, "received cookie lifetime expired, rejecting");
        !           231:                return FALSE;
        !           232:        }
        !           233: 
        !           234:        /* check if cookie is derived from old_secret */
        !           235:        if (t + this->secret_offset > this->secret_switch)
        !           236:        {
        !           237:                secret = chunk_from_thing(this->secret);
        !           238:        }
        !           239:        else
        !           240:        {
        !           241:                secret = chunk_from_thing(this->secret_old);
        !           242:        }
        !           243: 
        !           244:        /* compare own calculation against received */
        !           245:        if (!cookie_build(this, message, t, secret, &reference))
        !           246:        {
        !           247:                return FALSE;
        !           248:        }
        !           249:        if (chunk_equals_const(reference, cookie))
        !           250:        {
        !           251:                chunk_free(&reference);
        !           252:                return TRUE;
        !           253:        }
        !           254:        chunk_free(&reference);
        !           255:        return FALSE;
        !           256: }
        !           257: 
        !           258: /**
        !           259:  * Check if a valid cookie found
        !           260:  */
        !           261: static bool check_cookie(private_receiver_t *this, message_t *message)
        !           262: {
        !           263:        chunk_t data;
        !           264: 
        !           265:        /* check for a cookie. We don't use our parser here and do it
        !           266:         * quick and dirty for performance reasons.
        !           267:         * we assume the cookie is the first payload (which is a MUST), and
        !           268:         * the cookie's SPI length is zero. */
        !           269:        data = message->get_packet_data(message);
        !           270:        if (data.len <
        !           271:                 IKE_HEADER_LENGTH + NOTIFY_PAYLOAD_HEADER_LENGTH +
        !           272:                 sizeof(uint32_t) + this->hasher->get_hash_size(this->hasher) ||
        !           273:                *(data.ptr + 16) != PLV2_NOTIFY ||
        !           274:                *(uint16_t*)(data.ptr + IKE_HEADER_LENGTH + 6) != htons(COOKIE))
        !           275:        {
        !           276:                /* no cookie found */
        !           277:                return FALSE;
        !           278:        }
        !           279:        data.ptr += IKE_HEADER_LENGTH + NOTIFY_PAYLOAD_HEADER_LENGTH;
        !           280:        data.len = sizeof(uint32_t) + this->hasher->get_hash_size(this->hasher);
        !           281:        if (!cookie_verify(this, message, data))
        !           282:        {
        !           283:                DBG2(DBG_NET, "found cookie, but content invalid");
        !           284:                return FALSE;
        !           285:        }
        !           286:        return TRUE;
        !           287: }
        !           288: 
        !           289: /**
        !           290:  * Check if we currently require cookies
        !           291:  */
        !           292: static bool cookie_required(private_receiver_t *this,
        !           293:                                                        u_int half_open, uint32_t now)
        !           294: {
        !           295:        if (this->cookie_threshold && half_open >= this->cookie_threshold)
        !           296:        {
        !           297:                this->last_cookie = now;
        !           298:                return TRUE;
        !           299:        }
        !           300:        if (this->last_cookie && now < this->last_cookie + COOKIE_CALMDOWN_DELAY)
        !           301:        {
        !           302:                /* We don't disable cookies unless we haven't seen IKE_SA_INITs
        !           303:                 * for COOKIE_CALMDOWN_DELAY seconds. This avoids jittering between
        !           304:                 * cookie on / cookie off states, which is problematic. Consider the
        !           305:                 * following: A legitimate initiator sends a IKE_SA_INIT while we
        !           306:                 * are under a DoS attack. If we toggle our cookie behavior,
        !           307:                 * multiple retransmits of this IKE_SA_INIT might get answered with
        !           308:                 * and without cookies. The initiator goes on and retries with
        !           309:                 * a cookie, but it can't know if the completing IKE_SA_INIT response
        !           310:                 * is to its IKE_SA_INIT request with or without cookies. This is
        !           311:                 * problematic, as the cookie is part of AUTH payload data.
        !           312:                 */
        !           313:                this->last_cookie = now;
        !           314:                return TRUE;
        !           315:        }
        !           316:        return FALSE;
        !           317: }
        !           318: 
        !           319: /**
        !           320:  * Check if we should drop IKE_SA_INIT because of cookie/overload checking
        !           321:  */
        !           322: static bool drop_ike_sa_init(private_receiver_t *this, message_t *message)
        !           323: {
        !           324:        u_int half_open;
        !           325:        uint32_t now;
        !           326: 
        !           327:        now = time_monotonic(NULL);
        !           328:        half_open = charon->ike_sa_manager->get_half_open_count(
        !           329:                                                                                charon->ike_sa_manager, NULL, TRUE);
        !           330: 
        !           331:        /* check for cookies in IKEv2 */
        !           332:        if (message->get_major_version(message) == IKEV2_MAJOR_VERSION &&
        !           333:                cookie_required(this, half_open, now) && !check_cookie(this, message))
        !           334:        {
        !           335:                chunk_t cookie;
        !           336: 
        !           337:                DBG2(DBG_NET, "received packet from: %#H to %#H",
        !           338:                         message->get_source(message),
        !           339:                         message->get_destination(message));
        !           340:                if (!cookie_build(this, message, now - this->secret_offset,
        !           341:                                                  chunk_from_thing(this->secret), &cookie))
        !           342:                {
        !           343:                        return TRUE;
        !           344:                }
        !           345:                DBG2(DBG_NET, "sending COOKIE notify to %H",
        !           346:                         message->get_source(message));
        !           347:                send_notify(message, IKEV2_MAJOR_VERSION, IKE_SA_INIT, COOKIE, cookie);
        !           348:                chunk_free(&cookie);
        !           349:                if (++this->secret_used > COOKIE_REUSE)
        !           350:                {
        !           351:                        char secret[SECRET_LENGTH];
        !           352: 
        !           353:                        DBG1(DBG_NET, "generating new cookie secret after %d uses",
        !           354:                                 this->secret_used);
        !           355:                        if (this->rng->get_bytes(this->rng, SECRET_LENGTH, secret))
        !           356:                        {
        !           357:                                memcpy(this->secret_old, this->secret, SECRET_LENGTH);
        !           358:                                memcpy(this->secret, secret, SECRET_LENGTH);
        !           359:                                memwipe(secret, SECRET_LENGTH);
        !           360:                                this->secret_switch = now;
        !           361:                                this->secret_used = 0;
        !           362:                        }
        !           363:                        else
        !           364:                        {
        !           365:                                DBG1(DBG_NET, "failed to allocated cookie secret, keeping old");
        !           366:                        }
        !           367:                }
        !           368:                return TRUE;
        !           369:        }
        !           370: 
        !           371:        /* check if peer has too many IKE_SAs half open */
        !           372:        if (this->block_threshold &&
        !           373:                charon->ike_sa_manager->get_half_open_count(charon->ike_sa_manager,
        !           374:                                message->get_source(message), TRUE) >= this->block_threshold)
        !           375:        {
        !           376:                DBG1(DBG_NET, "ignoring IKE_SA setup from %H, "
        !           377:                         "peer too aggressive", message->get_source(message));
        !           378:                return TRUE;
        !           379:        }
        !           380: 
        !           381:        /* check if global half open IKE_SA limit reached */
        !           382:        if (this->init_limit_half_open &&
        !           383:            half_open >= this->init_limit_half_open)
        !           384:        {
        !           385:                DBG1(DBG_NET, "ignoring IKE_SA setup from %H, half open IKE_SA "
        !           386:                         "count of %d exceeds limit of %d", message->get_source(message),
        !           387:                         half_open, this->init_limit_half_open);
        !           388:                return TRUE;
        !           389:        }
        !           390: 
        !           391:        /* check if job load acceptable */
        !           392:        if (this->init_limit_job_load)
        !           393:        {
        !           394:                u_int jobs = 0, i;
        !           395: 
        !           396:                for (i = 0; i < JOB_PRIO_MAX; i++)
        !           397:                {
        !           398:                        jobs += lib->processor->get_job_load(lib->processor, i);
        !           399:                }
        !           400:                if (jobs > this->init_limit_job_load)
        !           401:                {
        !           402:                        DBG1(DBG_NET, "ignoring IKE_SA setup from %H, job load of %d "
        !           403:                                 "exceeds limit of %d", message->get_source(message),
        !           404:                                 jobs, this->init_limit_job_load);
        !           405:                        return TRUE;
        !           406:                }
        !           407:        }
        !           408:        return FALSE;
        !           409: }
        !           410: 
        !           411: /**
        !           412:  * Job callback to receive packets
        !           413:  */
        !           414: static job_requeue_t receive_packets(private_receiver_t *this)
        !           415: {
        !           416:        ike_sa_id_t *id;
        !           417:        packet_t *packet;
        !           418:        message_t *message;
        !           419:        host_t *src, *dst;
        !           420:        status_t status;
        !           421:        bool supported = TRUE;
        !           422:        chunk_t data, marker = chunk_from_chars(0x00, 0x00, 0x00, 0x00);
        !           423: 
        !           424:        /* read in a packet */
        !           425:        status = charon->socket->receive(charon->socket, &packet);
        !           426:        if (status == NOT_SUPPORTED)
        !           427:        {
        !           428:                return JOB_REQUEUE_NONE;
        !           429:        }
        !           430:        else if (status != SUCCESS)
        !           431:        {
        !           432:                DBG2(DBG_NET, "receiving from socket failed!");
        !           433:                return JOB_REQUEUE_FAIR;
        !           434:        }
        !           435: 
        !           436:        data = packet->get_data(packet);
        !           437:        if (data.len == 1 && data.ptr[0] == 0xFF)
        !           438:        {       /* silently drop NAT-T keepalives */
        !           439:                packet->destroy(packet);
        !           440:                return JOB_REQUEUE_DIRECT;
        !           441:        }
        !           442:        else if (data.len < marker.len)
        !           443:        {       /* drop packets that are too small */
        !           444:                DBG3(DBG_NET, "received packet is too short (%d bytes)", data.len);
        !           445:                packet->destroy(packet);
        !           446:                return JOB_REQUEUE_DIRECT;
        !           447:        }
        !           448: 
        !           449:        dst = packet->get_destination(packet);
        !           450:        src = packet->get_source(packet);
        !           451:        if (!charon->kernel->all_interfaces_usable(charon->kernel)
        !           452:                && !charon->kernel->get_interface(charon->kernel, dst, NULL))
        !           453:        {
        !           454:                DBG3(DBG_NET, "received packet from %#H to %#H on ignored interface",
        !           455:                         src, dst);
        !           456:                packet->destroy(packet);
        !           457:                return JOB_REQUEUE_DIRECT;
        !           458:        }
        !           459: 
        !           460:        /* if neither source nor destination port is 500 we assume an IKE packet
        !           461:         * with Non-ESP marker or an ESP packet */
        !           462:        if (dst->get_port(dst) != IKEV2_UDP_PORT &&
        !           463:                src->get_port(src) != IKEV2_UDP_PORT)
        !           464:        {
        !           465:                if (memeq(data.ptr, marker.ptr, marker.len))
        !           466:                {       /* remove Non-ESP marker */
        !           467:                        packet->skip_bytes(packet, marker.len);
        !           468:                }
        !           469:                else
        !           470:                {       /* this seems to be an ESP packet */
        !           471:                        this->esp_cb_mutex->lock(this->esp_cb_mutex);
        !           472:                        if (this->esp_cb.cb)
        !           473:                        {
        !           474:                                this->esp_cb.cb(this->esp_cb.data, packet);
        !           475:                        }
        !           476:                        else
        !           477:                        {
        !           478:                                packet->destroy(packet);
        !           479:                        }
        !           480:                        this->esp_cb_mutex->unlock(this->esp_cb_mutex);
        !           481:                        return JOB_REQUEUE_DIRECT;
        !           482:                }
        !           483:        }
        !           484: 
        !           485:        /* parse message header */
        !           486:        message = message_create_from_packet(packet);
        !           487:        if (message->parse_header(message) != SUCCESS)
        !           488:        {
        !           489:                DBG1(DBG_NET, "received invalid IKE header from %H - ignored",
        !           490:                         packet->get_source(packet));
        !           491:                charon->bus->alert(charon->bus, ALERT_PARSE_ERROR_HEADER, message);
        !           492:                message->destroy(message);
        !           493:                return JOB_REQUEUE_DIRECT;
        !           494:        }
        !           495: 
        !           496:        /* check IKE major version */
        !           497:        switch (message->get_major_version(message))
        !           498:        {
        !           499:                case IKEV2_MAJOR_VERSION:
        !           500: #ifndef USE_IKEV2
        !           501:                        if (message->get_exchange_type(message) == IKE_SA_INIT &&
        !           502:                                message->get_request(message))
        !           503:                        {
        !           504:                                send_notify(message, IKEV1_MAJOR_VERSION, INFORMATIONAL_V1,
        !           505:                                                        INVALID_MAJOR_VERSION, chunk_empty);
        !           506:                                supported = FALSE;
        !           507:                        }
        !           508: #endif /* USE_IKEV2 */
        !           509:                        break;
        !           510:                case IKEV1_MAJOR_VERSION:
        !           511: #ifndef USE_IKEV1
        !           512:                        if (message->get_exchange_type(message) == ID_PROT ||
        !           513:                                message->get_exchange_type(message) == AGGRESSIVE)
        !           514:                        {
        !           515:                                send_notify(message, IKEV2_MAJOR_VERSION, INFORMATIONAL,
        !           516:                                                        INVALID_MAJOR_VERSION, chunk_empty);
        !           517:                                supported = FALSE;
        !           518:                        }
        !           519: #endif /* USE_IKEV1 */
        !           520:                        break;
        !           521:                default:
        !           522: #ifdef USE_IKEV2
        !           523:                        send_notify(message, IKEV2_MAJOR_VERSION,
        !           524:                                                message->get_exchange_type(message),
        !           525:                                                INVALID_MAJOR_VERSION, chunk_empty);
        !           526: #elif defined(USE_IKEV1)
        !           527:                        send_notify(message, IKEV1_MAJOR_VERSION, INFORMATIONAL_V1,
        !           528:                                                INVALID_MAJOR_VERSION, chunk_empty);
        !           529: #endif /* USE_IKEV1 */
        !           530:                        supported = FALSE;
        !           531:                        break;
        !           532:        }
        !           533:        if (!supported)
        !           534:        {
        !           535:                DBG1(DBG_NET, "received unsupported IKE version %d.%d from %H, sending "
        !           536:                         "INVALID_MAJOR_VERSION", message->get_major_version(message),
        !           537:                         message->get_minor_version(message), packet->get_source(packet));
        !           538:                message->destroy(message);
        !           539:                return JOB_REQUEUE_DIRECT;
        !           540:        }
        !           541:        if (message->get_request(message) &&
        !           542:                message->get_exchange_type(message) == IKE_SA_INIT)
        !           543:        {
        !           544:                id = message->get_ike_sa_id(message);
        !           545:                if (this->initiator_only || !id->is_initiator(id) ||
        !           546:                        drop_ike_sa_init(this, message))
        !           547:                {
        !           548:                        message->destroy(message);
        !           549:                        return JOB_REQUEUE_DIRECT;
        !           550:                }
        !           551:        }
        !           552:        if (message->get_exchange_type(message) == ID_PROT ||
        !           553:                message->get_exchange_type(message) == AGGRESSIVE)
        !           554:        {
        !           555:                id = message->get_ike_sa_id(message);
        !           556:                if (id->get_responder_spi(id) == 0 &&
        !           557:                   (this->initiator_only || drop_ike_sa_init(this, message)))
        !           558:                {
        !           559:                        message->destroy(message);
        !           560:                        return JOB_REQUEUE_DIRECT;
        !           561:                }
        !           562:        }
        !           563: 
        !           564:        if (this->receive_delay)
        !           565:        {
        !           566:                if (this->receive_delay_type == 0 ||
        !           567:                        this->receive_delay_type == message->get_exchange_type(message))
        !           568:                {
        !           569:                        if ((message->get_request(message) && this->receive_delay_request) ||
        !           570:                                (!message->get_request(message) && this->receive_delay_response))
        !           571:                        {
        !           572:                                DBG1(DBG_NET, "using receive delay: %dms",
        !           573:                                         this->receive_delay);
        !           574:                                lib->scheduler->schedule_job_ms(lib->scheduler,
        !           575:                                                                (job_t*)process_message_job_create(message),
        !           576:                                                                this->receive_delay);
        !           577:                                return JOB_REQUEUE_DIRECT;
        !           578:                        }
        !           579:                }
        !           580:        }
        !           581:        lib->processor->queue_job(lib->processor,
        !           582:                                                          (job_t*)process_message_job_create(message));
        !           583:        return JOB_REQUEUE_DIRECT;
        !           584: }
        !           585: 
        !           586: METHOD(receiver_t, add_esp_cb, void,
        !           587:        private_receiver_t *this, receiver_esp_cb_t callback, void *data)
        !           588: {
        !           589:        this->esp_cb_mutex->lock(this->esp_cb_mutex);
        !           590:        this->esp_cb.cb = callback;
        !           591:        this->esp_cb.data = data;
        !           592:        this->esp_cb_mutex->unlock(this->esp_cb_mutex);
        !           593: }
        !           594: 
        !           595: METHOD(receiver_t, del_esp_cb, void,
        !           596:        private_receiver_t *this, receiver_esp_cb_t callback)
        !           597: {
        !           598:        this->esp_cb_mutex->lock(this->esp_cb_mutex);
        !           599:        if (this->esp_cb.cb == callback)
        !           600:        {
        !           601:                this->esp_cb.cb = NULL;
        !           602:                this->esp_cb.data = NULL;
        !           603:        }
        !           604:        this->esp_cb_mutex->unlock(this->esp_cb_mutex);
        !           605: }
        !           606: 
        !           607: METHOD(receiver_t, destroy, void,
        !           608:        private_receiver_t *this)
        !           609: {
        !           610:        this->rng->destroy(this->rng);
        !           611:        this->hasher->destroy(this->hasher);
        !           612:        this->esp_cb_mutex->destroy(this->esp_cb_mutex);
        !           613:        free(this);
        !           614: }
        !           615: 
        !           616: /*
        !           617:  * Described in header.
        !           618:  */
        !           619: receiver_t *receiver_create()
        !           620: {
        !           621:        private_receiver_t *this;
        !           622:        uint32_t now = time_monotonic(NULL);
        !           623: 
        !           624:        INIT(this,
        !           625:                .public = {
        !           626:                        .add_esp_cb = _add_esp_cb,
        !           627:                        .del_esp_cb = _del_esp_cb,
        !           628:                        .destroy = _destroy,
        !           629:                },
        !           630:                .esp_cb_mutex = mutex_create(MUTEX_TYPE_DEFAULT),
        !           631:                .secret_switch = now,
        !           632:                .secret_offset = random() % now,
        !           633:        );
        !           634: 
        !           635:        if (lib->settings->get_bool(lib->settings,
        !           636:                                                                "%s.dos_protection", TRUE, lib->ns))
        !           637:        {
        !           638:                this->cookie_threshold = lib->settings->get_int(lib->settings,
        !           639:                                        "%s.cookie_threshold", COOKIE_THRESHOLD_DEFAULT, lib->ns);
        !           640:                this->block_threshold = lib->settings->get_int(lib->settings,
        !           641:                                        "%s.block_threshold", BLOCK_THRESHOLD_DEFAULT, lib->ns);
        !           642:        }
        !           643:        this->init_limit_job_load = lib->settings->get_int(lib->settings,
        !           644:                                        "%s.init_limit_job_load", 0, lib->ns);
        !           645:        this->init_limit_half_open = lib->settings->get_int(lib->settings,
        !           646:                                        "%s.init_limit_half_open", 0, lib->ns);
        !           647:        this->receive_delay = lib->settings->get_int(lib->settings,
        !           648:                                        "%s.receive_delay", 0, lib->ns);
        !           649:        this->receive_delay_type = lib->settings->get_int(lib->settings,
        !           650:                                        "%s.receive_delay_type", 0, lib->ns);
        !           651:        this->receive_delay_request = lib->settings->get_bool(lib->settings,
        !           652:                                        "%s.receive_delay_request", TRUE, lib->ns);
        !           653:        this->receive_delay_response = lib->settings->get_bool(lib->settings,
        !           654:                                        "%s.receive_delay_response", TRUE, lib->ns);
        !           655:        this->initiator_only = lib->settings->get_bool(lib->settings,
        !           656:                                        "%s.initiator_only", FALSE, lib->ns);
        !           657: 
        !           658:        this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
        !           659:        if (!this->hasher)
        !           660:        {
        !           661:                DBG1(DBG_NET, "creating cookie hasher failed, no hashers supported");
        !           662:                free(this);
        !           663:                return NULL;
        !           664:        }
        !           665:        this->rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
        !           666:        if (!this->rng)
        !           667:        {
        !           668:                DBG1(DBG_NET, "creating cookie RNG failed, no RNG supported");
        !           669:                this->hasher->destroy(this->hasher);
        !           670:                free(this);
        !           671:                return NULL;
        !           672:        }
        !           673:        if (!this->rng->get_bytes(this->rng, SECRET_LENGTH, this->secret))
        !           674:        {
        !           675:                DBG1(DBG_NET, "creating cookie secret failed");
        !           676:                destroy(this);
        !           677:                return NULL;
        !           678:        }
        !           679:        memcpy(this->secret_old, this->secret, SECRET_LENGTH);
        !           680: 
        !           681:        lib->processor->queue_job(lib->processor,
        !           682:                (job_t*)callback_job_create_with_prio((callback_job_cb_t)receive_packets,
        !           683:                        this, NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
        !           684: 
        !           685:        return &this->public;
        !           686: }

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