-
Notifications
You must be signed in to change notification settings - Fork 8
/
range.c
147 lines (127 loc) · 3.65 KB
/
range.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <sys/types.h>
#ifdef WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#include "range.h"
#include "errors.h"
#ifndef INADDR_NONE
# define INADDR_NONE (in_addr_t)-1
#endif
extern int quiet;
/* is_ip checks if supplied string is an ip address in dotted-decimal
notation, and fills both members of range structure with its numerical value
(host byte order)/ Returns 1 on success, 0 on failure */
int is_ip(char* string, struct ip_range* range) {
unsigned long addr;
addr = inet_addr(string);
if(addr != INADDR_NONE) {
range->start_ip = ntohl(addr);
range->end_ip = ntohl(addr);
return 1;
} else return 0;
};
/* is_range1 checks if supplied string is an IP address range in
form xxx.xxx.xxx.xxx/xx (as in 192.168.1.2/24) and fills
range structure with start and end ip addresses of the interval.
Returns 1 on success, 0 on failure */
int is_range1(char* string, struct ip_range* range) {
char* separator;
unsigned long mask;
char* ip;
if((ip = (char *)malloc(strlen(string)+1))==NULL)
err_die("Malloc failed", quiet);
if (strlen(string)>19) return 0;
if(separator=(char*)strchr(string,'/')) {
separator++;
mask=atoi(separator);
if(mask<=0 || mask>32) return 0;
strcpy(ip, string);
ip[abs(string-separator)-1]=0;
if((range->start_ip=inet_addr(ip)) == INADDR_NONE) return 0;
/* mask=((1<<mask)-1)<<(sizeof(mask)*8-mask); */
if (mask == 32)
mask = ~0;
else
mask=((1<<mask)-1)<<(sizeof(mask)*8-mask);
range->start_ip=ntohl(range->start_ip); // We store ips in host byte order
range->start_ip &= mask;
range->end_ip = range->start_ip | ( ~ mask);
free(ip);
return 1;
}
free(ip);
return 0;
};
/* next_address function writes next ip address in range after prev_addr to
structure pointed by next_addr. Returns 1 if next ip found and 0 otherwise */
int next_address(const struct ip_range* range, const struct in_addr* prev_addr,
struct in_addr* next_addr) {
unsigned long pa; // previous address, host byte order
if(prev_addr) {
pa = ntohl(prev_addr->s_addr);
if(pa < range->end_ip) {
next_addr->s_addr=htonl(++pa);
return 1;
} else return 0;
} else {
next_addr->s_addr=htonl(range->start_ip);
return 1;
};
};
/* is_range2 checks if supplied string is an IP address range in
form xxx.xxx.xxx.xxx-xxx (as in 192.168.1.2-15) and fills
range structure with start and end ip addresses of the interval.
Returns 1 on success, 0 on failure */
int is_range2(char* string, struct ip_range* range) {
unsigned long last_octet; /*last octet of last ip in range*/
char* separator;
unsigned long addr;
char* ip;
if((ip = (char *)malloc(strlen(string)+1))==NULL)
err_die("Malloc failed", quiet);
strcpy(ip,string);
if(separator = (char*)strchr(ip,'-')) {
*separator=0;
separator++;
last_octet = atoi(separator);
if(last_octet<0 || last_octet > 255) {
free(ip);
return 0;
};
addr = inet_addr(ip);
if(addr == INADDR_NONE) {
free(ip);
return 0;
};
range->start_ip = ntohl(addr);
range->end_ip = (range->start_ip & 0xffffff00) | last_octet;
if (range->end_ip < range->start_ip) {
free(ip);
return 0;
};
free(ip);
return 1;
}
free(ip);
return 0;
};
int print_range(const struct ip_range* range) {
struct in_addr *addr;
if((addr = (struct in_addr*)malloc(sizeof(struct in_addr)))==NULL)
err_die("Malloc failed", quiet);
next_address(range, 0, addr);
printf("%s\n",inet_ntoa(*addr));
while(next_address(range, addr, addr)) {
printf("%s\n",inet_ntoa(*addr));
};
free(addr);
};