core, lib, modules: restructured source code tree
[sip-router] / src / modules / mangler / ip_helper.c
1 /*
2  * Sdp mangler module
3  *
4  * Copyright (C) 2001-2003 FhG Fokus
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * Kamailio 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  * Kamailio 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
23 #include "ip_helper.h"
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdio.h>
27 #include <ctype.h>
28 #include <sys/types.h>
29 #include <netinet/in.h>
30
31 /* given an ip and a mask it provides network address */
32 unsigned int
33 net_address (unsigned int ip, unsigned int mask)
34 {
35         return (ip & mask);
36 }
37
38 /*
39         returns 1 if ip belongs to address/net or 0 if not
40 */
41 int
42 same_net (unsigned int ip, unsigned int address, unsigned int mask)
43 {
44         return ((address & mask) == (ip & mask));
45 }
46
47
48 /* Small help func takes ip-address-integer and returns string
49    representation */
50 void
51 ip2str (unsigned int address, char **rr)
52 {
53         int i;
54         char *hlp, hlp2[5];     /* initial era hlp2[18] */
55         unsigned char *addrp = (unsigned char *) &address;
56         hlp = (char *) malloc (18);
57         hlp[0] = '\0';
58
59         for (i = 0; i < 3; i++)
60         {
61                 sprintf (hlp2, "%i.", addrp[i]);
62                 hlp = strcat (hlp, (char *) hlp2);
63         }
64         sprintf (hlp2, "%i", addrp[3]);
65         hlp = strcat (hlp, hlp2);
66         *rr = hlp;
67 }
68
69 /* Small help func takes ip-address-string, determines its validity
70    and write the integer representation at address.
71    Returns 1 if successful converted, 0 if the dotted isn't valid.
72    If you want to parse IP/netmask pairs, call parse_ip_netmask
73    first - it will remove the netmask, then use this func */
74 int
75 parse_ip_address (char *c, unsigned int *address)       //inet_aton
76 {
77         int quat, i, j, digit_bol;
78         char buf[20];
79         char *p, *q, *r;
80         unsigned char *addrp;
81
82         if (c == NULL)
83                 return 0;
84         if (strlen (c) >= 16)
85                 return 0;
86
87         quat = 0;
88         digit_bol = 1;
89         buf[0] = '\0';
90         /* cool dirty hack to address the bytes of the int easily */
91         addrp = (unsigned char *) address;
92
93         /* make a copy of the dotted string, because we modify it */
94         strncpy (buf, c, 20);
95         p = buf;
96
97         /* search three times for a dot in the string */
98         for (i = 0; i < 3; i++)
99         {
100                 if ((q = strchr (p, '.')) == NULL)
101                         return 0;
102                 else
103                 {
104                         *q = '\0';      /* cut off at the dot */
105                         if (strlen (p)) /* is the distance between dots greater 0 */
106                         {
107                                 r = p;
108                                 for (j = 0; j < strlen (p); j++, r++)   /* are all char of the
109                                                                          * byte digits */
110                                         digit_bol = digit_bol && isdigit ((unsigned char)*r);
111                                 if (digit_bol)
112                                 {
113                                         quat = atoi (p);
114                                         if (quat > 255) /* is it a byte or greater */
115                                                 return 0;
116                                         else
117                                                 addrp[i] =
118                                                         (unsigned char) quat;
119                                 }
120                                 else
121                                         return 0;
122                         }
123                         else
124                                 return 0;
125                 }
126                 p = q + 1;
127         }                       /* for */
128
129         /* and the last byte */
130         if (strlen (p))
131         {
132                 r = p;
133                 for (j = 0; j < strlen (p); j++, r++)
134                         digit_bol = digit_bol && isdigit ((unsigned char)*r);
135                 if (digit_bol)
136                 {
137                         quat = atoi (p);
138                         if (quat > 255)
139                                 {
140                                 return 0;
141                                 }
142                         else
143                                 addrp[3] = (unsigned char) quat;
144                         return 1;
145                 }
146                 else
147                         {
148                         return 0;
149                         }
150         }
151         else
152                 {
153                 return 0;
154                 }
155 }
156
157 /* return 1 if ALL str is a positive number or 0. no + signs allowed*/
158 int
159 is_positive_number (char *str)
160 {
161         int i;
162         if (str == NULL)
163                 return 0;
164         for (i = 0; i < strlen (str); i++)
165         {
166                 if (isdigit ((unsigned char)str[i]) == 0)
167                         return 0;
168         }
169         return 1;
170 }
171
172 /* return 0 in case of error */
173 unsigned int
174 make_mask (unsigned int length)
175 {
176         unsigned int res;
177         if ((length < 8) || (length > 30))
178                 return -1;      /* invalid value for mask */
179         /* fill it with 1 */
180         res = 0xFFFFFFFF;
181         /* shift it to right with 32-length positions */
182         res = htonl (res << (32 - length));
183         return res;
184 }
185
186 /* Small help func takes ip-address-string, determines if a valid
187    netmask is specified and inserts the netmask into mask.
188    Cuts of the netmask of the string, if it founds a netmask !!!
189    Returns 0 if no netmask found, -1 if netmask isn't valid, and
190    1 if successful.  
191         According to this function a mask is in form of 255.255.192.0
192         so an ip/mask looks like 10.0.0.0/255.255.192.0
193         we will extend it to 10.0.0.0/18 which will be also valid
194 */
195 int
196 parse_ip_netmask (char *c, char **ip, unsigned int *mask)
197 {
198         char *p, *q;
199         unsigned int netmask;
200
201         if (c == NULL)
202         {
203                 return -10;
204         }
205         p = c;
206
207
208         if ((q = strchr (p, '/')) == NULL)
209         {
210                 *mask = 0xFFFFFFFF;
211                 return 0;       /* no mask */
212         }
213         else
214         {
215                 *ip = (char *) malloc (q - p + 1);
216                 if ((*ip) == NULL)
217                         return -2;
218                 memcpy (*ip, p, q - p);
219                 (*ip)[q - p] = 0;
220
221                 // wrong (*q) = 0;                            /* cut of the netmask */
222                 q++;
223                 /*
224                  * two possibilities /16 or /255.255.192.0
225                  */
226                 if (is_positive_number (q) == 1)
227                 {
228                         /* we have a /16 mask */
229                         if ((netmask = make_mask (atoi (q))) == 0)
230                         {
231                                 *mask = 0;      /* error in value of /43 or something like */
232                                 return -1;
233                         }
234                         else
235                         {
236                                 *mask = netmask;
237                                 return 1;
238                         }
239                 }
240                 else /* we may have a 255.255.192.0 mask */ if (parse_ip_address (q, &netmask) == 1)    /* and parse the netmask */
241                 {
242                         *mask = netmask;
243                         return 1;
244                 }
245                 else
246                 {
247                         *mask = 0;
248                         return -1;
249                 }
250         }
251 }
252