Index: nsock/include/nsock.h =================================================================== --- nsock/include/nsock.h (revision 29742) +++ nsock/include/nsock.h (working copy) @@ -228,7 +228,8 @@ NSE_TYPE_WRITE = 3, NSE_TYPE_TIMER = 4, NSE_TYPE_PCAP_READ = 5, - NSE_TYPE_MAX = 6, + NSE_TYPE_LISTEN = 6, + NSE_TYPE_MAX = 7, }; /* At some point I was considering a NSE_TYPE_START and NSE_TYPE_CUSTOM */ /* Find the type of an event that spawned a callback */ @@ -497,6 +498,17 @@ nsock_event_id nsock_printf(nsock_pool nsp, nsock_iod nsiod, nsock_ev_handler handler, int timeout_msecs, void *userdata, char *format, ... ); +/* Server mode: listen for incoming connections. See nsock_accept_client() below + * to actually accept client connections from within the handler. + * ss and sslen arguments are the ones used to bind(2) the socket. */ +nsock_event_id nsock_listen(nsock_pool nsp, nsock_iod nsiod, nsock_ev_handler handler, int timeout_msecs, void *udata, + int proto, const struct sockaddr_storage *ss, size_t sslen); + +/* Server mode: get client socket from within a nsock_listen() event handler. + * This function returns the new file descriptor corresponding to the client + * socket. (see accept(2)) */ +int nsock_accept_client(nsock_event nse, struct sockaddr *saddr, socklen_t *sslen); + /* Send back an NSE_TYPE_TIMER after the number of milliseconds specified. Of * course it can also return due to error, cancellation, etc. */ nsock_event_id nsock_timer_create(nsock_pool nsp, nsock_ev_handler handler, int timeout_msecs, void *userdata); Index: nsock/src/nsock_listen.c =================================================================== --- nsock/src/nsock_listen.c (revision 0) +++ nsock/src/nsock_listen.c (working copy) @@ -0,0 +1,126 @@ +/*************************************************************************** + * nsock_listen.c -- Nsock server mode. * + * * + ***********************IMPORTANT NSOCK LICENSE TERMS*********************** + * * + * The nsock parallel socket event library is (C) 1999-2012 Insecure.Com * + * LLC This library is free software; you may redistribute and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; Version 2. This guarantees * + * your right to use, modify, and redistribute this software under certain * + * conditions. If this license is unacceptable to you, Insecure.Com LLC * + * may be willing to sell alternative licenses (contact * + * sales@insecure.com ). * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement stating * + * terms other than the (GPL) terms above, then that alternative license * + * agreement takes precedence over this comment. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * 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 v2.0 for more details * + * (http://www.gnu.org/licenses/gpl-2.0.html). * + * * + ***************************************************************************/ + +/* $Id$ */ + +#include "nsock_internal.h" + +#define NSOCK_LISTEN_BACKLOG 10 + + +nsock_event_id nsock_listen(nsock_pool nspool, nsock_iod nsiod, nsock_ev_handler handler, + int timeout_msecs, void *userdata, int proto, const struct sockaddr_storage *ss, size_t sslen) { + mspool *nsp = (mspool *)nspool; + msiod *nsi = (msiod *)nsiod; + msevent *nse; + int socktype; + int one = 1; + + nse = msevent_new(nsp, NSE_TYPE_LISTEN, nsiod, timeout_msecs, handler, userdata); + assert(nse); + + if (proto == IPPROTO_UDP) + socktype = SOCK_DGRAM; + else + socktype = SOCK_STREAM; + + nsi->sd = inheritable_socket(ss->ss_family, socktype, proto); + if (nsi->sd < 0) + goto listen_error; + + unblock_socket(nsi->sd); + + if (setsockopt(nsi->sd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) + goto listen_error; + + if (bind(nsi->sd, (const struct sockaddr *)ss, sslen) < 0) + goto listen_error; + + if (socktype == SOCK_STREAM) { + if (listen(nsi->sd, NSOCK_LISTEN_BACKLOG) < 0) + goto listen_error; + } + + if (nsp->tracelevel > 0) + nsock_trace(nsp, "Server socket created (listening) (EID #%li)", nse->id); + + nsp_add_event(nsp, nse); + return nse->id; + +listen_error: + nse->event_done = 1; + nse->errnum = socket_errno(); + nse->status = NSE_STATUS_ERROR; + + nsp_add_event(nsp, nse); + return nse->id; +} + +int nsock_accept_client(nsock_event nsevent, struct sockaddr *saddr, socklen_t *sslen) { + msevent *nse = (msevent *)nsevent; + int sd; + + if (nse->type != NSE_TYPE_LISTEN || nse->status != NSE_STATUS_SUCCESS) + return -1; + + sd = accept(nse->iod->sd, saddr, sslen); + if (sd < 0) { + nse->errnum = socket_errno(); + return -1; + } + + unblock_socket(sd); + return sd; +} + Property changes on: nsock/src/nsock_listen.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +Author Date Id Revision \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: nsock/src/nsock_internal.h =================================================================== --- nsock/src/nsock_internal.h (revision 29742) +++ nsock/src/nsock_internal.h (working copy) @@ -434,6 +434,8 @@ void handle_timer_result(mspool *ms, msevent *nse, enum nse_status status); +void handle_listen_result(mspool *ms, msevent *nse, enum nse_status status); + #if HAVE_PCAP void handle_pcap_read_result(mspool *ms, msevent *nse, enum nse_status status); #endif Index: nsock/src/Makefile.in =================================================================== --- nsock/src/Makefile.in (revision 29742) +++ nsock/src/Makefile.in (working copy) @@ -27,9 +27,9 @@ TARGET = libnsock.a -SRCS = error.c filespace.c gh_list.c nsock_connect.c nsock_core.c nsock_iod.c nsock_read.c nsock_timers.c nsock_write.c nsock_ssl.c nsock_event.c nsock_pool.c netutils.c nsock_pcap.c nsock_engines.c engine_select.c engine_epoll.c @COMPAT_SRCS@ +SRCS = error.c filespace.c gh_list.c nsock_connect.c nsock_core.c nsock_iod.c nsock_read.c nsock_timers.c nsock_write.c nsock_listen.c nsock_ssl.c nsock_event.c nsock_pool.c netutils.c nsock_pcap.c nsock_engines.c engine_select.c engine_epoll.c @COMPAT_SRCS@ -OBJS = error.o filespace.o gh_list.o nsock_connect.o nsock_core.o nsock_iod.o nsock_read.o nsock_timers.o nsock_write.o nsock_ssl.o nsock_event.o nsock_pool.o netutils.o nsock_pcap.o nsock_engines.o engine_select.o engine_epoll.o @COMPAT_OBJS@ +OBJS = error.o filespace.o gh_list.o nsock_connect.o nsock_core.o nsock_iod.o nsock_read.o nsock_timers.o nsock_write.o nsock_listen.o nsock_ssl.o nsock_event.o nsock_pool.o netutils.o nsock_pcap.o nsock_engines.o engine_select.o engine_epoll.o @COMPAT_OBJS@ DEPS = error.h filespace.h gh_list.h nsock_internal.h netutils.h nsock_pcap.h ../include/nsock.h $(NBASEDIR)/libnbase.a Index: nsock/src/nsock_event.c =================================================================== --- nsock/src/nsock_event.c (revision 29742) +++ nsock/src/nsock_event.c (working copy) @@ -145,6 +145,7 @@ first_ev_next(nse, &nse->iod->first_connect); break; + case NSE_TYPE_LISTEN: case NSE_TYPE_READ: first_ev_next(nse, &nse->iod->first_read); break; @@ -196,6 +197,7 @@ event_list = &nsp->connect_events; break; + case NSE_TYPE_LISTEN: case NSE_TYPE_READ: event_list = &nsp->read_events; break; @@ -280,6 +282,10 @@ handle_timer_result(nsp, nse, NSE_STATUS_CANCELLED); break; + case NSE_TYPE_LISTEN: + handle_listen_result(nsp, nse, NSE_STATUS_CANCELLED); + break; + #if HAVE_PCAP case NSE_TYPE_PCAP_READ: handle_pcap_read_result(nsp, nse, NSE_STATUS_CANCELLED); @@ -494,6 +500,7 @@ case NSE_TYPE_WRITE: return "WRITE"; case NSE_TYPE_TIMER: return "TIMER"; case NSE_TYPE_PCAP_READ: return "READ-PCAP"; + case NSE_TYPE_LISTEN: return "LISTEN"; default: return "UNKNOWN!"; } Index: nsock/src/nsock_core.c =================================================================== --- nsock/src/nsock_core.c (revision 29742) +++ nsock/src/nsock_core.c (working copy) @@ -230,6 +230,7 @@ iod->first_connect = gh_list_append(&iod->nsp->connect_events, nse); break; + case NSE_TYPE_LISTEN: case NSE_TYPE_READ: if (iod->first_read) iod->first_read = gh_list_insert_before(&iod->nsp->read_events, iod->first_read, nse); @@ -593,6 +594,11 @@ nse->status = status; } +void handle_listen_result(mspool *ms, msevent *nse, enum nse_status status) { + nse->event_done = 1; + nse->status = status; +} + /* Returns -1 if an error, otherwise the number of newly written bytes */ static int do_actual_read(mspool *ms, msevent *nse) { char buf[8192]; @@ -980,6 +986,13 @@ handle_write_result(nsp, nse, NSE_STATUS_TIMEOUT); break; + case NSE_TYPE_LISTEN: + if (ev != EV_NONE) + handle_listen_result(nsp, nse, NSE_STATUS_SUCCESS); + else if (!nse->event_done && nse->timeout.tv_sec && !TIMEVAL_AFTER(nse->timeout, nsock_tod)) + handle_listen_result(nsp, nse, NSE_STATUS_TIMEOUT); + break; + case NSE_TYPE_TIMER: if (nse->timeout.tv_sec && !TIMEVAL_AFTER(nse->timeout, nsock_tod)) handle_timer_result(nsp, nse, NSE_STATUS_SUCCESS); @@ -1169,6 +1182,7 @@ iod_add_event(nse->iod, nse); break; + case NSE_TYPE_LISTEN: case NSE_TYPE_READ: if (!nse->event_done) { assert(nse->iod->sd >= 0); @@ -1321,6 +1335,7 @@ nsi_peerport(nsi)); break; + case NSE_TYPE_LISTEN: case NSE_TYPE_TIMER: nsock_trace(ms, "Callback: %s %s %sfor EID %li", nse_type2str(nse->type), nse_status2str(nse->status), errstr,