1 /*
2  *  IPV4.c
3  *
4  *	Copyright 2007 VOSTROM Holdings, Inc.
5  *  This file is part of the Distribution.  See the file COPYING for details.
6  */
7 
8 #include <stdio.h>
9 #include <unistd.h>
10 #include <stdlib.h>
11 #include <sys/types.h>
12 #include <sys/socket.h>
13 #include <netinet/in.h>
14 #include <arpa/inet.h>
15 #include <string.h>
16 #include "IPV4u.h"
17 
own_i2a(char * dest,unsigned int x)18 static unsigned int own_i2a(char* dest, unsigned int x)
19 {
20 	register unsigned int tmp=x;
21 	register unsigned int len=0;
22 	if(x>=100)
23 	{
24 		*dest++=tmp/100+'0';
25 		tmp=tmp%100;
26 		++len;
27 	}
28 	if(x>=10)
29 	{
30 		*dest++=tmp/10+'0';
31 		tmp=tmp%10;
32 		++len;
33 	}
34 	*dest++=tmp+'0';
35 	return len+1;
36 }
37 
own_getipsize(unsigned char * ip)38 static int own_getipsize(unsigned char *ip)
39 {
40 	int sz=7; //at least
41 	int i;
42 	for(i=0;i<4;i++)
43 	{
44 		if(ip[i]>9)
45 			sz++;
46 		if(ip[i]>99)
47 			sz++;
48 	}
49 	return sz;
50 }
51 
own_inet_ntoa_r(struct in_addr in,char * buf,int sz)52 char *own_inet_ntoa_r(struct in_addr in,char* buf,int sz)
53 {
54 	unsigned int len;
55 	unsigned char *ip=(unsigned char*)&in;
56 	if(sz<own_getipsize(ip))
57 		return NULL;
58 	len =own_i2a(buf    ,ip[0]); buf[len]='.'; ++len;
59 	len+=own_i2a(buf+len,ip[1]); buf[len]='.'; ++len;
60 	len+=own_i2a(buf+len,ip[2]); buf[len]='.'; ++len;
61 	len+=own_i2a(buf+len,ip[3]); buf[len]=0;
62 	return buf;
63 }
64 
decimal_to_bytes(unsigned long ip,unsigned char * bytes)65 void decimal_to_bytes(unsigned long ip, unsigned char * bytes)
66 {
67     unsigned long netip;
68     unsigned char * p;
69     int i;
70     p=(unsigned char *)&netip;
71     netip=htonl(ip);
72     for(i=0;i<4;i++)
73         bytes[i]=p[i];
74 }
75 
ipv4_decimal_to_quaddot(unsigned long network,char * str,int sz)76 char* ipv4_decimal_to_quaddot(unsigned long network, char* str, int sz)
77 {
78     struct in_addr tmpaddr;
79     tmpaddr.s_addr=htonl(network);
80 
81 	if(str == NULL) return str;
82 
83 	/* thread safe versions */
84 	//addr2ascii(AF_INET, &tmpaddr.s_addr, sizeof(tmpaddr.s_addr), str);
85 	return own_inet_ntoa_r(tmpaddr, str, sz);
86 }
87 
ipv4_quaddot_to_decimal(char * quaddot,unsigned long * result)88 int ipv4_quaddot_to_decimal(char * quaddot, unsigned long * result)
89 {
90     struct in_addr tmpaddr;
91     if(!inet_aton(quaddot, &tmpaddr) )
92     {
93         return -1;
94     }
95     result[0]=ntohl(tmpaddr.s_addr);
96     return 0;
97 }
98 
ipv4_dflt_netmask(char * ip)99 char *ipv4_dflt_netmask(char * ip)
100 {
101     int a,b,c,d,cidr,r;
102     if(strchr(ip,'/')!= NULL)
103         r = sscanf(ip,"%3d.%3d.%3d.%3d/%2d",&a,&b,&c,&d,&cidr);
104 	else
105 		r= sscanf(ip,"%3d.%3d.%3d.%3d",&a,&b,&c,&d);
106    if(a <= 127)
107        return "255.0.0.0";
108    if(a <=191)
109        return "255.255.0.0";
110    return "255.255.255.0";
111 }
112 
ipv4_is_valid_quaddot(char * ip)113 int ipv4_is_valid_quaddot(char * ip)
114 {
115     int a,b,c,d,cidr,length;
116     int r = sscanf(ip,"%3d.%3d.%3d.%3d/%2d",&a,&b,&c,&d,&cidr);
117     length=strlen(ip);
118 
119     if(r<4 || (r==4 && length>16) || length > 19)
120         return 0;
121     if(a<0 || a>255 || b<0 || b>255 || c<0 || c>255 || d<0 || d>255 || (r>4 && cidr>32))
122         return 0;
123 
124     return 1;
125 }
126 
ipv4_netrange2cidr(unsigned long begip,unsigned long endip)127 int ipv4_netrange2cidr(unsigned long begip, unsigned long endip)
128 {
129 	int r,msk,i,b[4],e[4];
130 	b[0]=(begip>>24)&0xFF;
131 	b[1]=(begip>>16)&0xFF;
132 	b[2]=(begip>>8)&0xFF;
133 	b[3]=begip&0xFF;
134 	e[0]=(endip>>24)&0xFF;
135 	e[1]=(endip>>16)&0xFF;
136 	e[2]=(endip>>8)&0xFF;
137 	e[3]=endip&0xFF;
138 
139     for(r=0,i=0;i<4;i++)
140     {
141         if(b[i]==e[i])
142             r+=8;
143         else
144         {
145             for(msk=0x0080;msk && (b[i] & msk) == (e[i] & msk);msk>>=1)
146                 r++;
147             break;
148         }
149     }
150 	return r;
151 }
152 
ipv4_msk2cidr(char * s)153 int ipv4_msk2cidr(char * s)
154 {
155 	int b[4];
156 	int r,msk,i;
157     if(!ipv4_is_valid_quaddot(s))
158         return -1;
159 
160     sscanf(s,"%3d.%3d.%3d.%3d",b,b+1,b+2,b+3);
161     for(r=0,i=0;i<4;i++)
162     {
163         if(b[i]==0x00FF)
164             r+=8;
165         else
166         {
167             for(msk=0x0080;msk && (b[i] & msk);msk>>=1)
168                 r++;
169             break;
170         }
171     }
172 
173     return r;
174 }
175 
ipv4_parse(char * inputIP,char * outputIP,char * outputMsk)176 void ipv4_parse(char * inputIP, char *outputIP, char *outputMsk)
177 {
178     int a,b,c,d,e;
179     char * cidr;
180     if(!ipv4_is_valid_quaddot(inputIP))
181     {
182         outputIP[0]=0;
183         outputMsk[0]=0;
184         return;
185     }
186     cidr=strchr(inputIP,'/');
187     if(cidr)
188     {
189         sscanf(inputIP,"%3d.%3d.%3d.%3d/%2d",&a,&b,&c,&d,&e);
190         cidr[0]=0;
191         strcpy(outputIP,inputIP);
192         cidr[0]='/';
193         cidr++;
194         strcpy(outputMsk,cidr);
195     }
196     else
197     {
198         strcpy(outputIP,inputIP);
199         outputMsk[0]=0;
200     }
201 }
202 
ipv4_cidr2msk(int inputCidr,char * maskBuf)203 char * ipv4_cidr2msk(int inputCidr, char * maskBuf)
204 {
205     int b[4];
206     int i,msk;
207     if(inputCidr>32)
208         return NULL;
209     for(i=0;i<4;i++)
210     {
211         if(inputCidr>7)
212         {
213             b[i]=0x00FF;
214             inputCidr-=8;
215         }
216         else
217         {
218             b[i]=0;
219             if(inputCidr)
220             {
221                 for(msk=0x0080;inputCidr;inputCidr--,msk>>=1)
222                     b[i]|=msk;
223             }
224         }
225     }
226     sprintf(maskBuf,"%d.%d.%d.%d",b[0],b[1],b[2],b[3]);
227 	return maskBuf;
228 }
229 
ipv4_network(char * ipAddress,int inputCidr,char * network)230 char* ipv4_network(char * ipAddress, int inputCidr, char * network)
231 {
232     char ipMask[50];
233     unsigned long addr,mask;
234 	char str[20];
235 
236     if(ipv4_quaddot_to_decimal(ipAddress, &addr)<0)
237         return NULL;
238     if(!inputCidr)
239         inputCidr=ipv4_msk2cidr(ipv4_dflt_netmask(ipAddress));
240     ipv4_cidr2msk(inputCidr, ipMask);
241     if(ipv4_quaddot_to_decimal(ipMask, &mask)<0)
242         return NULL;
243 
244     sprintf(network,"%s/%d",ipv4_decimal_to_quaddot(addr&mask, str, 20),inputCidr);
245     return network;
246 }
247 
ipv4_in_network(char * ipAddress1,int cidr1,char * ipAddress2,int cidr2)248 int ipv4_in_network(char* ipAddress1,int cidr1,char *ipAddress2,int cidr2)
249 {
250     char net1[50],net2[50];
251     if(!ipv4_is_valid_quaddot(ipAddress1) || !ipv4_is_valid_quaddot(ipAddress2))
252         return 0;
253     if( strcmp(ipAddress1,"255.255.255.255")==0 || strcmp(ipAddress1,"0.0.0.0")==0 ||
254         strcmp(ipAddress1,"255.255.255.255")==0 || strcmp(ipAddress1,"0.0.0.0")==0)
255         return 0;
256     if(!cidr1 || cidr1==32)
257     {
258         if(cidr2>0)
259             return 0;
260         if(!strcmp(ipAddress1,ipAddress2))
261             return 1;
262         return 0;
263     }
264     if(!cidr2 || cidr2==32)
265     {
266         ipv4_network(ipAddress1, cidr1, net1);
267         ipv4_network(ipAddress2, cidr1, net2);
268     }
269     else
270     if(cidr2<cidr1)
271     {
272         ipv4_network(ipAddress1, cidr2, net1);
273         ipv4_network(ipAddress2, cidr2, net2);
274     }
275     else
276     {
277         ipv4_network(ipAddress1, cidr1, net1);
278         ipv4_network(ipAddress2, cidr1, net2);
279     }
280     if(!strcmp(net1,net2))
281         return 1;
282     return 0;
283  }
284