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