1 #include <time.h>
2 #include <unistd.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include "firedns.h"
6
7 #define max(a,b) (a > b ? a : b)
8
checkjunk(struct in_addr * ip)9 int checkjunk(struct in_addr *ip) {
10 unsigned char *cip = (unsigned char *)ip;
11 if (cip[0] == 10)
12 return 1;
13 if (cip[0] == 172 && (cip[1] >= 16 && cip[1] <= 31))
14 return 1;
15 if (cip[0] == 192 && cip[1] == 168)
16 return 1;
17 if (cip[0] == 192 && cip[1] == 0 && cip[2] == 2)
18 return 1;
19 if (cip[0] == 198 && (cip[1] == 18 || cip[1] == 19))
20 return 1;
21 if (cip[0] == 127)
22 return 1;
23 if (cip[0] >= 224 && cip[0] <= 240)
24 return 1;
25 if (cip[0] == 0)
26 return 1;
27
28 return 0;
29 }
30
checkjunk6(struct in6_addr * ip)31 int checkjunk6(struct in6_addr *ip) {
32 if (memcmp(ip,"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01",16) == 0)
33 return 1;
34 if (memcmp(ip,"\xfe\x80",2) == 0)
35 return 1;
36 /* FIXME: there's gotta be more of these */
37 return 0;
38 }
39
40 /* 0 - Everything looks good
41 * 1 - An MX has a non-routable IP
42 * 2 - An MX doesn't exist
43 * 3 - An MX is a CNAME
44 * 4 - An MX is an IP address
45 *
46 * 100 - Invalid syntax
47 * 103 - DNS timeout
48 */
main(int argc,char ** argv)49 int main(int argc, char **argv) {
50 struct firedns_mxlist *iter, *list;
51 int ret = 0;
52 int xml = 0;
53
54 if (argc == 3 && argv[1][0] == '-') {
55 int i = 1;
56 while (argv[1][i] != '\0') {
57 switch (argv[1][i]) {
58 case 'x':
59 xml = 1;
60 break;
61 }
62 i++;
63 }
64 argv[1] = argv[2];
65 argc--;
66 }
67
68 if (argc != 2) {
69 fprintf(stderr,"usage: [-x] %s <hostname>\n",argv[0]);
70 return 100;
71 }
72
73 list = iter = firedns_resolvemxalist(argv[1]);
74
75 if (iter == NULL)
76 return 103;
77
78 if (xml)
79 printf("<?xml version=\"1.0\"?>\n"
80 "<fdnsmxalist time=\"%d\" hostname=\"%s\">\n",(int)time(NULL),argv[1]);
81
82 while (iter != NULL) {
83 if (xml)
84 printf(" <mx hostname=\"%s\" protocol=\"%s\" priority=\"%d\" port=\"%d\">\n",iter->name,firedns_mx_name[iter->protocol],iter->priority,firedns_mx_port[iter->protocol]);
85 else
86 printf("%7s (%05d) %s:%d\n",firedns_mx_name[iter->protocol],iter->priority,iter->name,firedns_mx_port[iter->protocol]);
87 if (iter->cname != NULL) {
88 if (xml)
89 printf(" <error type=\"cname\" cname=\"%s\" />\n",iter->cname);
90 else
91 printf("ERROR: %s is a CNAME for %s\n",iter->name,iter->cname);
92 ret = max(ret,3);
93 }
94 if (firedns_aton4(iter->name) != NULL) {
95 if (xml)
96 printf(" <error type=\"ip4_mx\" />\n");
97 else
98 printf("ERROR: %s is an IPv4 address\n",iter->name);
99 ret = max(ret,4);
100 goto wrap;
101 }
102 if (firedns_aton6(iter->name) != NULL) {
103 if (xml)
104 printf(" <error type=\"ip6_mx\" />\n");
105 else
106 printf("ERROR: %s is an IPv6 address\n",iter->name);
107 ret = max(ret,4);
108 goto wrap;
109 }
110 if (iter->ip4list == NULL && iter->ip6list == NULL) {
111 if (xml)
112 printf(" <error type=\"nxdomain\" />\n");
113 else
114 printf("ERROR: %s does not exist\n",iter->name);
115 ret = max(ret,2);
116 } else {
117 struct firedns_ip4list *ipiter = iter->ip4list;
118 struct firedns_ip6list *ip6iter = iter->ip6list;
119
120 while (ipiter) {
121 if (xml)
122 printf(" <ip version=\"4\">%s",firedns_ntoa4(&ipiter->ip));
123 else
124 printf(" %s\n",firedns_ntoa4(&ipiter->ip));
125 if (checkjunk(&ipiter->ip)) {
126 if (xml)
127 printf("\n <error type=\"private-ip\" />\n ");
128 else
129 printf("ERROR: %s has an IP of %s, which is non-routable\n",iter->name,firedns_ntoa4(&ipiter->ip));
130 ret = max(ret,1);
131 }
132 if (xml)
133 printf("</ip>\n");
134 ipiter = ipiter->next;
135 }
136
137 while (ip6iter) {
138 if (xml)
139 printf(" <ip version=\"6\">%s",firedns_ntoa6(&ip6iter->ip));
140 else
141 printf(" %s\n",firedns_ntoa6(&ip6iter->ip));
142 if (checkjunk6(&ip6iter->ip)) {
143 if (xml)
144 printf("\n <error type=\"private-ip\" />\n ");
145 else
146 printf("ERROR: %s has an IP of %s, which is non-routable\n",iter->name,firedns_ntoa6(&ip6iter->ip));
147 ret = max(ret,1);
148 }
149 if (xml)
150 printf("</ip>\n");
151 ip6iter = ip6iter->next;
152 }
153 }
154 wrap:
155 if (xml)
156 printf(" </mx>\n");
157 iter = iter->next;
158 }
159
160 /* this is more to make sure freeing works than anything else */
161 firedns_free_mxalist(list);
162
163 if (xml)
164 printf("</fdnsmxalist>\n");
165
166 return ret;
167 }
168