/* * $Id: turnme.c,v 1.4 1997/08/29 14:41:52 alexis Exp $ * * Alexis Yushin, NLnet Development BV, 1997 * */ #include #include #include #include #include #include #include #include #include #define SMTP_PORT 25 #define SMTP_BUFFER 128 #define HOSTNAME_BUFFER 64 static struct sockaddr_in remote; static int s; static FILE *ws, *rs; static char buffer[SMTP_BUFFER]; static char hostname[HOSTNAME_BUFFER]; static int verbose; extern void usage(); extern void goodbye(); extern char *smtp_read(); extern struct hostent *gethostbyname2(); /* * Connects to the specified host and issue HELO + ETRN command for the * domain. * */ int main(argc, argv) int argc; char **argv; { register int c, s; struct hostent *host; char *progname; char *domain; extern char *optarg; extern int optind; int delay = 0; if((progname = rindex(argv[0], '/')) == NULL) { progname = argv[0]; } else { progname++; } verbose = 0; remote.sin_family = AF_INET; remote.sin_addr.s_addr = -1; remote.sin_port = htons(SMTP_PORT); openlog("turnme", LOG_PID, LOG_MAIL); while((c = getopt(argc, argv, "h:p:l:vd:")) != -1) { switch(c) { case 'h': if((host = gethostbyname2(optarg, AF_INET)) == NULL) { syslog(LOG_ERR, "cannot resolve name %s: %s", optarg, hstrerror(h_errno)); exit(1); } /* We always use the first address */ remote.sin_addr.s_addr = *(u_long *)host->h_addr_list[0]; break; case 'p': if((remote.sin_port = htons(atoi(optarg))) == 0) { syslog(LOG_ERR, "incorrect port number %s", optarg); exit(1); } break; case 'l': /* Not used, ignore siletly */ break; case 'v': #ifdef LOG_PERROR /* Nothing to do if not... */ closelog(); openlog("turnme", LOG_PID | LOG_PERROR, LOG_MAIL); #endif verbose++; break; case 'd': delay = atoi(optarg); break; default: usage(); } } argc -= optind; argv += optind; if(remote.sin_addr.s_addr == -1 || argc == 0) { usage(); } if(gethostname(hostname, HOSTNAME_BUFFER) == -1) { syslog(LOG_ERR, "cannot find out my hostname: %m"); exit(1); } if(delay) sleep(delay); /* Initialization is done by this moment */ if((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { syslog(LOG_ERR, "cannot create socket %m"); exit(1); } if(verbose) { fprintf(stdout, "Establishing connection...\n"); } if(connect(s, (struct sockaddr *)&remote, sizeof(struct sockaddr_in))) { syslog(LOG_ERR, "connect(2) failed: %m"); exit(1); } if((rs = fdopen(s, "r")) == NULL || (ws = fdopen(s, "w")) == NULL) { syslog(LOG_ERR, "cannot associate a file handler with the socket"); exit(1); } if(smtp_read(220) == NULL) { /* The msssage is not greeting */ syslog(LOG_ERR, "no greeting from remote"); goodbye(1); } fprintf(ws, "EHLO %s\n", hostname); if(verbose) { fprintf(stdout, ">>> EHLO %s\n", hostname); } fflush(ws); if(smtp_read(250) == NULL) { /* Wont talk with us */ syslog(LOG_ERR, "the remote will not talk to us"); goodbye(1); } while(argc) { domain = strtok(*argv, ","); while(domain) { fprintf(ws, "ETRN %s\n", domain); if(verbose) { fprintf(stdout, ">>> ETRN %s\n", domain); } fflush(ws); if(smtp_read(250) == NULL) { /* TURNME failed */ syslog(LOG_ERR, "ETRN command failed for %s", *argv); goodbye(1); } domain = strtok(NULL, ","); } argc--; argv++; } goodbye(0); /* Never reached */ } /* * Prints usage and exits the program. */ void usage() { fprintf(stderr, "usage: turnme [-v] -h hostname [-p port] [-l lock]" " [-d delay] domains\n"); exit(1); } /* * Say QUIT and leave */ void goodbye(exitcode) int exitcode; { fprintf(ws, "QUIT\n"); if(verbose) { fprintf(stdout, ">>> QUIT\n"); } fflush(ws); fclose(rs); fclose(ws); close(s); closelog(); exit(exitcode); } /* * Read and return the last SMTP response if matches int * */ char * smtp_read(code) int code; { int size; int response; while(fgets(buffer, SMTP_BUFFER, rs) != NULL) { if(verbose) { fputs(buffer, stdout); } if(buffer[3] != ' ') { continue; } buffer[3] = '\0'; if(atoi(buffer) != code) { return NULL; } buffer[3] = ' '; return buffer; } syslog(LOG_ERR, "cannot read from stream: %m"); /* Not reached */ }