1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <ndb.h>
5 #include "whois.h"
6
7 typedef struct Country Country;
8
9 struct Country
10 {
11 char *code;
12 char *name;
13 };
14
15 Country badc[] =
16 {
17 {"af", "afghanistan"},
18 {"cu", "cuba"},
19 {"ir", "iran"},
20 {"iq", "iraq"},
21 {"ly", "libya"},
22 {"kp", "north korea"},
23 {"sd", "sudan"},
24 {"sy", "syria"},
25 { 0, 0 }
26 };
27
28 Country goodc[] =
29 {
30 // the original, us and canada
31 {"us", "united states of america"},
32 {"ca", "canada"},
33 {"gov", "gov"},
34 {"mil", "mil"},
35
36 // the european union
37 { "eu", "european union" },
38 { "be", "belgium" },
39 { "de", "germany" },
40 { "fr", "france" },
41 { "it", "italy" },
42 { "lu", "luxembourg" },
43 { "nl", "netherlands" },
44 { "dk", "denmark" },
45 { "ie", "ireland" },
46 { "gb", "great britain" },
47 { "uk", "united kingdom" },
48 { "gr", "greece" },
49 { "es", "spain" },
50 { "pt", "portugal" },
51 { "au", "australia" },
52 { "fi", "finland" },
53 { "se", "sweden" },
54
55 // the rest
56 {"au", "australia"},
57 {"no", "norway"},
58 {"cz", "czech republic"},
59 {"hu", "hungary"},
60 {"pl", "poland"},
61 {"jp", "japan"},
62 {"ch", "switzerland"},
63 {"nz", "new zealand"},
64 { 0, 0 }
65 };
66
67 char *gov[] =
68 {
69 "gov",
70 "gouv",
71 "mil",
72 "government",
73 0,
74 };
75
76 Country allc[] =
77 {
78 { "ad", "andorra" },
79 { "ae", "united arab emirates" },
80 { "af", "afghanistan" },
81 { "ag", "antigua and barbuda" },
82 { "ai", "anguilla" },
83 { "al", "albania" },
84 { "am", "armenia" },
85 { "an", "netherlands antilles" },
86 { "ao", "angola" },
87 { "aq", "antarctica" },
88 { "ar", "argentina" },
89 { "as", "american samoa" },
90 { "at", "austria" },
91 { "au", "australia" },
92 { "aw", "aruba" },
93 { "az", "azerbaijan" },
94 { "ba", "bosnia and herzegovina" },
95 { "bb", "barbados" },
96 { "bd", "bangladesh" },
97 { "be", "belgium" },
98 { "bf", "burkina faso" },
99 { "bg", "bulgaria" },
100 { "bh", "bahrain" },
101 { "bi", "burundi" },
102 { "bj", "benin" },
103 { "bm", "bermuda" },
104 { "bn", "brunei darussalam" },
105 { "bo", "bolivia" },
106 { "br", "brazil" },
107 { "bs", "bahamas" },
108 { "bt", "bhutan" },
109 { "bu", "burma" },
110 { "bv", "bouvet island" },
111 { "bw", "botswana" },
112 { "by", "belarus" },
113 { "bz", "belize" },
114 { "ca", "canada" },
115 { "cc", "cocos (keeling) islands" },
116 { "cf", "central african republic" },
117 { "cg", "congo" },
118 { "ch", "switzerland" },
119 { "ci", "cote d'ivoire (ivory coast)" },
120 { "ck", "cook islands" },
121 { "cl", "chile" },
122 { "cm", "cameroon" },
123 { "cn", "china" },
124 { "co", "colombia" },
125 { "cr", "costa rica" },
126 { "cs", "czechoslovakia (former)" },
127 { "ct", "canton and enderbury island" },
128 { "cu", "cuba" },
129 { "cv", "cape verde" },
130 { "cx", "christmas island" },
131 { "cy", "cyprus" },
132 { "cz", "czech republic" },
133 { "dd", "german democratic republic" },
134 { "de", "germany" },
135 { "dj", "djibouti" },
136 { "dk", "denmark" },
137 { "dm", "dominica" },
138 { "do", "dominican republic" },
139 { "dz", "algeria" },
140 { "ec", "ecuador" },
141 { "ee", "estonia" },
142 { "eg", "egypt" },
143 { "eh", "western sahara" },
144 { "er", "eritrea" },
145 { "es", "spain" },
146 { "et", "ethiopia" },
147 { "eu", "european union" },
148 { "fi", "finland" },
149 { "fj", "fiji" },
150 { "fk", "falkland islands (malvinas)" },
151 { "fm", "micronesia" },
152 { "fo", "faroe islands" },
153 { "fr", "france" },
154 { "fx", "france, metropolitan" },
155 { "ga", "gabon" },
156 { "gb", "great britain (uk)" },
157 { "gd", "grenada" },
158 { "ge", "georgia" },
159 { "gf", "french guiana" },
160 { "gh", "ghana" },
161 { "gi", "gibraltar" },
162 { "gl", "greenland" },
163 { "gm", "gambia" },
164 { "gn", "guinea" },
165 { "gp", "guadeloupe" },
166 { "gq", "equatorial guinea" },
167 { "gr", "greece" },
168 { "gs", "s. georgia and s. sandwich isls." },
169 { "gt", "guatemala" },
170 { "gu", "guam" },
171 { "gw", "guinea-bissau" },
172 { "gy", "guyana" },
173 { "hk", "hong kong" },
174 { "hm", "heard and mcdonald islands" },
175 { "hn", "honduras" },
176 { "hr", "croatia (hrvatska)" },
177 { "ht", "haiti" },
178 { "hu", "hungary" },
179 { "id", "indonesia" },
180 { "ie", "ireland" },
181 { "il", "israel" },
182 { "in", "india" },
183 { "io", "british indian ocean territory" },
184 { "iq", "iraq" },
185 { "ir", "iran" },
186 { "is", "iceland" },
187 { "it", "italy" },
188 { "jm", "jamaica" },
189 { "jo", "jordan" },
190 { "jp", "japan" },
191 { "jt", "johnston island" },
192 { "ke", "kenya" },
193 { "kg", "kyrgyzstan" },
194 { "kh", "cambodia (democratic kampuchea)" },
195 { "ki", "kiribati" },
196 { "km", "comoros" },
197 { "kn", "saint kitts and nevis" },
198 { "kp", "korea (north)" },
199 { "kr", "korea (south)" },
200 { "kw", "kuwait" },
201 { "ky", "cayman islands" },
202 { "kz", "kazakhstan" },
203 { "la", "laos" },
204 { "lb", "lebanon" },
205 { "lc", "saint lucia" },
206 { "li", "liechtenstein" },
207 { "lk", "sri lanka" },
208 { "lr", "liberia" },
209 { "ls", "lesotho" },
210 { "lt", "lithuania" },
211 { "lu", "luxembourg" },
212 { "lv", "latvia" },
213 { "ly", "libya" },
214 { "ma", "morocco" },
215 { "mc", "monaco" },
216 { "md", "moldova" },
217 { "mg", "madagascar" },
218 { "mh", "marshall islands" },
219 { "mi", "midway islands" },
220 { "mk", "macedonia" },
221 { "ml", "mali" },
222 { "mm", "myanmar" },
223 { "mn", "mongolia" },
224 { "mo", "macau" },
225 { "mp", "northern mariana islands" },
226 { "mq", "martinique" },
227 { "mr", "mauritania" },
228 { "ms", "montserrat" },
229 { "mt", "malta" },
230 { "mu", "mauritius" },
231 { "mv", "maldives" },
232 { "mw", "malawi" },
233 { "mx", "mexico" },
234 { "my", "malaysia" },
235 { "mz", "mozambique" },
236 { "na", "namibia" },
237 { "nc", "new caledonia" },
238 { "ne", "niger" },
239 { "nf", "norfolk island" },
240 { "ng", "nigeria" },
241 { "ni", "nicaragua" },
242 { "nl", "netherlands" },
243 { "no", "norway" },
244 { "np", "nepal" },
245 { "nq", "dronning maud land" },
246 { "nr", "nauru" },
247 { "nt", "neutral zone" },
248 { "nu", "niue" },
249 { "nz", "new zealand (aotearoa)" },
250 { "om", "oman" },
251 { "pa", "panama" },
252 { "pc", "pacific islands" },
253 { "pe", "peru" },
254 { "pf", "french polynesia" },
255 { "pg", "papua new guinea" },
256 { "ph", "philippines" },
257 { "pk", "pakistan" },
258 { "pl", "poland" },
259 { "pm", "st. pierre and miquelon" },
260 { "pn", "pitcairn" },
261 { "pr", "puerto rico" },
262 { "pu", "united states misc. pacific islands" },
263 { "pt", "portugal" },
264 { "pw", "palau" },
265 { "py", "paraguay" },
266 { "qa", "qatar" },
267 { "re", "reunion" },
268 { "ro", "romania" },
269 { "ru", "russian federation" },
270 { "rw", "rwanda" },
271 { "sa", "saudi arabia" },
272 { "sb", "solomon islands" },
273 { "sc", "seychelles" },
274 { "sd", "sudan" },
275 { "se", "sweden" },
276 { "sg", "singapore" },
277 { "sh", "st. helena" },
278 { "si", "slovenia" },
279 { "sj", "svalbard and jan mayen islands" },
280 { "sk", "slovak republic" },
281 { "sl", "sierra leone" },
282 { "sm", "san marino" },
283 { "sn", "senegal" },
284 { "so", "somalia" },
285 { "sr", "suriname" },
286 { "st", "sao tome and principe" },
287 { "su", "ussr (former)" },
288 { "sv", "el salvador" },
289 { "sy", "syria" },
290 { "sz", "swaziland" },
291 { "tc", "turks and caicos islands" },
292 { "td", "chad" },
293 { "tf", "french southern territories" },
294 { "tg", "togo" },
295 { "th", "thailand" },
296 { "tj", "tajikistan" },
297 { "tk", "tokelau" },
298 { "tm", "turkmenistan" },
299 { "tn", "tunisia" },
300 { "to", "tonga" },
301 { "tp", "east timor" },
302 { "tr", "turkey" },
303 { "tt", "trinidad and tobago" },
304 { "tv", "tuvalu" },
305 { "tw", "taiwan" },
306 { "tz", "tanzania" },
307 { "ua", "ukraine" },
308 { "ug", "uganda" },
309 { "uk", "united kingdom" },
310 { "um", "us minor outlying islands" },
311 { "us", "united states" },
312 { "uy", "uruguay" },
313 { "uz", "uzbekistan" },
314 { "va", "vatican city state (holy see)" },
315 { "vc", "saint vincent and the grenadines" },
316 { "ve", "venezuela" },
317 { "vg", "virgin islands (british)" },
318 { "vi", "virgin islands (u.s.)" },
319 { "vn", "viet nam" },
320 { "vu", "vanuatu" },
321 { "wf", "wallis and futuna islands" },
322 { "wk", "wake island" },
323 { "ws", "samoa" },
324 { "yd", "democratic yemen" },
325 { "ye", "yemen" },
326 { "yt", "mayotte" },
327 { "yu", "yugoslavia" },
328 { "za", "south africa" },
329 { "zm", "zambia" },
330 { "zr", "zaire" },
331 { "zw", "zimbabwe" },
332
333 {"gov", "gov"},
334 {"mil", "mil"},
335
336 { 0, 0 }
337 };
338
339 int classdebug;
340
341 static int
incountries(char * s,Country * cp)342 incountries(char *s, Country *cp)
343 {
344 for(; cp->code != 0; cp++)
345 if(cistrcmp(s, cp->code) == 0
346 || cistrcmp(s, cp->name) == 0)
347 return 1;
348 return 0;
349 }
350
351 static int
indomains(char * s,char ** dp)352 indomains(char *s, char **dp)
353 {
354 for(; *dp != nil; dp++)
355 if(cistrcmp(s, *dp) == 0)
356 return 1;
357
358 return 0;
359 }
360
361 int
classify(char * ip,Ndbtuple * t)362 classify(char *ip, Ndbtuple *t)
363 {
364 int isgov, iscountry, isbadc, isgoodc;
365 char dom[256];
366 char *df[128];
367 Ndbtuple *nt, *x;
368 int n;
369
370 isgov = iscountry = isbadc = 0;
371 isgoodc = 1;
372
373 for(nt = t; nt != nil; nt = nt->entry){
374 if(strcmp(nt->attr, "country") == 0){
375 iscountry = 1;
376 if(incountries(nt->val, badc)){
377 if(classdebug)fprint(2, "isbadc\n");
378 isbadc = 1;
379 isgoodc = 0;
380 } else if(!incountries(nt->val, goodc)){
381 if(classdebug)fprint(2, "!isgoodc\n");
382 isgoodc = 0;
383 }
384 }
385
386 /* domain names can always hurt, even without forward verification */
387 if(strcmp(nt->attr, "dom") == 0){
388 strncpy(dom, nt->val, sizeof dom);
389 dom[sizeof(dom)-1] = 0;
390 n = getfields(dom, df, nelem(df), 0, ".");
391
392 /* a bad country in a domain name is always believed */
393 if(incountries(df[n-1], badc)){
394 if(classdebug)fprint(2, "isbadc dom\n");
395 isbadc = 1;
396 isgoodc = 0;
397 }
398
399 /* a goverment in a domain name is always believed */
400 if(n > 1 && indomains(df[n-2], gov))
401 isgov = 1;
402 }
403 }
404 if(iscountry == 0){
405 /* did the forward lookup work? */
406 for(nt = t; nt != nil; nt = nt->entry){
407 if(strcmp(nt->attr, "ip") == 0 && strcmp(nt->val, ip) == 0)
408 break;
409 }
410
411 /* see if the domain name ends in a country code */
412 if(nt != nil && (x = ndbfindattr(t, nt, "dom")) != nil){
413 strncpy(dom, x->val, sizeof dom);
414 dom[sizeof(dom)-1] = 0;
415 n = getfields(dom, df, nelem(df), 0, ".");
416 if(incountries(df[n-1], allc))
417 iscountry = 1;
418 }
419 }
420 if(iscountry == 0)
421 return Cunknown;
422 if(isbadc)
423 return Cbadc;
424 if(!isgoodc && isgov)
425 return Cbadgov;
426 return Cok;
427 }
428