int sys_select_ms(struct lwp *l, const struct sys_select_ms_args *uap, register_t *retval) { struct timeval tv; struct sys_select_args a = { .a = { .nfds = SCARG(uap, nfds), .readfds = SCARG(uap, readfds), .writefds = SCARG(uap, writefds), .exceptfds = SCARG(uap, exceptfds), } }; if (SCARG(uap, tmout) == TMO_FEVR) { a.a.tv = NULL; } else if (SCARG(uap, tmout) >= 0) { tv.tv_sec = SCARG(uap, tmout) / 1000; tv.tv_usec = (SCARG(uap, tmout) % 1000) * 1000; a.a.tv = &tv; } else { return EINVAL; } return sys_select(l, &a, retval); }
/**************************************************************************** wait for keyboard activity, swallowing network packets ****************************************************************************/ static void wait_keyboard(struct cli_state *cli) { fd_set fds; struct timeval timeout; while (1) { FD_ZERO(&fds); FD_SET(cli->fd,&fds); FD_SET(fileno(stdin),&fds); timeout.tv_sec = 20; timeout.tv_usec = 0; sys_select(MAX(cli->fd,fileno(stdin))+1,&fds,&timeout); if (FD_ISSET(fileno(stdin),&fds)) return; /* We deliberately use receive_smb instead of client_receive_smb as we want to receive session keepalives and then drop them here. */ if (FD_ISSET(cli->fd,&fds)) receive_smb(cli->fd,cli->inbuf,0); } }
asmlinkage int old_select(struct sel_arg_struct *arg) { struct sel_arg_struct a; if (copy_from_user(&a, arg, sizeof(a))) return -EFAULT; /* sys_select() does the appropriate kernel locking */ return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); }
static void do_smb_resolve(struct mdns_smbsrv_result *browsesrv) { DNSServiceRef mdns_conn_sdref = NULL; int mdnsfd; int fdsetsz; int ret; fd_set *fdset = NULL; struct timeval tv; DNSServiceErrorType err; TALLOC_CTX * ctx = talloc_tos(); err = DNSServiceResolve(&mdns_conn_sdref, 0 /* flags */, browsesrv->ifIndex, browsesrv->serviceName, browsesrv->regType, browsesrv->domain, do_smb_resolve_reply, NULL); if (err != kDNSServiceErr_NoError) { return; } mdnsfd = DNSServiceRefSockFD(mdns_conn_sdref); for (;;) { if (fdset != NULL) { TALLOC_FREE(fdset); } if (mdnsfd < 0 || mdnsfd >= FD_SETSIZE) { errno = EBADF; break; } fdsetsz = howmany(mdnsfd + 1, NFDBITS) * sizeof(fd_mask); fdset = TALLOC_ZERO(ctx, fdsetsz); FD_SET(mdnsfd, fdset); tv.tv_sec = 1; tv.tv_usec = 0; /* Wait until response received from mDNS daemon */ ret = sys_select(mdnsfd + 1, fdset, NULL, NULL, &tv); if (ret <= 0 && errno != EINTR) { break; } if (FD_ISSET(mdnsfd, fdset)) { /* Invoke callback function */ DNSServiceProcessResult(mdns_conn_sdref); break; } } TALLOC_FREE(fdset); DNSServiceRefDeallocate(mdns_conn_sdref); }
static void filter_child(int c, struct in_addr dest_ip) { int s; /* we have a connection from a new client, now connect to the server */ s = open_socket_out(SOCK_STREAM, &dest_ip, 139, LONG_CONNECT_TIMEOUT); if (s == -1) { DEBUG(0,("Unable to connect to %s\n", inet_ntoa(dest_ip))); exit(1); } while (c != -1 || s != -1) { fd_set fds; int num; FD_ZERO(&fds); if (s != -1) FD_SET(s, &fds); if (c != -1) FD_SET(c, &fds); num = sys_select(MAX(s+1, c+1),&fds,NULL); if (num <= 0) continue; if (c != -1 && FD_ISSET(c, &fds)) { if (!receive_smb(c, packet, 0)) { DEBUG(0,("client closed connection\n")); exit(0); } filter_request(packet); if (!send_smb(s, packet)) { DEBUG(0,("server is dead\n")); exit(1); } } if (s != -1 && FD_ISSET(s, &fds)) { if (!receive_smb(s, packet, 0)) { DEBUG(0,("server closed connection\n")); exit(0); } filter_reply(packet); if (!send_smb(c, packet)) { DEBUG(0,("client is dead\n")); exit(1); } } } DEBUG(0,("Connection closed\n")); exit(0); }
static void start_filter(char *desthost) { int s, c; struct in_addr dest_ip; CatchChild(); /* start listening on port 139 locally */ s = open_socket_in(SOCK_STREAM, 139, 0, 0, True); if (s == -1) { DEBUG(0,("bind failed\n")); exit(1); } if (listen(s, 5) == -1) { DEBUG(0,("listen failed\n")); } if (!resolve_name(desthost, &dest_ip, 0x20)) { DEBUG(0,("Unable to resolve host %s\n", desthost)); exit(1); } while (1) { fd_set fds; int num; struct sockaddr addr; int in_addrlen = sizeof(addr); FD_ZERO(&fds); FD_SET(s, &fds); num = sys_select(s+1,&fds,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); } } } } }
/* * Due to some executables calling the wrong select we sometimes * get wrong args. This determines how the args are being passed * (a single ptr to them all args passed) then calls * sys_select() with the appropriate args. -- Cort */ int ppc_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp) { if ( (unsigned long)n >= 4096 ) { unsigned long *buffer = (unsigned long *)n; if (verify_area(VERIFY_READ, buffer, 5*sizeof(unsigned long)) || __get_user(n, buffer) || __get_user(inp, ((fd_set **)(buffer+1))) || __get_user(outp, ((fd_set **)(buffer+2))) || __get_user(exp, ((fd_set **)(buffer+3))) || __get_user(tvp, ((struct timeval **)(buffer+4)))) return -EFAULT; } return sys_select(n, inp, outp, exp, tvp); }
asmlinkage int sunos_select(int width, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct timeval __user *tvp) { int ret; /* SunOS binaries expect that select won't change the tvp contents */ ret = sys_select (width, inp, outp, exp, tvp); if (ret == -EINTR && tvp) { time_t sec, usec; __get_user(sec, &tvp->tv_sec); __get_user(usec, &tvp->tv_usec); if (sec == 0 && usec == 0) ret = 0; } return ret; }
asmlinkage int old_select(unsigned long *buffer) { int n; fd_set *inp; fd_set *outp; fd_set *exp; struct timeval *tvp; n = verify_area(VERIFY_READ, buffer, 5*sizeof(unsigned long)); if (n) return n; n = get_user(buffer); inp = (fd_set *) get_user(buffer+1); outp = (fd_set *) get_user(buffer+2); exp = (fd_set *) get_user(buffer+3); tvp = (struct timeval *) get_user(buffer+4); return sys_select(n, inp, outp, exp, tvp); }
ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned int time_out) { fd_set fds; int selrtn; ssize_t readret; size_t nread = 0; struct timeval timeout; /* just checking .... */ if (maxcnt <= 0) return(0); /* Blocking read */ if (time_out <= 0) { if (mincnt == 0) mincnt = maxcnt; while (nread < mincnt) { #ifdef WITH_SSL if(fd == sslFd){ readret = SSL_read(ssl, buf + nread, maxcnt - nread); }else{ readret = read(fd, buf + nread, maxcnt - nread); } #else /* WITH_SSL */ readret = read(fd, buf + nread, maxcnt - nread); #endif /* WITH_SSL */ if (readret <= 0) return readret; nread += readret; } return((ssize_t)nread); } /* Most difficult - timeout read */ /* If this is ever called on a disk file and mincnt is greater then the filesize then system performance will suffer severely as select always returns true on disk files */ /* Set initial timeout */ timeout.tv_sec = (time_t)(time_out / 1000); timeout.tv_usec = (long)(1000 * (time_out % 1000)); for (nread=0; nread < mincnt; ) { FD_ZERO(&fds); FD_SET(fd,&fds); selrtn = sys_select(fd+1,&fds,&timeout); if(selrtn <= 0) return selrtn; #ifdef WITH_SSL if(fd == sslFd){ readret = SSL_read(ssl, buf + nread, maxcnt - nread); }else{ readret = read(fd, buf + nread, maxcnt - nread); } #else /* WITH_SSL */ readret = read(fd, buf+nread, maxcnt-nread); #endif /* WITH_SSL */ if (readret <= 0) return readret; nread += readret; } /* Return the number we got */ return((ssize_t)nread); }
static ssize_t read_socket_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned int time_out) { fd_set fds; int selrtn; ssize_t readret; size_t nread = 0; struct timeval timeout; /* just checking .... */ if (maxcnt <= 0) return(0); smb_read_error = 0; /* Blocking read */ if (time_out <= 0) { if (mincnt == 0) mincnt = maxcnt; while (nread < mincnt) { #ifdef WITH_SSL if(fd == sslFd){ readret = SSL_read(ssl, buf + nread, maxcnt - nread); }else{ readret = read(fd, buf + nread, maxcnt - nread); } #else /* WITH_SSL */ readret = read(fd, buf + nread, maxcnt - nread); #endif /* WITH_SSL */ if (readret == 0) { DEBUG(5,("read_socket_with_timeout: blocking read. EOF from client.\n")); smb_read_error = READ_EOF; return -1; } if (readret == -1) { DEBUG(0,("read_socket_with_timeout: read error = %s.\n", strerror(errno) )); smb_read_error = READ_ERROR; return -1; } nread += readret; } return((ssize_t)nread); } /* Most difficult - timeout read */ /* If this is ever called on a disk file and mincnt is greater then the filesize then system performance will suffer severely as select always returns true on disk files */ /* Set initial timeout */ timeout.tv_sec = (time_t)(time_out / 1000); timeout.tv_usec = (long)(1000 * (time_out % 1000)); for (nread=0; nread < mincnt; ) { FD_ZERO(&fds); FD_SET(fd,&fds); selrtn = sys_select(fd+1,&fds,&timeout); /* Check if error */ if(selrtn == -1) { /* something is wrong. Maybe the socket is dead? */ DEBUG(0,("read_socket_with_timeout: timeout read. select error = %s.\n", strerror(errno) )); smb_read_error = READ_ERROR; return -1; } /* Did we timeout ? */ if (selrtn == 0) { DEBUG(10,("read_socket_with_timeout: timeout read. select timed out.\n")); smb_read_error = READ_TIMEOUT; return -1; } #ifdef WITH_SSL if(fd == sslFd){ readret = SSL_read(ssl, buf + nread, maxcnt - nread); }else{ readret = read(fd, buf + nread, maxcnt - nread); } #else /* WITH_SSL */ readret = read(fd, buf+nread, maxcnt-nread); #endif /* WITH_SSL */ if (readret == 0) { /* we got EOF on the file descriptor */ DEBUG(5,("read_socket_with_timeout: timeout read. EOF from client.\n")); smb_read_error = READ_EOF; return -1; } if (readret == -1) { /* the descriptor is probably dead */ DEBUG(0,("read_socket_with_timeout: timeout read. read error = %s.\n", strerror(errno) )); smb_read_error = READ_ERROR; return -1; } nread += readret; } /* Return the number we got */ return((ssize_t)nread); }
static void wait_keyboard(char *buffer) #endif { fd_set fds; int selrtn; struct timeval timeout; #ifdef CLIX int delay = 0; #endif while (1) { extern int Client; FD_ZERO(&fds); FD_SET(Client,&fds); #ifndef CLIX FD_SET(fileno(stdin),&fds); #endif timeout.tv_sec = 20; timeout.tv_usec = 0; #ifdef CLIX timeout.tv_sec = 0; #endif selrtn = sys_select(&fds,&timeout); #ifndef CLIX if (FD_ISSET(fileno(stdin),&fds)) return; #else { char ch; int readret; set_blocking(fileno(stdin), False); readret = read_data( fileno(stdin), &ch, 1); set_blocking(fileno(stdin), True); if (readret == -1) { if (errno != EAGAIN) { /* should crash here */ DEBUG(1,("readchar stdin failed\n")); } } else if (readret != 0) { return ch; } } #endif /* We deliberately use receive_smb instead of client_receive_smb as we want to receive session keepalives and then drop them here. */ if (FD_ISSET(Client,&fds)) receive_smb(Client,buffer,0); #ifdef CLIX delay++; if (delay > 100000) { delay = 0; chkpath("\\",False); } #else chkpath("\\",False); #endif } }
int so_socksys(struct socksysreq *req) { int err = -EINVAL; int cmd = req->args[0]; if ((1 << cmd) & ((1 << SO_ACCEPT) | (1 << SO_BIND) | (1 << SO_CONNECT) | (1 << SO_GETPEERNAME) | (1 << SO_GETSOCKNAME) | (1 << SO_GETSOCKOPT) | (1 << SO_LISTEN) | (1 << SO_RECV) | (1 << SO_RECVFROM) | (1 << SO_SEND) | (1 << SO_SENDTO) | (1 << SO_SETSOCKOPT) | (1 << SO_SHUTDOWN) | (1 << SO_RECVMSG) | (1 << SO_SENDMSG))) { int fd = req->args[1]; (void) fd; /* These are all socket related and accept a file (socket) descriptor as their first argument. In situations where we are incapable of providing back a real socket, we must here first distinguish if the file descriptor corresponds to a socket or a stream. */ #if 0 if (it_is_a_socket) { #endif /* In this case, we have a real socket from the operating system's perspective and we can simply pass the arguments to the appropriate system call. */ #if 0 switch (cmd) { case SO_ACCEPT: /* FIXME: 32/64 conversion */ err = sys_accept(fd, (struct sockaddr *) req->args[2], req->args[3]); break; case SO_BIND: /* FIXME: 32/64 conversion */ err = sys_bind(fd, (struct sockaddr *) req->args[2], req->args[3]); break; case SO_CONNECT: /* FIXME: 32/64 conversion */ err = sys_connect(fd, (struct sockaddr *) req->args[2], req->args[3]); break; case SO_GETPEERNAME: /* FIXME: 32/64 conversion */ err = sys_getpeername(fd, (struct sockaddr *) req->args[2], (int *) req->args[3]); break; case SO_GETSOCKNAME: /* FIXME: 32/64 conversion */ err = sys_getsockname(fd, (struct sockaddr *) req->args[2], (int *) req->args[3]); break; case SO_GETSOCKOPT: /* FIXME: 32/64 conversion */ err = sys_getsockopt(fd, req->args[2], req->args[3], (char *) req->args[4], (int *) req->args[5]); break; case SO_LISTEN: /* FIXME: 32/64 conversion */ err = sys_listen(fd, req->args[2]); break; case SO_RECV: /* FIXME: 32/64 conversion */ err = sys_recv(fd, (void *) req->args[2], req->args[3], req->args[4]); break; case SO_RECVFROM: /* FIXME: 32/64 conversion */ err = sys_recvfrom(fd, (void *) req->args[2], req->args[3], req->args[4], (struct sockaddr *) req->args[5], (int *) req->args[6]); break; case SO_SEND: /* FIXME: 32/64 conversion */ err = sys_send(fd, (void *) req->args[2], req->args[3], req->args[4]); break; case SO_SENDTO: /* FIXME: 32/64 conversion */ err = sys_sendto(fd, (void *) req->args[2], req->args[3], req->args[4], (struct sockaddr *) req->args[5], req->args[6]); break; case SO_SETSOCKOPT: /* FIXME: 32/64 conversion */ err = sys_setsockopt(fd, req->args[2], req->args[3], (char *) req->args[4], req->args[5]); break; case SO_SHUTDOWN: /* FIXME: 32/64 conversion */ err = sys_shutdown(fd, req->args[2]); break; case SO_RECVMSG: /* FIXME: 32/64 conversion */ err = sys_recvmsg(fd, (struct msghdr *) req->args[2], req->args[3]); break; case SO_SENDMSG: /* FIXME: 32/64 conversion */ err = sys_sendmsg(fd, (struct msghdr *) req->args[2], req->args[3]); break; } #endif #if 0 } else { /* In this case, we do not have a real socket, but have a TPI stream from the operating system's perspective, and we will directly call the associated TPI routine. */ switch (cmd) { case SO_ACCEPT: /* FIXME: 32/64 conversion */ err = tpi_accept(fd, (struct sockaddr *) req->args[2], req->args[3]); break; case SO_BIND: /* FIXME: 32/64 conversion */ err = tpi_bind(fd, (struct sockaddr *) req->args[2], req->args[3]); break; case SO_CONNECT: /* FIXME: 32/64 conversion */ err = tpi_connect(fd, (struct sockaddr *) req->args[2], req->args[3]); break; case SO_GETPEERNAME: /* FIXME: 32/64 conversion */ err = tpi_getpeername(fd, (struct sockaddr *) req->args[2], (int *) req->args[3]); break; case SO_GETSOCKNAME: /* FIXME: 32/64 conversion */ err = tpi_getsockname(fd, (struct sockaddr *) req->args[2], (int *) req->args[3]); break; case SO_GETSOCKOPT: /* FIXME: 32/64 conversion */ err = tpi_getsockopt(fd, req->args[2], req->args[3], (char *) req->args[4], (int *) req->args[5]); break; case SO_LISTEN: /* FIXME: 32/64 conversion */ err = tpi_listen(fd, req->args[2]); break; case SO_RECV: /* FIXME: 32/64 conversion */ err = tpi_recv(fd, (void *) req->args[2], req->args[3], req->args[4]); break; case SO_RECVFROM: /* FIXME: 32/64 conversion */ err = tpi_recvfrom(fd, (void *) req->args[2], req->args[3], req->args[4], (struct sockaddr *) req->args[5], (int *) req->args[6]); break; case SO_SEND: /* FIXME: 32/64 conversion */ err = tpi_send(fd, (void *) req->args[2], req->args[3], req->args[4]); break; case SO_SENDTO: /* FIXME: 32/64 conversion */ err = tpi_sendto(fd, (void *) req->args[2], req->args[3], req->args[4], (struct sockaddr *) req->args[5], req->args[6]); break; case SO_SETSOCKOPT: /* FIXME: 32/64 conversion */ err = tpi_setsockopt(fd, req->args[2], req->args[3], (char *) req->args[4], req->args[5]); break; case SO_SHUTDOWN: /* FIXME: 32/64 conversion */ err = tpi_shutdown(fd, req->args[2]); break; case SO_RECVMSG: /* FIXME: 32/64 conversion */ err = tpi_recvmsg(fd, (struct msghdr *) req->args[2], req->args[3]); break; case SO_SENDMSG: /* FIXME: 32/64 conversion */ err = tpi_sendmsg(fd, (struct msghdr *) req->args[2], req->args[3]); break; } } #endif } if ((1 << cmd) & ((1 << SO_SOCKET) | (1 << SO_SOCKPAIR) | (1 << SO_SELECT) | (1 << SO_GETIPDOMAIN) | (1 << SO_SETIPDOMAIN) | (1 << SO_ADJTIME) | (1 << SO_SETREUID) | (1 << SO_SETREGID) | (1 << SO_GETTIME) | (1 << SO_SETTIME) | (1 << SO_GETITIMER) | (1 << SO_SETITIMER))) { /* These are BSD compatibiltiy functions and are how we create sockets in the first place. The BSD compatibility functions all have system calls in Linux, but we provide them for backward compatibility (to what!?). */ #if 0 switch (cmd) { case SO_SOCKET: /* FIXME: 32/64 conversion */ /* XXX: don't think so..., after checking for a stream */ err = sys_socket(req->args[1], req->args[2], req->args[3]); break; case SO_SOCKPAIR: /* FIXME: 32/64 conversion */ /* XXX: don't think so..., after checking for a stream */ err = sys_socketpair(req->args[1], req->args[2], req->args[3], (int *) req->args[4]); err = -EOPNOTSUPP; break; case SO_SELECT: /* FIXME: 32/64 conversion */ err = sys_select(req->args[1], (fd_set *) req->args[2], (fd_set *) req->args[3], (fd_set *) req->args[4], (struct timeval *) req->args[5]); break; case SO_GETIPDOMAIN: /* FIXME: 32/64 conversion */ todo(("Process SO_GETIPDOMAIN for compatibility.\n")); /* does not exist in Linux, need to use sys_newuname and copy the domainname portion */ err = -ENOSYS; break; case SO_SETIPDOMAIN: /* FIXME: 32/64 conversion */ err = sys_setdomainname((char *) req->args[1], req->args[2]); break; case SO_ADJTIME: /* FIXME: 32/64 conversion */ err = sys_admtimex((struct timex *) req->args[1]); break; case SO_SETREUID: /* FIXME: 32/64 conversion */ err = sys_setreuid(req->args[1], req->args[2]); break; case SO_SETREGID: /* FIXME: 32/64 conversion */ err = sys_setregid(req->args[1], req->args[2]); break; case SO_GETTIME: /* FIXME: 32/64 conversion */ err = sys_gettimeofday((struct timeval *) req->args[1], (struct timezone *) req->args[2]); break; case SO_SETTIME: /* FIXME: 32/64 conversion */ err = sys_settimeofday((struct timeval *) req->args[1], (struct timezone *) req->args[2]); break; case SO_GETITIMER: /* FIXME: 32/64 conversion */ err = sys_getitimer(req->args[1], (struct itimerval *) req->args[2]); break; case SO_SETITIMER: /* FIXME: 32/64 conversion */ err = sys_getitimer(req->args[1], (struct itimerval *) req->args[2], (struct itimerval *) req->args[3]); break; } #endif } return (err); }
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; */ }
BOOL receive_local_message( char *buffer, int buffer_len, int timeout) { struct sockaddr_in from; socklen_t fromlen = sizeof(from); int32 msg_len = 0; fd_set fds; int selrtn = -1; FD_ZERO(&fds); smb_read_error = 0; /* * We need to check for kernel oplocks before going into the select * here, as the EINTR generated by the linux kernel oplock may have * already been eaten. JRA. */ if (koplocks && koplocks->msg_waiting(&fds)) { return koplocks->receive_message(&fds, buffer, buffer_len); } while (timeout > 0 && selrtn == -1) { struct timeval to; int maxfd = oplock_sock; time_t starttime = time(NULL); FD_ZERO(&fds); maxfd = setup_oplock_select_set(&fds); to.tv_sec = timeout / 1000; to.tv_usec = (timeout % 1000) * 1000; DEBUG(5,("receive_local_message: doing select with timeout of %d ms\n", timeout)); selrtn = sys_select(maxfd+1,&fds,NULL,NULL,&to); if (selrtn == -1 && errno == EINTR) { /* could be a kernel oplock interrupt */ if (koplocks && koplocks->msg_waiting(&fds)) { return koplocks->receive_message(&fds, buffer, buffer_len); } /* * Linux 2.0.x seems to have a bug in that * it can return -1, EINTR with a timeout of zero. * Make sure we bail out here with a read timeout * if we got EINTR on a timeout of 1 or less. */ if (timeout <= 1) { smb_read_error = READ_TIMEOUT; return False; } /* Not a kernel interrupt - could be a SIGUSR1 message. We must restart. */ /* We need to decrement the timeout here. */ timeout -= ((time(NULL) - starttime)*1000); if (timeout < 0) timeout = 1; DEBUG(5,("receive_local_message: EINTR : new timeout %d ms\n", timeout)); continue; } /* Check if error */ if(selrtn == -1) { /* something is wrong. Maybe the socket is dead? */ smb_read_error = READ_ERROR; return False; } /* Did we timeout ? */ if (selrtn == 0) { smb_read_error = READ_TIMEOUT; return False; } } if (koplocks && koplocks->msg_waiting(&fds)) { return koplocks->receive_message(&fds, buffer, buffer_len); } if (!FD_ISSET(oplock_sock, &fds)) return False; /* * From here down we deal with the smbd <--> smbd * oplock break protocol only. */ /* * Read a loopback udp message. */ msg_len = sys_recvfrom(oplock_sock, &buffer[OPBRK_CMD_HEADER_LEN], buffer_len - OPBRK_CMD_HEADER_LEN, 0, (struct sockaddr *)&from, &fromlen); if(msg_len < 0) { DEBUG(0,("receive_local_message. Error in recvfrom. (%s).\n",strerror(errno))); return False; } /* Validate message length. */ if(msg_len > (buffer_len - OPBRK_CMD_HEADER_LEN)) { DEBUG(0,("receive_local_message: invalid msg_len (%d) max can be %d\n", msg_len, buffer_len - OPBRK_CMD_HEADER_LEN)); return False; } /* Validate message from address (must be localhost). */ if(from.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) { DEBUG(0,("receive_local_message: invalid 'from' address \ (was %lx should be 127.0.0.1)\n", (long)from.sin_addr.s_addr)); return False; }
int do_smb_browse(void) { int mdnsfd; int fdsetsz; int ret; fd_set *fdset = NULL; struct mdns_browse_state bstate; struct mdns_smbsrv_result *resptr; struct timeval tv; DNSServiceRef mdns_conn_sdref = NULL; DNSServiceErrorType err; TALLOC_CTX * ctx = talloc_stackframe(); ZERO_STRUCT(bstate); err = DNSServiceBrowse(&mdns_conn_sdref, 0, 0, "_smb._tcp", "", do_smb_browse_reply, &bstate); if (err != kDNSServiceErr_NoError) { d_printf("Error connecting to the Multicast DNS daemon\n"); TALLOC_FREE(ctx); return 1; } mdnsfd = DNSServiceRefSockFD(mdns_conn_sdref); for (;;) { if (fdset != NULL) { TALLOC_FREE(fdset); } fdsetsz = howmany(mdnsfd + 1, NFDBITS) * sizeof(fd_mask); fdset = TALLOC_ZERO(ctx, fdsetsz); FD_SET(mdnsfd, fdset); tv.tv_sec = 1; tv.tv_usec = 0; /* Wait until response received from mDNS daemon */ ret = sys_select(mdnsfd + 1, fdset, NULL, NULL, &tv); if (ret <= 0 && errno != EINTR) { break; } if (FD_ISSET(mdnsfd, fdset)) { /* Invoke callback function */ if (DNSServiceProcessResult(mdns_conn_sdref)) { break; } if (bstate.browseDone) { break; } } } DNSServiceRefDeallocate(mdns_conn_sdref); if (bstate.listhead != NULL) { resptr = bstate.listhead; while (resptr != NULL) { struct mdns_smbsrv_result *oldresptr; oldresptr = resptr; /* Resolve smb service instance */ do_smb_resolve(resptr); resptr = resptr->nextResult; } } TALLOC_FREE(ctx); return 0; }
asmlinkage int sunos_select(int width, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp) { /* SunOS binaries expect that select won't change the tvp contents */ current->personality |= STICKY_TIMEOUTS; return sys_select (width, inp, outp, exp, tvp); }
BOOL receive_local_message(fd_set * fds, char *buffer, int buffer_len, int timeout) { struct sockaddr_in from; int fromlen = sizeof(from); int32 msg_len = 0; smb_read_error = 0; if (timeout != 0) { struct timeval to; int selrtn; int maxfd = oplock_sock; if (koplocks && koplocks->notification_fd != -1) { FD_SET(koplocks->notification_fd, fds); maxfd = MAX(maxfd, koplocks->notification_fd); } to.tv_sec = timeout / 1000; to.tv_usec = (timeout % 1000) * 1000; selrtn = sys_select(maxfd + 1, fds, &to); if (selrtn == -1 && errno == EINTR) { /* could be a kernel oplock interrupt */ if (koplocks && koplocks->msg_waiting(fds)) { return koplocks->receive_message(fds, buffer, buffer_len); } } /* Check if error */ if (selrtn == -1) { /* something is wrong. Maybe the socket is dead? */ smb_read_error = READ_ERROR; return False; } /* Did we timeout ? */ if (selrtn == 0) { smb_read_error = READ_TIMEOUT; return False; } } if (koplocks && koplocks->msg_waiting(fds)) { return koplocks->receive_message(fds, buffer, buffer_len); } if (!FD_ISSET(oplock_sock, fds)) return False; /* * From here down we deal with the smbd <--> smbd * oplock break protocol only. */ /* * Read a loopback udp message. */ msg_len = recvfrom(oplock_sock, &buffer[OPBRK_CMD_HEADER_LEN], buffer_len - OPBRK_CMD_HEADER_LEN, 0, (struct sockaddr *)&from, &fromlen); if (msg_len < 0) { DEBUG(0, ("receive_local_message. Error in recvfrom. (%s).\n", strerror(errno))); return False; } /* Validate message length. */ if (msg_len > (buffer_len - OPBRK_CMD_HEADER_LEN)) { DEBUG(0, ("receive_local_message: invalid msg_len (%d) max can be %d\n", msg_len, buffer_len - OPBRK_CMD_HEADER_LEN)); return False; } /* Validate message from address (must be localhost). */ if (from.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) { DEBUG(0, ("receive_local_message: invalid 'from' address \ (was %lx should be 127.0.0.1\n", (long)from.sin_addr.s_addr)); return False; }
static void process_loop(void) { /* We'll be doing this a lot */ while (1) { struct winbindd_cli_state *state; fd_set r_fds, w_fds; int maxfd, listen_sock, listen_priv_sock, selret; struct timeval timeout; /* Handle messages */ message_dispatch(); /* refresh the trusted domain cache */ rescan_trusted_domains(); /* Free up temporary memory */ lp_talloc_free(); main_loop_talloc_free(); /* Initialise fd lists for select() */ listen_sock = open_winbindd_socket(); listen_priv_sock = open_winbindd_priv_socket(); if (listen_sock == -1 || listen_priv_sock == -1) { perror("open_winbind_socket"); exit(1); } maxfd = MAX(listen_sock, listen_priv_sock); FD_ZERO(&r_fds); FD_ZERO(&w_fds); FD_SET(listen_sock, &r_fds); FD_SET(listen_priv_sock, &r_fds); timeout.tv_sec = WINBINDD_ESTABLISH_LOOP; timeout.tv_usec = 0; if (opt_dual_daemon) { maxfd = dual_select_setup(&w_fds, maxfd); } /* Set up client readers and writers */ state = winbindd_client_list(); while (state) { /* Dispose of client connection if it is marked as finished */ if (state->finished) { struct winbindd_cli_state *next = state->next; remove_client(state); state = next; continue; } /* Select requires we know the highest fd used */ if (state->sock > maxfd) maxfd = state->sock; /* Add fd for reading */ if (state->read_buf_len != sizeof(state->request)) FD_SET(state->sock, &r_fds); /* Add fd for writing */ if (state->write_buf_len) FD_SET(state->sock, &w_fds); state = state->next; } /* Call select */ selret = sys_select(maxfd + 1, &r_fds, &w_fds, NULL, &timeout); if (selret == 0) continue; if ((selret == -1 && errno != EINTR) || selret == 0) { /* Select error, something is badly wrong */ perror("select"); exit(1); } /* Create a new connection if listen_sock readable */ if (selret > 0) { if (opt_dual_daemon) { dual_select(&w_fds); } if (FD_ISSET(listen_sock, &r_fds)) { while (winbindd_num_clients() > WINBINDD_MAX_SIMULTANEOUS_CLIENTS - 1) { DEBUG(5,("winbindd: Exceeding %d client connections, removing idle connection.\n", WINBINDD_MAX_SIMULTANEOUS_CLIENTS)); if (!remove_idle_client()) { DEBUG(0,("winbindd: Exceeding %d client connections, no idle connection found\n", WINBINDD_MAX_SIMULTANEOUS_CLIENTS)); break; } } /* new, non-privileged connection */ new_connection(listen_sock, False); } if (FD_ISSET(listen_priv_sock, &r_fds)) { while (winbindd_num_clients() > WINBINDD_MAX_SIMULTANEOUS_CLIENTS - 1) { DEBUG(5,("winbindd: Exceeding %d client connections, removing idle connection.\n", WINBINDD_MAX_SIMULTANEOUS_CLIENTS)); if (!remove_idle_client()) { DEBUG(0,("winbindd: Exceeding %d client connections, no idle connection found\n", WINBINDD_MAX_SIMULTANEOUS_CLIENTS)); break; } } /* new, privileged connection */ new_connection(listen_priv_sock, True); } /* Process activity on client connections */ for (state = winbindd_client_list(); state; state = state->next) { /* Data available for reading */ if (FD_ISSET(state->sock, &r_fds)) { /* Read data */ winbind_client_read(state); /* * If we have the start of a * packet, then check the * length field to make sure * the client's not talking * Mock Swedish. */ if (state->read_buf_len >= sizeof(uint32) && *(uint32 *) &state->request != sizeof(state->request)) { DEBUG(0,("process_loop: Invalid request size from pid %lu: %d bytes sent, should be %ld\n", (unsigned long)state->request.pid, *(uint32 *) &state->request, (unsigned long)sizeof(state->request))); DEBUGADD(0, ("This usually means that you are running old wbinfo, pam_winbind or libnss_winbind clients\n")); remove_client(state); break; } /* A request packet might be complete */ if (state->read_buf_len == sizeof(state->request)) { winbind_process_packet(state); } } /* Data available for writing */ if (FD_ISSET(state->sock, &w_fds)) client_write(state); } } #if 0 winbindd_check_cache_size(time(NULL)); #endif /* Check signal handling things */ if (do_sigterm) terminate(); if (do_sighup) { DEBUG(3, ("got SIGHUP\n")); msg_reload_services(MSG_SMB_CONF_UPDATED, (pid_t) 0, NULL, 0); do_sighup = False; } if (do_sigusr2) { print_winbindd_status(); do_sigusr2 = False; } } }