Coverage Report

Created: 2023-06-07 06:37

/src/rtpproxy/src/rtpp_network.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2004-2006 Maxim Sobolev <sobomax@FreeBSD.org>
3
 * Copyright (c) 2006-2009 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 <arpa/inet.h>
33
#include <assert.h>
34
#include <ctype.h>
35
#include <netdb.h>
36
#include <stdio.h>
37
#include <stdlib.h>
38
#include <string.h>
39
#include <unistd.h>
40
41
#include "config_pp.h"
42
43
#if !defined(NO_ERR_H)
44
#include <err.h>
45
#endif
46
47
#include "rtpp_network.h"
48
49
int
50
ishostseq(const struct sockaddr *ia1, const struct sockaddr *ia2)
51
58.8M
{
52
53
58.8M
    if (ia1->sa_family != ia2->sa_family)
54
23.5M
  return 0;
55
56
35.3M
    switch (ia1->sa_family) {
57
35.2M
    case AF_INET:
58
35.2M
  return (satosin(ia1)->sin_addr.s_addr ==
59
35.2M
    satosin(ia2)->sin_addr.s_addr);
60
61
34.5k
    case AF_INET6:
62
34.5k
  return (memcmp(&satosin6(ia1)->sin6_addr.s6_addr[0],
63
34.5k
    &satosin6(ia2)->sin6_addr.s6_addr[0],
64
34.5k
    sizeof(struct in6_addr)) == 0);
65
66
0
    default:
67
0
  break;
68
35.3M
    }
69
    /* Can't happen */
70
0
    abort();
71
35.3M
}
72
73
int
74
ishostnull(const struct sockaddr *ia)
75
204
{
76
204
    struct in6_addr *ap;
77
78
204
    switch (ia->sa_family) {
79
31
    case AF_INET:
80
31
  return (satosin(ia)->sin_addr.s_addr == INADDR_ANY);
81
82
173
    case AF_INET6:
83
173
  ap = &satosin6(ia)->sin6_addr;
84
173
  return ((*(const uint32_t *)(const void *)(&ap->s6_addr[0]) == 0) &&
85
173
    (*(const uint32_t *)(const void *)(&ap->s6_addr[4]) == 0) &&
86
173
    (*(const uint32_t *)(const void *)(&ap->s6_addr[8]) == 0) &&
87
173
    (*(const uint32_t *)(const void *)(&ap->s6_addr[12]) == 0));
88
89
0
    default:
90
0
  break;
91
204
    }
92
93
0
    abort();
94
204
}
95
96
uint16_t
97
getport(const struct sockaddr *ia)
98
0
{
99
100
0
    return (ntohs(getnport(ia)));
101
0
}
102
103
uint16_t
104
getnport(const struct sockaddr *ia)
105
0
{
106
107
0
    switch (ia->sa_family) {
108
0
    case AF_INET:
109
0
        return (satosin(ia)->sin_port);
110
111
0
    case AF_INET6:
112
0
        return (satosin6(ia)->sin6_port);
113
114
0
    default:
115
0
        break;
116
0
    }
117
    /* Can't happen */
118
0
    abort();
119
0
}
120
121
int
122
isaddrseq(const struct sockaddr *ia1, const struct sockaddr *ia2)
123
0
{
124
125
0
    if (ishostseq(ia1, ia2) == 0)
126
0
        return (0);
127
0
    return (getport(ia1) == getport(ia2));
128
0
}
129
130
void
131
setport(struct sockaddr *ia, int portnum)
132
0
{
133
134
0
    assert(IS_VALID_PORT(portnum));
135
136
0
    switch (ia->sa_family) {
137
0
    case AF_INET:
138
0
        satosin(ia)->sin_port = htons(portnum);
139
0
        return;
140
141
0
    case AF_INET6:
142
0
        satosin6(ia)->sin6_port = htons(portnum);
143
0
        return;
144
145
0
    default:
146
0
        break;
147
0
    }
148
    /* Can't happen */
149
0
    abort();
150
0
}
151
152
void
153
setanyport(struct sockaddr *ia)
154
0
{
155
156
0
    switch (ia->sa_family) {
157
0
    case AF_INET:
158
0
        satosin(ia)->sin_port = 0;
159
0
        return;
160
161
0
    case AF_INET6:
162
0
        satosin6(ia)->sin6_port = 0;
163
0
        return;
164
165
0
    default:
166
0
        break;
167
0
    }
168
    /* Can't happen */
169
0
    abort();
170
0
}
171
172
char *
173
addr2char_r(const struct sockaddr *ia, char *buf, int size)
174
0
{
175
0
    void *addr;
176
177
0
    switch (ia->sa_family) {
178
0
    case AF_INET:
179
0
  addr = &(satosin(ia)->sin_addr);
180
0
  break;
181
182
0
    case AF_INET6:
183
0
  addr = &(satosin6(ia)->sin6_addr);
184
0
  break;
185
186
0
    default:
187
0
  abort();
188
0
    }
189
190
0
    return (char *)((void *)inet_ntop(ia->sa_family, addr, buf, size));
191
0
}
192
193
char *
194
addrport2char_r(const struct sockaddr *ia, char *buf, int size, char portsep)
195
0
{
196
0
    char abuf[MAX_ADDR_STRLEN];
197
0
    const char *bs, *es;
198
199
0
    switch (ia->sa_family) {
200
0
    case AF_INET:
201
0
        bs = es = "";
202
0
        break;
203
204
0
    case AF_INET6:
205
0
        bs = "[";
206
0
        es = "]";
207
0
        break;
208
209
0
    default:
210
0
        abort();
211
0
    }
212
213
0
    if (addr2char_r(ia, abuf, MAX_ADDR_STRLEN) == NULL)
214
0
        return (NULL);
215
0
    snprintf(buf, size, "%s%s%s%c%u", bs, abuf, es, portsep, getport(ia));
216
0
    return (buf);
217
0
}
218
219
int
220
resolve(struct sockaddr *ia, int pf, const char *host,
221
  const char *servname, int flags)
222
262k
{
223
262k
    int n;
224
262k
    struct addrinfo hints, *res;
225
226
262k
    memset(&hints, 0, sizeof(hints));
227
262k
    hints.ai_flags = flags;      /* We create listening sockets */
228
262k
    hints.ai_family = pf;        /* Protocol family */
229
262k
    hints.ai_socktype = SOCK_DGRAM;     /* UDP */
230
231
262k
    n = getaddrinfo(host, servname, &hints, &res);
232
262k
    if (n == 0) {
233
  /* Use the first socket address returned */
234
262k
  memcpy(ia, res->ai_addr, res->ai_addrlen);
235
262k
  freeaddrinfo(res);
236
262k
    }
237
238
262k
    return n;
239
262k
}
240
241
#if !defined(BYTE_ORDER)
242
# error "BYTE_ORDER needs to be defined"
243
#endif
244
245
/*
246
 * Checksum routine for Internet Protocol family headers.
247
 */
248
uint16_t
249
rtpp_in_cksum(void *p, int len)
250
0
{
251
0
    int sum = 0, oddbyte = 0, v = 0;
252
0
    u_char *cp = p;
253
254
    /* we assume < 2^16 bytes being summed */
255
0
    while (len > 0) {
256
0
        if (oddbyte) {
257
0
            sum += v + *cp++;
258
0
            len--;
259
0
        }
260
0
        if (((long)cp & 1) == 0) {
261
0
            while ((len -= 2) >= 0) {
262
0
                sum += *(u_short *)cp;
263
0
                cp += 2;
264
0
            }
265
0
        } else {
266
0
            while ((len -= 2) >= 0) {
267
#if BYTE_ORDER == BIG_ENDIAN
268
                sum += *cp++ << 8;
269
                sum += *cp++;
270
#else
271
0
                sum += *cp++;
272
0
                sum += *cp++ << 8;
273
0
#endif
274
0
            }
275
0
        }
276
0
        if ((oddbyte = len & 1) != 0) {
277
#if BYTE_ORDER == BIG_ENDIAN
278
            v = *cp << 8;
279
#else
280
0
            v = *cp;
281
0
#endif
282
0
        }
283
0
    }
284
0
    if (oddbyte)
285
0
        sum += v;
286
0
    sum = (sum >> 16) + (sum & 0xffff); /* add in accumulated carries */
287
0
    sum += sum >> 16;               /* add potential last carry */
288
0
    return (0xffff & ~sum);
289
0
}
290
291
int
292
local4remote(const struct sockaddr *ra, struct sockaddr_storage *la)
293
10
{
294
10
    int s, r;
295
10
    socklen_t llen;
296
297
10
    s = socket(ra->sa_family, SOCK_DGRAM, 0);
298
10
    if (s == -1) {
299
0
        return (-1);
300
0
    }
301
10
    if (connect(s, ra, SA_LEN(ra)) == -1) {
302
0
        close(s);
303
0
        return (-1);
304
0
    }
305
10
    llen = sizeof(*la);
306
10
    r = getsockname(s, sstosa(la), &llen);
307
10
    close(s);
308
10
    return (r);
309
10
}
310
311
int
312
extractaddr(const char *str, const char **begin, const char **end, int *pf)
313
262k
{
314
262k
    const char *t;
315
262k
    int tpf;
316
317
262k
    if (*str != '[') {
318
261k
  tpf = AF_INET;
319
536k
  for (t = str; *str != '\0'; str++) {
320
536k
      if (!isdigit(*str) && *str != '.')
321
261k
    break;
322
536k
  }
323
261k
    } else {
324
494
  tpf = AF_INET6;
325
494
  str++;
326
3.57k
  for (t = str; *str != '\0'; str++) {
327
3.57k
      if (!isxdigit(*str) && *str != ':')
328
488
    break;
329
3.57k
  }
330
494
  if (*str != ']')
331
25
      return (-1);
332
494
    }
333
262k
    if (t == str)
334
160
  return (-1);
335
262k
    if (tpf == AF_INET6)
336
462
  *end = (char *)(str + 1);
337
261k
    else
338
261k
  *end = (char *)str;
339
262k
    *pf = tpf;
340
262k
    *begin = (char *)t;
341
262k
    return(str - t);
342
262k
}
343
344
int
345
setbindhost(struct sockaddr *ia, int pf, const char *bindhost,
346
  const char *servname)
347
0
{
348
0
    int n;
349
350
    /*
351
     * If user specified * then change it to NULL,
352
     * that will make getaddrinfo to return addr_any socket
353
     */
354
0
    if (bindhost && (strcmp(bindhost, "*") == 0))
355
0
  bindhost = NULL;
356
357
0
    if ((n = resolve(ia, pf, bindhost, servname, AI_PASSIVE)) != 0) {
358
0
  warnx("setbindhost: %s for %s %s", gai_strerror(n), bindhost, servname);
359
0
  return -1;
360
0
    }
361
0
    return 0;
362
0
}