/* doscan - Denial Of Service Capable Auditing of Networks -*- C++ -*- * Copyright (C) 2003 Florian Weimer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include "opt.h" #include "tcp_server.h" #include #include #include #include #include #include #include #include // tcp_accept_handler tcp_accept_handler::tcp_accept_handler(event_queue& q, unsigned port) : fd_handler(q, make_server(0, port), watch_read) { set_infinite_timeout(); } tcp_accept_handler::tcp_accept_handler(event_queue& q, ipv4_t host, unsigned port) : fd_handler(q, make_server(host, port), watch_read) { set_infinite_timeout(); } tcp_accept_handler::~tcp_accept_handler() { int old_fd = fd(); if (old_fd >= 0) { unwatch(); close(old_fd); } } bool tcp_accept_handler::on_activity(activity) { struct sockaddr_in sa; socklen_t len = sizeof(sa); int result = accept(fd(), reinterpret_cast(&sa), &len); if (result >= 0) { if (sa.sin_family != AF_INET) { fprintf(stderr, "%s: accept() returned unknown socket family %u\n", opt_program, static_cast(sa.sin_family)); exit(EXIT_FAILURE); } new_connection(result, ntohl(sa.sin_addr.s_addr), ntohs(sa.sin_port)); return true; } // We ignore *all* errors. return true; } bool tcp_accept_handler::on_timeout(ticks_t) { // Only called when termination has been requested return false; } int tcp_accept_handler::make_server(ipv4_t host, unsigned short port) { int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { int err = errno; ipv4_string_t a; // If we encounter an error at this point, it is not actually // network-related, so we bail out immediately. ipv4_address_to_string (host, a); fprintf (stderr, "%s: could not create socket for %s:%u, error was: %s\n", opt_program, a, port, strerror (err)); fprintf (stderr, "%s: try the '--connections' option with a smaller value\n", opt_program); exit (EXIT_FAILURE); } // Make socket non-blocking. int flags = fcntl (sockfd, F_GETFL, 0); if (fcntl (sockfd, F_SETFL, flags | O_NONBLOCK) == -1) { int err = errno; ipv4_string_t a; // Again, this error is not network-related. ipv4_address_to_string (host, a); fprintf (stderr, "%s: could not set non-blocking mode for %s:%u, error was: %s\n", opt_program, a, port, strerror (err)); exit (EXIT_FAILURE); } // Reuse existing addresses. int one = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1) { int err = errno; ipv4_string_t a; // Again, this error is not network-related. ipv4_address_to_string (host, a); fprintf (stderr, "%s: could not reuse address for %s:%u, error was: %s\n", opt_program, a, port, strerror (err)); exit (EXIT_FAILURE); } // Bind socket to the requested address. struct sockaddr_in sa; memset (&sa, 0, sizeof (sa)); sa.sin_family = AF_INET; sa.sin_port = htons (port); sa.sin_addr.s_addr = htonl (host); if (bind (sockfd, (struct sockaddr *)&sa, sizeof (sa)) == -1) { int err = errno; ipv4_string_t a; // Again, this error is not network-related. ipv4_address_to_string (host, a); fprintf (stderr, "%s: could not bind socket to %s:%u, error was: %s\n", opt_program, a, port, strerror (err)); exit (EXIT_FAILURE); } // Now listen on the socket. if (listen (sockfd, 0) == -1) { int err = errno; ipv4_string_t a; // Again, this error is not network-related. ipv4_address_to_string (host, a); fprintf (stderr, "%s: could not listen on %s:%u, error was: %s\n", opt_program, a, port, strerror (err)); exit (EXIT_FAILURE); } return sockfd; } // arch-tag: 4c4fb5a0-a565-475d-83f8-257cf7b22cb3