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 */ |