Coverage Report

Created: 2025-07-09 06:29

/src/opensips/ip_addr.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * ip address & address family related functions
3
 *
4
 * Copyright (C) 2001-2003 FhG Fokus
5
 *
6
 * This file is part of opensips, a free SIP server.
7
 *
8
 * opensips is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 2 of the License, or
11
 * (at your option) any later version
12
 *
13
 * opensips is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
21
 *
22
 * History:
23
 * --------
24
 *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free
25
 *  2004-10-01  mk_net fixes bad network addresses now (andrei)
26
 */
27
28
/*!
29
 * \file
30
 * \brief OpenSIPS IP address & address family related functions
31
 */
32
33
#include <stdlib.h>
34
#include <stdio.h>
35
36
#include "ut.h"
37
#include "ip_addr.h"
38
#include "dprint.h"
39
#include "mem/mem.h"
40
41
char _ip_addr_A_buffs[IP_ADDR2STR_BUF_NO][IP_ADDR_MAX_STR_SIZE];
42
43
struct net* mk_net(const struct ip_addr* ip, struct ip_addr* mask)
44
0
{
45
0
  struct net* n;
46
0
  int warning;
47
0
  unsigned int r;
48
49
0
  warning=0;
50
0
  if ((ip->af != mask->af) || (ip->len != mask->len)){
51
0
    LM_CRIT("trying to use a different mask family"
52
0
        " (eg. ipv4/ipv6mask or ipv6/ipv4mask)\n");
53
0
    goto error;
54
0
  }
55
0
  n=(struct net*)pkg_malloc(sizeof(struct net));
56
0
  if (n==0){
57
0
    LM_CRIT("memory allocation failure\n");
58
0
    goto error;
59
0
  }
60
0
  n->ip=*ip;
61
0
  n->mask=*mask;
62
0
  for (r=0; r<n->ip.len/4; r++) { /*ipv4 & ipv6 addresses are multiple of 4*/
63
0
    n->ip.u.addr32[r] &= n->mask.u.addr32[r];
64
0
    if (n->ip.u.addr32[r]!=ip->u.addr32[r]) warning=1;
65
0
  };
66
0
  if (warning){
67
0
    LM_WARN("invalid network address/netmask "
68
0
          "combination fixed...\n");
69
0
    print_ip("original network address:", ip, "/");
70
0
    print_ip("", mask, "\n");
71
0
    print_ip("fixed    network address:", &(n->ip), "/");
72
0
    print_ip("", &(n->mask), "\n");
73
0
  };
74
0
  return n;
75
0
error:
76
0
  return 0;
77
0
}
78
79
80
81
struct net* mk_net_bitlen(const struct ip_addr* ip, unsigned int bitlen)
82
0
{
83
0
  struct ip_addr mask;
84
0
  unsigned int r;
85
86
0
  if (bitlen>ip->len*8){
87
0
    LM_CRIT("bad bitlen number %d\n", bitlen);
88
0
    goto error;
89
0
  }
90
0
  memset(&mask,0, sizeof(mask));
91
0
  for (r=0;r<bitlen/8;r++) mask.u.addr[r]=0xff;
92
0
  if (bitlen%8) mask.u.addr[r]=  ~((1<<(8-(bitlen%8)))-1);
93
0
  mask.af=ip->af;
94
0
  mask.len=ip->len;
95
96
0
  return mk_net(ip, &mask);
97
0
error:
98
0
  return 0;
99
0
}
100
101
102
103
void print_ip(char* p, const struct ip_addr* ip, char *s)
104
0
{
105
0
  switch(ip->af){
106
0
    case AF_INET:
107
0
      LM_DBG("%s%d.%d.%d.%d%s", (p)?p:"",
108
0
                ip->u.addr[0],
109
0
                ip->u.addr[1],
110
0
                ip->u.addr[2],
111
0
                ip->u.addr[3],
112
0
                (s)?s:""
113
0
                );
114
0
      break;
115
0
    case AF_INET6:
116
0
      LM_DBG("%s%x:%x:%x:%x:%x:%x:%x:%x%s", (p)?p:"",
117
0
                      htons(ip->u.addr16[0]),
118
0
                      htons(ip->u.addr16[1]),
119
0
                      htons(ip->u.addr16[2]),
120
0
                      htons(ip->u.addr16[3]),
121
0
                      htons(ip->u.addr16[4]),
122
0
                      htons(ip->u.addr16[5]),
123
0
                      htons(ip->u.addr16[6]),
124
0
                      htons(ip->u.addr16[7]),
125
0
                      (s)?s:""
126
0
        );
127
0
      break;
128
0
    default:
129
0
      LM_DBG("warning unknown address family %d\n", ip->af);
130
0
  }
131
0
}
132
133
134
135
void stdout_print_ip(struct ip_addr* ip)
136
0
{
137
0
  switch(ip->af){
138
0
    case AF_INET:
139
0
      printf("%d.%d.%d.%d", ip->u.addr[0],
140
0
                ip->u.addr[1],
141
0
                ip->u.addr[2],
142
0
                ip->u.addr[3]);
143
0
      break;
144
0
    case AF_INET6:
145
0
      printf("%x:%x:%x:%x:%x:%x:%x:%x", htons(ip->u.addr16[0]),
146
0
                      htons(ip->u.addr16[1]),
147
0
                      htons(ip->u.addr16[2]),
148
0
                      htons(ip->u.addr16[3]),
149
0
                      htons(ip->u.addr16[4]),
150
0
                      htons(ip->u.addr16[5]),
151
0
                      htons(ip->u.addr16[6]),
152
0
                      htons(ip->u.addr16[7])
153
0
        );
154
0
      break;
155
0
    default:
156
0
      LM_DBG("warning unknown address family %d\n", ip->af);
157
0
  }
158
0
}
159
160
161
162
void print_net(struct net* net)
163
0
{
164
0
  if (net==0){
165
0
    LM_WARN("null pointer\n");
166
0
    return;
167
0
  }
168
0
  print_ip("", &net->ip, "/"); print_ip("", &net->mask, "");
169
0
}
170
171
172
int ip_addr_is_1918(str *s_ip, int check_rfc_6333)
173
0
{
174
0
  static struct {
175
0
    uint32_t netaddr;
176
0
    uint32_t mask;
177
0
  } nets_1918[] = {
178
0
    { 0x0a000000, 0xffffffffu << 24},  /* "10.0.0.0"    RFC 1918 */
179
0
    { 0xac100000, 0xffffffffu << 20},  /* "172.16.0.0"  RFC 1918 */
180
0
    { 0xc0a80000, 0xffffffffu << 16},  /* "192.168.0.0" RFC 1918 */
181
0
    { 0x64400000, 0xffffffffu << 22},  /* "100.64.0.0"  RFC 6598 */
182
0
    { 0x7f000000, 0xffffffffu << 24},  /* "127.0.0.0"   RFC 1122 */
183
0
    { 0xc0000000, 0xffffffffu << 3},   /* "192.0.0.0"   RFC 6333 */
184
0
    { 0, 0}
185
0
  };
186
0
  struct ip_addr *ip;
187
0
  uint32_t netaddr;
188
0
  int i;
189
190
0
  if (!check_rfc_6333)
191
0
    nets_1918[5].netaddr = 0;
192
193
  /* is it an IPv4 address? */
194
0
  if ( (ip=str2ip(s_ip))==NULL )
195
0
    return 0;
196
197
0
  netaddr = ntohl(ip->u.addr32[0]);
198
199
0
  for (i = 0; nets_1918[i].netaddr != 0; i++) {
200
0
    if ((netaddr & nets_1918[i].mask) == nets_1918[i].netaddr)
201
0
      return 1;
202
0
  }
203
204
0
  return 0;
205
0
}
206
207
208
#ifdef USE_MCAST
209
210
/* Returns 1 if the given address is a multicast address */
211
int is_mcast(struct ip_addr* ip)
212
{
213
  if (!ip){
214
    LM_ERR("invalid parameter value\n");
215
    return -1;
216
  }
217
218
  if (ip->af==AF_INET){
219
    return IN_MULTICAST(htonl(ip->u.addr32[0]));
220
  } else if (ip->af==AF_INET6){
221
    return IN6_IS_ADDR_MULTICAST((struct in6_addr *)(void *)ip->u.addr);
222
  } else {
223
    LM_ERR("unsupported protocol family\n");
224
    return -1;
225
  }
226
}
227
228
int mk_net_cidr(const str *cidr, struct net *out_net)
229
{
230
  str ip_str, px_str;
231
  unsigned int prefix_len = UINT_MAX;
232
  struct ip_addr *ip;
233
  struct net *tmp_cidr;
234
  char *c;
235
236
  ip_str.s = cidr->s;
237
238
  c = q_memchr(ip_str.s, '/', cidr->len);
239
  if (c) {
240
    ip_str.len = c - ip_str.s;
241
    px_str.s = c + 1;
242
    px_str.len = cidr->len - ip_str.len - 1;
243
244
    if (px_str.len > 0 && str2int(&px_str, &prefix_len) != 0) {
245
      LM_ERR("bad characters in network prefix length (CIDR: %.*s)\n",
246
              cidr->len, cidr->s);
247
      goto error;
248
    }
249
  } else {
250
    ip_str.len = cidr->len;
251
  }
252
253
  if (!(ip=str2ip(&ip_str)) && !(ip=str2ip6(&ip_str))) {
254
    LM_ERR("invalid IP address <%.*s>\n", ip_str.len, ip_str.s);
255
    goto error;
256
  }
257
258
  if (prefix_len == UINT_MAX)
259
    prefix_len = (ip->af == AF_INET ? 32 : 128);
260
261
  /* now that we know the AF family, we can validate the prefix len */
262
  if ((ip->af==AF_INET && prefix_len>32) ||
263
          (ip->af==AF_INET6 && prefix_len>128)) {
264
    LM_ERR("network prefix length %d too large for AF %d (ip: %.*s)\n",
265
            prefix_len, ip->af, ip_str.len, ip_str.s);
266
    goto error;
267
  }
268
269
  tmp_cidr = mk_net_bitlen(ip, prefix_len);
270
  if (!tmp_cidr) {
271
    LM_ERR("oom\n");
272
    goto error;
273
  }
274
275
  *out_net = *tmp_cidr;
276
  pkg_free(tmp_cidr);
277
  return 0;
278
279
error:
280
  memset(out_net, 0, sizeof *out_net);
281
  return -1;
282
}
283
284
#endif /* USE_MCAST */