1 /*
2 */
3
4 #include "graph.h"
5
6 #include <arpa/inet.h>
7
8 /******************************************************************************
9 IP address functions
10 ******************************************************************************/
11
12 /*
13 * Returns 0 (error) or 1 (ok)
14 */
15
ip_pton(char * text,ip_t * cidr)16 int ip_pton (char *text, ip_t *cidr)
17 {
18 int r ;
19 char *p ;
20 char addr [IPADDRLEN] ;
21
22 r = 1 ;
23
24 strncpy (addr, text, sizeof addr) ;
25 p = strchr (addr, '/') ;
26 if (p == NULL)
27 cidr->preflen = -1 ;
28 else
29 {
30 *p = '\0' ;
31 cidr->preflen = atoi (p + 1) ;
32 }
33
34 switch (inet_pton (AF_INET6, addr, &cidr->u.adr6))
35 {
36 case -1 : /* system error */
37 r = 0 ;
38 break ;
39 case 0 : /* not parseable with AF_INET6 */
40 switch (inet_pton (AF_INET, addr, &cidr->u.adr4))
41 {
42 case -1 : /* system error */
43 r = 0 ;
44 break ;
45 case 0 : /* not parseable with AF_INET */
46 r = 0 ;
47 break ;
48 case 1 : /* Ok with AF_INET */
49 if (cidr->preflen < 0)
50 cidr->preflen = 32 ;
51 else if (cidr->preflen > 32)
52 r = 0 ;
53 cidr->family = INET4 ;
54 break ;
55 default : /* not possible... */
56 r = 0 ;
57 break ;
58 }
59 break ;
60 case 1 : /* Ok with AF_INET6 */
61 if (cidr->preflen < 0)
62 cidr->preflen = 128 ;
63 else if (cidr->preflen > 128)
64 r = 0 ;
65 cidr->family = INET6 ;
66 break ;
67 default : /* not possible... */
68 r = 0 ;
69 break ;
70 }
71
72 if (p != NULL)
73 *p = '/' ; /* leave input string the same as before */
74
75 return r ;
76 }
77
ip_ntop(ip_t * cidr,iptext_t text,int prefix)78 int ip_ntop (ip_t *cidr, iptext_t text, int prefix)
79 {
80 const char *p ;
81 int l ;
82 int size ;
83
84 size = sizeof (iptext_t) ;
85 switch (cidr->family)
86 {
87 case INET4 :
88 p = inet_ntop (AF_INET, &cidr->u.adr4, text, size) ;
89 break ;
90 case INET6 :
91 p = inet_ntop (AF_INET6, &cidr->u.adr6, text, size) ;
92 break ;
93 default :
94 p = NULL ;
95 break ;
96 }
97
98 l = strlen (text) ;
99 if (p != NULL && prefix && l + 4 < size)
100 sprintf (text + l, "/%d", cidr->preflen) ;
101
102 return p != NULL ;
103 }
104
ip_equal(ip_t * adr1,ip_t * adr2)105 int ip_equal (ip_t *adr1, ip_t *adr2)
106 {
107 int r ;
108
109 r = 0 ;
110 if (adr1->family == adr2->family && adr1->preflen == adr2->preflen)
111 {
112 switch (adr1->family)
113 {
114 case INET4 :
115 r = ! bcmp (&adr1->u.adr4, &adr2->u.adr4, sizeof adr1->u.adr4) ;
116 break ;
117 case INET6 :
118 r = ! bcmp (&adr1->u.adr6, &adr2->u.adr6, sizeof adr1->u.adr6) ;
119 break ;
120 }
121 }
122
123 return r ;
124 }
125
126
127 /*
128 * Inspired from bitncmp (ISC)
129 *
130 * Copyright (c) 1996,1999 by Internet Software Consortium.
131 *
132 * Permission to use, copy, modify, and distribute this software for any
133 * purpose with or without fee is hereby granted, provided that the above
134 * copyright notice and this permission notice appear in all copies.
135 *
136 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
137 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
138 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
139 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
140 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
141 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
142 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
143 * SOFTWARE.
144 */
145
prefix_match(void * adr,void * cidr,int preflen)146 int prefix_match (void *adr, void *cidr, int preflen)
147 {
148 unsigned int lb, rb;
149 int x, b;
150
151 b = preflen / 8 ;
152 x = memcmp (adr, cidr, b);
153 if (x == 0)
154 {
155 lb = ((unsigned char *) adr) [b] ;
156 rb = ((unsigned char *) cidr) [b] ;
157 for (b = preflen % 8 ; b > 0 ; b--)
158 {
159 if ((lb & 0x80) != (rb & 0x80)) {
160 if (lb & 0x80)
161 x = 1 ;
162 else x = -1 ;
163 break ;
164 }
165 lb <<= 1 ;
166 rb <<= 1 ;
167 }
168 }
169 return x ;
170 }
171
172 /*
173 * Match the given address with the network address.
174 * Each address has a prefix len inside.
175 * The "prefix" parameter tells if the adress prefix length
176 * must be tested (1) or ignored (0) for the comparison.
177 */
178
ip_match(ip_t * adr,ip_t * network,int prefix)179 int ip_match (ip_t *adr, ip_t *network, int prefix)
180 {
181 int r ;
182
183 if (adr->family != network->family)
184 return 0 ;
185
186 if (prefix && adr->preflen < network->preflen)
187 return 0 ;
188
189 switch (network->family)
190 {
191 case INET4 :
192 r = prefix_match (&adr->u.adr4, &network->u.adr4, network->preflen) ;
193 break ;
194 case INET6 :
195 r = prefix_match (&adr->u.adr6, &network->u.adr6, network->preflen) ;
196 break ;
197 default :
198 r = 1 ;
199 break ;
200 }
201
202 return r == 0 ;
203 }
204
ip_netof(ip_t * srcadr,ip_t * dstadr)205 void ip_netof (ip_t *srcadr, ip_t *dstadr)
206 {
207 unsigned char *s, *d ;
208 unsigned int o, b, mask ;
209
210 bzero (dstadr, sizeof *dstadr) ;
211
212 dstadr->family = srcadr->family ;
213 dstadr->preflen = srcadr->preflen ;
214
215 s = (srcadr->family == INET4) ?
216 (unsigned char *) &srcadr->u.adr4 :
217 (unsigned char *) &srcadr->u.adr6 ;
218 d = (dstadr->family == INET6) ?
219 (unsigned char *) &dstadr->u.adr4 :
220 (unsigned char *) &dstadr->u.adr6 ;
221
222 b = srcadr->preflen ;
223 o = 0 ;
224 while (b)
225 {
226 if (b >= 8)
227 {
228 mask = 0xff ;
229 b -= 8 ;
230 }
231 else
232 {
233 mask = 0xff << (8 - b) ;
234 b = 0 ;
235 }
236 d [o] = s [o] & mask ;
237 o++ ;
238 }
239 }
240