r5037: got rid of all of the TALLOC_DEPRECATED stuff. My apologies for the
[jelmer/samba4-debian.git] / source / lib / util_sock.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Tim Potter      2000-2001
6    
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.
11    
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.
16    
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.
20 */
21
22 #include "includes.h"
23 #include "system/network.h"
24
25
26 /****************************************************************************
27  Determine if a file descriptor is in fact a socket.
28 ****************************************************************************/
29 BOOL is_a_socket(int fd)
30 {
31         int v,l;
32         l = sizeof(int);
33         return getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0;
34 }
35
36 enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
37
38 typedef struct smb_socket_option {
39         const char *name;
40         int level;
41         int option;
42         int value;
43         int opttype;
44 } smb_socket_option;
45
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},
50 #ifdef TCP_NODELAY
51   {"TCP_NODELAY",       IPPROTO_TCP,   TCP_NODELAY,     0,                 OPT_BOOL},
52 #endif
53 #ifdef IPTOS_LOWDELAY
54   {"IPTOS_LOWDELAY",    IPPROTO_IP,    IP_TOS,          IPTOS_LOWDELAY,    OPT_ON},
55 #endif
56 #ifdef IPTOS_THROUGHPUT
57   {"IPTOS_THROUGHPUT",  IPPROTO_IP,    IP_TOS,          IPTOS_THROUGHPUT,  OPT_ON},
58 #endif
59 #ifdef SO_REUSEPORT
60   {"SO_REUSEPORT",      SOL_SOCKET,    SO_REUSEPORT,    0,                 OPT_BOOL},
61 #endif
62 #ifdef SO_SNDBUF
63   {"SO_SNDBUF",         SOL_SOCKET,    SO_SNDBUF,       0,                 OPT_INT},
64 #endif
65 #ifdef SO_RCVBUF
66   {"SO_RCVBUF",         SOL_SOCKET,    SO_RCVBUF,       0,                 OPT_INT},
67 #endif
68 #ifdef SO_SNDLOWAT
69   {"SO_SNDLOWAT",       SOL_SOCKET,    SO_SNDLOWAT,     0,                 OPT_INT},
70 #endif
71 #ifdef SO_RCVLOWAT
72   {"SO_RCVLOWAT",       SOL_SOCKET,    SO_RCVLOWAT,     0,                 OPT_INT},
73 #endif
74 #ifdef SO_SNDTIMEO
75   {"SO_SNDTIMEO",       SOL_SOCKET,    SO_SNDTIMEO,     0,                 OPT_INT},
76 #endif
77 #ifdef SO_RCVTIMEO
78   {"SO_RCVTIMEO",       SOL_SOCKET,    SO_RCVTIMEO,     0,                 OPT_INT},
79 #endif
80   {NULL,0,0,0,0}};
81
82 /****************************************************************************
83  Print socket options.
84 ****************************************************************************/
85
86 static void print_socket_options(int s)
87 {
88         int value, vlen = 4;
89         const smb_socket_option *p = &socket_options[0];
90
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));
94                 } else {
95                         DEBUG(5,("socket option %s = %d\n",p->name,value));
96                 }
97         }
98  }
99
100 /****************************************************************************
101  Set user socket options.
102 ****************************************************************************/
103
104 void set_socket_options(int fd, const char *options)
105 {
106         fstring tok;
107
108         while (next_token(&options,tok," \t,", sizeof(tok))) {
109                 int ret=0,i;
110                 int value = 1;
111                 char *p;
112                 BOOL got_value = False;
113
114                 if ((p = strchr_m(tok,'='))) {
115                         *p = 0;
116                         value = atoi(p+1);
117                         got_value = True;
118                 }
119
120                 for (i=0;socket_options[i].name;i++)
121                         if (strequal(socket_options[i].name,tok))
122                                 break;
123
124                 if (!socket_options[i].name) {
125                         DEBUG(0,("Unknown socket option %s\n",tok));
126                         continue;
127                 }
128
129                 switch (socket_options[i].opttype) {
130                 case OPT_BOOL:
131                 case OPT_INT:
132                         ret = setsockopt(fd,socket_options[i].level,
133                                                 socket_options[i].option,(char *)&value,sizeof(int));
134                         break;
135
136                 case OPT_ON:
137                         if (got_value)
138                                 DEBUG(0,("syntax error - %s does not take a value\n",tok));
139
140                         {
141                                 int on = socket_options[i].value;
142                                 ret = setsockopt(fd,socket_options[i].level,
143                                                         socket_options[i].option,(char *)&on,sizeof(int));
144                         }
145                         break;    
146                 }
147       
148                 if (ret != 0)
149                         DEBUG(0,("Failed to set socket option %s (Error %s)\n",tok, strerror(errno) ));
150         }
151
152         print_socket_options(fd);
153 }
154
155 /****************************************************************************
156  Read from a socket.
157 ****************************************************************************/
158
159 ssize_t read_udp_socket(int fd, char *buf, size_t len, 
160                         struct ipv4_addr *from_addr, int *from_port)
161 {
162         ssize_t ret;
163         struct sockaddr_in sock;
164         socklen_t socklen = sizeof(sock);
165
166         ret = recvfrom(fd,buf,len, 0, (struct sockaddr *)&sock, &socklen);
167         if (ret <= 0) {
168                 DEBUG(2,("read socket failed. ERRNO=%s\n",strerror(errno)));
169                 return 0;
170         }
171
172         if (from_addr) {
173                 from_addr->addr = sock.sin_addr.s_addr;
174         }
175         if (from_port) {
176                 *from_port = ntohs(sock.sin_port);
177         }
178
179         return ret;
180 }
181
182
183
184 /****************************************************************************
185  Check the timeout. 
186 ****************************************************************************/
187
188 static BOOL timeout_until(struct timeval *timeout,
189                           const struct timeval *endtime)
190 {
191         struct timeval now;
192
193         GetTimeOfDay(&now);
194
195         if ((now.tv_sec > endtime->tv_sec) ||
196             ((now.tv_sec == endtime->tv_sec) &&
197              (now.tv_usec > endtime->tv_usec)))
198                 return False;
199
200         timeout->tv_sec = endtime->tv_sec - now.tv_sec;
201         timeout->tv_usec = endtime->tv_usec - now.tv_usec;
202         return True;
203 }
204
205
206 /****************************************************************************
207  Read data from the client, reading exactly N bytes, with timeout. 
208 ****************************************************************************/
209
210 ssize_t read_data_until(int fd,char *buffer,size_t N,
211                         const struct timeval *endtime)
212 {
213         ssize_t ret;
214         size_t total=0;  
215  
216         while (total < N) {
217
218                 if (endtime != NULL) {
219                         fd_set r_fds;
220                         struct timeval timeout;
221                         int res;
222
223                         FD_ZERO(&r_fds);
224                         FD_SET(fd, &r_fds);
225
226                         if (!timeout_until(&timeout, endtime))
227                                 return -1;
228
229                         res = sys_select(fd+1, &r_fds, NULL, NULL, &timeout);
230                         if (res <= 0)
231                                 return -1;
232                 }
233
234                 ret = sys_read(fd,buffer + total,N - total);
235
236                 if (ret == 0) {
237                         DEBUG(10,("read_data: read of %d returned 0. Error = %s\n", (int)(N - total), strerror(errno) ));
238                         return 0;
239                 }
240
241                 if (ret == -1) {
242                         DEBUG(0,("read_data: read failure for %d. Error = %s\n", (int)(N - total), strerror(errno) ));
243                         return -1;
244                 }
245                 total += ret;
246         }
247         return (ssize_t)total;
248 }
249
250 /****************************************************************************
251  Write data to a fd with timeout.
252 ****************************************************************************/
253
254 ssize_t write_data_until(int fd,char *buffer,size_t N,
255                          const struct timeval *endtime)
256 {
257         size_t total=0;
258         ssize_t ret;
259
260         while (total < N) {
261
262                 if (endtime != NULL) {
263                         fd_set w_fds;
264                         struct timeval timeout;
265                         int res;
266
267                         FD_ZERO(&w_fds);
268                         FD_SET(fd, &w_fds);
269
270                         if (!timeout_until(&timeout, endtime))
271                                 return -1;
272
273                         res = sys_select(fd+1, NULL, &w_fds, NULL, &timeout);
274                         if (res <= 0)
275                                 return -1;
276                 }
277
278                 ret = sys_write(fd,buffer + total,N - total);
279
280                 if (ret == -1) {
281                         DEBUG(0,("write_data: write failure. Error = %s\n", strerror(errno) ));
282                         return -1;
283                 }
284                 if (ret == 0)
285                         return total;
286
287                 total += ret;
288         }
289         return (ssize_t)total;
290 }
291
292
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 )
297 {
298         struct sockaddr_in sock;
299         int res;
300
301         memset( (char *)&sock, '\0', sizeof(sock) );
302
303 #ifdef HAVE_SOCK_SIN_LEN
304         sock.sin_len         = sizeof(sock);
305 #endif
306         sock.sin_port        = htons( port );
307         sock.sin_family      = AF_INET;
308         sock.sin_addr.s_addr = socket_addr;
309
310         res = socket( AF_INET, type, 0 );
311         if( res == -1 ) {
312                 DEBUG(0,("open_socket_in(): socket() call failed: %s\n", strerror(errno)));
313                 return -1;
314         }
315
316         /* This block sets/clears the SO_REUSEADDR and possibly SO_REUSEPORT. */
317         {
318                 int val = rebind ? 1 : 0;
319                 setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val));
320 #ifdef SO_REUSEPORT
321                 setsockopt(res,SOL_SOCKET,SO_REUSEPORT,(char *)&val,sizeof(val));
322 #endif
323         }
324
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)));
328                 close( res ); 
329                 return( -1 ); 
330         }
331
332         DEBUG( 10, ( "bind succeeded on port %d\n", port ) );
333
334         return( res );
335  }
336
337
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)
342 {
343         struct sockaddr_in sock_out;
344         int res,ret;
345         int connect_loop = 250; /* 250 milliseconds */
346         int loops = (timeout) / connect_loop;
347
348         /* create a socket to write to */
349         res = socket(PF_INET, type, 0);
350         if (res == -1) 
351         { DEBUG(0,("socket error\n")); return -1; }
352         
353         if (type != SOCK_STREAM) return(res);
354         
355         memset((char *)&sock_out,'\0',sizeof(sock_out));
356         putip((char *)&sock_out.sin_addr,(char *)addr);
357         
358         sock_out.sin_port = htons( port );
359         sock_out.sin_family = PF_INET;
360         
361         /* set it non-blocking */
362         set_blocking(res,False);
363         
364         DEBUG(3,("Connecting to %s at port %d\n", sys_inet_ntoa(*addr),port));
365         
366         /* and connect it to the destination */
367 connect_again:
368         ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out));
369         
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);
374                 goto connect_again;
375         }
376         
377         if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY ||
378                         errno == EAGAIN)) {
379                 DEBUG(1,("timeout connecting to %s:%d\n", sys_inet_ntoa(*addr),port));
380                 close(res);
381                 return -1;
382         }
383         
384 #ifdef EISCONN
385         if (ret < 0 && errno == EISCONN) {
386                 errno = 0;
387                 ret = 0;
388         }
389 #endif
390         
391         if (ret < 0) {
392                 DEBUG(2,("error connecting to %s:%d (%s)\n",
393                          sys_inet_ntoa(*addr),port,strerror(errno)));
394                 close(res);
395                 return -1;
396         }
397         
398         /* set it blocking again */
399         set_blocking(res,True);
400         
401         return res;
402 }
403
404 /*
405   open a connected UDP socket to host on port
406 */
407 int open_udp_socket(const char *host, int port)
408 {
409         int type = SOCK_DGRAM;
410         struct sockaddr_in sock_out;
411         int res;
412         struct ipv4_addr addr;
413         TALLOC_CTX *mem_ctx;
414
415         mem_ctx = talloc_init("open_udp_socket");
416         if (!mem_ctx) {
417                 return -1;
418         }
419         addr = interpret_addr2(host);
420
421         res = socket(PF_INET, type, 0);
422         if (res == -1) {
423                 return -1;
424         }
425
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;
430         
431         talloc_free(mem_ctx);
432
433         if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))) {
434                 close(res);
435                 return -1;
436         }
437
438         return res;
439 }
440
441
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)
447 {
448         struct hostent *hp;
449         int     i;
450         
451         if ((hp = sys_gethostbyname(remotehost)) == 0) {
452                 DEBUG(0,("sys_gethostbyname(%s): lookup failure.\n", remotehost));
453                 return False;
454         } 
455
456         /*
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.
462          */
463         
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));
468                 return False;
469         }
470         
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)
474                         return True;
475         }
476         
477         /*
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.
481          */
482         
483         DEBUG(0,("host name/address mismatch: %s != %s\n",
484                  sys_inet_ntoa(addr), hp->h_name));
485         return False;
486 }
487
488  
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)
493 {
494         char *name_buf;
495         struct hostent *hp;
496         struct ipv4_addr addr;
497         char *p;
498
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
502            possible */
503         if (!lp_hostname_lookups() && (force_lookup == False)) {
504                 return get_socket_addr(mem_ctx, fd);
505         }
506         
507         p = get_socket_addr(mem_ctx, fd);
508
509         name_buf = talloc_strdup(mem_ctx, "UNKNOWN");
510         if (fd == -1) return name_buf;
511
512         addr = interpret_addr2(p);
513         
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);
518         } else {
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");
523                 }
524         }
525
526         alpha_strcpy(name_buf, name_buf, "_-.", strlen(name_buf)+1);
527         if (strstr(name_buf,"..")) {
528                 name_buf = talloc_strdup(mem_ctx, "UNKNOWN");
529         }
530
531         return name_buf;
532 }
533
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)
538 {
539         struct sockaddr sa;
540         struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
541         int     length = sizeof(sa);
542
543         if (fd == -1 || getpeername(fd, &sa, &length) == -1) {
544                 return talloc_strdup(mem_ctx, "0.0.0.0");
545         }
546         
547         return talloc_strdup(mem_ctx, (char *)inet_ntoa(sockin->sin_addr));
548 }
549
550
551
552 /*******************************************************************
553 this is like socketpair but uses tcp. It is used by the Samba
554 regression test code
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])
561 {
562         int listener;
563         struct sockaddr_in sock;
564         struct sockaddr_in sock2;
565         socklen_t socklen = sizeof(sock);
566         int connect_done = 0;
567         
568         fd[0] = fd[1] = listener = -1;
569
570         memset(&sock, 0, sizeof(sock));
571         
572         if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
573
574         memset(&sock2, 0, sizeof(sock2));
575 #ifdef HAVE_SOCK_SIN_LEN
576         sock2.sin_len = sizeof(sock2);
577 #endif
578         sock2.sin_family = PF_INET;
579
580         bind(listener, (struct sockaddr *)&sock2, sizeof(sock2));
581
582         if (listen(listener, 1) != 0) goto failed;
583
584         if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0) goto failed;
585
586         if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
587
588         set_blocking(fd[1], 0);
589
590         sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
591
592         if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) {
593                 if (errno != EINPROGRESS) goto failed;
594         } else {
595                 connect_done = 1;
596         }
597
598         if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1) goto failed;
599
600         close(listener);
601         if (connect_done == 0) {
602                 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0
603                     && errno != EISCONN) goto failed;
604         }
605
606         set_blocking(fd[1], 1);
607
608         /* all OK! */
609         return 0;
610
611  failed:
612         if (fd[0] != -1) close(fd[0]);
613         if (fd[1] != -1) close(fd[1]);
614         if (listener != -1) close(listener);
615         return -1;
616 }
617
618
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)
627 {
628         int fd[2];
629         if (socketpair_tcp(fd) != 0) {
630                 DEBUG(0,("socketpair_tcp failed (%s)\n", strerror(errno)));
631                 return -1;
632         }
633         if (fork() == 0) {
634                 close(fd[0]);
635                 close(0);
636                 close(1);
637                 dup(fd[1]);
638                 dup(fd[1]);
639                 exit(system(prog));
640         }
641         close(fd[1]);
642         return fd[0];
643 }
644
645
646 /*
647   determine if a packet is pending for receive on a socket
648 */
649 BOOL socket_pending(int fd)
650 {
651         fd_set fds;
652         int selrtn;
653         struct timeval timeout;
654
655         FD_ZERO(&fds);
656         FD_SET(fd,&fds);
657         
658         /* immediate timeout */
659         timeout.tv_sec = 0;
660         timeout.tv_usec = 0;
661
662         /* yes, this is supposed to be a normal select not a sys_select() */
663         selrtn = select(fd+1,&fds,NULL,NULL,&timeout);
664                 
665         if (selrtn == 1) {
666                 /* the fd is readable */
667                 return True;
668         }
669
670         return False;
671 }