Coverage Report

Created: 2026-09-01 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rtpproxy/src/rtpp_bindaddrs.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2004-2006 Maxim Sobolev <sobomax@FreeBSD.org>
3
 * Copyright (c) 2006-2016 Sippy Software, Inc., http://www.sippysoft.com
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
 * SUCH DAMAGE.
26
 *
27
 */
28
29
#include <sys/types.h>
30
#include <sys/socket.h>
31
#include <netinet/in.h>
32
#include <errno.h>
33
#include <netdb.h>
34
#include <pthread.h>
35
#include <stddef.h>
36
#include <stdlib.h>
37
#include <string.h>
38
39
#include "config.h"
40
41
#include "rtpp_types.h"
42
#include "rtpp_defines.h"
43
#include "rtpp_cfg.h"
44
#include "rtpp_log.h"
45
#include "rtpp_log_obj.h"
46
#include "rtpp_network.h"
47
#include "rtpp_mallocs.h"
48
#include "rtpp_codeptr.h"
49
#include "rtpp_refcnt.h"
50
#include "rtpp_str.h"
51
#include "rtpp_bindaddr.h"
52
#include "rtpp_bindaddrs.h"
53
54
struct bindaddr_list {
55
    struct rtpp_bindaddr bindaddr;
56
    struct bindaddr_list *next;
57
};
58
59
struct rtpp_bindaddrs_pvt {
60
    struct rtpp_bindaddrs pub;
61
    struct bindaddr_list *bindaddr_list;
62
    pthread_mutex_t bindaddr_lock;
63
};
64
65
static void rtpp_bindaddrs_dtor(struct rtpp_bindaddrs_pvt *);
66
67
static const struct rtpp_bindaddr *
68
addr2bindaddr_i(struct rtpp_bindaddrs *pub, const struct sockaddr *ia,
69
  const char **ep, const struct rtpp_bindaddr_params *params)
70
2.04k
{
71
2.04k
    struct bindaddr_list *bl;
72
2.04k
    struct rtpp_bindaddrs_pvt *cf;
73
2.04k
    struct sockaddr_storage *ap;
74
75
2.04k
    PUB2PVT(pub, cf);
76
2.04k
    pthread_mutex_lock(&cf->bindaddr_lock);
77
191k
    for (bl = cf->bindaddr_list; bl != NULL; bl = bl->next) {
78
191k
        const struct rtpp_bindaddr *ba = &bl->bindaddr;
79
191k
        if (ishostseq(ba->addr, ia) != 0) {
80
1.84k
            const rtpp_str_const_t *bll = &ba->params.label;
81
1.84k
            if (params != NULL && !rtpp_str_match(&params->label, bll))
82
0
                continue;
83
1.84k
            pthread_mutex_unlock(&cf->bindaddr_lock);
84
1.84k
            return (ba);
85
1.84k
        }
86
191k
    }
87
199
    bl = rtpp_zmalloc(sizeof(*bl) + sizeof(struct sockaddr_storage));
88
199
    if (bl == NULL) {
89
0
        pthread_mutex_unlock(&cf->bindaddr_lock);
90
0
        *ep = strerror(errno);
91
0
        return (NULL);
92
0
    }
93
199
    ap = (struct sockaddr_storage *)((char *)bl + sizeof(*bl));
94
199
    memcpy(ap, ia, SA_LEN(ia));
95
199
    bl->bindaddr.addr = sstosa(ap);
96
199
    if (params != NULL) {
97
4
        bl->bindaddr.params = *params;
98
4
    }
99
199
    bl->next = cf->bindaddr_list;
100
199
    cf->bindaddr_list = bl;
101
199
    pthread_mutex_unlock(&cf->bindaddr_lock);
102
199
    return (&bl->bindaddr);
103
199
}
104
105
static const struct rtpp_bindaddr *
106
addr2bindaddr(struct rtpp_bindaddrs *pub, const struct sockaddr *ia,
107
  const char **ep)
108
215
{
109
110
215
    return addr2bindaddr_i(pub, ia, ep, NULL);
111
215
}
112
113
static const struct rtpp_bindaddr *
114
label2bindaddr(struct rtpp_bindaddrs *pub, const rtpp_str_const_t *label)
115
199
{
116
199
    struct bindaddr_list *bl;
117
199
    struct rtpp_bindaddrs_pvt *cf;
118
119
199
    PUB2PVT(pub, cf);
120
199
    pthread_mutex_lock(&cf->bindaddr_lock);
121
37.5k
    for (bl = cf->bindaddr_list; bl != NULL; bl = bl->next) {
122
37.3k
  const rtpp_str_const_t *blabel = &bl->bindaddr.params.label;
123
37.3k
  if (blabel->s != NULL && rtpp_str_match(blabel, label))
124
0
      break;
125
37.3k
    }
126
199
    pthread_mutex_unlock(&cf->bindaddr_lock);
127
199
    return (bl == NULL ? NULL : &bl->bindaddr);
128
199
}
129
130
static const struct rtpp_bindaddr *
131
host2bindaddr(struct rtpp_bindaddrs *pub, const char *host, int pf,
132
  int ai_flags, const char **ep, const struct rtpp_bindaddr_params *params)
133
1.87k
{
134
1.87k
    int n;
135
1.87k
    struct sockaddr_storage ia;
136
1.87k
    const struct rtpp_bindaddr *rval;
137
138
1.87k
    if (params != NULL && params->label.s != NULL && label2bindaddr(pub, &params->label) != NULL) {
139
0
  *ep = "duplicate label";
140
0
  return (NULL);
141
0
    }
142
143
    /*
144
     * If user specified * then change it to NULL,
145
     * that will make getaddrinfo to return addr_any socket
146
     */
147
1.87k
    if (host != NULL && is_wildcard(host, pf))
148
376
        host = NULL;
149
150
1.87k
    if (host != NULL) {
151
1.50k
        ai_flags |= is_numhost(host, pf) ? AI_NUMERICHOST : 0;
152
1.50k
    } else {
153
376
        ai_flags &= ~AI_ADDRCONFIG;
154
376
    }
155
156
1.87k
    if ((n = resolve(sstosa(&ia), pf, host, SERVICE, ai_flags)) != 0) {
157
47
        *ep = gai_strerror(n);
158
47
        return (NULL);
159
47
    }
160
1.82k
    rval = addr2bindaddr_i(pub, sstosa(&ia), ep, params);
161
1.82k
    return (rval);
162
1.87k
}
163
164
static const struct rtpp_bindaddr *
165
bindaddr4af(struct rtpp_bindaddrs *pub, int af)
166
2.62k
{
167
2.62k
    struct bindaddr_list *bl;
168
2.62k
    struct rtpp_bindaddrs_pvt *cf;
169
170
2.62k
    PUB2PVT(pub, cf);
171
2.62k
    pthread_mutex_lock(&cf->bindaddr_lock);
172
42.2k
    for (bl = cf->bindaddr_list; bl != NULL; bl = bl->next) {
173
42.1k
        if (bl->bindaddr.addr->sa_family == af) {
174
2.57k
            pthread_mutex_unlock(&cf->bindaddr_lock);
175
2.57k
            return (&bl->bindaddr);
176
2.57k
        }
177
42.1k
    }
178
46
    pthread_mutex_unlock(&cf->bindaddr_lock);
179
46
    return (NULL);
180
2.62k
}
181
182
static void
183
rtpp_bindaddrs_dtor(struct rtpp_bindaddrs_pvt *cf)
184
4
{
185
4
    struct bindaddr_list *bl, *bl_next;
186
187
203
    for (bl = cf->bindaddr_list; bl != NULL; bl = bl_next) {
188
199
        bl_next = bl->next;
189
199
        free(bl);
190
199
    }
191
4
    pthread_mutex_destroy(&cf->bindaddr_lock);
192
4
}
193
194
static const struct rtpp_bindaddr *
195
rtpp_bindaddrs_local4remote(struct rtpp_bindaddrs *pub, const struct rtpp_cfg *cfsp,
196
  struct rtpp_log *log, int pf, const char *host, const char *port)
197
466
{
198
466
    struct sockaddr_storage local_addr;
199
466
    const struct rtpp_bindaddr *rval;
200
466
    const char *errmsg;
201
202
466
    int ai_flags = cfsp->no_resolve ? AI_NUMERICHOST : 0;
203
466
    int n = resolve(sstosa(&local_addr), pf, host, port, ai_flags);
204
466
    if (n != 0) {
205
250
        RTPP_LOG(log, RTPP_LOG_ERR, "invalid remote address: %s: %s", host,
206
250
          gai_strerror(n));
207
250
        return (NULL);
208
250
    }
209
216
    if (local4remote(sstosa(&local_addr), &local_addr) == -1) {
210
1
        RTPP_LOG(log, RTPP_LOG_ERR, "can't find local address for remote address: %s",
211
1
          host);
212
1
        return (NULL);
213
1
    }
214
215
    rval = addr2bindaddr(pub, sstosa(&local_addr), &errmsg);
215
215
    if (rval == NULL) {
216
0
        RTPP_LOG(log, RTPP_LOG_ERR, "invalid local address: %s", errmsg);
217
0
        return (NULL);
218
0
    }
219
215
    return (rval);
220
215
}
221
222
DEFINE_SMETHODS(rtpp_bindaddrs,
223
    .addr2 = &addr2bindaddr,
224
    .label2 = &label2bindaddr,
225
    .host2 = &host2bindaddr,
226
    .foraf = &bindaddr4af,
227
    .local4remote = &rtpp_bindaddrs_local4remote,
228
);
229
230
struct rtpp_bindaddrs *
231
rtpp_bindaddrs_ctor(void)
232
4
{
233
4
    struct rtpp_bindaddrs_pvt *cf;
234
235
4
    cf = rtpp_rzmalloc(sizeof(*cf), PVT_RCOFFS(cf));
236
4
    if (cf == NULL)
237
0
        goto e0;
238
4
    if (pthread_mutex_init(&cf->bindaddr_lock, NULL) != 0)
239
0
        goto e1;
240
4
    PUBINST_FININIT(&cf->pub, cf, rtpp_bindaddrs_dtor);
241
4
    return (&(cf->pub));
242
0
e1:
243
0
    RTPP_OBJ_DECREF(&(cf->pub));
244
0
e0:
245
    return (NULL);
246
0
}