2 Unix SMB/CIFS implementation.
3 Samba utility functions
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Tim Potter 2000-2001
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "system/network.h"
26 /****************************************************************************
27 Determine if a file descriptor is in fact a socket.
28 ****************************************************************************/
29 BOOL is_a_socket(int fd)
33 return getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0;
36 enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
38 typedef struct smb_socket_option {
46 static const smb_socket_option socket_options[] = {
47 {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL},
48 {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL},
49 {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL},
51 {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL},
54 {"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON},
56 #ifdef IPTOS_THROUGHPUT
57 {"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON},
60 {"SO_REUSEPORT", SOL_SOCKET, SO_REUSEPORT, 0, OPT_BOOL},
63 {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT},
66 {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT},
69 {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT},
72 {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT},
75 {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT},
78 {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT},
82 /****************************************************************************
84 ****************************************************************************/
86 static void print_socket_options(int s)
89 const smb_socket_option *p = &socket_options[0];
91 for (; p->name != NULL; p++) {
92 if (getsockopt(s, p->level, p->option, (void *)&value, &vlen) == -1) {
93 DEBUG(5,("Could not test socket option %s.\n", p->name));
95 DEBUG(5,("socket option %s = %d\n",p->name,value));
100 /****************************************************************************
101 Set user socket options.
102 ****************************************************************************/
104 void set_socket_options(int fd, const char *options)
108 while (next_token(&options,tok," \t,", sizeof(tok))) {
112 BOOL got_value = False;
114 if ((p = strchr_m(tok,'='))) {
120 for (i=0;socket_options[i].name;i++)
121 if (strequal(socket_options[i].name,tok))
124 if (!socket_options[i].name) {
125 DEBUG(0,("Unknown socket option %s\n",tok));
129 switch (socket_options[i].opttype) {
132 ret = setsockopt(fd,socket_options[i].level,
133 socket_options[i].option,(char *)&value,sizeof(int));
138 DEBUG(0,("syntax error - %s does not take a value\n",tok));
141 int on = socket_options[i].value;
142 ret = setsockopt(fd,socket_options[i].level,
143 socket_options[i].option,(char *)&on,sizeof(int));
149 DEBUG(0,("Failed to set socket option %s (Error %s)\n",tok, strerror(errno) ));
152 print_socket_options(fd);
155 /****************************************************************************
157 ****************************************************************************/
159 ssize_t read_udp_socket(int fd, char *buf, size_t len,
160 struct ipv4_addr *from_addr, int *from_port)
163 struct sockaddr_in sock;
164 socklen_t socklen = sizeof(sock);
166 ret = recvfrom(fd,buf,len, 0, (struct sockaddr *)&sock, &socklen);
168 DEBUG(2,("read socket failed. ERRNO=%s\n",strerror(errno)));
173 from_addr->addr = sock.sin_addr.s_addr;
176 *from_port = ntohs(sock.sin_port);
184 /****************************************************************************
186 ****************************************************************************/
188 static BOOL timeout_until(struct timeval *timeout,
189 const struct timeval *endtime)
195 if ((now.tv_sec > endtime->tv_sec) ||
196 ((now.tv_sec == endtime->tv_sec) &&
197 (now.tv_usec > endtime->tv_usec)))
200 timeout->tv_sec = endtime->tv_sec - now.tv_sec;
201 timeout->tv_usec = endtime->tv_usec - now.tv_usec;
206 /****************************************************************************
207 Read data from the client, reading exactly N bytes, with timeout.
208 ****************************************************************************/
210 ssize_t read_data_until(int fd,char *buffer,size_t N,
211 const struct timeval *endtime)
218 if (endtime != NULL) {
220 struct timeval timeout;
226 if (!timeout_until(&timeout, endtime))
229 res = sys_select(fd+1, &r_fds, NULL, NULL, &timeout);
234 ret = sys_read(fd,buffer + total,N - total);
237 DEBUG(10,("read_data: read of %d returned 0. Error = %s\n", (int)(N - total), strerror(errno) ));
242 DEBUG(0,("read_data: read failure for %d. Error = %s\n", (int)(N - total), strerror(errno) ));
247 return (ssize_t)total;
250 /****************************************************************************
251 Write data to a fd with timeout.
252 ****************************************************************************/
254 ssize_t write_data_until(int fd,char *buffer,size_t N,
255 const struct timeval *endtime)
262 if (endtime != NULL) {
264 struct timeval timeout;
270 if (!timeout_until(&timeout, endtime))
273 res = sys_select(fd+1, NULL, &w_fds, NULL, &timeout);
278 ret = sys_write(fd,buffer + total,N - total);
281 DEBUG(0,("write_data: write failure. Error = %s\n", strerror(errno) ));
289 return (ssize_t)total;
293 /****************************************************************************
294 Open a socket of the specified type, port, and address for incoming data.
295 ****************************************************************************/
296 int open_socket_in( int type, int port, int dlevel, uint32_t socket_addr, BOOL rebind )
298 struct sockaddr_in sock;
301 memset( (char *)&sock, '\0', sizeof(sock) );
303 #ifdef HAVE_SOCK_SIN_LEN
304 sock.sin_len = sizeof(sock);
306 sock.sin_port = htons( port );
307 sock.sin_family = AF_INET;
308 sock.sin_addr.s_addr = socket_addr;
310 res = socket( AF_INET, type, 0 );
312 DEBUG(0,("open_socket_in(): socket() call failed: %s\n", strerror(errno)));
316 /* This block sets/clears the SO_REUSEADDR and possibly SO_REUSEPORT. */
318 int val = rebind ? 1 : 0;
319 setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val));
321 setsockopt(res,SOL_SOCKET,SO_REUSEPORT,(char *)&val,sizeof(val));
325 /* now we've got a socket - we need to bind it */
326 if( bind( res, (struct sockaddr *)&sock, sizeof(sock) ) == -1 ) {
327 DEBUG(0,("bind failed on port %d - %s\n", port, strerror(errno)));
332 DEBUG( 10, ( "bind succeeded on port %d\n", port ) );
338 /****************************************************************************
339 create an outgoing socket. timeout is in milliseconds.
340 **************************************************************************/
341 int open_socket_out(int type, struct ipv4_addr *addr, int port, int timeout)
343 struct sockaddr_in sock_out;
345 int connect_loop = 250; /* 250 milliseconds */
346 int loops = (timeout) / connect_loop;
348 /* create a socket to write to */
349 res = socket(PF_INET, type, 0);
351 { DEBUG(0,("socket error\n")); return -1; }
353 if (type != SOCK_STREAM) return(res);
355 memset((char *)&sock_out,'\0',sizeof(sock_out));
356 putip((char *)&sock_out.sin_addr,(char *)addr);
358 sock_out.sin_port = htons( port );
359 sock_out.sin_family = PF_INET;
361 /* set it non-blocking */
362 set_blocking(res,False);
364 DEBUG(3,("Connecting to %s at port %d\n", sys_inet_ntoa(*addr),port));
366 /* and connect it to the destination */
368 ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out));
370 /* Some systems return EAGAIN when they mean EINPROGRESS */
371 if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY ||
372 errno == EAGAIN) && loops--) {
373 msleep(connect_loop);
377 if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY ||
379 DEBUG(1,("timeout connecting to %s:%d\n", sys_inet_ntoa(*addr),port));
385 if (ret < 0 && errno == EISCONN) {
392 DEBUG(2,("error connecting to %s:%d (%s)\n",
393 sys_inet_ntoa(*addr),port,strerror(errno)));
398 /* set it blocking again */
399 set_blocking(res,True);
405 open a connected UDP socket to host on port
407 int open_udp_socket(const char *host, int port)
409 int type = SOCK_DGRAM;
410 struct sockaddr_in sock_out;
412 struct ipv4_addr addr;
415 mem_ctx = talloc_init("open_udp_socket");
419 addr = interpret_addr2(host);
421 res = socket(PF_INET, type, 0);
426 memset((char *)&sock_out,'\0',sizeof(sock_out));
427 putip((char *)&sock_out.sin_addr,(char *)&addr);
428 sock_out.sin_port = htons(port);
429 sock_out.sin_family = PF_INET;
431 talloc_free(mem_ctx);
433 if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))) {
442 /*******************************************************************
443 matchname - determine if host name matches IP address. Used to
444 confirm a hostname lookup to prevent spoof attacks
445 ******************************************************************/
446 static BOOL matchname(char *remotehost, struct ipv4_addr addr)
451 if ((hp = sys_gethostbyname(remotehost)) == 0) {
452 DEBUG(0,("sys_gethostbyname(%s): lookup failure.\n", remotehost));
457 * Make sure that gethostbyname() returns the "correct" host name.
458 * Unfortunately, gethostbyname("localhost") sometimes yields
459 * "localhost.domain". Since the latter host name comes from the
460 * local DNS, we just have to trust it (all bets are off if the local
461 * DNS is perverted). We always check the address list, though.
464 if (strcasecmp(remotehost, hp->h_name)
465 && strcasecmp(remotehost, "localhost")) {
466 DEBUG(0,("host name/name mismatch: %s != %s\n",
467 remotehost, hp->h_name));
471 /* Look up the host address in the address list we just got. */
472 for (i = 0; hp->h_addr_list[i]; i++) {
473 if (memcmp(hp->h_addr_list[i], (char *) & addr, sizeof(addr)) == 0)
478 * The host name does not map to the original host address. Perhaps
479 * someone has compromised a name server. More likely someone botched
480 * it, but that could be dangerous, too.
483 DEBUG(0,("host name/address mismatch: %s != %s\n",
484 sys_inet_ntoa(addr), hp->h_name));
489 /*******************************************************************
490 return the DNS name of the remote end of a socket
491 ******************************************************************/
492 char *get_socket_name(TALLOC_CTX *mem_ctx, int fd, BOOL force_lookup)
496 struct ipv4_addr addr;
499 /* reverse lookups can be *very* expensive, and in many
500 situations won't work because many networks don't link dhcp
501 with dns. To avoid the delay we avoid the lookup if
503 if (!lp_hostname_lookups() && (force_lookup == False)) {
504 return get_socket_addr(mem_ctx, fd);
507 p = get_socket_addr(mem_ctx, fd);
509 name_buf = talloc_strdup(mem_ctx, "UNKNOWN");
510 if (fd == -1) return name_buf;
512 addr = interpret_addr2(p);
514 /* Look up the remote host name. */
515 if ((hp = gethostbyaddr((char *)&addr.addr, sizeof(addr.addr), AF_INET)) == 0) {
516 DEBUG(1,("Gethostbyaddr failed for %s\n",p));
517 name_buf = talloc_strdup(mem_ctx, p);
519 name_buf = talloc_strdup(mem_ctx, (char *)hp->h_name);
520 if (!matchname(name_buf, addr)) {
521 DEBUG(0,("Matchname failed on %s %s\n",name_buf,p));
522 name_buf = talloc_strdup(mem_ctx, "UNKNOWN");
526 alpha_strcpy(name_buf, name_buf, "_-.", strlen(name_buf)+1);
527 if (strstr(name_buf,"..")) {
528 name_buf = talloc_strdup(mem_ctx, "UNKNOWN");
534 /*******************************************************************
535 return the IP addr of the remote end of a socket as a string
536 ******************************************************************/
537 char *get_socket_addr(TALLOC_CTX *mem_ctx, int fd)
540 struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
541 int length = sizeof(sa);
543 if (fd == -1 || getpeername(fd, &sa, &length) == -1) {
544 return talloc_strdup(mem_ctx, "0.0.0.0");
547 return talloc_strdup(mem_ctx, (char *)inet_ntoa(sockin->sin_addr));
552 /*******************************************************************
553 this is like socketpair but uses tcp. It is used by the Samba
555 The function guarantees that nobody else can attach to the socket,
556 or if they do that this function fails and the socket gets closed
557 returns 0 on success, -1 on failure
558 the resulting file descriptors are symmetrical
559 ******************************************************************/
560 static int socketpair_tcp(int fd[2])
563 struct sockaddr_in sock;
564 struct sockaddr_in sock2;
565 socklen_t socklen = sizeof(sock);
566 int connect_done = 0;
568 fd[0] = fd[1] = listener = -1;
570 memset(&sock, 0, sizeof(sock));
572 if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
574 memset(&sock2, 0, sizeof(sock2));
575 #ifdef HAVE_SOCK_SIN_LEN
576 sock2.sin_len = sizeof(sock2);
578 sock2.sin_family = PF_INET;
580 bind(listener, (struct sockaddr *)&sock2, sizeof(sock2));
582 if (listen(listener, 1) != 0) goto failed;
584 if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0) goto failed;
586 if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
588 set_blocking(fd[1], 0);
590 sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
592 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) {
593 if (errno != EINPROGRESS) goto failed;
598 if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1) goto failed;
601 if (connect_done == 0) {
602 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0
603 && errno != EISCONN) goto failed;
606 set_blocking(fd[1], 1);
612 if (fd[0] != -1) close(fd[0]);
613 if (fd[1] != -1) close(fd[1]);
614 if (listener != -1) close(listener);
619 /*******************************************************************
620 run a program on a local tcp socket, this is used to launch smbd
621 when regression testing
622 the return value is a socket which is attached to a subprocess
623 running "prog". stdin and stdout are attached. stderr is left
624 attached to the original stderr
625 ******************************************************************/
626 int sock_exec(const char *prog)
629 if (socketpair_tcp(fd) != 0) {
630 DEBUG(0,("socketpair_tcp failed (%s)\n", strerror(errno)));
647 determine if a packet is pending for receive on a socket
649 BOOL socket_pending(int fd)
653 struct timeval timeout;
658 /* immediate timeout */
662 /* yes, this is supposed to be a normal select not a sys_select() */
663 selrtn = select(fd+1,&fds,NULL,NULL,&timeout);
666 /* the fd is readable */