Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/networking/dnsd.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/networking/dnsd.c
r902 r1770 18 18 */ 19 19 20 #include <unistd.h> 21 #include <string.h> 22 #include <signal.h> 23 #include <arpa/inet.h> 24 #include <sys/socket.h> 25 #include <ctype.h> 26 #include "busybox.h" 27 28 static char *fileconf = "/etc/dnsd.conf"; 29 #define LOCK_FILE "/var/run/dnsd.lock" 30 #define LOG_FILE "/var/log/dnsd.log" 31 32 #define is_daemon() (flags&16) 33 #define is_verbose() (flags&32) 34 //#define DEBUG 35 20 #include <syslog.h> 21 #include "libbb.h" 22 23 //#define DEBUG 1 24 #define DEBUG 0 36 25 37 26 enum { … … 81 70 }; 82 71 83 static struct dns_entry *dnsentry = NULL; 84 static int daemonmode = 0; 72 static struct dns_entry *dnsentry; 85 73 static uint32_t ttl = DEFAULT_TTL; 86 74 75 static const char *fileconf = "/etc/dnsd.conf"; 76 77 // Must match getopt32 call 78 #define OPT_daemon (option_mask32 & 0x10) 79 #define OPT_verbose (option_mask32 & 0x20) 80 81 87 82 /* 88 83 * Convert host name from C-string to dns length/string. … … 91 86 { 92 87 int i = (q[0] == '.') ? 0 : 1; 93 for (; i < MAX_HOST_LEN-1 && *q; i++, q++)88 for (; i < MAX_HOST_LEN-1 && *q; i++, q++) 94 89 a[i] = tolower(*q); 95 90 a[0] = i - 1; … … 103 98 { 104 99 int i = 0, s = 0; 105 while(rip[i]) i++; 106 for(--i; i >= 0; i--) { 107 if(rip[i] == '.') { 100 while (rip[i]) 101 i++; 102 for (--i; i >= 0; i--) { 103 if (rip[i] == '.') { 108 104 rip[i] = s; 109 105 s = 0; … … 113 109 114 110 /* 115 * Append message to log file116 */117 static void log_message(char *filename, char *message)118 {119 FILE *logfile;120 if (!daemonmode)121 return;122 logfile = fopen(filename, "a");123 if (!logfile)124 return;125 fprintf(logfile, "%s\n", message);126 fclose(logfile);127 }128 129 /*130 111 * Read one line of hostname/IP from file 131 112 * Returns 0 for each valid entry read, -1 at EOF 132 113 * Assumes all host names are lower case only 133 * Hostnames with more than one label isnot handled correctly.114 * Hostnames with more than one label are not handled correctly. 134 115 * Presently the dot is copied into name without 135 116 * converting to a length/string substring for that label. 136 117 */ 137 138 static int getfileentry(FILE * fp, struct dns_entry *s, int verb) 118 static int getfileentry(FILE * fp, struct dns_entry *s) 139 119 { 140 120 unsigned int a,b,c,d; 141 char *r, *name; 142 143 restart: 144 if(!(r = bb_get_line_from_file(fp))) 121 char *line, *r, *name; 122 123 restart: 124 line = r = xmalloc_fgets(fp); 125 if (!r) 145 126 return -1; 146 while (*r == ' ' || *r == '\t') {127 while (*r == ' ' || *r == '\t') { 147 128 r++; 148 if(!*r || *r == '#' || *r == '\n') 129 if (!*r || *r == '#' || *r == '\n') { 130 free(line); 149 131 goto restart; /* skipping empty/blank and commented lines */ 132 } 150 133 } 151 134 name = r; 152 while (*r != ' ' && *r != '\t')135 while (*r != ' ' && *r != '\t') 153 136 r++; 154 *r++ = 0; 155 if(sscanf(r,"%u.%u.%u.%u",&a,&b,&c,&d) != 4) 156 goto restart; /* skipping wrong lines */ 157 158 sprintf(s->ip,"%u.%u.%u.%u",a,b,c,d); 159 sprintf(s->rip,".%u.%u.%u.%u",d,c,b,a); 137 *r++ = '\0'; 138 if (sscanf(r, ".%u.%u.%u.%u"+1, &a, &b, &c, &d) != 4) { 139 free(line); 140 goto restart; /* skipping wrong lines */ 141 } 142 143 sprintf(s->ip, ".%u.%u.%u.%u"+1, a, b, c, d); 144 sprintf(s->rip, ".%u.%u.%u.%u", d, c, b, a); 160 145 undot((uint8_t*)s->rip); 161 convname(s->name,(uint8_t*)name); 162 163 if(verb) 164 fprintf(stderr,"\tname:%s, ip:%s\n",&(s->name[1]),s->ip); 165 166 return 0; /* warningkiller */ 146 convname(s->name, (uint8_t*)name); 147 148 if (OPT_verbose) 149 fprintf(stderr, "\tname:%s, ip:%s\n", &(s->name[1]),s->ip); 150 151 free(line); 152 return 0; 167 153 } 168 154 … … 170 156 * Read hostname/IP records from file 171 157 */ 172 static void dnsentryinit( int verb)158 static void dnsentryinit(void) 173 159 { 174 160 FILE *fp; 175 161 struct dns_entry *m, *prev; 162 176 163 prev = dnsentry = NULL; 177 178 fp = bb_xfopen(fileconf, "r"); 164 fp = xfopen(fileconf, "r"); 179 165 180 166 while (1) { 181 m = xmalloc(sizeof(struct dns_entry)); 182 183 m->next = NULL; 184 if (getfileentry(fp, m, verb)) 167 m = xzalloc(sizeof(*m)); 168 /*m->next = NULL;*/ 169 if (getfileentry(fp, m)) 185 170 break; 186 171 … … 194 179 } 195 180 196 197 /*198 * Set up UDP socket199 */200 static int listen_socket(char *iface_addr, int listen_port)201 {202 struct sockaddr_in a;203 char msg[100];204 int s;205 int yes = 1;206 s = bb_xsocket(PF_INET, SOCK_DGRAM, 0);207 #ifdef SO_REUSEADDR208 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0)209 bb_perror_msg_and_die("setsockopt() failed");210 #endif211 memset(&a, 0, sizeof(a));212 a.sin_port = htons(listen_port);213 a.sin_family = AF_INET;214 if (!inet_aton(iface_addr, &a.sin_addr))215 bb_perror_msg_and_die("bad iface address");216 bb_xbind(s, (struct sockaddr *)&a, sizeof(a));217 listen(s, 50); /* bb_xlisten? */218 sprintf(msg, "accepting UDP packets on addr:port %s:%d\n",219 iface_addr, (int)listen_port);220 log_message(LOG_FILE, msg);221 return s;222 }223 224 181 /* 225 182 * Look query up in dns records and return answer if found … … 231 188 struct dns_entry *d = dnsentry; 232 189 233 if(d) do { 234 #ifdef DEBUG 235 if(qs && d) { 236 char *p,*q; 237 q = (char *)&(qs[1]); 238 p = &(d->name[1]); 239 fprintf(stderr, "\n%s: %d/%d p:%s q:%s %d", 240 __FUNCTION__, strlen(p), (int)(d->name[0]), 241 p, q, strlen(q)); 242 } 190 do { 191 #if DEBUG 192 char *p,*q; 193 q = (char *)&(qs[1]); 194 p = &(d->name[1]); 195 fprintf(stderr, "\n%s: %d/%d p:%s q:%s %d", 196 __FUNCTION__, (int)strlen(p), (int)(d->name[0]), 197 p, q, (int)strlen(q)); 243 198 #endif 244 if (type == REQ_A) { 245 for (i = 1; i <= (int)(d->name[0]); i++)246 if (tolower(qs[i]) != d->name[i])199 if (type == REQ_A) { /* search by host name */ 200 for (i = 1; i <= (int)(d->name[0]); i++) 201 if (tolower(qs[i]) != d->name[i]) 247 202 break; 248 if(i > (int)(d->name[0])) { 249 #ifdef DEBUG 250 fprintf(stderr, " OK"); 251 #endif 203 if (i > (int)(d->name[0])) { 252 204 strcpy((char *)as, d->ip); 253 #if defDEBUG254 fprintf(stderr, " as:%s\n", as);205 #if DEBUG 206 fprintf(stderr, " OK as:%s\n", as); 255 207 #endif 256 208 return 0; 257 209 } 258 } else 259 if (type == REQ_PTR) { /* search by IP-address */ 210 } else if (type == REQ_PTR) { /* search by IP-address */ 260 211 if (!strncmp((char*)&d->rip[1], (char*)&qs[1], strlen(d->rip)-1)) { 261 212 strcpy((char *)as, d->name); … … 263 214 } 264 215 } 265 } while ((d = d->next) != NULL); 216 d = d->next; 217 } while (d); 266 218 return -1; 267 219 } … … 271 223 * Decode message and generate answer 272 224 */ 273 #define eret(s) do { fprintf (stderr, "%s\n", s); return -1; } while (0)274 225 static int process_packet(uint8_t * buf) 275 226 { … … 286 237 287 238 head = (struct dns_head *)buf; 288 if (head->nquer == 0) 289 eret("no queries"); 290 291 if ((head->flags & 0x8000)) 292 eret("ignoring response packet"); 239 if (head->nquer == 0) { 240 bb_error_msg("no queries"); 241 return -1; 242 } 243 244 if (head->flags & 0x8000) { 245 bb_error_msg("ignoring response packet"); 246 return -1; 247 } 293 248 294 249 from = (void *)&head[1]; // start of query string … … 317 272 318 273 // We have a standard query 319 log_message(LOG_FILE, (char *)from);274 bb_info_msg("%s", (char *)from); 320 275 lookup_result = table_lookup(type, answstr, (uint8_t*)from); 321 276 if (lookup_result != 0) { … … 331 286 memcpy(answstr, &a.s_addr, 4); // save before a disappears 332 287 outr.rlen = 4; // uint32_t IP 333 } 334 else 288 } else 335 289 outr.rlen = strlen((char *)answstr) + 1; // a host name 336 290 outr.r = answstr; // 32 bit ip or a host name … … 352 306 next += outr.rlen; 353 307 354 empty_packet: 308 empty_packet: 309 355 310 flags = ntohs(head->flags); 356 311 // clear rcode and RA, set responsebit and our new flags … … 360 315 head->nquer = htons(1); 361 316 362 packet_len = next - (void *)buf;317 packet_len = (uint8_t *)next - buf; 363 318 return packet_len; 364 319 } … … 369 324 static void interrupt(int x) 370 325 { 371 unlink(LOCK_FILE);372 write(2, "interrupt exiting\n", 18);326 /* unlink("/var/run/dnsd.lock"); */ 327 bb_error_msg("interrupt, exiting\n"); 373 328 exit(2); 374 329 } 375 330 376 331 int dnsd_main(int argc, char **argv); 377 332 int dnsd_main(int argc, char **argv) 378 333 { 334 const char *listen_interface = "0.0.0.0"; 335 char *sttl, *sport; 336 len_and_sockaddr *lsa; 379 337 int udps; 380 338 uint16_t port = 53; 381 339 uint8_t buf[MAX_PACK_LEN]; 382 unsigned long flags = 0; 383 char *listen_interface = "0.0.0.0"; 384 char *sttl=NULL, *sport=NULL; 385 386 if(argc > 1) 387 flags = bb_getopt_ulflags(argc, argv, "i:c:t:p:dv", &listen_interface, &fileconf, &sttl, &sport); 388 if(sttl) 389 if(!(ttl = atol(sttl))) 390 bb_show_usage(); 391 if(sport) 392 if(!(port = atol(sport))) 393 bb_show_usage(); 394 395 if(is_verbose()) { 396 fprintf(stderr,"listen_interface: %s\n", listen_interface); 397 fprintf(stderr,"ttl: %d, port: %d\n", ttl, port); 398 fprintf(stderr,"fileconf: %s\n", fileconf); 399 } 400 401 if(is_daemon()) 402 #ifdef BB_NOMMU 403 /* reexec for vfork() do continue parent */ 404 vfork_daemon_rexec(1, 0, argc, argv, "-d"); 405 #else 406 bb_xdaemon(1, 0); 407 #endif 408 409 dnsentryinit(is_verbose()); 340 341 getopt32(argv, "i:c:t:p:dv", &listen_interface, &fileconf, &sttl, &sport); 342 //if (option_mask32 & 0x1) // -i 343 //if (option_mask32 & 0x2) // -c 344 if (option_mask32 & 0x4) // -t 345 ttl = xatou_range(sttl, 1, 0xffffffff); 346 if (option_mask32 & 0x8) // -p 347 port = xatou_range(sport, 1, 0xffff); 348 349 if (OPT_verbose) { 350 bb_info_msg("listen_interface: %s", listen_interface); 351 bb_info_msg("ttl: %d, port: %d", ttl, port); 352 bb_info_msg("fileconf: %s", fileconf); 353 } 354 355 if (OPT_daemon) { 356 bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv); 357 openlog(applet_name, LOG_PID, LOG_DAEMON); 358 logmode = LOGMODE_SYSLOG; 359 } 360 361 dnsentryinit(); 410 362 411 363 signal(SIGINT, interrupt); 412 signal(SIGPIPE, SIG_IGN);364 /* why? signal(SIGPIPE, SIG_IGN); */ 413 365 signal(SIGHUP, SIG_IGN); 414 366 #ifdef SIGTSTP … … 419 371 #endif 420 372 421 udps = listen_socket(listen_interface, port); 422 if (udps < 0) 423 exit(1); 373 lsa = xdotted2sockaddr(listen_interface, port); 374 udps = xsocket(lsa->sa.sa_family, SOCK_DGRAM, 0); 375 xbind(udps, &lsa->sa, lsa->len); 376 /* xlisten(udps, 50); - ?!! DGRAM sockets are never listened on I think? */ 377 bb_info_msg("Accepting UDP packets on %s", 378 xmalloc_sockaddr2dotted(&lsa->sa)); 424 379 425 380 while (1) { 426 fd_set fdset;427 381 int r; 428 429 FD_ZERO(&fdset); 430 FD_SET(udps, &fdset); 431 // Block until a message arrives 432 if((r = select(udps + 1, &fdset, NULL, NULL, NULL)) < 0) 433 bb_perror_msg_and_die("select error"); 434 else 435 if(r == 0) 436 bb_perror_msg_and_die("select spurious return"); 437 438 /* Can this test ever be false? */ 439 if (FD_ISSET(udps, &fdset)) { 440 struct sockaddr_in from; 441 int fromlen = sizeof(from); 442 r = recvfrom(udps, buf, sizeof(buf), 0, 443 (struct sockaddr *)&from, 444 (void *)&fromlen); 445 if(is_verbose()) 446 fprintf(stderr, "\n--- Got UDP size=%d ", r); 447 log_message(LOG_FILE, "\n--- Got UDP "); 448 449 if (r < 12 || r > 512) { 450 bb_error_msg("invalid packet size"); 451 continue; 452 } 453 if (r > 0) { 454 r = process_packet(buf); 455 if (r > 0) 456 sendto(udps, buf, 457 r, 0, (struct sockaddr *)&from, 458 fromlen); 459 } 460 } // end if 461 } // end while 382 socklen_t fromlen = lsa->len; 383 // FIXME: need to get *DEST* address (to which of our addresses 384 // this query was directed), and reply from the same address. 385 // Or else we can exhibit usual UDP ugliness: 386 // [ip1.multihomed.ip2] <= query to ip1 <= peer 387 // [ip1.multihomed.ip2] => reply from ip2 => peer (confused) 388 r = recvfrom(udps, buf, sizeof(buf), 0, &lsa->sa, &fromlen); 389 if (OPT_verbose) 390 bb_info_msg("Got UDP packet"); 391 if (r < 12 || r > 512) { 392 bb_error_msg("invalid packet size"); 393 continue; 394 } 395 r = process_packet(buf); 396 if (r <= 0) 397 continue; 398 sendto(udps, buf, r, 0, &lsa->sa, fromlen); 399 } 462 400 return 0; 463 401 } 464 465
Note:
See TracChangeset
for help on using the changeset viewer.