-
Notifications
You must be signed in to change notification settings - Fork 3
/
stip.c
220 lines (198 loc) · 9.37 KB
/
stip.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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
//-----------------------------------------------------------------------------------------------------------
// stip.c - STatus IP adress - программа выдает информацию по заданному IP.
//-----------------------------------------------------------------------------------------------------------
#include <stdio.h>
#include "convern.h" // ditobi(), AddZero(), exchs()
//-----------------------------------------------------------------------------------------------------------
// Версия IP протокола.
#define IP_VERSION 4
//-----------------------------------------------------------------------------------------------------------
void print(unsigned char *s);
//-----------------------------------------------------------------------------------------------------------
const char *help =
"Usage: ip4 [Options] IP[/mask]\n\
Usage: ip4 -h\tShow help (this document).\n\n\
Options:\n\
-m\tSet mask in short format, for example: ip4 -m 192.168.0.1/19\n\
\tor ip4 192.168.0.1/19\n\
-M\tSet mask in long format, for example: ip4 -M 192.168.0.1/255.255.224.0\n\n\
Important:\nIf you not use -M option, you must not set Mask after IP,\n\
for example: ip4 192.168.0.1/255.254.0.0 (not right). Mask calculating automaticaly by\n\
the Net Class. For example: ip4 192.168.0.1 (Class C, Mask is 255.255.255.0).\n\
To Set the Mask, you must use -m(default) and -M Options.";
//-----------------------------------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
if(argc > 1)
{
unsigned char ip[IP_VERSION+1] = {0, 0, 0, 0}; // IP и маска, задаваемые пользователем
unsigned char broadcast[IP_VERSION]; // широковещательный адрес
unsigned char net[IP_VERSION]; // адрес сети
unsigned char mask[IP_VERSION] = {255, 255, 255, 255}; // расчитываемая маска
unsigned char invmask[IP_VERSION]; // инвертированная маска
//unsigned char host[IP_VERSION]; // узел сети
//unsigned char hostadr[IP_VERSION]; // узел сети
unsigned char netclass; // класс сети
unsigned char firsthost[IP_VERSION]; // первый узел сети
unsigned char lasthost[IP_VERSION]; // последный узел сети
unsigned long long maxhosts = 1u; // количество доступных хостов в сети
// Первые байты классов сетей A, B, C, D, представляющие
// максимальный адресс соответствующей сети + 1 :)
const unsigned char CLASSES[IP_VERSION] = {128u, 192u, 224u, 240u};
unsigned i, j;
unsigned char s[9];
// Если параметры заданы...
if(argv[1][0] == '-')
{
switch(argv[1][1])
{
case 'm': sscanf(argv[2], "%u %*c %u %*c %u %*c %u %*c %u", &ip[0], &ip[1], &ip[2], &ip[3], &ip[4]);
break;
case 'M': sscanf(argv[2], "%u %*c %u %*c %u %*c %u %*c %u %*c %u %*c %u %*c %u",
&ip[0], &ip[1], &ip[2], &ip[3], &mask[0], &mask[1], &mask[2], &mask[3]);
// Если маска указана неверно - прерывание программы с предупреждением
// пользователя. Маска может быть неверно задана только когда пользователь
// задает ее в таком формате 255.255.255.214, что в двоичном представлении
// есть 11111111.11111111.11111111.11010110, но маска представляет собой
// непрерывную последовательность единиц, заканчивающаяся непрерывной
// последовательностью нулей. Это значит, что маска 255.255.255.214 задана
// не верно.
for(i = 0; i < IP_VERSION; i++)
if(mask[i] < 255u)
{
// переводим байт отличный от 255 в двоичное представление.
ditobi(mask[i], s);
exchs(s);
AddZero(s, 8);
// проверяем корректность установленных битов.
for(j = 0; j < 8; j++)
if(s[j] == '0')
{
// первый 0 встретился - значит и остальные биты должны быть нулевыми.
for(j++; j < 8; j++)
if(s[j] == '1') {
printf("%-18s: ", "Incorrect mask");
print(mask);
return 0;
}
break;
}
break;
}
// Преобразуем эту маску в краткий формат.
ip[IP_VERSION] = i * 8 + j;
break;
case 'h': puts(help);
return 0;
}
}
else // Если опции(Options) не заданы...
sscanf(argv[1], "%u %*c %u %*c %u %*c %u %*c %u", &ip[0], &ip[1], &ip[2], &ip[3], &ip[4]);
// Если маска не указана, то определим ее по классу сети с помощью CLASSES.
for(i = 0; i < IP_VERSION; i++)
if(ip[0] < CLASSES[i]) {
if(!ip[IP_VERSION])
ip[IP_VERSION] = (i+1u)*8u;
break;
}
// Определим класс сети в символическом обозначении для вывода.
netclass = 'A' + i;
// Нахождение адреса сети. Чтобы его определить, нужно применить
// операцию & над IP-адресом и маской. Но та маска, что у нас есть -
// просто число, указывающее количество установленных бит в 32-х
// разрядной сетке(для IPv4). Данную пользователем маску надо представить
// в виде, например для /19, как 255.255.224.0 и потом уже применять
// операцию & над IP-адресом и этой маской :)
// Узнаем сколько байт установленны в 255.
i = ip[IP_VERSION] / 8; // столько байт установленно в 255
j = ip[IP_VERSION] % 8; // столько бит установленны в 1, а остальные в 0
// найдем число, которому соответствует то количество установленных
// бит в байте. Но есть ньюанс: биты стовятся в 1, например для маски /19,
// начиная со старшей части, поэтому число которое мы найдем нужно отобразить
// в зеркальном отражении или просто напросто сместить в старшую часть :)
mask[i] = (1 << j) - 1;
mask[i] <<= (8 - j);
// Установим остальные байты в 0 - байты до которых маска не дотянуласть,
// например для маски /19, это будет 4-й байт(для IPv4).
for(i++; i < IP_VERSION; i++)
mask[i] = 0;
// Находим адрес сети.
for(i = 0; i < IP_VERSION; i++)
net[i] = ip[i] & mask[i];
// Нахождение широковещятельного адреса. Чтобы его определить, нужно применить
// | над инверсией маски и адреса сети(или любого IP адреса из этой сети).
// Инверсия маски.
for(i = 0; i < IP_VERSION; i++)
invmask[i] = ~mask[i];
// Находим широковещятельный адрес.
for(i = 0; i < IP_VERSION; i++)
broadcast[i] = net[i] | invmask[i];
/*
// находим номер узла. номер узла получается применением & над инвертированной
// маской и заданным IP.
for(i = 0; i < IP_VERSION; i++)
host[i] = ip[i] & invmask[i];
// найдем адрес узла. чтобы его получить надо провести операцию & над номером
// узла и адресом сети.
for(i = 0; i < IP_VERSION; i++)
hostadr[i] = host[i] | net[i];
*/
// найдем адрес первого хоста - делается это очень просто, путем прибавления
// единицы к последнему октету адреса сети и найдем адрес последнего хоста,
// путем вычитания единицы из последнего октета широковещательного адреса :)
for(i = 0; i < IP_VERSION; i++)
firsthost[i] = net[i];
firsthost[IP_VERSION-1]++;
for(i = 0; i < IP_VERSION; i++)
lasthost[i] = broadcast[i];
lasthost[IP_VERSION-1]--;
// найдем количество всех доступных адресов в сети. количество находится очень просто,
// возведением двойки в степень нулевых битов маски и вычитаем два адреса, так как
// они уже заняты адресом сети и широковещательным адресом.
maxhosts = (maxhosts << (IP_VERSION * 8u - ip[4])) - 2u;
// Теперь покажем IP, маску, адрес сети, адрес узла, широковещятельный адрес итд...
printf("%-18s: ", "IP address");
print(ip);
printf("%-18s: ", "Mask");
print(mask);
printf("%-18s: ", "Net address");
print(net);
printf("%-18s: ", "Inv Mask");
print(invmask);
//printf("%-18s: ", "Host address");
//print(hostadr);
printf("%-18s: ", "First host");
print(firsthost);
printf("%-18s: ", "Last host");
print(lasthost);
printf("%-18s: ", "Broadcast address");
print(broadcast);
printf("%-18s: %u\n", "Total Hosts", maxhosts);
printf("%-18s: %c\n", "Class", netclass);
}
else
puts(help);
return 0;
}
//-----------------------------------------------------------------------------------------------------------
// функция печатает IP, маску, адрес сети и широковещятельный
// адрес в традиционном и двоичном представлении.
void print(unsigned char *s)
{
unsigned i;
unsigned char buf[9];
for(i = 0; i < IP_VERSION-1; i++)
printf("%03u.", s[i]);
printf("%03u\t", s[i]);
for(i = 0; i < IP_VERSION-1; i++) {
ditobi(s[i], buf);
exchs(buf);
AddZero(buf, 8);
printf("%s.", buf);
}
ditobi(s[i], buf);
exchs(buf);
AddZero(buf, 8);
printf("%s\n", buf);
}
//-----------------------------------------------------------------------------------------------------------