Coverage Report

Created: 2026-03-14 06:51

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
0
{
71
0
    struct bindaddr_list *bl;
72
0
    struct rtpp_bindaddrs_pvt *cf;
73
0
    struct sockaddr_storage *ap;
74
75
0
    PUB2PVT(pub, cf);
76
0
    pthread_mutex_lock(&cf->bindaddr_lock);
77
0
    for (bl = cf->bindaddr_list; bl != NULL; bl = bl->next) {
78
0
        const struct rtpp_bindaddr *ba = &bl->bindaddr;
79
0
        if (ishostseq(ba->addr, ia) != 0) {
80
0
            const rtpp_str_const_t *bll = &ba->params.label;
81
0
            if (params != NULL && !rtpp_str_match(&params->label, bll))
82
0
                continue;
83
0
            pthread_mutex_unlock(&cf->bindaddr_lock);
84
0
            return (ba);
85
0
        }
86
0
    }
87
0
    bl = rtpp_zmalloc(sizeof(*bl) + sizeof(struct sockaddr_storage));
88
0
    if (bl == NULL) {
89
0
        pthread_mutex_unlock(&cf->bindaddr_lock);
90
0
        *ep = strerror(errno);
91
0
        return (NULL);
92
0
    }
93
0
    ap = (struct sockaddr_storage *)((char *)bl + sizeof(*bl));
94
0
    memcpy(ap, ia, SA_LEN(ia));
95
0
    bl->bindaddr.addr = sstosa(ap);
96
0
    if (params != NULL) {
97
0
        bl->bindaddr.params = *params;
98
0
    }
99
0
    bl->next = cf->bindaddr_list;
100
0
    cf->bindaddr_list = bl;
101
0
    pthread_mutex_unlock(&cf->bindaddr_lock);
102
0
    return (&bl->bindaddr);
103
0
}
104
105
static const struct rtpp_bindaddr *
106
addr2bindaddr(struct rtpp_bindaddrs *pub, const struct sockaddr *ia,
107
  const char **ep)
108
0
{
109
110
0
    return addr2bindaddr_i(pub, ia, ep, NULL);
111
0
}
112
113
static const struct rtpp_bindaddr *
114
label2bindaddr(struct rtpp_bindaddrs *pub, const rtpp_str_const_t *label)
115
0
{
116
0
    struct bindaddr_list *bl;
117
0
    struct rtpp_bindaddrs_pvt *cf;
118
119
0
    PUB2PVT(pub, cf);
120
0
    pthread_mutex_lock(&cf->bindaddr_lock);
121
0
    for (bl = cf->bindaddr_list; bl != NULL; bl = bl->next) {
122
0
  const rtpp_str_const_t *blabel = &bl->bindaddr.params.label;
123
0
  if (blabel->s != NULL && rtpp_str_match(blabel, label))
124
0
      break;
125
0
    }
126
0
    pthread_mutex_unlock(&cf->bindaddr_lock);
127
0
    return (bl == NULL ? NULL : &bl->bindaddr);
128
0
}
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
0
{
134
0
    int n;
135
0
    struct sockaddr_storage ia;
136
0
    const struct rtpp_bindaddr *rval;
137
138
0
    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
0
    if (host != NULL && is_wildcard(host, pf))
148
0
        host = NULL;
149
150
0
    if (host != NULL) {
151
0
        ai_flags |= is_numhost(host, pf) ? AI_NUMERICHOST : 0;
152
0
    } else {
153
0
        ai_flags &= ~AI_ADDRCONFIG;
154
0
    }
155
156
0
    if ((n = resolve(sstosa(&ia), pf, host, SERVICE, ai_flags)) != 0) {
157
0
        *ep = gai_strerror(n);
158
0
        return (NULL);
159
0
    }
160
0
    rval = addr2bindaddr_i(pub, sstosa(&ia), ep, params);
161
0
    return (rval);
162
0
}
163
164
static const struct rtpp_bindaddr *
165
bindaddr4af(struct rtpp_bindaddrs *pub, int af)
166
0
{
167
0
    struct bindaddr_list *bl;
168
0
    struct rtpp_bindaddrs_pvt *cf;
169
170
0
    PUB2PVT(pub, cf);
171
0
    pthread_mutex_lock(&cf->bindaddr_lock);
172
0
    for (bl = cf->bindaddr_list; bl != NULL; bl = bl->next) {
173
0
        if (bl->bindaddr.addr->sa_family == af) {
174
0
            pthread_mutex_unlock(&cf->bindaddr_lock);
175
0
            return (&bl->bindaddr);
176
0
        }
177
0
    }
178
0
    pthread_mutex_unlock(&cf->bindaddr_lock);
179
0
    return (NULL);
180
0
}
181
182
static void
183
rtpp_bindaddrs_dtor(struct rtpp_bindaddrs_pvt *cf)
184
0
{
185
0
    struct bindaddr_list *bl, *bl_next;
186
187
0
    for (bl = cf->bindaddr_list; bl != NULL; bl = bl_next) {
188
0
        bl_next = bl->next;
189
0
        free(bl);
190
0
    }
191
0
    pthread_mutex_destroy(&cf->bindaddr_lock);
192
0
}
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
0
{
198
0
    struct sockaddr_storage local_addr;
199
0
    const struct rtpp_bindaddr *rval;
200
0
    const char *errmsg;
201
202
0
    int ai_flags = cfsp->no_resolve ? AI_NUMERICHOST : 0;
203
0
    int n = resolve(sstosa(&local_addr), pf, host, port, ai_flags);
204
0
    if (n != 0) {
205
0
        RTPP_LOG(log, RTPP_LOG_ERR, "invalid remote address: %s: %s", host,
206
0
          gai_strerror(n));
207
0
        return (NULL);
208
0
    }
209
0
    if (local4remote(sstosa(&local_addr), &local_addr) == -1) {
210
0
        RTPP_LOG(log, RTPP_LOG_ERR, "can't find local address for remote address: %s",
211
0
          host);
212
0
        return (NULL);
213
0
    }
214
0
    rval = addr2bindaddr(pub, sstosa(&local_addr), &errmsg);
215
0
    if (rval == NULL) {
216
0
        RTPP_LOG(log, RTPP_LOG_ERR, "invalid local address: %s", errmsg);
217
0
        return (NULL);
218
0
    }
219
0
    return (rval);
220
0
}
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
0
{
233
0
    struct rtpp_bindaddrs_pvt *cf;
234
235
0
    cf = rtpp_rzmalloc(sizeof(*cf), PVT_RCOFFS(cf));
236
0
    if (cf == NULL)
237
0
        goto e0;
238
0
    if (pthread_mutex_init(&cf->bindaddr_lock, NULL) != 0)
239
0
        goto e1;
240
0
    PUBINST_FININIT(&cf->pub, cf, rtpp_bindaddrs_dtor);
241
0
    return (&(cf->pub));
242
0
e1:
243
0
    RTPP_OBJ_DECREF(&(cf->pub));
244
0
e0:
245
    return (NULL);
246
0
}