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*)∈
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