Coverage Report

Created: 2026-02-26 06:48

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_bindaddrs.h"
49
50
struct bindaddr_list {
51
    struct sockaddr_storage *bindaddr;
52
    struct bindaddr_list *next;
53
};
54
55
struct rtpp_bindaddrs_pvt {
56
    struct rtpp_bindaddrs pub;
57
    struct bindaddr_list *bindaddr_list;
58
    pthread_mutex_t bindaddr_lock;
59
};
60
61
static const struct sockaddr *
62
addr2bindaddr(struct rtpp_bindaddrs *pub, const struct sockaddr *ia, const char **ep)
63
1.41k
{
64
1.41k
    struct bindaddr_list *bl;
65
1.41k
    struct rtpp_bindaddrs_pvt *cf;
66
67
1.41k
    PUB2PVT(pub, cf);
68
1.41k
    pthread_mutex_lock(&cf->bindaddr_lock);
69
152k
    for (bl = cf->bindaddr_list; bl != NULL; bl = bl->next) {
70
152k
        if (ishostseq(sstosa(bl->bindaddr), ia) != 0) {
71
1.24k
            pthread_mutex_unlock(&cf->bindaddr_lock);
72
1.24k
            return (sstosa(bl->bindaddr));
73
1.24k
        }
74
152k
    }
75
173
    bl = malloc(sizeof(*bl) + sizeof(*bl->bindaddr));
76
173
    if (bl == NULL) {
77
0
        pthread_mutex_unlock(&cf->bindaddr_lock);
78
0
        *ep = strerror(errno);
79
0
        return (NULL);
80
0
    }
81
173
    bl->bindaddr = (struct sockaddr_storage *)((char *)bl + sizeof(*bl));
82
173
    memcpy(bl->bindaddr, ia, SA_LEN(ia));
83
173
    bl->next = cf->bindaddr_list;
84
173
    cf->bindaddr_list = bl;
85
173
    pthread_mutex_unlock(&cf->bindaddr_lock);
86
173
    return (sstosa(bl->bindaddr));
87
173
}
88
89
static const struct sockaddr *
90
host2bindaddr(struct rtpp_bindaddrs *pub, const char *host, int pf,
91
  int ai_flags, const char **ep)
92
1.25k
{
93
1.25k
    int n;
94
1.25k
    struct sockaddr_storage ia;
95
1.25k
    const struct sockaddr *rval;
96
97
    /*
98
     * If user specified * then change it to NULL,
99
     * that will make getaddrinfo to return addr_any socket
100
     */
101
1.25k
    if (host != NULL && is_wildcard(host, pf))
102
404
        host = NULL;
103
104
1.25k
    if (host != NULL) {
105
848
        ai_flags |= is_numhost(host, pf) ? AI_NUMERICHOST : 0;
106
848
    } else {
107
404
        ai_flags &= ~AI_ADDRCONFIG;
108
404
    }
109
110
1.25k
    if ((n = resolve(sstosa(&ia), pf, host, SERVICE, ai_flags)) != 0) {
111
39
        *ep = gai_strerror(n);
112
39
        return (NULL);
113
39
    }
114
1.21k
    rval = addr2bindaddr(pub, sstosa(&ia), ep);
115
1.21k
    return (rval);
116
1.25k
}
117
118
static const struct sockaddr *
119
bindaddr4af(struct rtpp_bindaddrs *pub, int af)
120
2.09k
{
121
2.09k
    struct bindaddr_list *bl;
122
2.09k
    struct rtpp_bindaddrs_pvt *cf;
123
124
2.09k
    PUB2PVT(pub, cf);
125
2.09k
    pthread_mutex_lock(&cf->bindaddr_lock);
126
34.3k
    for (bl = cf->bindaddr_list; bl != NULL; bl = bl->next) {
127
34.3k
        if (sstosa(bl->bindaddr)->sa_family == af) {
128
2.05k
            pthread_mutex_unlock(&cf->bindaddr_lock);
129
2.05k
            return (sstosa(bl->bindaddr));
130
2.05k
        }
131
34.3k
    }
132
36
    pthread_mutex_unlock(&cf->bindaddr_lock);
133
36
    return (NULL);
134
2.09k
}
135
136
static void
137
rtpp_bindaddrs_dtor(struct rtpp_bindaddrs *pub)
138
4
{
139
4
    struct rtpp_bindaddrs_pvt *cf;
140
4
    struct bindaddr_list *bl, *bl_next;
141
142
4
    PUB2PVT(pub, cf);
143
177
    for (bl = cf->bindaddr_list; bl != NULL; bl = bl_next) {
144
173
        bl_next = bl->next;
145
173
        free(bl);
146
173
    }
147
4
    free(cf);
148
4
}
149
150
static const struct sockaddr *
151
rtpp_bindaddrs_local4remote(struct rtpp_bindaddrs *pub, const struct rtpp_cfg *cfsp,
152
  struct rtpp_log *log, int pf, const char *host, const char *port)
153
683
{
154
683
    struct sockaddr_storage local_addr;
155
683
    const struct sockaddr *rval;
156
683
    const char *errmsg;
157
158
683
    int ai_flags = cfsp->no_resolve ? AI_NUMERICHOST : 0;
159
683
    int n = resolve(sstosa(&local_addr), pf, host, port, ai_flags);
160
683
    if (n != 0) {
161
479
        RTPP_LOG(log, RTPP_LOG_ERR, "invalid remote address: %s: %s", host,
162
479
          gai_strerror(n));
163
479
        return (NULL);
164
479
    }
165
204
    if (local4remote(sstosa(&local_addr), &local_addr) == -1) {
166
1
        RTPP_LOG(log, RTPP_LOG_ERR, "can't find local address for remote address: %s",
167
1
          host);
168
1
        return (NULL);
169
1
    }
170
203
    rval = addr2bindaddr(pub, sstosa(&local_addr), &errmsg);
171
203
    if (rval == NULL) {
172
0
        RTPP_LOG(log, RTPP_LOG_ERR, "invalid local address: %s", errmsg);
173
0
        return (NULL);
174
0
    }
175
203
    return (rval);
176
203
}
177
178
struct rtpp_bindaddrs *
179
rtpp_bindaddrs_ctor(void)
180
4
{
181
4
    struct rtpp_bindaddrs_pvt *cf;
182
183
4
    cf = rtpp_zmalloc(sizeof(*cf));
184
4
    if (cf == NULL)
185
0
        goto e0;
186
4
    if (pthread_mutex_init(&cf->bindaddr_lock, NULL) != 0)
187
0
        goto e1;
188
4
    cf->pub.addr2 = addr2bindaddr;
189
4
    cf->pub.host2 = host2bindaddr;
190
4
    cf->pub.foraf = bindaddr4af;
191
4
    cf->pub.dtor = rtpp_bindaddrs_dtor;
192
4
    cf->pub.local4remote = rtpp_bindaddrs_local4remote;
193
4
    return (&(cf->pub));
194
0
e1:
195
0
    free(cf);
196
0
e0:
197
    return (NULL);
198
0
}