Coverage Report

Created: 2025-08-26 06:50

/src/open5gs/lib/core/ogs-sockopt.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
3
 *
4
 * This file is part of Open5GS.
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU Affero General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
18
 */
19
20
#include "core-config-private.h"
21
22
#if HAVE_FCNTL_H
23
#include <fcntl.h>
24
#endif
25
26
#if HAVE_NETINET_TCP_H
27
#include <netinet/tcp.h>
28
#endif
29
30
#include "ogs-core.h"
31
32
#undef OGS_LOG_DOMAIN
33
0
#define OGS_LOG_DOMAIN __ogs_sock_domain
34
35
void ogs_sockopt_init(ogs_sockopt_t *option)
36
0
{
37
0
    ogs_assert(option);
38
39
0
    memset(option, 0, sizeof *option);
40
41
0
    option->sctp.spp_hbinterval = 5000;         /* 5 seconds */
42
0
    option->sctp.spp_sackdelay = 200;           /* 200 ms */
43
0
    option->sctp.srto_initial = 3000;           /* 3 seconds */
44
0
    option->sctp.srto_min = 1000;               /* 1 seconds */
45
0
    option->sctp.srto_max = 5000;               /* 5 seconds */
46
0
    option->sctp.sinit_num_ostreams = OGS_DEFAULT_SCTP_MAX_NUM_OF_OSTREAMS;
47
0
    option->sctp.sinit_max_instreams = 65535;
48
0
    option->sctp.sinit_max_attempts = 4;
49
0
    option->sctp.sinit_max_init_timeo = 8000;   /* 8 seconds */
50
51
0
    option->sctp_nodelay = true;
52
0
    option->tcp_nodelay = true;
53
0
}
54
55
int ogs_nonblocking(ogs_socket_t fd)
56
0
{
57
#ifdef _WIN32
58
    int rc;
59
    ogs_assert(fd != INVALID_SOCKET);
60
61
    u_long io_mode = 1;
62
    rc = ioctlsocket(fd, FIONBIO, &io_mode);
63
    if (rc != OGS_OK) {
64
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "ioctlsocket failed");
65
        return OGS_ERROR;
66
    }
67
#else
68
0
    int rc;
69
0
    int flags;
70
0
    ogs_assert(fd != INVALID_SOCKET);
71
72
0
    flags = fcntl(fd, F_GETFL, NULL);
73
0
    if (flags < 0) {
74
0
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "F_GETFL failed");
75
0
        return OGS_ERROR;
76
0
    }
77
0
    if (!(flags & O_NONBLOCK)) {
78
0
        rc = fcntl(fd, F_SETFL, (flags | O_NONBLOCK));
79
0
        if (rc != OGS_OK) {
80
0
            ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "F_SETFL failed");
81
0
            return OGS_ERROR;
82
0
        }
83
0
    }
84
0
#endif
85
86
0
    return OGS_OK;
87
0
}
88
89
int ogs_closeonexec(ogs_socket_t fd)
90
0
{
91
0
#ifndef _WIN32
92
0
    int rc;
93
0
    int flags;
94
95
0
    ogs_assert(fd != INVALID_SOCKET);
96
0
    flags = fcntl(fd, F_GETFD, NULL);
97
0
    if (flags < 0) {
98
0
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "F_GETFD failed");
99
0
        return OGS_ERROR;
100
0
    }
101
0
    if (!(flags & FD_CLOEXEC)) {
102
0
        rc = fcntl(fd, F_SETFD, (flags | FD_CLOEXEC));
103
0
        if (rc != OGS_OK) {
104
0
            ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "F_SETFD failed");
105
0
            return OGS_ERROR;
106
0
        }
107
0
    }
108
0
#endif
109
110
0
    return OGS_OK;
111
0
}
112
113
int ogs_listen_reusable(ogs_socket_t fd, int on)
114
0
{
115
0
#if defined(SO_REUSEADDR) && !defined(_WIN32)
116
0
    int rc;
117
118
0
    ogs_assert(fd != INVALID_SOCKET);
119
120
0
    ogs_debug("Turn on SO_REUSEADDR");
121
0
    rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(int));
122
0
    if (rc != OGS_OK) {
123
0
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
124
0
                "setsockopt(SOL_SOCKET, SO_REUSEADDR) failed");
125
0
        return OGS_ERROR;
126
0
    }
127
0
#endif
128
129
0
    return OGS_OK;
130
0
}
131
132
int ogs_tcp_nodelay(ogs_socket_t fd, int on)
133
0
{
134
0
#if defined(TCP_NODELAY) && !defined(_WIN32)
135
0
    int rc;
136
137
0
    ogs_assert(fd != INVALID_SOCKET);
138
139
0
    ogs_debug("Turn on TCP_NODELAY");
140
0
    rc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(int));
141
0
    if (rc != OGS_OK) {
142
0
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
143
0
                "setsockopt(IPPROTO_TCP, TCP_NODELAY) failed");
144
0
        return OGS_ERROR;
145
0
    }
146
0
#endif
147
148
0
    return OGS_OK;
149
0
}
150
151
int ogs_so_linger(ogs_socket_t fd, int l_linger)
152
0
{
153
0
#if defined(SO_LINGER) && !defined(_WIN32)
154
0
    struct linger l;
155
0
    int rc;
156
157
0
    ogs_assert(fd != INVALID_SOCKET);
158
159
0
    memset(&l, 0, sizeof(l));
160
0
    l.l_onoff = 1;
161
0
    l.l_linger = l_linger;
162
163
0
    ogs_debug("SO_LINGER:[%d]", l_linger);
164
0
    rc = setsockopt(fd, SOL_SOCKET, SO_LINGER,
165
0
            (void *)&l, sizeof(struct linger));
166
0
    if (rc != OGS_OK) {
167
0
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
168
0
                "setsockopt(SOL_SOCKET, SO_LINGER) failed");
169
0
        return OGS_ERROR;
170
0
    }
171
0
#endif
172
173
0
    return OGS_OK;
174
0
}
175
176
int ogs_bind_to_device(ogs_socket_t fd, const char *device)
177
0
{
178
0
#if defined(SO_BINDTODEVICE) && !defined(_WIN32)
179
0
    int rc;
180
181
0
    ogs_assert(fd != INVALID_SOCKET);
182
0
    ogs_assert(device);
183
184
0
    ogs_debug("SO_BINDTODEVICE:[%s]", device);
185
0
    rc = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device)+1);
186
0
    if (rc != OGS_OK) {
187
0
        int err = ogs_errno;
188
0
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
189
0
                "setsockopt(SOL_SOCKET, SO_BINDTODEVICE, %s) failed", device);
190
0
        if (err == OGS_EPERM)
191
0
            ogs_error("You need to grant CAP_NET_RAW privileges to use SO_BINDTODEVICE.");
192
0
        return OGS_ERROR;
193
0
    }
194
0
#endif
195
196
0
    return OGS_OK;
197
0
}