~yolanda.robla/ubuntu/trusty/memcached/add_distribution

« back to all changes in this revision

Viewing changes to memcached.c

  • Committer: Bazaar Package Importer
  • Author(s): David Martínez Moreno
  • Date: 2010-05-12 11:41:22 UTC
  • mfrom: (1.1.7 upstream) (3.3.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100512114122-e2dphwiezevuny1t
Tags: 1.4.5-1
* New upstream release.  Main changes since 1.4.2 are:
  New features:
  - Support for SASL authentication.
  - New script damemtop - a memcached top.
  - Slab optimizations.
  - New stats, for reclaimed memory and SASL events.
  Bugs fixed:
  - Malicious input can crash server (CVE-2010-1152).  Closes: #579913.
  - Fixed several problems with slab handling and growth.
  - Provide better error reporting.
  - Fix get stats accounting.
  - Fixed backwards compatibility with delete 0.
  - Documentation fixes.
  - Various build fixes, among others, fixed FTBFS with gcc-4.5 (closes:
    #565033).
* Refreshed and renamed 01_init_script_compliant_with_LSB.patch.
* Fixed lintian warnings by adding $remote_fs to init.d script.
* Removed non-existent document (doc/memory_management.txt).
* debian/control: Bumped Standards-Version to 3.8.4 (no changes).

Show diffs side-by-side

added added

removed removed

Lines of Context:
94
94
static int add_iov(conn *c, const void *buf, int len);
95
95
static int add_msghdr(conn *c);
96
96
 
 
97
 
97
98
/* time handling */
98
99
static void set_current_time(void);  /* update the global variable holding
99
100
                              global 32-bit seconds-since-start time
148
149
 
149
150
static void stats_init(void) {
150
151
    stats.curr_items = stats.total_items = stats.curr_conns = stats.total_conns = stats.conn_structs = 0;
151
 
    stats.get_cmds = stats.set_cmds = stats.get_hits = stats.get_misses = stats.evictions = 0;
 
152
    stats.get_cmds = stats.set_cmds = stats.get_hits = stats.get_misses = stats.evictions = stats.reclaimed = 0;
152
153
    stats.curr_bytes = stats.listen_disabled_num = 0;
153
154
    stats.accepting_conns = true; /* assuming we start in this state. */
154
155
 
164
165
    STATS_LOCK();
165
166
    stats.total_items = stats.total_conns = 0;
166
167
    stats.evictions = 0;
 
168
    stats.reclaimed = 0;
167
169
    stats.listen_disabled_num = 0;
168
170
    stats_prefix_clear();
169
171
    STATS_UNLOCK();
463
465
        free(c->write_and_free);
464
466
        c->write_and_free = 0;
465
467
    }
 
468
 
 
469
    if (c->sasl_conn) {
 
470
        assert(settings.sasl);
 
471
        sasl_dispose(&c->sasl_conn);
 
472
        c->sasl_conn = NULL;
 
473
    }
466
474
}
467
475
 
468
476
/*
937
945
    case PROTOCOL_BINARY_RESPONSE_NOT_STORED:
938
946
        errstr = "Not stored.";
939
947
        break;
 
948
    case PROTOCOL_BINARY_RESPONSE_AUTH_ERROR:
 
949
        errstr = "Auth failure.";
 
950
        break;
940
951
    default:
941
952
        assert(false);
942
953
        errstr = "UNHANDLED ERROR";
1454
1465
    c->write_and_go = conn_closing;
1455
1466
}
1456
1467
 
 
1468
static void init_sasl_conn(conn *c) {
 
1469
    assert(c);
 
1470
    /* should something else be returned? */
 
1471
    if (!settings.sasl)
 
1472
        return;
 
1473
 
 
1474
    if (!c->sasl_conn) {
 
1475
        int result=sasl_server_new("memcached",
 
1476
                                   NULL, NULL, NULL, NULL,
 
1477
                                   NULL, 0, &c->sasl_conn);
 
1478
        if (result != SASL_OK) {
 
1479
            if (settings.verbose) {
 
1480
                fprintf(stderr, "Failed to initialize SASL conn.\n");
 
1481
            }
 
1482
            c->sasl_conn = NULL;
 
1483
        }
 
1484
    }
 
1485
}
 
1486
 
 
1487
static void bin_list_sasl_mechs(conn *c) {
 
1488
    // Guard against a disabled SASL.
 
1489
    if (!settings.sasl) {
 
1490
        write_bin_error(c, PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND,
 
1491
                        c->binary_header.request.bodylen
 
1492
                        - c->binary_header.request.keylen);
 
1493
        return;
 
1494
    }
 
1495
 
 
1496
    init_sasl_conn(c);
 
1497
    const char *result_string = NULL;
 
1498
    unsigned int string_length = 0;
 
1499
    int result=sasl_listmech(c->sasl_conn, NULL,
 
1500
                             "",   /* What to prepend the string with */
 
1501
                             " ",  /* What to separate mechanisms with */
 
1502
                             "",   /* What to append to the string */
 
1503
                             &result_string, &string_length,
 
1504
                             NULL);
 
1505
    if (result != SASL_OK) {
 
1506
        /* Perhaps there's a better error for this... */
 
1507
        if (settings.verbose) {
 
1508
            fprintf(stderr, "Failed to list SASL mechanisms.\n");
 
1509
        }
 
1510
        write_bin_error(c, PROTOCOL_BINARY_RESPONSE_AUTH_ERROR, 0);
 
1511
        return;
 
1512
    }
 
1513
    write_bin_response(c, (char*)result_string, 0, 0, string_length);
 
1514
}
 
1515
 
 
1516
static void process_bin_sasl_auth(conn *c) {
 
1517
    // Guard for handling disabled SASL on the server.
 
1518
    if (!settings.sasl) {
 
1519
        write_bin_error(c, PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND,
 
1520
                        c->binary_header.request.bodylen
 
1521
                        - c->binary_header.request.keylen);
 
1522
        return;
 
1523
    }
 
1524
 
 
1525
    assert(c->binary_header.request.extlen == 0);
 
1526
 
 
1527
    int nkey = c->binary_header.request.keylen;
 
1528
    int vlen = c->binary_header.request.bodylen - nkey;
 
1529
 
 
1530
    if (nkey > MAX_SASL_MECH_LEN) {
 
1531
        write_bin_error(c, PROTOCOL_BINARY_RESPONSE_EINVAL, vlen);
 
1532
        c->write_and_go = conn_swallow;
 
1533
        return;
 
1534
    }
 
1535
 
 
1536
    char *key = binary_get_key(c);
 
1537
    assert(key);
 
1538
 
 
1539
    item *it = item_alloc(key, nkey, 0, 0, vlen);
 
1540
 
 
1541
    if (it == 0) {
 
1542
        write_bin_error(c, PROTOCOL_BINARY_RESPONSE_ENOMEM, vlen);
 
1543
        c->write_and_go = conn_swallow;
 
1544
        return;
 
1545
    }
 
1546
 
 
1547
    c->item = it;
 
1548
    c->ritem = ITEM_data(it);
 
1549
    c->rlbytes = vlen;
 
1550
    conn_set_state(c, conn_nread);
 
1551
    c->substate = bin_reading_sasl_auth_data;
 
1552
}
 
1553
 
 
1554
static void process_bin_complete_sasl_auth(conn *c) {
 
1555
    assert(settings.sasl);
 
1556
    const char *out = NULL;
 
1557
    unsigned int outlen = 0;
 
1558
 
 
1559
    assert(c->item);
 
1560
    init_sasl_conn(c);
 
1561
 
 
1562
    int nkey = c->binary_header.request.keylen;
 
1563
    int vlen = c->binary_header.request.bodylen - nkey;
 
1564
 
 
1565
    char mech[nkey+1];
 
1566
    memcpy(mech, ITEM_key((item*)c->item), nkey);
 
1567
    mech[nkey] = 0x00;
 
1568
 
 
1569
    if (settings.verbose)
 
1570
        fprintf(stderr, "mech:  ``%s'' with %d bytes of data\n", mech, vlen);
 
1571
 
 
1572
    const char *challenge = vlen == 0 ? NULL : ITEM_data((item*) c->item);
 
1573
 
 
1574
    int result=-1;
 
1575
 
 
1576
    switch (c->cmd) {
 
1577
    case PROTOCOL_BINARY_CMD_SASL_AUTH:
 
1578
        result = sasl_server_start(c->sasl_conn, mech,
 
1579
                                   challenge, vlen,
 
1580
                                   &out, &outlen);
 
1581
        break;
 
1582
    case PROTOCOL_BINARY_CMD_SASL_STEP:
 
1583
        result = sasl_server_step(c->sasl_conn,
 
1584
                                  challenge, vlen,
 
1585
                                  &out, &outlen);
 
1586
        break;
 
1587
    default:
 
1588
        assert(false); /* CMD should be one of the above */
 
1589
        /* This code is pretty much impossible, but makes the compiler
 
1590
           happier */
 
1591
        if (settings.verbose) {
 
1592
            fprintf(stderr, "Unhandled command %d with challenge %s\n",
 
1593
                    c->cmd, challenge);
 
1594
        }
 
1595
        break;
 
1596
    }
 
1597
 
 
1598
    item_unlink(c->item);
 
1599
 
 
1600
    if (settings.verbose) {
 
1601
        fprintf(stderr, "sasl result code:  %d\n", result);
 
1602
    }
 
1603
 
 
1604
    switch(result) {
 
1605
    case SASL_OK:
 
1606
        write_bin_response(c, "Authenticated", 0, 0, strlen("Authenticated"));
 
1607
        pthread_mutex_lock(&c->thread->stats.mutex);
 
1608
        c->thread->stats.auth_cmds++;
 
1609
        pthread_mutex_unlock(&c->thread->stats.mutex);
 
1610
        break;
 
1611
    case SASL_CONTINUE:
 
1612
        add_bin_header(c, PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE, 0, 0, outlen);
 
1613
        if(outlen > 0) {
 
1614
            add_iov(c, out, outlen);
 
1615
        }
 
1616
        conn_set_state(c, conn_mwrite);
 
1617
        c->write_and_go = conn_new_cmd;
 
1618
        break;
 
1619
    default:
 
1620
        if (settings.verbose)
 
1621
            fprintf(stderr, "Unknown sasl response:  %d\n", result);
 
1622
        write_bin_error(c, PROTOCOL_BINARY_RESPONSE_AUTH_ERROR, 0);
 
1623
        pthread_mutex_lock(&c->thread->stats.mutex);
 
1624
        c->thread->stats.auth_cmds++;
 
1625
        c->thread->stats.auth_errors++;
 
1626
        pthread_mutex_unlock(&c->thread->stats.mutex);
 
1627
    }
 
1628
}
 
1629
 
 
1630
static bool authenticated(conn *c) {
 
1631
    assert(settings.sasl);
 
1632
    bool rv = false;
 
1633
 
 
1634
    switch (c->cmd) {
 
1635
    case PROTOCOL_BINARY_CMD_SASL_LIST_MECHS: /* FALLTHROUGH */
 
1636
    case PROTOCOL_BINARY_CMD_SASL_AUTH:       /* FALLTHROUGH */
 
1637
    case PROTOCOL_BINARY_CMD_SASL_STEP:       /* FALLTHROUGH */
 
1638
    case PROTOCOL_BINARY_CMD_VERSION:         /* FALLTHROUGH */
 
1639
        rv = true;
 
1640
        break;
 
1641
    default:
 
1642
        if (c->sasl_conn) {
 
1643
            const void *uname = NULL;
 
1644
            sasl_getprop(c->sasl_conn, SASL_USERNAME, &uname);
 
1645
            rv = uname != NULL;
 
1646
        }
 
1647
    }
 
1648
 
 
1649
    if (settings.verbose > 1) {
 
1650
        fprintf(stderr, "authenticated() in cmd 0x%02x is %s\n",
 
1651
                c->cmd, rv ? "true" : "false");
 
1652
    }
 
1653
 
 
1654
    return rv;
 
1655
}
 
1656
 
1457
1657
static void dispatch_bin_command(conn *c) {
1458
1658
    int protocol_error = 0;
1459
1659
 
1461
1661
    int keylen = c->binary_header.request.keylen;
1462
1662
    uint32_t bodylen = c->binary_header.request.bodylen;
1463
1663
 
 
1664
    if (settings.sasl && !authenticated(c)) {
 
1665
        write_bin_error(c, PROTOCOL_BINARY_RESPONSE_AUTH_ERROR, 0);
 
1666
        c->write_and_go = conn_closing;
 
1667
        return;
 
1668
    }
 
1669
 
1464
1670
    MEMCACHED_PROCESS_COMMAND_START(c->sfd, c->rcurr, c->rbytes);
1465
1671
    c->noreply = true;
1466
1672
 
1593
1799
                protocol_error = 1;
1594
1800
            }
1595
1801
            break;
 
1802
        case PROTOCOL_BINARY_CMD_SASL_LIST_MECHS:
 
1803
            if (extlen == 0 && keylen == 0 && bodylen == 0) {
 
1804
                bin_list_sasl_mechs(c);
 
1805
            } else {
 
1806
                protocol_error = 1;
 
1807
            }
 
1808
            break;
 
1809
        case PROTOCOL_BINARY_CMD_SASL_AUTH:
 
1810
        case PROTOCOL_BINARY_CMD_SASL_STEP:
 
1811
            if (extlen == 0 && keylen != 0) {
 
1812
                bin_read_key(c, bin_reading_sasl_auth, 0);
 
1813
            } else {
 
1814
                protocol_error = 1;
 
1815
            }
 
1816
            break;
1596
1817
        default:
1597
1818
            write_bin_error(c, PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND, bodylen);
1598
1819
    }
1834
2055
    case bin_read_flush_exptime:
1835
2056
        process_bin_flush(c);
1836
2057
        break;
 
2058
    case bin_reading_sasl_auth:
 
2059
        process_bin_sasl_auth(c);
 
2060
        break;
 
2061
    case bin_reading_sasl_auth_data:
 
2062
        process_bin_complete_sasl_auth(c);
 
2063
        break;
1837
2064
    default:
1838
2065
        fprintf(stderr, "Not handling substate %d\n", c->substate);
1839
2066
        assert(0);
2069
2296
    }
2070
2297
}
2071
2298
 
2072
 
static inline void set_noreply_maybe(conn *c, token_t *tokens, size_t ntokens)
 
2299
static inline bool set_noreply_maybe(conn *c, token_t *tokens, size_t ntokens)
2073
2300
{
2074
2301
    int noreply_index = ntokens - 2;
2075
2302
 
2084
2311
        && strcmp(tokens[noreply_index].value, "noreply") == 0) {
2085
2312
        c->noreply = true;
2086
2313
    }
 
2314
    return c->noreply;
2087
2315
}
2088
2316
 
2089
2317
void append_stat(const char *name, ADD_STAT add_stats, conn *c,
2174
2402
    APPEND_STAT("cas_misses", "%llu", (unsigned long long)thread_stats.cas_misses);
2175
2403
    APPEND_STAT("cas_hits", "%llu", (unsigned long long)slab_stats.cas_hits);
2176
2404
    APPEND_STAT("cas_badval", "%llu", (unsigned long long)slab_stats.cas_badval);
 
2405
    APPEND_STAT("auth_cmds", "%llu", (unsigned long long)thread_stats.auth_cmds);
 
2406
    APPEND_STAT("auth_errors", "%llu", (unsigned long long)thread_stats.auth_errors);
2177
2407
    APPEND_STAT("bytes_read", "%llu", (unsigned long long)thread_stats.bytes_read);
2178
2408
    APPEND_STAT("bytes_written", "%llu", (unsigned long long)thread_stats.bytes_written);
2179
2409
    APPEND_STAT("limit_maxbytes", "%llu", (unsigned long long)settings.maxbytes);
2208
2438
    APPEND_STAT("tcp_backlog", "%d", settings.backlog);
2209
2439
    APPEND_STAT("binding_protocol", "%s",
2210
2440
                prot_text(settings.binding_protocol));
 
2441
    APPEND_STAT("auth_enabled_sasl", "%s", settings.sasl ? "yes" : "no");
2211
2442
    APPEND_STAT("item_size_max", "%d", settings.item_size_max);
2212
2443
}
2213
2444
 
2398
2629
            } else {
2399
2630
                pthread_mutex_lock(&c->thread->stats.mutex);
2400
2631
                c->thread->stats.get_misses++;
 
2632
                c->thread->stats.get_cmds++;
2401
2633
                pthread_mutex_unlock(&c->thread->stats.mutex);
2402
2634
                MEMCACHED_COMMAND_GET(c->sfd, key, nkey, -1, 0);
2403
2635
            }
2651
2883
 
2652
2884
    assert(c != NULL);
2653
2885
 
2654
 
    set_noreply_maybe(c, tokens, ntokens);
 
2886
    if (ntokens > 3) {
 
2887
        bool hold_is_zero = strcmp(tokens[KEY_TOKEN+1].value, "0") == 0;
 
2888
        bool sets_noreply = set_noreply_maybe(c, tokens, ntokens);
 
2889
        bool valid = (ntokens == 4 && (hold_is_zero || sets_noreply))
 
2890
            || (ntokens == 5 && hold_is_zero && sets_noreply);
 
2891
        if (!valid) {
 
2892
            out_string(c, "CLIENT_ERROR bad command line format.  "
 
2893
                       "Usage: delete <key> [noreply]");
 
2894
            return;
 
2895
        }
 
2896
    }
 
2897
 
2655
2898
 
2656
2899
    key = tokens[KEY_TOKEN].value;
2657
2900
    nkey = tokens[KEY_TOKEN].length;
2756
2999
 
2757
3000
        process_arithmetic_command(c, tokens, ntokens, 0);
2758
3001
 
2759
 
    } else if (ntokens >= 3 && ntokens <= 4 && (strcmp(tokens[COMMAND_TOKEN].value, "delete") == 0)) {
 
3002
    } else if (ntokens >= 3 && ntokens <= 5 && (strcmp(tokens[COMMAND_TOKEN].value, "delete") == 0)) {
2760
3003
 
2761
3004
        process_delete_command(c, tokens, ntokens);
2762
3005
 
2908
3151
 
2909
3152
        if (c->rbytes == 0)
2910
3153
            return 0;
 
3154
 
2911
3155
        el = memchr(c->rcurr, '\n', c->rbytes);
2912
 
        if (!el)
 
3156
        if (!el) {
 
3157
            if (c->rbytes > 1024) {
 
3158
                /*
 
3159
                 * We didn't have a '\n' in the first k. This _has_ to be a
 
3160
                 * large multiget, if not we should just nuke the connection.
 
3161
                 */
 
3162
                char *ptr = c->rcurr;
 
3163
                while (*ptr == ' ') { /* ignore leading whitespaces */
 
3164
                    ++ptr;
 
3165
                }
 
3166
 
 
3167
                if (ptr - c->rcurr > 100 ||
 
3168
                    (strncmp(ptr, "get ", 4) && strncmp(ptr, "gets ", 5))) {
 
3169
 
 
3170
                    conn_set_state(c, conn_closing);
 
3171
                    return 1;
 
3172
                }
 
3173
            }
 
3174
 
2913
3175
            return 0;
 
3176
        }
2914
3177
        cont = el + 1;
2915
3178
        if ((el - c->rcurr) > 1 && *(el - 1) == '\r') {
2916
3179
            el--;
2972
3235
 * close.
2973
3236
 * before reading, move the remaining incomplete fragment of a command
2974
3237
 * (if any) to the beginning of the buffer.
 
3238
 *
 
3239
 * To protect us from someone flooding a connection with bogus data causing
 
3240
 * the connection to eat up all available memory, break out and start looking
 
3241
 * at the data I've got after a number of reallocs...
 
3242
 *
2975
3243
 * @return enum try_read_result
2976
3244
 */
2977
3245
static enum try_read_result try_read_network(conn *c) {
2978
3246
    enum try_read_result gotdata = READ_NO_DATA_RECEIVED;
2979
3247
    int res;
2980
 
 
 
3248
    int num_allocs = 0;
2981
3249
    assert(c != NULL);
2982
3250
 
2983
3251
    if (c->rcurr != c->rbuf) {
2988
3256
 
2989
3257
    while (1) {
2990
3258
        if (c->rbytes >= c->rsize) {
 
3259
            if (num_allocs == 4) {
 
3260
                return gotdata;
 
3261
            }
 
3262
            ++num_allocs;
2991
3263
            char *new_rbuf = realloc(c->rbuf, c->rsize * 2);
2992
3264
            if (!new_rbuf) {
2993
3265
                if (settings.verbose > 0)
3812
4084
    printf("-C            Disable use of CAS\n");
3813
4085
    printf("-b            Set the backlog queue limit (default: 1024)\n");
3814
4086
    printf("-B            Binding protocol - one of ascii, binary, or auto (default)\n");
3815
 
    printf("-I            Override the size of each slab page. Adjusts max item size\n");
 
4087
    printf("-I            Override the size of each slab page. Adjusts max item size\n"
 
4088
           "              (default: 1mb, min: 1k, max: 128m)\n");
 
4089
#ifdef ENABLE_SASL
 
4090
    printf("-S            Turn on Sasl authentication\n");
 
4091
#endif
3816
4092
    return;
3817
4093
}
3818
4094
 
3893
4169
        return;
3894
4170
 
3895
4171
    if ((fp = fopen(pid_file, "w")) == NULL) {
3896
 
        fprintf(stderr, "Could not open the pid file %s for writing\n", pid_file);
 
4172
        vperror("Could not open the pid file %s for writing", pid_file);
3897
4173
        return;
3898
4174
    }
3899
4175
 
3900
4176
    fprintf(fp,"%ld\n", (long)pid);
3901
4177
    if (fclose(fp) == -1) {
3902
 
        fprintf(stderr, "Could not close the pid file %s.\n", pid_file);
 
4178
        vperror("Could not close the pid file %s", pid_file);
3903
4179
        return;
3904
4180
    }
3905
4181
}
3909
4185
      return;
3910
4186
 
3911
4187
  if (unlink(pid_file) != 0) {
3912
 
      fprintf(stderr, "Could not remove the pid file %s.\n", pid_file);
 
4188
      vperror("Could not remove the pid file %s", pid_file);
3913
4189
  }
3914
4190
 
3915
4191
}
3991
4267
 
3992
4268
    /* udp socket */
3993
4269
    static int *u_socket = NULL;
 
4270
    bool protocol_specified = false;
 
4271
    bool tcp_specified = false;
 
4272
    bool udp_specified = false;
3994
4273
 
3995
4274
    /* handle SIGINT */
3996
4275
    signal(SIGINT, sig_handler);
4028
4307
          "b:"  /* backlog queue limit */
4029
4308
          "B:"  /* Binding protocol */
4030
4309
          "I:"  /* Max item size */
 
4310
          "S"   /* Sasl ON */
4031
4311
        ))) {
4032
4312
        switch (c) {
4033
4313
        case 'a':
4037
4317
 
4038
4318
        case 'U':
4039
4319
            settings.udpport = atoi(optarg);
 
4320
            udp_specified = true;
4040
4321
            break;
4041
4322
        case 'p':
4042
4323
            settings.port = atoi(optarg);
 
4324
            tcp_specified = true;
4043
4325
            break;
4044
4326
        case 's':
4045
4327
            settings.socketpath = optarg;
4138
4420
            settings.backlog = atoi(optarg);
4139
4421
            break;
4140
4422
        case 'B':
 
4423
            protocol_specified = true;
4141
4424
            if (strcmp(optarg, "auto") == 0) {
4142
4425
                settings.binding_protocol = negotiating_prot;
4143
4426
            } else if (strcmp(optarg, "binary") == 0) {
4180
4463
                );
4181
4464
            }
4182
4465
            break;
 
4466
        case 'S': /* set Sasl authentication to true. Default is false */
 
4467
#ifndef ENABLE_SASL
 
4468
            fprintf(stderr, "This server is not built with SASL support.\n");
 
4469
            exit(EX_USAGE);
 
4470
#endif
 
4471
            settings.sasl = true;
 
4472
            break;
4183
4473
        default:
4184
4474
            fprintf(stderr, "Illegal argument \"%c\"\n", c);
4185
4475
            return 1;
4186
4476
        }
4187
4477
    }
4188
4478
 
 
4479
    if (settings.sasl) {
 
4480
        if (!protocol_specified) {
 
4481
            settings.binding_protocol = binary_prot;
 
4482
        } else {
 
4483
            if (settings.binding_protocol != binary_prot) {
 
4484
                fprintf(stderr, "ERROR: You cannot allow the ASCII protocol while using SASL.\n");
 
4485
                exit(EX_USAGE);
 
4486
            }
 
4487
        }
 
4488
    }
 
4489
 
 
4490
    if (tcp_specified && !udp_specified) {
 
4491
        settings.udpport = settings.port;
 
4492
    } else if (udp_specified && !tcp_specified) {
 
4493
        settings.port = settings.udpport;
 
4494
    }
 
4495
 
4189
4496
    if (maxcore != 0) {
4190
4497
        struct rlimit rlim_new;
4191
4498
        /*
4248
4555
        }
4249
4556
    }
4250
4557
 
 
4558
    /* Initialize Sasl if -S was specified */
 
4559
    if (settings.sasl) {
 
4560
        init_sasl();
 
4561
    }
 
4562
 
4251
4563
    /* daemonize if requested */
4252
4564
    /* if we want to ensure our ability to dump core, don't chdir to / */
4253
4565
    if (do_daemonize) {