?? util_sock.c
字號:
/* Unix SMB/Netbios implementation. Version 1.9. Samba utility functions Copyright (C) Andrew Tridgell 1992-1998 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., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "includes.h"#ifdef WITH_SSL#include <ssl.h>#undef Realloc /* SSLeay defines this and samba has a function of this name */extern SSL *ssl;extern int sslFd;#endif /* WITH_SSL */extern int DEBUGLEVEL;BOOL passive = False;/* the client file descriptor */int Client = -1;/* the last IP received from */struct in_addr lastip;/* the last port received from */int lastport=0;int smb_read_error = 0;/****************************************************************************determine if a file descriptor is in fact a socket****************************************************************************/BOOL is_a_socket(int fd){ int v,l; l = sizeof(int); return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);}enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};static const struct{ char *name; int level; int option; int value; int opttype;} socket_options[] = { {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL}, {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL}, {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL},#ifdef TCP_NODELAY {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL},#endif#ifdef IPTOS_LOWDELAY {"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON},#endif#ifdef IPTOS_THROUGHPUT {"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON},#endif#ifdef SO_SNDBUF {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT},#endif#ifdef SO_RCVBUF {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT},#endif#ifdef SO_SNDLOWAT {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT},#endif#ifdef SO_RCVLOWAT {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT},#endif#ifdef SO_SNDTIMEO {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT},#endif#ifdef SO_RCVTIMEO {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT},#endif {NULL,0,0,0,0}}; /****************************************************************************set user socket options****************************************************************************/void set_socket_options(int fd, char *options){ fstring tok; while (next_token(&options,tok," \t,", sizeof(tok))) { int ret=0,i; int value = 1; char *p; BOOL got_value = False; if ((p = strchr(tok,'='))) { *p = 0; value = atoi(p+1); got_value = True; } for (i=0;socket_options[i].name;i++) if (strequal(socket_options[i].name,tok)) break; if (!socket_options[i].name) { DEBUG(0,("Unknown socket option %s\n",tok)); continue; } switch (socket_options[i].opttype) { case OPT_BOOL: case OPT_INT: ret = setsockopt(fd,socket_options[i].level, socket_options[i].option,(char *)&value,sizeof(int)); break; case OPT_ON: if (got_value) DEBUG(0,("syntax error - %s does not take a value\n",tok)); { int on = socket_options[i].value; ret = setsockopt(fd,socket_options[i].level, socket_options[i].option,(char *)&on,sizeof(int)); } break; } if (ret != 0) DEBUG(0,("Failed to set socket option %s\n",tok)); }}/**************************************************************************** close the socket communication****************************************************************************/void close_sockets(void ){#ifdef WITH_SSL sslutil_disconnect(Client);#endif /* WITH_SSL */ close(Client); Client = -1;}/****************************************************************************write to a socket****************************************************************************/ssize_t write_socket(int fd,char *buf,size_t len){ ssize_t ret=0; if (passive) return(len); DEBUG(6,("write_socket(%d,%d)\n",fd,(int)len)); ret = write_data(fd,buf,len); DEBUG(6,("write_socket(%d,%d) wrote %d\n",fd,(int)len,(int)ret)); if(ret <= 0) DEBUG(1,("write_socket: Error writing %d bytes to socket %d: ERRNO = %s\n", (int)len, fd, strerror(errno) )); return(ret);}/****************************************************************************read from a socket****************************************************************************/ssize_t read_udp_socket(int fd,char *buf,size_t len){ ssize_t ret; struct sockaddr_in sock; int socklen; socklen = sizeof(sock); memset((char *)&sock,'\0',socklen); memset((char *)&lastip,'\0',sizeof(lastip)); ret = (ssize_t)recvfrom(fd,buf,len,0,(struct sockaddr *)&sock,&socklen); if (ret <= 0) { DEBUG(2,("read socket failed. ERRNO=%s\n",strerror(errno))); return(0); } lastip = sock.sin_addr; lastport = ntohs(sock.sin_port); DEBUG(10,("read_udp_socket: lastip %s lastport %d read: %d\n", inet_ntoa(lastip), lastport, ret)); return(ret);}/****************************************************************************read data from a device with a timout in msec.mincount = if timeout, minimum to read before returningmaxcount = number to be read.time_out = timeout in milliseconds****************************************************************************/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); 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_with_timeout: blocking read. EOF from client.\n")); smb_read_error = READ_EOF; return -1; } if (readret == -1) { DEBUG(0,("read_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_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_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_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_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);}/****************************************************************************send a keepalive packet (rfc1002)****************************************************************************/BOOL send_keepalive(int client){ unsigned char buf[4]; buf[0] = 0x85; buf[1] = buf[2] = buf[3] = 0; return(write_data(client,(char *)buf,4) == 4);}/**************************************************************************** read data from the client, reading exactly N bytes. ****************************************************************************/ssize_t read_data(int fd,char *buffer,size_t N){ ssize_t ret; size_t total=0; smb_read_error = 0; while (total < N) {#ifdef WITH_SSL if(fd == sslFd){ ret = SSL_read(ssl, buffer + total, N - total); }else{ ret = read(fd,buffer + total,N - total); }#else /* WITH_SSL */ ret = read(fd,buffer + total,N - total);#endif /* WITH_SSL */ if (ret == 0) { DEBUG(10,("read_data: read of %d returned 0. Error = %s\n", (int)(N - total), strerror(errno) )); smb_read_error = READ_EOF; return 0; } if (ret == -1) { DEBUG(0,("read_data: read failure for %d. Error = %s\n", (int)(N - total), strerror(errno) )); smb_read_error = READ_ERROR; return -1; } total += ret; } return (ssize_t)total;}/**************************************************************************** write data to a fd ****************************************************************************/ssize_t write_data(int fd,char *buffer,size_t N){ size_t total=0; ssize_t ret; while (total < N) {#ifdef WITH_SSL if(fd == sslFd){ ret = SSL_write(ssl,buffer + total,N - total); }else{ ret = write(fd,buffer + total,N - total); }#else /* WITH_SSL */ ret = write(fd,buffer + total,N - total);#endif /* WITH_SSL */ if (ret == -1) { DEBUG(1,("write_data: write failure. Error = %s\n", strerror(errno) )); return -1; } if (ret == 0) return total; total += ret; } return (ssize_t)total;}/****************************************************************************read 4 bytes of a smb packet and return the smb length of the packetstore the result in the bufferThis version of the function will return a length of zero on receivinga keepalive packet.timeout is in milliseconds.****************************************************************************/static ssize_t read_smb_length_return_keepalive(int fd,char *inbuf,unsigned int timeout){ ssize_t len=0; int msg_type; BOOL ok = False; while (!ok) { if (timeout > 0) ok = (read_with_timeout(fd,inbuf,4,4,timeout) == 4); else ok = (read_data(fd,inbuf,4) == 4); if (!ok) return(-1);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -