static void listener(void) { int sock; sock = open_socket_in(SOCK_STREAM, TCP_PORT); if (listen(sock, 20) == -1) { fprintf(stderr,"listen failed\n"); exit(1); } printf("waiting for connections\n"); signal(SIGCHLD, SIG_IGN); while (1) { struct sockaddr addr; socklen_t in_addrlen = sizeof(addr); int fd; while (waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0) ; fd = accept(sock, &addr, &in_addrlen); if (fd != -1) { if (fork() == 0) server(fd); close(fd); } } }
int main(int argc, char *argv[]) { int listen_port; char *host1, *host2; int sock_in; if (argc < 4) { printf("Usage: udpproxy <port> <host1> <host2>\n"); exit(1); } listen_port = atoi(argv[1]); host1 = argv[2]; host2 = argv[3]; sock_in = open_socket_in(listen_port); if (sock_in == -1) { fprintf(stderr,"sock on port %d failed - %s\n", listen_port, strerror(errno)); exit(1); } main_loop(sock_in, host1, host2); return 0; }
static bool open_sockets(void) { struct sockaddr_storage ss; const char *sock_addr = lp_nbt_client_socket_address(); if (!interpret_string_addr(&ss, sock_addr, AI_NUMERICHOST|AI_PASSIVE)) { DEBUG(0,("open_sockets: unable to get socket address " "from string %s", sock_addr)); return false; } ServerFD = open_socket_in( SOCK_DGRAM, (RootPort ? 137 : 0), (RootPort ? 0 : 3), &ss, true ); if (ServerFD == -1) { return false; } set_socket_options( ServerFD, "SO_BROADCAST" ); DEBUG(3, ("Socket opened.\n")); return true; }
void start_accept_loop(int port, int (*fn)(int )) { int s; /* open an incoming socket */ s = open_socket_in(SOCK_STREAM, port); if (s == -1) exit_cleanup(RERR_SOCKETIO); /* ready to listen */ if (listen(s, 5) == -1) { close(s); exit_cleanup(RERR_SOCKETIO); } /* now accept incoming connections - forking a new process for each incoming connection */ while (1) { fd_set fds; int fd; struct sockaddr addr; int in_addrlen = sizeof(addr); FD_ZERO(&fds); FD_SET(s, &fds); if (select(s+1, &fds, NULL, NULL, NULL) != 1) { continue; } if(!FD_ISSET(s, &fds)) continue; fd = accept(s,&addr,&in_addrlen); if (fd == -1) continue; signal(SIGCHLD, SIG_IGN); /* we shouldn't have any children left hanging around but I have had reports that on Digital Unix zombies are produced, so this ensures that they are reaped */ #ifdef WNOHANG waitpid(-1, NULL, WNOHANG); #endif if (fork()==0) { close(s); set_nonblocking(fd); _exit(fn(fd)); } close(fd); } }
int main(int argc, char *argv[]) { int listen_port, dest_port; char *host; int sock_in; int sock_out; int listen_fd; struct sockaddr addr; int in_addrlen = sizeof(addr); if (argc < 4) { printf("Usage: sockspy <inport> <host> <port>\n"); exit(1); } listen_port = atoi(argv[1]); host = argv[2]; dest_port = atoi(argv[3]); listen_fd = open_socket_in(listen_port); if (listen_fd == -1) { fprintf(stderr,"listen on port %d failed - %s\n", listen_port, strerror(errno)); exit(1); } if (listen(listen_fd, 100) == -1) { fprintf(stderr,"listen failed\n"); exit(1); } while (1) { sock_in = accept(listen_fd,&addr,&in_addrlen); if (sock_in == -1) { fprintf(stderr,"accept on port %d failed - %s\n", listen_port, strerror(errno)); exit(1); } if (fork() == 0) { close(listen_fd); sock_out = open_socket_out(host, dest_port); if (sock_out == -1) { exit(1); } main_loop(sock_in, sock_out); _exit(0); } close(sock_in); } return 0; }
static BOOL open_sockets(BOOL isdaemon, int port) { /* * The sockets opened here will be used to receive broadcast * packets *only*. Interface specific sockets are opened in * make_subnet() in namedbsubnet.c. Thus we bind to the * address "0.0.0.0". The parameter 'socket address' is * now deprecated. */ if ( isdaemon ) ClientNMB = open_socket_in(SOCK_DGRAM, port, 0, interpret_addr(lp_socket_address()), True); else ClientNMB = 0; ClientDGRAM = open_socket_in(SOCK_DGRAM, DGRAM_PORT, 3, interpret_addr(lp_socket_address()), True); if ( ClientNMB == -1 ) return( False ); #ifndef _XBOX /* we are never interested in SIGPIPE */ BlockSignals(True,SIGPIPE); #endif set_socket_options( ClientNMB, "SO_BROADCAST" ); set_socket_options( ClientDGRAM, "SO_BROADCAST" ); /* Ensure we're non-blocking. */ set_blocking( ClientNMB, False); set_blocking( ClientDGRAM, False); DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) ); return( True ); }
static struct subnet_record *make_subnet(char *name, enum subnet_type type, struct in_addr myip, struct in_addr bcast_ip, struct in_addr mask_ip) { struct subnet_record *subrec = NULL; int nmb_sock, dgram_sock; /* Check if we are creating a non broadcast subnet - if so don't create sockets. */ if(type != NORMAL_SUBNET) { nmb_sock = -1; dgram_sock = -1; } else { /* * Attempt to open the sockets on port 137/138 for this interface * and bind them. * Fail the subnet creation if this fails. */ if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, myip.s_addr)) == -1) { DEBUG(0,("make_subnet: Failed to open nmb socket on interface %s \ for port %d. Error was %s\n", inet_ntoa(myip), global_nmb_port, strerror(errno))); return NULL; } if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, myip.s_addr)) == -1) { DEBUG(0,("make_subnet: Failed to open dgram socket on interface %s \ for port %d. Error was %s\n", inet_ntoa(myip), DGRAM_PORT, strerror(errno))); return NULL; }
/**************************************************************************** open the socket communication **************************************************************************/ static BOOL open_sockets(void) { ServerFD = open_socket_in( SOCK_DGRAM, (RootPort ? 137 : 0), (RootPort ? 0 : 3), interpret_addr(lp_socket_address()), True ); if (ServerFD == -1) return(False); set_socket_options( ServerFD, "SO_BROADCAST" ); DEBUG(3, ("Socket opened.\n")); return True; }
/******************************************************** resolve via "wins" method *********************************************************/ static BOOL resolve_wins (const char *name, struct in_addr *return_ip, int name_type) { int sock; struct in_addr wins_ip; BOOL wins_ismyip; /* * "wins" means do a unicast lookup to the WINS server. * Ignore if there is no WINS server specified or if the * WINS server is one of our interfaces (if we're being * called from within nmbd - we can't do this call as we * would then block). */ DEBUG (3, ("resolve_name: Attempting wins lookup for name %s<0x%x>\n", name, name_type)); if (!*lp_wins_server ()) { DEBUG (3, ("resolve_name: WINS server resolution selected and no WINS server present.\n")); return False; } wins_ip = *interpret_addr2 (lp_wins_server ()); wins_ismyip = ismyip (wins_ip); if ((wins_ismyip && !global_in_nmbd) || !wins_ismyip) { sock = open_socket_in (SOCK_DGRAM, 0, 3, interpret_addr (lp_socket_address ()), True); if (sock != -1) { struct in_addr *iplist = NULL; int count; iplist = name_query (sock, name, name_type, False, True, wins_ip, &count, NULL); if (iplist != NULL) { *return_ip = iplist[0]; free ((char *) iplist); close (sock); return True; } close (sock); } } return False; }
static void start_filter(char *desthost) { int s, c; struct in_addr dest_ip; CatchChild(); /* start listening on port 445 locally */ s = open_socket_in(SOCK_STREAM, 445, 0, 0, True); if (s == -1) { d_printf("bind failed\n"); exit(1); } if (listen(s, 5) == -1) { d_printf("listen failed\n"); } if (!resolve_name(desthost, &dest_ip, 0x20)) { d_printf("Unable to resolve host %s\n", desthost); exit(1); } while (1) { fd_set fds; int num; struct sockaddr addr; socklen_t in_addrlen = sizeof(addr); FD_ZERO(&fds); FD_SET(s, &fds); num = sys_select_intr(s+1,&fds,NULL,NULL,NULL); if (num > 0) { c = accept(s, &addr, &in_addrlen); if (c != -1) { if (fork() == 0) { close(s); filter_child(c, dest_ip); exit(0); } else { close(c); } } } } }
static void start_filter(char *desthost) { int s, c; struct sockaddr_storage dest_ss; struct sockaddr_storage my_ss; CatchChild(); /* start listening on port 445 locally */ zero_sockaddr(&my_ss); s = open_socket_in(SOCK_STREAM, TCP_SMB_PORT, 0, &my_ss, True); if (s == -1) { d_printf("bind failed\n"); exit(1); } if (listen(s, 5) == -1) { d_printf("listen failed\n"); } if (!resolve_name(desthost, &dest_ss, 0x20, false)) { d_printf("Unable to resolve host %s\n", desthost); exit(1); } while (1) { int num, revents; struct sockaddr_storage ss; socklen_t in_addrlen = sizeof(ss); num = poll_intr_one_fd(s, POLLIN|POLLHUP, -1, &revents); if ((num > 0) && (revents & (POLLIN|POLLHUP|POLLERR))) { c = accept(s, (struct sockaddr *)&ss, &in_addrlen); if (c != -1) { if (fork() == 0) { close(s); filter_child(c, &dest_ss); exit(0); } else { close(c); } } } } }
/* check to see if nmbd is running on localhost by looking for a __SAMBA__ response */ BOOL nmbd_running(void) { int fd, count, flags; struct in_addr *ip_list; if ((fd = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr("127.0.0.1"), True)) != -1) { if ((ip_list = name_query(fd, "__SAMBA__", 0, True, True, loopback_ip, &count, &flags, NULL)) != NULL) { SAFE_FREE(ip_list); close(fd); return True; } close (fd); } return False; }
/******************************************************** resolve via "bcast" method *********************************************************/ static BOOL resolve_bcast (const char *name, struct in_addr *return_ip, int name_type) { int sock, i; /* * "bcast" means do a broadcast lookup on all the local interfaces. */ DEBUG (3, ("resolve_name: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type)); sock = open_socket_in (SOCK_DGRAM, 0, 3, interpret_addr (lp_socket_address ()), True); if (sock != -1) { struct in_addr *iplist = NULL; int count; int num_interfaces = iface_count (); static char so_broadcast[] = "SO_BROADCAST"; set_socket_options (sock, so_broadcast); /* * Lookup the name on all the interfaces, return on * the first successful match. */ for (i = 0; i < num_interfaces; i++) { struct in_addr sendto_ip; /* Done this way to fix compiler error on IRIX 5.x */ sendto_ip = *iface_bcast (*iface_n_ip (i)); iplist = name_query (sock, name, name_type, True, True, sendto_ip, &count, NULL); if (iplist != NULL) { *return_ip = iplist[0]; free ((char *) iplist); close (sock); return True; } } close (sock); } return False; }
static struct subnet_record *make_subnet(const char *name, enum subnet_type type, struct in_addr myip, struct in_addr bcast_ip, struct in_addr mask_ip) { struct subnet_record *subrec = NULL; int nmb_sock, dgram_sock; /* Check if we are creating a non broadcast subnet - if so don't create sockets. */ if(type != NORMAL_SUBNET) { nmb_sock = -1; dgram_sock = -1; } else { /* * Attempt to open the sockets on port 137/138 for this interface * and bind them. * Fail the subnet creation if this fails. */ if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, myip.s_addr,True)) == -1) { if( DEBUGLVL( 0 ) ) { Debug1( "nmbd_subnetdb:make_subnet()\n" ); Debug1( " Failed to open nmb socket on interface %s ", inet_ntoa(myip) ); Debug1( "for port %d. ", global_nmb_port ); Debug1( "Error was %s\n", strerror(errno) ); } return NULL; } if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, myip.s_addr,True)) == -1) { if( DEBUGLVL( 0 ) ) { Debug1( "nmbd_subnetdb:make_subnet()\n" ); Debug1( " Failed to open dgram socket on interface %s ", inet_ntoa(myip) ); Debug1( "for port %d. ", DGRAM_PORT ); Debug1( "Error was %s\n", strerror(errno) ); } return NULL; } /* Make sure we can broadcast from these sockets. */ set_socket_options(nmb_sock,"SO_BROADCAST"); set_socket_options(dgram_sock,"SO_BROADCAST"); /* Set them non-blocking. */ set_blocking(nmb_sock, False); set_blocking(dgram_sock, False); } subrec = SMB_MALLOC_P(struct subnet_record); if (!subrec) { DEBUG(0,("make_subnet: malloc fail !\n")); close(nmb_sock); close(dgram_sock); return(NULL); } ZERO_STRUCTP(subrec); if((subrec->subnet_name = SMB_STRDUP(name)) == NULL) { DEBUG(0,("make_subnet: malloc fail for subnet name !\n")); close(nmb_sock); close(dgram_sock); ZERO_STRUCTP(subrec); SAFE_FREE(subrec); return(NULL); } DEBUG(2, ("making subnet name:%s ", name )); DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip))); DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip))); subrec->namelist_changed = False; subrec->work_changed = False; subrec->bcast_ip = bcast_ip; subrec->mask_ip = mask_ip; subrec->myip = myip; subrec->type = type; subrec->nmb_sock = nmb_sock; subrec->dgram_sock = dgram_sock; return subrec; }
int open_socket_in(int type, int port, int dlevel,uint32 socket_addr, BOOL rebind) { #ifndef EMBED struct hostent *hp; pstring host_name; #endif struct sockaddr_in sock; int res; #ifndef EMBED /* get my host name */ if (gethostname(host_name, MAXHOSTNAMELEN) == -1) { DEBUG(0,("gethostname failed\n")); return -1; } /* get host info */ if ((hp = Get_Hostbyname(host_name)) == 0) { DEBUG(0,( "Get_Hostbyname: Unknown host %s\n",host_name)); return -1; } #endif memset((char *)&sock,'\0',sizeof(sock)); #ifdef EMBED sock.sin_addr.s_addr = htonl(INADDR_ANY); #else memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length); #endif #ifdef HAVE_SOCK_SIN_LEN sock.sin_len = sizeof(sock); #endif sock.sin_port = htons( port ); #ifdef EMBED sock.sin_family = AF_INET; #else sock.sin_family = hp->h_addrtype; #endif sock.sin_addr.s_addr = socket_addr; #ifdef EMBED res = socket(AF_INET, type, 0); #else res = socket(hp->h_addrtype, type, 0); #endif if (res == -1) { DEBUG(0,("socket failed\n")); return -1; } { int val=1; if(rebind) val=1; else val=0; if(setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val)) == -1) DEBUG(dlevel,("setsockopt: SO_REUSEADDR=%d on port %d failed with error = %s\n", val, port, strerror(errno) )); #ifdef SO_REUSEPORT if(setsockopt(res,SOL_SOCKET,SO_REUSEPORT,(char *)&val,sizeof(val)) == -1) DEBUG(dlevel,("setsockopt: SO_REUSEPORT=%d on port %d failed with error = %s\n", val, port, strerror(errno) )); #endif /* SO_REUSEPORT */ } /* now we've got a socket - we need to bind it */ if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) { if (port) { if (port == SMB_PORT || port == NMB_PORT) DEBUG(dlevel,("bind failed on port %d socket_addr=%s (%s)\n", port,inet_ntoa(sock.sin_addr),strerror(errno))); close(res); if (dlevel > 0 && port < 1000) port = 7999; if (port >= 1000 && port < 9000) return(open_socket_in(type,port+1,dlevel,socket_addr,rebind)); } return(-1); } DEBUG(3,("bind succeeded on port %d\n",port)); return res; }
static bool smbd_open_one_socket(struct smbd_parent_context *parent, struct tevent_context *ev_ctx, struct messaging_context *msg_ctx, const struct sockaddr_storage *ifss, uint16_t port) { struct smbd_open_socket *s; s = talloc(parent, struct smbd_open_socket); if (!s) { return false; } s->parent = parent; s->fd = open_socket_in(SOCK_STREAM, port, parent->sockets == NULL ? 0 : 2, ifss, true); if (s->fd == -1) { DEBUG(0,("smbd_open_once_socket: open_socket_in: " "%s\n", strerror(errno))); TALLOC_FREE(s); /* * We ignore an error here, as we've done before */ return true; } /* ready to listen */ set_socket_options(s->fd, "SO_KEEPALIVE"); set_socket_options(s->fd, lp_socket_options()); /* Set server socket to * non-blocking for the accept. */ set_blocking(s->fd, False); if (listen(s->fd, SMBD_LISTEN_BACKLOG) == -1) { DEBUG(0,("open_sockets_smbd: listen: " "%s\n", strerror(errno))); close(s->fd); TALLOC_FREE(s); return false; } s->msg_ctx = msg_ctx; s->fde = tevent_add_fd(ev_ctx, s, s->fd, TEVENT_FD_READ, smbd_accept_connection, s); if (!s->fde) { DEBUG(0,("open_sockets_smbd: " "tevent_add_fd: %s\n", strerror(errno))); close(s->fd); TALLOC_FREE(s); return false; } tevent_fd_set_close_fn(s->fde, smbd_open_socket_close_fn); DLIST_ADD_END(parent->sockets, s, struct smbd_open_socket *); return true; }
static struct subnet_record *make_subnet(const char *name, enum subnet_type type, struct in_addr myip, struct in_addr bcast_ip, struct in_addr mask_ip) { struct subnet_record *subrec = NULL; int nmb_sock = -1; int dgram_sock = -1; int nmb_bcast = -1; int dgram_bcast = -1; bool bind_bcast = lp_nmbd_bind_explicit_broadcast(); /* Check if we are creating a non broadcast subnet - if so don't create sockets. */ if (type == NORMAL_SUBNET) { struct sockaddr_storage ss; struct sockaddr_storage ss_bcast; in_addr_to_sockaddr_storage(&ss, myip); in_addr_to_sockaddr_storage(&ss_bcast, bcast_ip); /* * Attempt to open the sockets on port 137/138 for this interface * and bind them. * Fail the subnet creation if this fails. */ nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port, 0, &ss, true); if (nmb_sock == -1) { DEBUG(0, ("nmbd_subnetdb:make_subnet()\n")); DEBUGADD(0,(" Failed to open nmb socket on interface %s ", inet_ntoa(myip))); DEBUGADD(0,("for port %d. ", global_nmb_port)); DEBUGADD(0,("Error was %s\n", strerror(errno))); goto failed; } set_socket_options(nmb_sock,"SO_BROADCAST"); set_blocking(nmb_sock, false); if (bind_bcast) { nmb_bcast = open_socket_in(SOCK_DGRAM, global_nmb_port, 0, &ss_bcast, true); if (nmb_bcast == -1) { DEBUG(0, ("nmbd_subnetdb:make_subnet()\n")); DEBUGADD(0,(" Failed to open nmb bcast socket on interface %s ", inet_ntoa(bcast_ip))); DEBUGADD(0,("for port %d. ", global_nmb_port)); DEBUGADD(0,("Error was %s\n", strerror(errno))); goto failed; } set_socket_options(nmb_bcast, "SO_BROADCAST"); set_blocking(nmb_bcast, false); } dgram_sock = open_socket_in(SOCK_DGRAM, DGRAM_PORT, 3, &ss, true); if (dgram_sock == -1) { DEBUG(0, ("nmbd_subnetdb:make_subnet()\n")); DEBUGADD(0,(" Failed to open dgram socket on interface %s ", inet_ntoa(myip))); DEBUGADD(0,("for port %d. ", DGRAM_PORT)); DEBUGADD(0,("Error was %s\n", strerror(errno))); goto failed; } set_socket_options(dgram_sock, "SO_BROADCAST"); set_blocking(dgram_sock, false); if (bind_bcast) { dgram_bcast = open_socket_in(SOCK_DGRAM, DGRAM_PORT, 3, &ss_bcast, true); if (dgram_bcast == -1) { DEBUG(0, ("nmbd_subnetdb:make_subnet()\n")); DEBUGADD(0,(" Failed to open dgram bcast socket on interface %s ", inet_ntoa(bcast_ip))); DEBUGADD(0,("for port %d. ", DGRAM_PORT)); DEBUGADD(0,("Error was %s\n", strerror(errno))); goto failed; } set_socket_options(dgram_bcast, "SO_BROADCAST"); set_blocking(dgram_bcast, false); } } subrec = SMB_MALLOC_P(struct subnet_record); if (!subrec) { DEBUG(0,("make_subnet: malloc fail !\n")); goto failed; } ZERO_STRUCTP(subrec); if((subrec->subnet_name = SMB_STRDUP(name)) == NULL) { DEBUG(0,("make_subnet: malloc fail for subnet name !\n")); goto failed; } DEBUG(2, ("making subnet name:%s ", name )); DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip))); DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip))); subrec->namelist_changed = False; subrec->work_changed = False; subrec->bcast_ip = bcast_ip; subrec->mask_ip = mask_ip; subrec->myip = myip; subrec->type = type; subrec->nmb_sock = nmb_sock; subrec->nmb_bcast = nmb_bcast; subrec->dgram_sock = dgram_sock; subrec->dgram_bcast = dgram_bcast; return subrec; failed: SAFE_FREE(subrec); if (nmb_sock != -1) { close(nmb_sock); } if (nmb_bcast != -1) { close(nmb_bcast); } if (dgram_sock != -1) { close(dgram_sock); } if (dgram_bcast != -1) { close(dgram_bcast); } return NULL; }
static bool open_sockets(bool isdaemon, int port) { struct sockaddr_storage ss; const char *sock_addr = lp_socket_address(); /* * The sockets opened here will be used to receive broadcast * packets *only*. Interface specific sockets are opened in * make_subnet() in namedbsubnet.c. Thus we bind to the * address "0.0.0.0". The parameter 'socket address' is * now deprecated. */ if (!interpret_string_addr(&ss, sock_addr, AI_NUMERICHOST|AI_PASSIVE)) { DEBUG(0,("open_sockets: unable to get socket address " "from string %s", sock_addr)); return false; } if (ss.ss_family != AF_INET) { DEBUG(0,("open_sockets: unable to use IPv6 socket" "%s in nmbd\n", sock_addr)); return false; } if (isdaemon) { ClientNMB = open_socket_in(SOCK_DGRAM, port, 0, &ss, true); } else { ClientNMB = 0; } if (ClientNMB == -1) { return false; } ClientDGRAM = open_socket_in(SOCK_DGRAM, DGRAM_PORT, 3, &ss, true); if (ClientDGRAM == -1) { if (ClientNMB != 0) { close(ClientNMB); } return false; } /* we are never interested in SIGPIPE */ BlockSignals(True,SIGPIPE); set_socket_options( ClientNMB, "SO_BROADCAST" ); set_socket_options( ClientDGRAM, "SO_BROADCAST" ); /* Ensure we're non-blocking. */ set_blocking( ClientNMB, False); set_blocking( ClientDGRAM, False); DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) ); return( True ); }
static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ports) { int num_interfaces = iface_count(); int num_sockets = 0; int fd_listenset[FD_SETSIZE]; fd_set listen_set; int s; int maxfd = 0; int i; char *ports; if (!is_daemon) { return open_sockets_inetd(); } #ifdef HAVE_ATEXIT { static int atexit_set; if(atexit_set == 0) { atexit_set=1; atexit(killkids); } } #endif #ifndef _XBOX /* Stop zombies */ CatchChild(); #endif FD_ZERO(&listen_set); /* use a reasonable default set of ports - listing on 445 and 139 */ if (!smb_ports) { ports = lp_smb_ports(); if (!ports || !*ports) { ports = smb_xstrdup(SMB_PORTS); } else { ports = smb_xstrdup(ports); } } else { ports = smb_xstrdup(smb_ports); } if (lp_interfaces() && lp_bind_interfaces_only()) { /* We have been given an interfaces line, and been told to only bind to those interfaces. Create a socket per interface and bind to only these. */ /* Now open a listen socket for each of the interfaces. */ for(i = 0; i < num_interfaces; i++) { struct in_addr *ifip = iface_n_ip(i); fstring tok; const char *ptr; if(ifip == NULL) { DEBUG(0,("open_sockets_smbd: interface %d has NULL IP address !\n", i)); continue; } for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { unsigned port = atoi(tok); if (port == 0) { continue; } s = fd_listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True); if(s == -1) return False; /* ready to listen */ set_socket_options(s,"SO_KEEPALIVE"); set_socket_options(s,user_socket_options); /* Set server socket to non-blocking for the accept. */ set_blocking(s,False); if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { DEBUG(0,("listen: %s\n",strerror(errno))); close(s); return False; } FD_SET(s,&listen_set); maxfd = MAX( maxfd, s); num_sockets++; if (num_sockets >= FD_SETSIZE) { DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n")); return False; } } } } else { /* Just bind to 0.0.0.0 - accept connections from anywhere. */ fstring tok; const char *ptr; num_interfaces = 1; for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { unsigned port = atoi(tok); if (port == 0) continue; /* open an incoming socket */ s = open_socket_in(SOCK_STREAM, port, 0, interpret_addr(lp_socket_address()),True); if (s == -1) return(False); /* ready to listen */ #ifndef _XBOX set_socket_options(s,"SO_KEEPALIVE"); #endif set_socket_options(s,user_socket_options); /* Set server socket to non-blocking for the accept. */ set_blocking(s,False); if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { DEBUG(0,("open_sockets_smbd: listen: %s\n", strerror(errno))); close(s); return False; } fd_listenset[num_sockets] = s; FD_SET(s,&listen_set); maxfd = MAX( maxfd, s); num_sockets++; if (num_sockets >= FD_SETSIZE) { DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n")); return False; } } } SAFE_FREE(ports); /* Listen to messages */ message_register(MSG_SMB_SAM_SYNC, msg_sam_sync); message_register(MSG_SMB_SAM_REPL, msg_sam_repl); message_register(MSG_SHUTDOWN, msg_exit_server); message_register(MSG_SMB_FILE_RENAME, msg_file_was_renamed); message_register(MSG_SMB_CONF_UPDATED, smb_conf_updated); #ifdef DEVELOPER message_register(MSG_SMB_INJECT_FAULT, msg_inject_fault); #endif /* now accept incoming connections - forking a new process for each incoming connection */ DEBUG(2,("waiting for a connection\n")); while (1) { fd_set lfds; int num; /* Free up temporary memory from the main smbd. */ lp_TALLOC_FREE(); /* Ensure we respond to PING and DEBUG messages from the main smbd. */ message_dispatch(); memcpy((char *)&lfds, (char *)&listen_set, sizeof(listen_set)); num = sys_select(maxfd+1,&lfds,NULL,NULL,NULL); if (num == -1 && errno == EINTR) { if (got_sig_term) { exit_server_cleanly(NULL); } /* check for sighup processing */ if (reload_after_sighup) { change_to_root_user(); DEBUG(1,("Reloading services after SIGHUP\n")); reload_services(False); reload_after_sighup = 0; } continue; } /* check if we need to reload services */ check_reload(time(NULL)); /* Find the sockets that are read-ready - accept on these. */ for( ; num > 0; num--) { struct sockaddr addr; socklen_t in_addrlen = sizeof(addr); s = -1; for(i = 0; i < num_sockets; i++) { if(FD_ISSET(fd_listenset[i],&lfds)) { s = fd_listenset[i]; /* Clear this so we don't look at it again. */ FD_CLR(fd_listenset[i],&lfds); break; } } smbd_set_server_fd(accept(s,&addr,&in_addrlen)); if (smbd_server_fd() == -1 && errno == EINTR) continue; if (smbd_server_fd() == -1) { DEBUG(0,("open_sockets_smbd: accept: %s\n", strerror(errno))); continue; } /* Ensure child is set to blocking mode */ set_blocking(smbd_server_fd(),True); if (smbd_server_fd() != -1 && interactive) { #ifdef _XBOX xb_IncClientCount(); #endif return True; } if (allowable_number_of_smbd_processes() && smbd_server_fd() != -1 && sys_fork()==0) { /* Child code ... */ /* close the listening socket(s) */ for(i = 0; i < num_sockets; i++) close(fd_listenset[i]); /* close our standard file descriptors */ close_low_fds(False); am_parent = 0; set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); set_socket_options(smbd_server_fd(),user_socket_options); /* this is needed so that we get decent entries in smbstatus for port 445 connects */ set_remote_machine_name(get_peer_addr(smbd_server_fd()), False); /* Reset the state of the random * number generation system, so * children do not get the same random * numbers as each other */ set_need_random_reseed(); /* tdb needs special fork handling - remove CLEAR_IF_FIRST flags */ if (tdb_reopen_all(1) == -1) { DEBUG(0,("tdb_reopen_all failed.\n")); smb_panic("tdb_reopen_all failed."); } return True; } /* The parent doesn't need this socket */ close(smbd_server_fd()); /* Sun May 6 18:56:14 2001 [email protected]: Clear the closed fd info out of server_fd -- and more importantly, out of client_fd in util_sock.c, to avoid a possible getpeername failure if we reopen the logs and use %I in the filename. */ smbd_set_server_fd(-1); /* Force parent to check log size after * spawning child. Fix from * [email protected]. The * parent smbd will log to logserver.smb. It * writes only two messages for each child * started/finished. But each child writes, * say, 50 messages also in logserver.smb, * begining with the debug_count of the * parent, before the child opens its own log * file logserver.client. In a worst case * scenario the size of logserver.smb would be * checked after about 50*50=2500 messages * (ca. 100kb). * */ force_check_log_size(); } /* end for num */ } /* end while 1 */ /* NOTREACHED return True; */ }
static int init_sockets_smbd(const char *smb_ports, int listenset[FD_SETSIZE]) { int num_interfaces = iface_count(); char * ports; int num_sockets = 0; int i, s; /* use a reasonable default set of ports - listing on 445 and 139 */ if (!smb_ports) { ports = lp_smb_ports(); if (!ports || !*ports) { ports = smb_xstrdup(SMB_PORTS); } else { ports = smb_xstrdup(ports); } } else { ports = smb_xstrdup(smb_ports); } if (lp_interfaces() && lp_bind_interfaces_only()) { /* We have been given an interfaces line, and been told to only bind to those interfaces. Create a socket per interface and bind to only these. */ /* Now open a listen socket for each of the interfaces. */ for(i = 0; i < num_interfaces; i++) { struct in_addr *ifip = iface_n_ip(i); fstring tok; const char *ptr; if(ifip == NULL) { DEBUG(0,("init_sockets_smbd: interface %d has NULL IP address !\n", i)); continue; } for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { unsigned port = atoi(tok); if (port == 0) { continue; } s = listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True); if (s < 0 || s >= FD_SETSIZE) return 0; /* ready to listen */ set_socket_options(s,"SO_KEEPALIVE"); set_socket_options(s,user_socket_options); /* Set server socket to non-blocking for the accept. */ set_blocking(s,False); if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { DEBUG(0,("listen: %s\n",strerror(errno))); close(s); return 0; } num_sockets++; if (num_sockets >= FD_SETSIZE) { DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n")); return 0; } } } } else { /* Just bind to 0.0.0.0 - accept connections from anywhere. */ fstring tok; const char *ptr; num_interfaces = 1; for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { unsigned port = atoi(tok); if (port == 0) continue; /* open an incoming socket */ s = open_socket_in(SOCK_STREAM, port, 0, interpret_addr(lp_socket_address()),True); if (s < 0 || s >= FD_SETSIZE) return 0; /* ready to listen */ set_socket_options(s,"SO_KEEPALIVE"); set_socket_options(s,user_socket_options); /* Set server socket to non-blocking for the accept. */ set_blocking(s,False); if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { DEBUG(0,("init_sockets_smbd: listen: %s\n", strerror(errno))); close(s); return 0; } listenset[num_sockets] = s; num_sockets++; if (num_sockets >= FD_SETSIZE) { DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n")); return 0; } } } SAFE_FREE(ports); return num_sockets; }
void start_accept_loop(int port, int (*fn)(int )) { int s; extern char *bind_address; extern int default_af_hint; /* open an incoming socket */ s = open_socket_in(SOCK_STREAM, port, bind_address, default_af_hint); if (s == -1) exit_cleanup(RERR_SOCKETIO); /* ready to listen */ if (listen(s, 5) == -1) { close(s); exit_cleanup(RERR_SOCKETIO); } /* now accept incoming connections - forking a new process for each incoming connection */ while (1) { fd_set fds; pid_t pid; int fd; struct sockaddr_storage addr; socklen_t addrlen = sizeof addr; /* close log file before the potentially very long select so file can be trimmed by another process instead of growing forever */ log_close(); FD_ZERO(&fds); FD_SET(s, &fds); if (select(s+1, &fds, NULL, NULL, NULL) != 1) { continue; } if(!FD_ISSET(s, &fds)) continue; fd = accept(s,(struct sockaddr *)&addr,&addrlen); if (fd == -1) continue; signal(SIGCHLD, SIG_IGN); /* we shouldn't have any children left hanging around but I have had reports that on Digital Unix zombies are produced, so this ensures that they are reaped */ #ifdef WNOHANG while (waitpid(-1, NULL, WNOHANG) > 0); #endif if ((pid = fork()) == 0) { close(s); /* open log file in child before possibly giving up privileges */ log_open(); _exit(fn(fd)); } else if (pid < 0) { rprintf(FERROR, RSYNC_NAME ": could not create child server process: %s\n", strerror(errno)); close(fd); /* This might have happened because we're * overloaded. Sleep briefly before trying to * accept again. */ sleep(2); } else { /* Parent doesn't need this fd anymore. */ close(fd); } } }