1 /*
2  * $Id: com-socket.c,v 1.7.2.2 2005/01/10 11:37:36 mt Exp $
3  *
4  * Common functions for TCP/IP sockets
5  *
6  * Author(s): Jens-Gero Boehm <jens-gero.boehm@suse.de>
7  *            Pieter Hollants <pieter.hollants@suse.de>
8  *            Marius Tomaschewski <mt@suse.de>
9  *            Volker Wiegand <volker.wiegand@suse.de>
10  *
11  * This file is part of the SuSE Proxy Suite
12  *            See also  http://proxy-suite.suse.de/
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version
17  * 2 of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the
26  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
27  * Boston, MA 02111-1307, USA.
28  *
29  * A history log can be found at the end of this file.
30  */
31 
32 #ifndef lint
33 static char rcsid[] = "$Id: com-socket.c,v 1.7.2.2 2005/01/10 11:37:36 mt Exp $";
34 #endif
35 
36 #include <config.h>
37 
38 #if defined(STDC_HEADERS)
39 #  include <stdio.h>
40 #  include <string.h>
41 #  include <stdlib.h>
42 #  include <stdarg.h>
43 #  include <errno.h>
44 #endif
45 
46 #if defined(HAVE_UNISTD_H)
47 #  include <unistd.h>
48 #endif
49 
50 #if defined(TIME_WITH_SYS_TIME)
51 #  include <sys/time.h>
52 #  include <time.h>
53 #else
54 #  if defined(HAVE_SYS_TIME_H)
55 #    include <sys/time.h>
56 #  else
57 #    include <time.h>
58 #  endif
59 #endif
60 
61 #if defined(HAVE_SYS_SELECT_H)
62 #  include <sys/select.h>
63 #endif
64 
65 #if defined(HAVE_FCNTL_H)
66 #  include <fcntl.h>
67 #elif defined(HAVE_SYS_FCNTL_H)
68 #  include <sys/fcntl.h>
69 #endif
70 
71 #include <sys/ioctl.h>
72 #if defined(HAVE_SYS_FILIO_H)
73 #include <sys/filio.h>
74 #endif
75 
76 #include <sys/socket.h>
77 #include <netinet/in.h>
78 #if defined(HAVE_NETINET_IN_SYSTM_H)
79 #   include <netinet/in_systm.h>
80 #endif
81 #include <arpa/inet.h>
82 #include <netdb.h>
83 
84 #if defined(HAVE_STROPTS_H)
85 #   include <stropts.h>
86 #endif
87 #if defined(HAVE_SYS_PARAM_H)
88 #   include <sys/param.h>
89 #endif
90 #if defined(HAVE_SYS_CONF_H)
91 #   include <sys/conf.h>
92 #endif
93 #if defined(HAVE_SYS_SOCKIO_H)
94 #  include <sys/sockio.h>
95 #endif
96 #if defined(I_NREAD) && (defined(__sun__) || !defined(FIONREAD))
97 #   define FIONREAD I_NREAD
98 #endif
99 
100 #if defined(HAVE_NET_IF_H)
101 #  include <net/if.h>
102 #endif
103 #if defined(HAVE_NET_PFVAR_H)
104 #  include <net/pfvar.h>
105 #endif
106 
107 #if defined(HAVE_NETINET_IP_H)
108 #   include <netinet/ip.h>
109 #endif
110 
111 #if defined(HAVE_NETINET_IP_COMPAT_H)
112 #   include <netinet/ip_compat.h>
113 #endif
114 #if defined(HAVE_NETINET_IP_FIL_COMPAT_H)
115 #   include <netinet/ip_fil_compat.h>
116 #endif
117 #if defined(HAVE_NETINET_IP_FIL_H)
118 #   include <netinet/ip_fil.h>
119 #endif
120 #if defined(HAVE_NETINET_IP_NAT_H)
121 #   include <netinet/ip_nat.h>
122 #endif
123 
124 #if defined(HAVE_LINUX_NETFILTER_IPV4_H)
125 #   include <linux/netfilter_ipv4.h>
126 #endif
127 
128 #if defined(HAVE_LIBWRAP)
129 #   if defined(HAVE_SYSLOG_H)
130 #      include <syslog.h>
131 #   endif
132 #   if defined(NEED_SYS_SYSLOG_H)
133 #      include <sys/syslog.h>
134 #   endif
135 #   include <tcpd.h>
136 #endif
137 
138 #include "com-config.h"
139 #include "com-debug.h"
140 #include "com-misc.h"
141 #include "com-socket.h"
142 #include "com-syslog.h"
143 
144 
145 /* ------------------------------------------------------------ */
146 
147 #if !defined(SOMAXCONN)
148 #  define SOMAXCONN	5	/* Default accept queue size	*/
149 #endif
150 
151 #if !defined(NETSIZ)
152 #  define NETSIZ	8192	/* Default network buffer size	*/
153 #endif
154 
155 
156 /* ------------------------------------------------------------ */
157 
158 static void socket_cleanup (void);
159 static void socket_accept  (void);
160 
161 static void socket_ll_read (HLS *hls);
162 static void socket_ll_write(HLS *hls);
163 
164 
165 /* ------------------------------------------------------------ */
166 
167 static int initflag = 0;	/* Have we been initialized?	*/
168 
169 static int lsock = -1;		/* Daemon: listening socket	*/
170 static ACPT_CB acpt_fp = NULL;	/* Call back function pointer	*/
171 
172 static HLS *hlshead = NULL;	/* Chain of HighLevSock's	*/
173 
174 #if defined(HAVE_LIBWRAP)
175 int allow_severity = LOG_INFO;	/* TCP Wrapper log levels	*/
176 int deny_severity  = LOG_WARNING;
177 #endif
178 
179 static int maxrecv_bufsiz = -1;	/* max receive buffer size	*/
180 
181 /* ------------------------------------------------------------ **
182 **
183 **	Function......:	socket_cleanup
184 **
185 **	Parameters....:	(none)
186 **
187 **	Return........:	(none)
188 **
189 **	Purpose.......: Clean up the socket related data.
190 **
191 ** ------------------------------------------------------------ */
192 
socket_cleanup(void)193 static void socket_cleanup(void)
194 {
195 	socket_lclose(1);
196 
197 	while (hlshead != NULL)
198 		socket_kill(hlshead);
199 }
200 
201 
202 /* ------------------------------------------------------------ **
203 **
204 **	Function......:	socket_listen
205 **
206 **	Parameters....:	addr		IP address where to listen
207 **			port		TCP port where to listen
208 **
209 **	Return........:	0=success, -1=failure (EADDRINUSE)
210 **			Other errors make the program die.
211 **
212 **	Purpose.......: Opens a listening port.
213 **
214 ** ------------------------------------------------------------ */
215 
socket_listen(u_int32_t addr,u_int16_t port,ACPT_CB func)216 int socket_listen(u_int32_t addr, u_int16_t port, ACPT_CB func)
217 {
218 	struct sockaddr_in saddr;
219 
220 	if (initflag == 0) {
221 		atexit(socket_cleanup);
222 		initflag = 1;
223 
224 		/*
225 		** Check if we should limit the recv buffer size...
226 		** (because the link on the write side is much slower)
227 		*/
228 		if(maxrecv_bufsiz < 0) {
229 			maxrecv_bufsiz = config_int(NULL, "MaxRecvBufSize", 0);
230 			if(maxrecv_bufsiz < 0)
231 				maxrecv_bufsiz = 0;
232 		}
233 	}
234 
235 	/*
236 	** Remember whom to call back for accept
237 	*/
238 	acpt_fp = func;
239 
240 	/*
241 	** Prepare and open the listening socket
242 	*/
243 	memset(&saddr, 0, sizeof(saddr));
244 	saddr.sin_addr.s_addr = htonl(addr);
245 	saddr.sin_family      = AF_INET;
246 	saddr.sin_port        = htons(port);
247 
248 #if defined(COMPILE_DEBUG)
249 	debug(2, "about to listen: %s:%d",
250 			inet_ntoa(saddr.sin_addr), (int) port);
251 #endif
252 
253 	if ((lsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
254 		syslog_error("can't create listener socket");
255 		exit(EXIT_FAILURE);
256 	}
257 	socket_opts(lsock, SK_LISTEN);
258 
259 	if (bind(lsock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
260 		if (errno == EADDRINUSE) {
261 			syslog_write(T_WRN,
262 				"port %d is in use...", (int) port);
263 			return -1;
264 		}
265 		syslog_error("can't bind to %s:%d",
266 				inet_ntoa(saddr.sin_addr), (int) port);
267 		exit(EXIT_FAILURE);
268 	}
269 	listen(lsock, SOMAXCONN);
270 	return 0;
271 }
272 
273 
274 /* ------------------------------------------------------------ **
275 **
276 **	Function......:	socket_lclose
277 **
278 **	Parameters....:	shut		Call shutdown if non-zero
279 **
280 **	Return........:	(none)
281 **
282 **	Purpose.......: Close the listening socket.
283 **
284 ** ------------------------------------------------------------ */
285 
socket_lclose(int shut)286 void socket_lclose(int shut)
287 {
288 	if (lsock != -1) {
289 		if (shut)
290 			shutdown(lsock, 2);
291 		close(lsock);
292 		lsock = -1;
293 	}
294 }
295 
296 
297 /* ------------------------------------------------------------ **
298 **
299 **	Function......:	socket_accept
300 **
301 **	Parameters....:	(none)
302 **
303 **	Return........:	(none)
304 **
305 **	Purpose.......: Accept a new client connection.
306 **
307 ** ------------------------------------------------------------ */
308 
socket_accept(void)309 static void socket_accept(void)
310 {
311 	char peer[PEER_LEN] = {0};
312 	char dest[PEER_LEN] = {0};
313 	struct sockaddr_in saddr;
314 	int nsock, len;
315 
316 	/*
317 	** Let the show begin ...
318 	*/
319 	memset(&saddr, 0, sizeof(saddr));
320 	len = sizeof(saddr);
321 	nsock = accept(lsock, (struct sockaddr *) &saddr, &len);
322 	if (nsock < 0) {
323 		syslog_error("can't accept client");
324 		return;
325 	}
326 
327 	misc_strncpy(peer, inet_ntoa(saddr.sin_addr), sizeof(peer));
328 	memset(&saddr, 0, sizeof(saddr));
329 	if( !getsockname(nsock, (struct sockaddr *)&saddr, &len)) {
330 		misc_strncpy(dest, inet_ntoa(saddr.sin_addr), sizeof(dest));
331 	}
332 
333 #if defined(COMPILE_DEBUG)
334 	debug(2, "accepted %d=%s on %s", nsock, NIL(peer), NIL(dest));
335 #endif
336 
337 #if defined(HAVE_LIBWRAP)
338 	/*
339 	** Use the TCP Wrapper to control access
340 	*/
341 	if (config_bool(NULL, "TCPWrapper", 0)) {
342 		struct request_info req;
343 		char *wn;
344 
345 		wn = config_str(NULL, "TCPWrapperName", misc_getprog());
346 		if( !(wn && *wn)) wn = "ftp-proxy"; /* fall back... */
347 
348 		request_init(&req, RQ_DAEMON, wn,
349 					RQ_FILE, nsock, NULL);
350 		fromhost(&req);
351 		if (hosts_access(&req) == 0) {
352 			close(nsock);
353 			syslog_write(U_ERR,
354 				"%s reject: '%s' (Wrap)", wn, peer);
355 			return;
356 		}
357 	}
358 #endif
359 
360 	/*
361 	** Setup some basic socket options
362 	*/
363 	socket_opts(nsock, SK_CONTROL);
364 
365 	/*
366 	** Perform user level initialization
367 	*/
368 	if (acpt_fp)
369 		(*acpt_fp)(nsock);
370 }
371 
372 
373 /* ------------------------------------------------------------ **
374 **
375 **	Function......:	socket_init
376 **
377 **	Parameters....:	sock		Accepted new socket
378 **					Can be -1 (e.g. for
379 **					accepting sockets)
380 **
381 **	Return........:	Pointer to newly created Channel
382 **
383 **	Purpose.......: Allocate and initialize a new High
384 **			Level Socket (HLS).
385 **
386 ** ------------------------------------------------------------ */
387 
socket_init(int sock)388 HLS *socket_init(int sock)
389 {
390 	HLS *hls;
391 
392 	if (initflag == 0) {
393 		atexit(socket_cleanup);
394 		initflag = 1;
395 
396 		/*
397 		** Check if we should limit the recv buffer size...
398 		** (because the link on the write side is much slower)
399 		*/
400 		if(maxrecv_bufsiz < 0) {
401 			maxrecv_bufsiz = config_int(NULL, "MaxRecvBufSize", 0);
402 			if(maxrecv_bufsiz < 0)
403 				maxrecv_bufsiz = 0;
404 		}
405 	}
406 
407 	hls = (HLS *) misc_alloc(FL, sizeof(HLS));
408 	hls->next = hlshead;
409 	hlshead   = hls;
410 
411 	if ((hls->sock = sock) != -1) {
412 		hls->addr = socket_sck2addr(sock, REM_END, &(hls->port));
413 		misc_strncpy(hls->peer, socket_addr2str(hls->addr),
414 		             sizeof(hls->peer));
415 	} else {
416 		hls->addr = 0;
417 		hls->port = 0;
418 		memset(hls->peer, 0, sizeof(hls->peer));
419 	}
420 
421 	hls->kill = 0;
422 	hls->ernr = 0;
423 	hls->retr = 0;
424 	hls->flag = 0;
425 	hls->more = 0;
426 	hls->ctyp = "HLS-TYPE";
427 
428 	hls->wbuf = NULL;
429 	hls->rbuf = NULL;
430 
431 	hls->wcnt = 0;
432 	hls->rcnt = 0;
433 
434 #if defined(COMPILE_DEBUG)
435 	debug(2, "created HLS for %d=%s:%d",
436 			hls->sock, hls->peer, (int) hls->port);
437 #endif
438 	return hls;
439 }
440 
441 
442 /* ------------------------------------------------------------ **
443 **
444 **	Function......:	socket_opts
445 **
446 **	Parameters....:	sock		Socket to be worked upon
447 **			kind		SK_... value (a "Macro")
448 **
449 **	Return........:	(none)
450 **
451 **	Purpose.......: Setup socket options according to the
452 **			intended use (listen, control, data).
453 **
454 ** ------------------------------------------------------------ */
455 
socket_opts(int sock,int kind)456 void socket_opts(int sock, int kind)
457 {
458 #if defined(ENABLE_SO_LINGER)
459 	struct linger lin;
460 #endif
461 	int opt, len;
462 
463 	opt = 1;
464 	len = sizeof(opt);
465 	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, len);
466 
467 #if defined(ENABLE_SO_LINGER)
468 	if (kind == SK_LISTEN) {
469 		lin.l_onoff  = 0;
470 		lin.l_linger = 0;
471 	} else {
472 		lin.l_onoff  = 1;
473 		lin.l_linger = 60;
474 	}
475 	len = sizeof(lin);
476 	setsockopt(sock, SOL_SOCKET, SO_LINGER, &lin, len);
477 #endif
478 
479 #if defined(SO_OOBINLINE)
480 	if (kind == SK_CONTROL) {
481 		opt = 1;
482 		len = sizeof(opt);
483 		setsockopt(sock, SOL_SOCKET, SO_OOBINLINE, &opt, len);
484 	}
485 #endif
486 
487 	if (kind != SK_LISTEN) {
488 		opt = 1;
489 		len = sizeof(opt);
490 		setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &opt, len);
491 	}
492 
493 #if defined(IPTOS_THROUGHPUT) && defined(IPTOS_LOWDELAY)
494 	if (kind == SK_DATA)
495 		opt = IPTOS_THROUGHPUT;
496 	else
497 		opt = IPTOS_LOWDELAY;
498 	len = sizeof(opt);
499 	setsockopt(sock, IPPROTO_IP, IP_TOS, &opt, len);
500 #endif
501 }
502 
503 
504 /* ------------------------------------------------------------ **
505 **
506 **	Function......:	socket_kill
507 **
508 **	Parameters....:	hls		Pointer to HighLevSock
509 **
510 **	Return........:	(none)
511 **
512 **	Purpose.......: Destroy a High Level Socket.
513 **
514 ** ------------------------------------------------------------ */
515 
socket_kill(HLS * hls)516 void socket_kill(HLS *hls)
517 {
518 	HLS *curr, *prev;
519 	BUF *buf;
520 
521 	if (hls == NULL)		/* Basic sanity check	*/
522 		misc_die(FL, "socket_kill: ?hls?");
523 
524 #if defined(COMPILE_DEBUG)
525 	debug(2, "deleting HLS %s %d=%s:%d", NIL(hls->ctyp),
526 			hls->sock, hls->peer, (int) hls->port);
527 #endif
528 
529 	/*
530 	** Find and de-chain the socket
531 	*/
532 	for (curr = hlshead, prev = NULL; curr != NULL; ) {
533 		if (curr == hls) {
534 			if (prev == NULL)
535 				hlshead = curr->next;
536 			else
537 				prev->next = curr->next;
538 			break;
539 		}
540 		prev = curr;
541 		curr = curr->next;
542 	}
543 
544 	/*
545 	** Now destroy the socket itself
546 	*/
547 	if (hls->sock != -1)
548 		close(hls->sock);
549 	for (buf = hls->wbuf; buf != NULL; ) {
550 		hls->wbuf = buf->next;
551 		misc_free(FL, buf);
552 		buf = hls->wbuf;
553 	}
554 	for (buf = hls->rbuf; buf != NULL; ) {
555 		hls->rbuf = buf->next;
556 		misc_free(FL, buf);
557 		buf = hls->rbuf;
558 	}
559 	misc_free(FL, hls);
560 }
561 
562 
563 /* ------------------------------------------------------------ **
564 **
565 **	Function......:	socket_gets
566 **
567 **	Parameters....:	hls		Pointer to HighLevSock
568 **			ptr		Pointer to read buffer
569 **			len		Size of buf to be filled
570 **					(includes trailing zero)
571 **
572 **	Return........:	Pointer to filled buf
573 **
574 **	Purpose.......: Read one line of input from a HighLevSock.
575 **			This function waits for complete lines with
576 **			(CR)LF at the end, which will be discarded.
577 **
578 ** ------------------------------------------------------------ */
579 
socket_gets(HLS * hls,char * ptr,int len)580 char *socket_gets(HLS *hls, char *ptr, int len)
581 {
582 	int cnt;
583 	BUF *buf;
584 
585 	if (hls == NULL || ptr == NULL || len <= 0)
586 		misc_die(FL, "socket_gets: ?hls? ?ptr? ?len?");
587 
588 	if (hls->rbuf == NULL) {
589 		errno = 0;
590 		return NULL;
591 	}
592 	len--;		/* Account for the trailing null byte */
593 
594 	/*
595 	** Transfer at most one line of data
596 	*/
597 	hls->more = 0;
598 	for (buf = hls->rbuf, cnt = 0; buf != NULL && cnt < len; ) {
599 		if (buf->cur >= buf->len) {
600 			hls->rbuf = buf->next;
601 			misc_free(FL, buf);
602 			if(NULL == (buf = hls->rbuf)) {
603 				/*
604 				** last buffer in HLS and no EOL found;
605 				** restore the data into the HLS and
606 				** exit to wait to read more
607 				*/
608 				hls->more = 1;
609 				hls->rbuf = (BUF *)misc_alloc(FL, sizeof(BUF) + cnt);
610 				hls->rbuf->len = cnt;
611 				hls->rbuf->cur = 0;
612 				memcpy(hls->rbuf->dat, ptr, cnt);
613 #if defined(COMPILE_DEBUG)
614 				debug(4, "preread %d bytes while waiting "
615 					 "for end-of-line: '%.128s'%s",
616 					 cnt, hls->rbuf->dat,
617 					 (cnt > 128) ? "..." : "");
618 #endif
619 				return NULL;
620 			}
621 			continue;
622 		}
623 		if (buf->dat[buf->cur] == '\r')
624 			break;
625 		if (buf->dat[buf->cur] == '\n')
626 			break;
627 		ptr[cnt++] = buf->dat[buf->cur++];
628 	}
629 	ptr[cnt] = '\0';	/* Add the trailing null byte */
630 
631 	/*
632 	** Remove possible newline and used up buffer
633 	*/
634 	if (buf != NULL) {
635 		while (buf->cur < buf->len &&
636 				buf->dat[buf->cur] == '\r')
637 			buf->cur++;
638 		while (buf->cur < buf->len &&
639 				buf->dat[buf->cur] == '\n')
640 			buf->cur++;
641 		if (buf->cur >= buf->len) {
642 			hls->rbuf = buf->next;
643 			misc_free(FL, buf);
644 			buf = hls->rbuf;
645 		}
646 	}
647 
648 #if defined(COMPILE_DEBUG)
649 	debug(2, "gets %s %d=%s: %d bytes '%.128s'%s", hls->ctyp,
650 		hls->sock, hls->peer, cnt, ptr, (cnt > 128) ? "..." : "");
651 #endif
652 	return ptr;
653 }
654 
655 
656 /* ------------------------------------------------------------ **
657 **
658 **	Function......:	socket_flag
659 **
660 **	Parameters....:	hls		Pointer to HighLevSock
661 **			flag		Flags to be applied
662 **
663 **	Return........:	(none)
664 **
665 **	Purpose.......: Set the send() flags for the next write.
666 **			They will be reset with the write/printf
667 **			function.
668 **
669 ** ------------------------------------------------------------ */
670 
socket_flag(HLS * hls,int flag)671 void socket_flag(HLS *hls, int flag)
672 {
673 	if (hls == NULL)		/* Basic sanity check	*/
674 		misc_die(FL, "socket_flag: ?hls?");
675 
676 	/*
677 	** Store for the next write / printf call
678 	*/
679 	hls->flag = flag;
680 }
681 
682 
683 /* ------------------------------------------------------------ **
684 **
685 **	Function......:	socket_write
686 **
687 **	Parameters....:	hls		Pointer to HighLevSock
688 **			ptr		Pointer to write buffer
689 **			len		Number of bytes to write
690 **
691 **	Return........:	0=success, -1=failure
692 **
693 **	Purpose.......: Write to High Level Socket.
694 **
695 ** ------------------------------------------------------------ */
696 
socket_write(HLS * hls,char * ptr,int len)697 int socket_write(HLS *hls, char *ptr, int len)
698 {
699 	BUF *buf, *tmp;
700 
701 	if (hls == NULL || ptr == NULL)
702 		misc_die(FL, "socket_write: ?hls? ?ptr?");
703 
704 	if (hls->kill != 0)	/* Socket already doomed?	*/
705 		return 0;
706 
707 #if defined(COMPILE_DEBUG)
708 	debug(2, "write %s %d=%s: %d bytes",
709 			hls->ctyp, hls->sock, hls->peer, len);
710 #endif
711 
712 	/*
713 	** Allocate a new buffer for the data
714 	*/
715 	buf = (BUF *) misc_alloc(FL, sizeof(BUF) + len);
716 	buf->len = len;
717 	buf->cur = 0;
718 	memcpy(buf->dat, ptr, len);
719 
720 	buf->flg  = hls->flag;
721 	hls->flag = 0;
722 
723 	/*
724 	** Chain the newly filled buffer
725 	*/
726 	if (hls->wbuf == NULL)
727 		hls->wbuf = buf;
728 	else {
729 		for (tmp = hls->wbuf; tmp->next; tmp = tmp->next)
730 			;
731 		tmp->next = buf;
732 	}
733 	buf->next = NULL;
734 
735 	return 0;
736 }
737 
738 
739 /* ------------------------------------------------------------ **
740 **
741 **	Function......:	socket_printf
742 **
743 **	Parameters....:	hls		Pointer to HighLevSock
744 **			fmt		Format string for output
745 **
746 **	Return........:	0=success, -1=failure
747 **
748 **	Purpose.......: Write to High Level Socket.
749 **
750 ** ------------------------------------------------------------ */
751 
socket_printf(HLS * hls,char * fmt,...)752 int socket_printf(HLS *hls, char *fmt, ...)
753 {
754 	va_list aptr;
755 	char str[NETSIZ];
756 	int len;
757 	BUF *buf, *tmp;
758 
759 	if (hls == NULL || fmt == NULL)
760 		misc_die(FL, "socket_printf: ?hls? ?fmt?");
761 
762 	if (hls->kill != 0)	/* Socket already doomed?	*/
763 		return 0;
764 
765 	/*
766 	** Prepare the new stuff to be written
767 	*/
768 	memset(str, 0, sizeof(str));
769 	va_start(aptr, fmt);
770 #if defined(HAVE_VSNPRINTF)
771 	vsnprintf(str, sizeof(str), fmt, aptr);
772 #else
773 	vsprintf(str, fmt, aptr);
774 #endif
775 	va_end(aptr);
776 	len = strlen(str);
777 
778 #if defined(COMPILE_DEBUG)
779 	while (len > 0) {
780 		if (str[len-1] == '\r' || str[len-1] == '\n')
781 			len--;
782 		else
783 			break;
784 	}
785 	if (len > 128) {
786 		fmt = "...";
787 		len = 128;
788 	} else
789 		fmt = "";
790 	debug(2, "printf %s %d=%s: %d bytes '%.*s'%s", hls->ctyp,
791 		hls->sock, hls->peer, strlen(str), len, str, fmt);
792 	len = strlen(str);
793 #endif
794 
795 	/*
796 	** Allocate a new buffer for the data
797 	*/
798 	buf = (BUF *) misc_alloc(FL, sizeof(BUF) + len);
799 	buf->len = len;
800 	buf->cur = 0;
801 	memcpy(buf->dat, str, len);
802 
803 	buf->flg  = hls->flag;
804 	hls->flag = 0;
805 
806 	/*
807 	** Chain the newly filled buffer
808 	*/
809 	if (hls->wbuf == NULL)
810 		hls->wbuf = buf;
811 	else {
812 		for (tmp = hls->wbuf; tmp->next; tmp = tmp->next)
813 			;
814 		tmp->next = buf;
815 	}
816 	buf->next = NULL;
817 
818 	return 0;
819 }
820 
821 
822 /* ------------------------------------------------------------ **
823 **
824 **	Function......:	socket_file
825 **
826 **	Parameters....:	hls		Pointer to HighLevSock
827 **			file		Name of file to print
828 **			crlf		0=send LF, 1=send CRLF
829 **
830 **	Return........:	0=success, -1=failure
831 **
832 **	Purpose.......: Output the contents of a file to the
833 **			High Level Socket. The line end can
834 **			either be LF or CRLF.
835 **
836 ** ------------------------------------------------------------ */
837 
socket_file(HLS * hls,char * file,int crlf)838 int socket_file(HLS *hls, char *file, int crlf)
839 {
840 	char buf[1024], *p, *lend;
841 	FILE *fp;
842 
843 	if (hls == NULL || file == NULL)
844 		misc_die(FL, "socket_file: ?hls? ?file?");
845 
846 	lend = (crlf ? "\r\n" : "\n");
847 
848 	if ((fp = fopen(file, "r")) == NULL)
849 		return -1;
850 	while (fgets(buf, sizeof(buf), fp) != NULL) {
851 		if ((p = strchr(buf, '\n')) != NULL)
852 			*p = '\0';
853 		socket_printf(hls, "%s%s", buf, lend);
854 	}
855 	fclose(fp);
856 
857 	return 0;
858 }
859 
860 
861 /* ------------------------------------------------------------ **
862 **
863 **	Function......:	socket_exec
864 **
865 **	Parameters....:	timeout		Maximum seconds to wait
866 **			close_flag	Pointer to close_flag
867 **
868 **	Return........:	0=timeout, 1=activity, -1=error
869 **
870 **	Purpose.......: Prepare all relevant sockets, call the
871 **			select function (main waiting point),
872 **			and handle the outstanding actions.
873 **
874 ** ------------------------------------------------------------ */
875 
socket_exec(int timeout,int * close_flag)876 int socket_exec(int timeout, int *close_flag)
877 {
878 	HLS *hls;
879 	fd_set rfds, wfds;
880 	int fdcnt, i;
881 	struct timeval tv;
882 
883 	/*
884 	** Prepare the select() input structures
885 	*/
886 	fdcnt = -1;
887 	FD_ZERO(&rfds);
888 	FD_ZERO(&wfds);
889 
890 	/*
891 	** Allow the daemon listening socket to accept
892 	*/
893 	if (lsock != -1) {
894 		fdcnt = lsock;
895 		FD_SET(lsock, &rfds);
896 	}
897 
898 	/*
899 	** Last but not least walk through the connections
900 	*/
901 	for (hls = hlshead; hls != NULL; hls = hls->next) {
902 		if (hls->sock == -1)
903 			continue;
904 		if (hls->kill != 0 && hls->wbuf == NULL) {
905 			close(hls->sock);
906 			hls->sock = -1;
907 #if defined(COMPILE_DEBUG)
908 			debug(4, "FD_CLR %s", hls->ctyp);
909 #endif
910 			/*
911 			** The following return ensures that
912 			** killed sockets will be detected.
913 			*/
914 			return 1;
915 		}
916 		if (hls->sock > fdcnt)
917 			fdcnt = hls->sock;
918 		if (hls->wbuf != NULL && hls->peer[0] != '\0') {
919 			FD_SET(hls->sock, &wfds);
920 #if defined(COMPILE_DEBUG)
921 			debug(4, "FD_SET %s for W", hls->ctyp);
922 #endif
923 		}
924 		if(hls->more >= 0) {
925 			FD_SET(hls->sock, &rfds);
926 #if defined(COMPILE_DEBUG)
927 			debug(4, "FD_SET %s for R", hls->ctyp);
928 #endif
929 		}
930 	}
931 
932 	/*
933 	** If not a single descriptor remains, we are doomed
934 	*/
935 	if (fdcnt == -1) {
936 		if (close_flag)
937 			*close_flag = 1;
938 		return 1;	/* Return as non-defect situation */
939 	}
940 
941 	/*
942 	** Wait for the next event
943 	*/
944 	tv.tv_sec  = timeout;
945 	tv.tv_usec = 0;
946 	i = select(fdcnt + 1, &rfds, &wfds, NULL, &tv);
947 	if (i == 0) {
948 #if defined(COMPILE_DEBUG)
949 		debug(2, "select: timeout (%d)", (int) time(NULL));
950 #endif
951 		return 0;
952 	}
953 	if (i < 0) {
954 		if (errno == EINTR)
955 			return 1;
956 		syslog_error("can't execute select");
957 		return -1;
958 	}
959 
960 	/*
961 	** Check the various sources of events
962 	*/
963 	if (lsock != -1 && FD_ISSET(lsock, &rfds))
964 		socket_accept();
965 	for (hls = hlshead; hls != NULL; hls = hls->next) {
966 
967 		if (hls->sock == -1)
968 			continue;
969 
970 		if (FD_ISSET(hls->sock, &wfds))
971 			socket_ll_write(hls);
972 		if (hls->sock == -1)	/* May be dead by now */
973 			continue;
974 
975 		if (FD_ISSET(hls->sock, &rfds))
976 			socket_ll_read(hls);
977 		if (hls->sock == -1)	/* May be dead by now */
978 			continue;
979 
980 		if (hls->kill != 0 && hls->wbuf == NULL) {
981 			close(hls->sock);
982 			hls->sock = -1;
983 		}
984 	}
985 	return 1;
986 }
987 
988 
989 /* ------------------------------------------------------------ **
990 **
991 **	Function......:	socket_ll_read
992 **
993 **	Parameters....:	hls		Pointer to HighLevSock
994 **
995 **	Return........:	(none)
996 **
997 **	Purpose.......: Socket low level read routine. If
998 **			peer is not set, we are listening.
999 **
1000 ** ------------------------------------------------------------ */
1001 
socket_ll_read(HLS * hls)1002 static void socket_ll_read(HLS *hls)
1003 {
1004 	int len, cnt, nsock;
1005 	BUF *buf, *tmp;
1006 	struct sockaddr_in saddr;
1007 
1008 	if (hls == NULL)
1009 		misc_die(FL, "socket_ll_read: ?hls?");
1010 
1011 	/*
1012 	** If the peer is not (yet) filled, this is a listening
1013 	** socket. In this case we need to accept() the (data)
1014 	** connection (e.g. FTP passive client or active server).
1015 	*/
1016 	if (hls->peer[0] == '\0') {
1017 		memset(&saddr, 0, sizeof(saddr));
1018 		len = sizeof(saddr);
1019 		nsock = accept(hls->sock,
1020 				(struct sockaddr *) &saddr, &len);
1021 		if (nsock < 0) {
1022 			hls->ernr = errno;
1023 			syslog_error("can't accept %s", hls->ctyp);
1024 			shutdown(hls->sock, 2);
1025 			close(hls->sock);
1026 			hls->sock = -1;
1027 			return;
1028 		}
1029 		socket_opts(nsock, SK_DATA);
1030 
1031 		/*
1032 		** Update the High Level Socket
1033 		*/
1034 		shutdown(hls->sock, 2);		/* the "acceptor" */
1035 		close(hls->sock);
1036 		hls->sock = nsock;
1037 		hls->addr = socket_sck2addr(nsock, REM_END, &(hls->port));
1038 		misc_strncpy(hls->peer, socket_addr2str(hls->addr),
1039 		             sizeof(hls->peer));
1040 #if defined(COMPILE_DEBUG)
1041 		debug(2, "accept %s (%d) from %s",
1042 				hls->ctyp, hls->sock, hls->peer);
1043 #endif
1044 		return;
1045 	}
1046 
1047 	/*
1048 	** Get the number of bytes waiting to be read
1049 	*/
1050 	len = 0;
1051 	if( (cnt=ioctl(hls->sock, FIONREAD, &len)) < 0) {
1052 		hls->ernr = errno;
1053 		syslog_error("can't get num of bytes: %s %d=%s",
1054 		             hls->ctyp, hls->sock, hls->peer);
1055 		close(hls->sock);
1056 		hls->sock = -1;
1057 		return;
1058 	}
1059 #if defined(COMPILE_DEBUG)
1060 	debug(4, "ll_read: FIONREAD reported %d bytes for %s %d=%s",
1061 		len, hls->ctyp, hls->sock, hls->peer);
1062 #endif
1063 
1064 	/*
1065 	** Check if the socket has been closed
1066 	*/
1067 	if (len == 0) {
1068 #if defined(I_NREAD) && defined(__sun__)
1069 		/*
1070 		** solaris powers up select and returns "no data"
1071 		** (both, len == cnt == 0) in the middle of a data
1072 		** transfer; this was interpreted as EOF and has
1073 		** caused transfer aborts on bigger files.
1074 		** wait and retry before we assume this is a EOF.
1075 		*/
1076 		if((0 == cnt) && (++hls->retr < MAX_RETRIES)) {
1077 			syslog_write(T_DBG,
1078 			      "zero bytes to read reported: %s %d=%s",
1079 			      hls->ctyp, hls->sock, hls->peer);
1080 			usleep(10000);
1081 			return;
1082 		}
1083 #endif
1084 
1085 		/*
1086 		** OK, EOF recived - should be cnt>0 and len == 0
1087 		** on solaris / I_NREAD according to streamio(7I)
1088 		*/
1089 #if defined(COMPILE_DEBUG)
1090 		debug(1, "closed: %s %d=%s, len=%d, cnt=%d",
1091 			hls->ctyp, hls->sock, hls->peer, len, cnt);
1092 #endif
1093 		close(hls->sock);
1094 		hls->sock = -1;
1095 		return;
1096 	}
1097 	/*
1098 	** else reset retry counter on success
1099 	*/
1100 	hls->retr = 0;
1101 
1102 	/*
1103 	** Limit the receive buffer sizes
1104 	*/
1105 	if(maxrecv_bufsiz > 0 && len > maxrecv_bufsiz)
1106 		len = maxrecv_bufsiz;
1107 
1108 	/*
1109 	** Now read the data that is waiting
1110 	*/
1111 	buf = (BUF *) misc_alloc(FL, sizeof(BUF) + len);
1112 	do {
1113 		errno = 0;
1114 		cnt = recv(hls->sock, buf->dat, len, 0);
1115 	} while (cnt == -1 && EINTR == errno);
1116 
1117 	if (cnt != len) {
1118 		if(cnt > 0) {
1119 			/*
1120 			** hmm... seems to be solaris, isn't? :-)
1121 			*/
1122 			syslog_write(T_DBG,
1123 			"recvd %d bytes while %d reported: %s %d=%s",
1124 			cnt, len, hls->ctyp, hls->sock, hls->peer);
1125 		} else {
1126 			/*
1127 			** report as error because we use FIONREAD
1128 			** above and handle EOF's (len = 0) there...
1129 			*/
1130 			hls->ernr = errno;
1131 			syslog_error("can't ll_read: %s %d=%s",
1132 			             hls->ctyp, hls->sock, hls->peer);
1133 			close(hls->sock);
1134 			hls->sock = -1;
1135 			misc_free(FL, buf);
1136 			return;
1137 		}
1138 	}
1139 	buf->len = cnt;
1140 	buf->cur = 0;
1141 	buf->flg = 0;
1142 
1143 	/*
1144 	** Update byte conter
1145 	*/
1146 	hls->rcnt += cnt;
1147 
1148 	/*
1149 	** Chain the newly filled buffer
1150 	*/
1151 	if (hls->rbuf == NULL)
1152 		hls->rbuf = buf;
1153 	else {
1154 		for (tmp = hls->rbuf; tmp->next; tmp = tmp->next)
1155 			;
1156 		tmp->next = buf;
1157 	}
1158 	buf->next = NULL;
1159 
1160 #if defined(COMPILE_DEBUG)
1161 	debug(3, "ll_read %s %d=%s: %d/%d bytes",
1162 			hls->ctyp, hls->sock, hls->peer,
1163 			cnt, hls->rcnt);
1164 #endif
1165 }
1166 
1167 
1168 /* ------------------------------------------------------------ **
1169 **
1170 **	Function......:	socket_ll_write
1171 **
1172 **	Parameters....:	hls		Pointer to HighLevSock
1173 **
1174 **	Return........:	(none)
1175 **
1176 **	Purpose.......: Socket low level write routine.
1177 **
1178 ** ------------------------------------------------------------ */
1179 
socket_ll_write(HLS * hls)1180 static void socket_ll_write(HLS *hls)
1181 {
1182 	int cnt, tot;
1183 	BUF *buf;
1184 
1185 	if (hls == NULL)
1186 		misc_die(FL, "socket_ll_write: ?hls?");
1187 
1188 	/*
1189 	** Try to send as much as possible
1190 	*/
1191 	for (buf = hls->wbuf, tot = 0; buf != NULL; ) {
1192 		do
1193 			cnt = send(hls->sock, buf->dat + buf->cur,
1194 					buf->len - buf->cur, buf->flg);
1195 		while (cnt == -1 && errno == EINTR);
1196 
1197 		/*
1198 		** Did we write anything?
1199 		*/
1200 		if (cnt < 0) {
1201 			if (tot == 0) {
1202 				hls->ernr = errno;
1203 				syslog_error("can't ll_write: %s %d=%s",
1204 				             hls->ctyp, hls->sock, hls->peer);
1205 				close(hls->sock);
1206 				hls->sock = -1;
1207 				return;
1208 			}
1209 			break;	/* At least the first write was ok */
1210 		}
1211 
1212 #if defined(COMPILE_DEBUG)
1213 		debug(4, "ll_write %s %d=%s: sent %d bytes",
1214 			hls->ctyp, hls->sock, hls->peer, cnt);
1215 #endif
1216 
1217 		/*
1218 		** Update byte conter
1219 		*/
1220 		tot += cnt;
1221 		hls->wcnt += cnt;
1222 
1223 		/*
1224 		** Advance the write pointers
1225 		*/
1226 		if ((buf->cur += cnt) < buf->len)
1227 			break;	/* Partly sent, try again later */
1228 
1229 		/*
1230 		** This buffer is done, try and send next one
1231 		*/
1232 		hls->wbuf = buf->next;
1233 		misc_free(FL, buf);
1234 		buf = hls->wbuf;
1235 	}
1236 
1237 #if defined(COMPILE_DEBUG)
1238 	debug(3, "ll_write %s %d=%s: %d/%d bytes",
1239 			hls->ctyp, hls->sock, hls->peer,
1240 			tot, hls->wcnt);
1241 #endif
1242 }
1243 
1244 
1245 /* ------------------------------------------------------------ **
1246 **
1247 **	Function......:	socket_msgline
1248 **
1249 **	Parameters....:	fmt		String to expand
1250 **
1251 **	Return........:	Pointer to expanded string
1252 **			(Gets overwritten by subsequent calls)
1253 **
1254 **	Purpose.......: Compose a message line, by copying the
1255 **			given string and expanding % escapes.
1256 **
1257 ** ------------------------------------------------------------ */
1258 
socket_msgline(char * fmt)1259 char *socket_msgline(char *fmt)
1260 {
1261 	static char str[1024];
1262 	char tmp[1024];
1263 	size_t i, j;
1264 	time_t now;
1265 	struct tm *t;
1266 
1267 	if (fmt == NULL)		/* Basic sanity check	*/
1268 		misc_die(FL, "socket_msgline: ?fmt?");
1269 
1270 	time(&now);
1271 	t = localtime(&now);
1272 
1273 	for (i = 0; (*fmt != '\0') && (i < (sizeof(str) - 64)); fmt++) {
1274 		if (*fmt != '%') {
1275 			str[i++] = *fmt;
1276 			continue;
1277 		}
1278 
1279 		/*
1280 		** Escape alert ...
1281 		*/
1282 		memset(tmp, 0, sizeof(tmp));
1283 		switch (*++fmt) {
1284 			case 'b':
1285 			case 'B':
1286 				strncpy(tmp, misc_getdate(), sizeof(tmp)-1);
1287 				break;
1288 			case 'd':
1289 			case 'D':
1290 #if defined(HAVE_SNPRINTF)
1291 				snprintf(tmp, sizeof(tmp),
1292 						"%04d/%02d/%02d",
1293 						t->tm_year + 1900,
1294 						t->tm_mon  + 1,
1295 						t->tm_mday);
1296 #else
1297 				sprintf(tmp, "%04d/%02d/%02d",
1298 						t->tm_year + 1900,
1299 						t->tm_mon  + 1,
1300 						t->tm_mday);
1301 #endif
1302 				break;
1303 			case 'h':
1304 			case 'H':
1305 				if (gethostname(tmp, sizeof(tmp)) < 0)
1306 					strncpy(tmp, "[unknown host]",
1307 						sizeof(tmp)-1);
1308 				break;
1309 			case 'n':
1310 			case 'N':
1311 				if (getfqdomainname(tmp, sizeof(tmp)) < 0)
1312 					strncpy(tmp, "[unknown network]",
1313 						sizeof(tmp)-1);
1314 				break;
1315 			case 't':
1316 			case 'T':
1317 #if defined(HAVE_SNPRINTF)
1318 				snprintf(tmp, sizeof(tmp),
1319 						"%02d:%02d:%02d",
1320 						t->tm_hour,
1321 						t->tm_min,
1322 						t->tm_sec);
1323 #else
1324 				sprintf(tmp, "%02d:%02d:%02d",
1325 						t->tm_hour,
1326 						t->tm_min,
1327 						t->tm_sec);
1328 #endif
1329 				break;
1330 			case 'v':
1331 			case 'V':
1332 				strncpy(tmp, misc_getvers(), sizeof(tmp)-1);
1333 				break;
1334 			case '%':
1335 				tmp[0] = '%';
1336 				break;
1337 			default:
1338 			break;
1339 		}
1340 		tmp[sizeof(tmp)-1] = '\0'; /* paranoia :-) */
1341 		j = strlen(tmp);
1342 		if ((i + j) < (sizeof(str) - 64)) {
1343 			memcpy(str + i, tmp, j);
1344 			i += j;
1345 		}
1346 	}
1347 
1348 	return str;
1349 }
1350 
1351 
1352 /* ------------------------------------------------------------ **
1353 **
1354 **	Function......:	socket_d_bind
1355 **
1356 **	Parameters....:	sock		socket descriptor
1357 **			addr		IP address we want to bind
1358 **			lrng		Lower TCP port range limit
1359 **			urng		Upper TCP port range limit
1360 **			incr		use rand or increment mode
1361 **
1362 **	Return........:	bound port, 0 (INPORT_ANY) on failure
1363 **
1364 **	Purpose.......: Binds a socket, taking care of a given
1365 **                      port range using rand or incrementing
1366 **                      the port number.
1367 **                      Note: this function covers also dynamic
1368 **                            ports assigning with a 0 range:
1369 **                            lrng = urng = 0 ( = INPORT_ANY)
1370 **
1371 ** ------------------------------------------------------------ */
socket_d_bind(int sock,u_int32_t addr,u_int16_t lrng,u_int16_t urng,int incr)1372 u_int16_t socket_d_bind(int sock, u_int32_t addr,
1373 			u_int16_t lrng, u_int16_t urng,
1374 			int incr)
1375 {
1376 	struct sockaddr_in saddr;
1377 	u_int16_t          port = INPORT_ANY;
1378 	int                retry= MAX_RETRIES, err = -1;
1379 
1380 	/* Sanity check */
1381 	if(sock < 0)
1382 		return INPORT_ANY;
1383 
1384 	/* check port range */
1385 	if( !(lrng<=urng)) {
1386 #if defined(COMPILE_DEBUG)
1387 		debug(2, "socket_d_bind: invalid port range %d-%d",
1388 		         lrng, urng);
1389 #endif
1390 		return INPORT_ANY;
1391 	}
1392 
1393 	memset(&saddr, 0, sizeof(saddr));
1394 	saddr.sin_addr.s_addr = htonl(addr);
1395 	saddr.sin_family      = AF_INET;
1396 
1397 #if defined(COMPILE_DEBUG)
1398 	debug(4, "socket_d_bind using %s", incr ? "increment" : "random");
1399 #endif
1400 
1401 	if(incr) {
1402 		for (port = lrng; err && (port <= urng); port++) {
1403 
1404 			saddr.sin_port = htons(port);
1405 
1406 			while(0 <= retry--) {
1407 				errno = 0;
1408 				err = bind(sock, (struct sockaddr *)&saddr,
1409 				                 sizeof(saddr));
1410 #if defined(COMPILE_DEBUG)
1411 				debug(2, "bind %s:%d result: %d, status: %s",
1412 				         socket_addr2str(addr),
1413 				         port, err, strerror(errno));
1414 #endif
1415 				if(0 == err) {
1416 					/* bind succeed */
1417 #if defined(COMPILE_DEBUG)
1418 					debug(2, "bind succeeded,"
1419 						 "port: %d, result: %d",
1420 						 port, err);
1421 #endif
1422 					retry = -1; break;
1423 				} else {
1424 					/* bind failed: fatal error? */
1425 					if( !(EINTR == errno ||
1426 					      EAGAIN == errno ||
1427 					      EADDRINUSE == errno)) {
1428 #if defined(COMPILE_DEBUG)
1429 						debug(4, "bind failed,"
1430 						      "result: %d, error %s",
1431 						      err, strerror(errno));
1432 #endif
1433 						return INPORT_ANY;
1434 					}
1435 				}
1436 			}
1437 		}
1438 	} else {
1439 		int port_range = (urng - lrng) + 1;
1440 
1441 		while(err && (0 < port_range--)) {
1442 
1443 			port = misc_rand(lrng, urng);
1444 			saddr.sin_port = htons(port);
1445 
1446 			while(0 <= retry--) {
1447 				err = bind(sock, (struct sockaddr *)&saddr,
1448 				                 sizeof(saddr));
1449 #if defined(COMPILE_DEBUG)
1450 				debug(2, "bind %s:%d, result: %d, status: %s",
1451 				         socket_addr2str(addr),
1452 				         port, err, strerror(errno));
1453 #endif
1454 				if(0 == err) {
1455 					/* bind succeed */
1456 #if defined(COMPILE_DEBUG)
1457 					debug(2, "bind succeeded, port: %d,"
1458 						 "result: %d", port, err);
1459 #endif
1460 					retry = -1; break;
1461 				} else {
1462 					/* bind failed: fatal error? */
1463 					if( !(EINTR == errno ||
1464 					      EAGAIN == errno ||
1465 					      EADDRINUSE == errno)) {
1466 #if defined(COMPILE_DEBUG)
1467 						debug(2, "bind failed, "
1468 							"result: %d, error %s",
1469 							err, strerror(errno));
1470 #endif
1471 						return INPORT_ANY;
1472 					}
1473 				}
1474 			}
1475 		}
1476 	}
1477 
1478 	if((0 == err) &&
1479 	   (INADDR_NONE != socket_sck2addr(sock, LOC_END, &port)))
1480 	{
1481 #if defined(COMPILE_DEBUG)
1482 		debug(2, "bound socket to port %d", port);
1483 #endif
1484 		return port;
1485 	}
1486 #if defined(COMPILE_DEBUG)
1487 	debug(2, "bind error - port %d, IP %d",
1488 		port, socket_sck2addr(sock, LOC_END, NULL));
1489 #endif
1490 	return INPORT_ANY;
1491 }
1492 
1493 /* ------------------------------------------------------------ **
1494 **
1495 **	Function......:	socket_d_listen
1496 **
1497 **	Parameters....:	addr		IP address we want to bind
1498 **			lrng		Lower TCP port range limit
1499 **			urng		Upper TCP port range limit
1500 **			phls		Pointer where HLS will go
1501 **			ctyp		Desired comms type identifier
1502 **			incr		use rand or incremental bind
1503 **
1504 **	Return........:	Listening port (0=failure)
1505 **
1506 **	Purpose.......: Open a listening socket, suitable for
1507 **			an additional data connection (e.g. FTP).
1508 **
1509 ** ------------------------------------------------------------ */
1510 
socket_d_listen(u_int32_t addr,u_int16_t lrng,u_int16_t urng,HLS ** phls,char * ctyp,int incr)1511 u_int16_t socket_d_listen(u_int32_t addr,
1512 			  u_int16_t lrng, u_int16_t urng,
1513 			  HLS **phls, char *ctyp,
1514 			  int incr)
1515 {
1516 	int       sock;
1517 	u_int16_t port;
1518 
1519 	if (phls == NULL || ctyp == NULL)	/* Sanity check	*/
1520 		misc_die(FL, "socket_d_listen: ?phls? ?ctyp?");
1521 
1522 	/*
1523 	** Create the socket and prepare it for binding
1524 	*/
1525 	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
1526 		syslog_error("can't create %s socket", ctyp);
1527 		exit(EXIT_FAILURE);
1528 	}
1529 	socket_opts(sock, SK_LISTEN);
1530 
1531 	port = socket_d_bind(sock, addr, lrng, urng, incr);
1532 	if (INPORT_ANY == port) {
1533 		/* nothing found? */
1534 		close(sock);
1535 		return 0;
1536 	}
1537 	listen(sock, 1);
1538 
1539 	/*
1540 	** Allocate the corresponding High Level Socket
1541 	*/
1542 	if ((*phls = socket_init(-1)) == NULL)
1543 		misc_die(FL, "socket_d_listen: ?*phls?");
1544 	(*phls)->sock = sock;
1545 	(*phls)->ctyp = ctyp;
1546 
1547 #if defined(COMPILE_DEBUG)
1548 	debug(2, "listen: %s (fd=%d) %s:%d", (*phls)->ctyp,
1549 		(*phls)->sock, socket_addr2str(addr), (int)port);
1550 #endif
1551 	return port;
1552 }
1553 
1554 
1555 /* ------------------------------------------------------------ **
1556 **
1557 **	Function......:	socket_d_connect
1558 **
1559 **	Parameters....:	addr		Destination IP address
1560 **			port		Destination TCP port
1561 **			ladr		Local IP address
1562 **			lrng		Lower TCP port range limit
1563 **			urng		Upper TCP port range limit
1564 **			phls		Pointer where HLS will go
1565 **			ctyp		Desired comms type identifier
1566 **			incr		use rand or incremental bind
1567 **
1568 **	Return........:	Local end of connected port (0=failure)
1569 **
1570 **	Purpose.......: Open a connecting socket, suitable for
1571 **			an additional data connection (e.g. FTP).
1572 **
1573 ** ------------------------------------------------------------ */
1574 
socket_d_connect(u_int32_t addr,u_int16_t port,u_int32_t ladr,u_int16_t lrng,u_int16_t urng,HLS ** phls,char * ctyp,int incr)1575 u_int16_t socket_d_connect(u_int32_t addr, u_int16_t port,
1576 			   u_int32_t ladr,
1577 			   u_int16_t lrng, u_int16_t urng,
1578 			   HLS **phls, char *ctyp,
1579 			   int incr)
1580 {
1581 	struct sockaddr_in saddr;
1582 	int                sock  = -1; /* mark socket invalid */
1583 	int                retry = MAX_RETRIES;
1584 	u_int16_t          lprt  = lrng;
1585 
1586 	if (phls == NULL || ctyp == NULL)	/* Sanity check	*/
1587 		misc_die(FL, "socket_d_connect: ?phls? ?ctyp?");
1588 
1589 	while(0 <= retry--)
1590 	{
1591 		/*
1592 		** First of all, get a socket
1593 		*/
1594 		if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
1595 			syslog_error("can't create %s socket", ctyp);
1596 			exit(EXIT_FAILURE);
1597 		}
1598 		socket_opts(sock, SK_DATA);
1599 
1600 		/*
1601 		** check if we have to use a port range
1602 		*/
1603 		if( !(INPORT_ANY == lrng && INPORT_ANY == urng)) {
1604 			/*
1605 			** Bind the socket, taking care of a given port range
1606 			*/
1607 			if(incr) {
1608 #if defined(COMPILE_DEBUG)
1609 				debug(2, "%s: about to bind to %s:range(%d-%d)",
1610 				         ctyp, socket_addr2str(ladr),
1611 				         lprt, urng);
1612 #endif
1613 				lprt = socket_d_bind(sock, ladr,
1614 				                     lprt, urng, incr);
1615 			} else {
1616 #if defined(COMPILE_DEBUG)
1617 				debug(2, "%s: about to bind to %s:range(%d-%d)",
1618 				         ctyp, socket_addr2str(ladr),
1619 				         lrng, urng);
1620 #endif
1621 				lprt = socket_d_bind(sock, ladr,
1622 				                     lrng, urng, incr);
1623 			}
1624 			if (INPORT_ANY == lprt) {
1625 				/* nothing found? */
1626 				close(sock);
1627 				return 0;
1628 			}
1629 		} else lprt = INPORT_ANY;
1630 
1631 		/*
1632 		** Actually connect the socket
1633 		*/
1634 		memset(&saddr, 0, sizeof(saddr));
1635 		saddr.sin_addr.s_addr = htonl(addr);
1636 		saddr.sin_family      = AF_INET;
1637 		saddr.sin_port        = htons(port);
1638 
1639 		if (connect(sock, (struct sockaddr *) &saddr,
1640 		                  sizeof(saddr)) < 0)
1641 		{
1642 #if defined(COMPILE_DEBUG)
1643 			debug(2, "%s: connect failed with '%s'",
1644 			         ctyp, strerror(errno));
1645 #endif
1646 			close(sock);
1647 			sock = -1;
1648 			/* check if is makes sense to retry?
1649 			** perhaps we only need an other
1650 			** local port (EADDRNOTAVAIL) for
1651 			** this destination?
1652 			*/
1653 			if( !(EINTR == errno ||
1654 			      EAGAIN == errno ||
1655 			      EADDRINUSE == errno ||
1656 			      EADDRNOTAVAIL == errno))
1657 			{
1658 				/*
1659 				** an other (real) error ocurred
1660 				*/
1661 				return 0;
1662 			} else
1663 			if(incr && INPORT_ANY != lprt) {
1664 				/*
1665 				** increment lower range if we use
1666 				** increment mode and have a range
1667 				*/
1668 				if(lprt < urng) {
1669 					lprt++; /* incr lower range */
1670 				} else {
1671 				/*
1672 				** no more ports in range we can try
1673 				*/
1674 					return 0;
1675 				}
1676 			}
1677 		} else break;
1678 	}
1679 
1680 	/*
1681 	** check if we have a valid, connected socket
1682 	*/
1683 	if(-1 == sock) {
1684 		close(sock);
1685 		return 0;
1686 	}
1687 
1688 	/*
1689 	** Allocate the corresponding High Level Socket
1690 	*/
1691 	if ((*phls = socket_init(sock)) == NULL)
1692 		misc_die(FL, "socket_d_connect: ?*phls?");
1693 	(*phls)->ctyp = ctyp;
1694 
1695 	(void) socket_sck2addr(sock, LOC_END, &port);
1696 #if defined(COMPILE_DEBUG)
1697 	debug(2, "connect: %s fd=%d", (*phls)->ctyp, (*phls)->sock);
1698 #endif
1699 	return port;
1700 }
1701 
1702 
1703 /* ------------------------------------------------------------ **
1704 **
1705 **	Function......:	socket_str2addr
1706 **
1707 **	Parameters....:	name		Host name or address
1708 **			dflt		Default value
1709 **
1710 **	Return........:	Resolved address or default
1711 **
1712 **	Purpose.......: Resolver for DNS names / IP addresses.
1713 **
1714 ** ------------------------------------------------------------ */
1715 
socket_str2addr(char * name,u_int32_t dflt)1716 u_int32_t socket_str2addr(char *name, u_int32_t dflt)
1717 {
1718 	struct hostent *hptr;
1719 	struct in_addr iadr;
1720 
1721 #if defined(COMPILE_DEBUG)
1722 	debug(3, "str2addr: in='%.1024s'", NIL(name));
1723 #endif
1724 
1725 	if (name == NULL)		/* Basic sanity check	*/
1726 		return dflt;
1727 	memset(&iadr, 0, sizeof(iadr));
1728 
1729 	/*
1730 	** Try to interpret as dotted decimal
1731 	*/
1732 	if (*name >= '0' && *name <= '9') {
1733 		if (inet_aton(name, &iadr) == 0)
1734 			return dflt;	/* Can't be valid ...	*/
1735 		return ntohl(iadr.s_addr);
1736 	}
1737 
1738 	/*
1739 	** Try to resolve the host as a DNS name
1740 	*/
1741 	if ((hptr = gethostbyname(name)) != NULL) {
1742 		memcpy(&iadr.s_addr, hptr->h_addr, sizeof(iadr.s_addr));
1743 		return (u_int32_t) ntohl(iadr.s_addr);
1744 	}
1745 
1746 	/*
1747 	** Well, then return the default
1748 	*/
1749 	return dflt;
1750 }
1751 
1752 
1753 /* ------------------------------------------------------------ **
1754 **
1755 **	Function......:	socket_str2port
1756 **
1757 **	Parameters....:	name		Host name or address
1758 **			dflt		Default value
1759 **
1760 **	Return........:	Resolved port or default
1761 **
1762 **	Purpose.......: Resolver for TCP ports.
1763 **
1764 ** ------------------------------------------------------------ */
1765 
socket_str2port(char * name,u_int16_t dflt)1766 u_int16_t socket_str2port(char *name, u_int16_t dflt)
1767 {
1768 	struct servent *sptr;
1769 
1770 	if (name == NULL)		/* Basic sanity check	*/
1771 		return dflt;
1772 
1773 	/*
1774 	** Try to interpret as numeric port value
1775 	*/
1776 	if (*name >= '0' && *name <= '9')
1777 		return (u_int16_t) atoi(name);
1778 
1779 	/*
1780 	** Try to resolve from /etc/services, NIS, etc.
1781 	*/
1782 	if ((sptr = getservbyname(name, "tcp")) != NULL)
1783 		return (u_int16_t) ntohs(sptr->s_port);
1784 
1785 	/*
1786 	** Well, then return the default
1787 	*/
1788 	return dflt;
1789 }
1790 
1791 
1792 /* ------------------------------------------------------------ **
1793 **
1794 **	Function......:	socket_addr2str
1795 **
1796 **	Parameters....:	addr		IP address in host order
1797 **
1798 **	Return........:	Dotted decimal string for addr
1799 **
1800 **	Purpose.......: Convert IP address (host byte order) into
1801 **	                human readable form.
1802 **			The buffer is reused in subsequent calls,
1803 **			so the caller better move the result away.
1804 **
1805 ** ------------------------------------------------------------ */
1806 
socket_addr2str(u_int32_t addr)1807 char *socket_addr2str(u_int32_t addr)
1808 {
1809 	struct in_addr iadr;
1810 	static char str[PEER_LEN];
1811 
1812 	memset(&iadr, 0, sizeof(iadr));
1813 	iadr.s_addr = htonl(addr);
1814 	misc_strncpy(str, inet_ntoa(iadr), sizeof(str));
1815 	return str;
1816 }
1817 
1818 
1819 /* ------------------------------------------------------------ **
1820 **
1821 **	Function......:	socket_sck2addr
1822 **
1823 **	Parameters....:	sock		Socket descriptor
1824 **			peer		LOC_END or REM_END
1825 **			port		Pointer to port
1826 **
1827 **	Return........:	IP address in host byte order
1828 **			or INADDR_NONE on failure
1829 **
1830 **	Purpose.......: Retrieve the IP address of a socket,
1831 **			for either the peer or the local end
1832 **			in host byte order.
1833 **
1834 ** ------------------------------------------------------------ */
1835 
socket_sck2addr(int sock,int peer,u_int16_t * port)1836 u_int32_t socket_sck2addr(int sock, int peer, u_int16_t *port)
1837 {
1838 	struct sockaddr_in saddr;
1839 	int len, r;
1840 	char *s;
1841 
1842 	/*
1843 	** Retrieve the actual values
1844 	*/
1845 	memset(&saddr, 0, sizeof(saddr));
1846 	len = sizeof(saddr);
1847 	if (peer == LOC_END) {
1848 		r = getsockname(sock, (struct sockaddr *) &saddr, &len);
1849 		s = "sock";
1850 	} else {
1851 		r = getpeername(sock, (struct sockaddr *) &saddr, &len);
1852 		s = "peer";
1853 	}
1854 	if (r < 0) {
1855 		syslog_error("can't get %sname for socket %d", s, sock);
1856 		return INADDR_NONE;
1857 	}
1858 
1859 	/*
1860 	** Return the port if requested
1861 	*/
1862 	if (port != NULL)
1863 		*port = (u_int16_t) ntohs(saddr.sin_port);
1864 
1865 	/*
1866 	** Return the address part
1867 	*/
1868 	return (u_int32_t) ntohl(saddr.sin_addr.s_addr);
1869 }
1870 
1871 
1872 /* ------------------------------------------------------------ **
1873 **
1874 **	Function......:	socket_chkladdr
1875 **
1876 **	Parameters....:	addr		ip address to check
1877 **
1878 **	Return........:	0 if not found, 1 if found, -1 on error
1879 **
1880 **	Purpose.......: Check if addr (in network byte order)
1881 **			is used on an local network interface.
1882 **
1883 ** ------------------------------------------------------------ */
1884 
socket_chkladdr(u_int32_t addr)1885 int        socket_chkladdr(u_int32_t addr)
1886 {
1887 #define DEFAULT_IFNUM	512
1888 	struct ifconf  ifc;
1889 	int            ifn = DEFAULT_IFNUM;
1890 	int            i, sock;
1891 
1892 	sock = socket(AF_INET, SOCK_DGRAM, 0);
1893 	if(-1 == sock) {
1894 #if defined(COMPILE_DEBUG)
1895 		debug(2, "can not create socket: %s", NIL(strerror(errno)));
1896 #endif
1897 		return -1;
1898 	}
1899 
1900 #if defined(SIOCGIFNUM)
1901 	if( ioctl(sock, SIOCGIFNUM, (char *) &ifn) < 0) {
1902 #if defined(COMPILE_DEBUG)
1903 		debug(2, "ioctl SIOCGIFNUM failed: %s", NIL(strerror(errno)));
1904 #endif
1905 		ifn = DEFAULT_IFNUM;	/* ignore failure */
1906 	}
1907 #endif	/* SIOCGIFNUM */
1908 
1909 	ifc.ifc_len = ifn * sizeof (struct ifreq);
1910 	ifc.ifc_buf = malloc(ifc.ifc_len);
1911 	if( !ifc.ifc_buf) {
1912 #if defined(COMPILE_DEBUG)
1913 		debug(2, "malloc(ifc.ifc_len=%d) failed: %s",
1914 			 ifc.ifc_len, NIL(strerror(errno)));
1915 #endif
1916 		close(sock);
1917 		return -1;
1918 	}
1919         memset(ifc.ifc_buf, 0, ifc.ifc_len);
1920 
1921 	if( ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
1922 #if defined(COMPILE_DEBUG)
1923 		debug(2, "ioctl SIOCGIFCONF failed: %s", NIL(strerror(errno)));
1924 #endif
1925 		free(ifc.ifc_buf);
1926 		close(sock);
1927 		return -1;
1928 	}
1929 	close(sock);
1930 
1931 	for( i=0; i<ifc.ifc_len; ) {
1932 		struct ifreq       *ifr = (struct ifreq *) &ifc.ifc_buf[i];
1933 		struct sockaddr_in *sa  = (struct sockaddr_in*) &ifr->ifr_addr;
1934 
1935 		i += sizeof( *ifr);
1936 
1937 		if(AF_INET     != ifr->ifr_addr.sa_family
1938 		|| INADDR_ANY  == sa->sin_addr.s_addr
1939 		|| INADDR_NONE == sa->sin_addr.s_addr)
1940 			continue;
1941 
1942 #if defined(COMPILE_DEBUG)
1943 		debug(4, "interface %s has ip-address: %s",
1944 			 ifr->ifr_name, inet_ntoa(sa->sin_addr));
1945 #endif
1946 
1947 		if( sa->sin_addr.s_addr == addr) {
1948 #if defined(COMPILE_DEBUG)
1949 			debug(2, "found local ip addr: %s",
1950 				 inet_ntoa(sa->sin_addr));
1951 #endif
1952 			free(ifc.ifc_buf);
1953 			return 1;
1954 		}
1955 	}
1956 	free(ifc.ifc_buf);
1957 
1958 #if defined(COMPILE_DEBUG)
1959 	debug(2, "requested ip addr is not a local one");
1960 #endif
1961 	return 0;
1962 }
1963 
1964 
1965 /* ------------------------------------------------------------ **
1966 **
1967 **	Function......:	socket_orgdst
1968 **
1969 **	Parameters....:	phls	pointer to high-level socket
1970 **			addr	pointer to in_addr_t
1971 **			port	pointer to in_port_t
1972 **
1973 **	Return........:	0 on success, -1 on error
1974 **
1975 **	Purpose.......: get the original (transparent) destination
1976 **	                addr and port the peer / client wanted to
1977 **	                connect (network byte order!).
1978 **
1979 ** ------------------------------------------------------------ */
1980 
socket_orgdst(HLS * phls,u_int32_t * addr,u_int16_t * port)1981 int socket_orgdst(HLS *phls, u_int32_t *addr, u_int16_t *port)
1982 {
1983 	struct sockaddr_in   name;
1984 #if defined(HAVE_LINUX_NETFILTER_IPV4_H) && defined(SO_ORIGINAL_DST)
1985 	struct sockaddr_in   dest;
1986 #endif
1987 #if defined(HAVE_NETINET_IP_NAT_H) && defined(SIOCGNATL)
1988 	natlookup_t          natlook, *nlptr = &natlook;
1989 	int                  rc, nat_fd = -1;
1990 #endif
1991 #if defined(HAVE_NET_PFVAR_H)
1992 	int                  rc, nat_fd = -1;
1993 	struct protoent      *proto;
1994 	struct sockaddr_in   peer;
1995 	struct pfioc_natlook natlook;
1996 #endif
1997 	socklen_t            len;
1998 
1999 	/*
2000 	** sanity args checks
2001 	*/
2002 	if( !(phls && -1 != phls->sock && addr && port))
2003 		return -1;
2004 
2005 	len = sizeof(name);
2006 	memset(&name, 0, len);
2007 	if(getsockname(phls->sock, (struct sockaddr *)&name, &len) < 0) {
2008 		syslog_error("can't get sockname for socket %d", phls->sock);
2009 		return -1;
2010 	}
2011 	syslog_write(T_DBG, "socket name address is %s:%d",
2012 		     socket_addr2str(ntohl(name.sin_addr.s_addr)),
2013 		                     ntohs(name.sin_port));
2014 
2015 #if defined(HAVE_LINUX_NETFILTER_IPV4_H) && defined(SO_ORIGINAL_DST)
2016 	/*
2017 	** IP-Tables uses SO_ORIGINAL_DST getsockopt call
2018 	*/
2019 	len = sizeof(dest);
2020 	memset(&dest, 0, len);
2021 	if(getsockopt(phls->sock, SOL_IP, SO_ORIGINAL_DST, &dest, &len) < 0) {
2022 		switch(errno) {
2023 		case ENOPROTOOPT:
2024 			/*
2025 			** no iptables support / 2.2 kernel
2026 			** ==> use getsockname dst bellow
2027 			*/
2028 		break;
2029 		case ENOENT:
2030 			/*
2031 			** 2.4 kernel without iptables support
2032 			** ==> getsockname does not work here
2033 			*/
2034 			syslog_write(T_WRN,
2035 			"iptables not supported or ipchains support active");
2036 			return -1;
2037 		break;
2038 		default:
2039 			syslog_error(
2040 				"can't get iptables transparent destination");
2041 			return -1;
2042 		break;
2043 		}
2044 	} else {
2045 		if((name.sin_port == dest.sin_port) &&
2046 		   (name.sin_addr.s_addr == dest.sin_addr.s_addr)) {
2047 			syslog_write(T_DBG,
2048 			      "iptables transparent destination %s:%d is local",
2049 			      socket_addr2str(ntohl(dest.sin_addr.s_addr)),
2050 			      ntohs(dest.sin_port));
2051 			return -1;
2052 		}
2053 
2054 		syslog_write(T_DBG, "iptables transparent destination: %s:%d",
2055 			socket_addr2str(ntohl(dest.sin_addr.s_addr)),
2056 			ntohs(dest.sin_port));
2057 
2058 		*addr = dest.sin_addr.s_addr;
2059 		*port = dest.sin_port;
2060 		return 0;
2061 	}
2062 #endif
2063 
2064 #if defined(HAVE_NET_PFVAR_H)
2065 
2066 	/*
2067 	** OpenBSD PF table lookup
2068 	*/
2069 	len = sizeof(peer);
2070 	memset(&peer, 0, len);
2071 	if(getpeername(phls->sock, (struct sockaddr *)&peer, &len) < 0) {
2072 		syslog_error("can't get peername for socket %d", phls->sock);
2073 		return -1;
2074 	}
2075 	syslog_write(T_DBG, "socket peer address is %s:%d",
2076 		     socket_addr2str(ntohl(peer.sin_addr.s_addr)),
2077 		                     ntohs(peer.sin_port));
2078 
2079 	if(!(proto = getprotobyname("tcp"))) {
2080 		syslog_error("can't get protocol number for tcp");
2081 		return -1;
2082 	}
2083 
2084 	if((nat_fd = open("/dev/pf", O_RDWR, 0)) < 0) {
2085 		endprotoent();
2086 		syslog_error("can't open pf device '/dev/pf'");
2087 		return -1;
2088 	}
2089 
2090 	memset(&natlook, 0, sizeof(natlook));
2091 	natlook.af              = AF_INET;
2092 	natlook.proto           = proto->p_proto;
2093 	natlook.direction       = PF_OUT;
2094 	natlook.saddr.v4.s_addr = peer.sin_addr.s_addr;		/* peer */
2095 	natlook.sport           = peer.sin_port;
2096 	natlook.daddr.v4.s_addr = name.sin_addr.s_addr;		/* sock */
2097 	natlook.dport           = name.sin_port;
2098 
2099 	endprotoent();
2100 
2101 	rc = ioctl(nat_fd, DIOCNATLOOK, &natlook);
2102 	close(nat_fd);
2103 
2104 	if(rc < 0) {
2105 		if(errno != ENOENT) {
2106 			syslog_error("can't get pfnat transparent destination");
2107 		}
2108 		return -1;
2109 	}
2110 
2111 #if defined(COMPILE_DEBUG)
2112 	debug(2, "pfnat transparent proxy destination: %s:%d",
2113 			socket_addr2str(ntohl(natlook.rdaddr.v4.s_addr)),
2114 			ntohs(natlook.rdport));
2115 #endif
2116 
2117 	if((natlook.rdport == name.sin_port) &&
2118 	   (natlook.rdaddr.v4.s_addr == name.sin_addr.s_addr))
2119 	{
2120 		syslog_write(T_DBG, "pfnat proxy destination %s:%d is local",
2121 		       socket_addr2str(ntohl(natlook.rdaddr.v4.s_addr)),
2122 		       ntohs(natlook.rdport));
2123 		return -1;
2124 	}
2125 	syslog_write(T_DBG, "pfnat transparent destination: %s:%d",
2126 	             socket_addr2str(ntohl(natlook.rdaddr.v4.s_addr)),
2127 	             ntohs(natlook.rdport));
2128 
2129 	*addr = natlook.rdaddr.v4.s_addr;
2130 	*port = natlook.rdport;
2131 	return 0;
2132 #endif
2133 
2134 #if defined(HAVE_NETINET_IP_NAT_H) && defined(SIOCGNATL)
2135 	/*
2136 	** BSD ipnat table lookup
2137 	*/
2138 	if ((nat_fd = open(IPNAT_NAME, O_RDONLY, 0)) < 0) {
2139 		syslog_error("can't open ipnat device '%.*s'",
2140 		             MAX_PATH_SIZE, IPNAT_NAME);
2141 		return -1;
2142 	}
2143 
2144 	memset(&natlook, 0, sizeof(natlook));
2145 	natlook.nl_flags        = IPN_TCP;
2146 	natlook.nl_inip.s_addr  = name.sin_addr.s_addr;
2147 	natlook.nl_inport       = name.sin_port;
2148 	natlook.nl_outip.s_addr = htonl(phls->addr);
2149 	natlook.nl_outport      = htons(phls->port);
2150 
2151 	/*
2152 	** handle versions differences...
2153 	*/
2154 	rc = 0;
2155 	if(63 == (SIOCGNATL & 0xff)) {
2156 		rc = ioctl(nat_fd, SIOCGNATL, &nlptr);
2157 #if defined(COMPILE_DEBUG)
2158 		debug(2, "SIOCGNATL using &natlookptr: rc=%d", rc);
2159 #endif
2160 	} else {
2161 		rc = ioctl(nat_fd, SIOCGNATL, &natlook);
2162 #if defined(COMPILE_DEBUG)
2163 		debug(2, "SIOCGNATL using &natlook: rc=%d", rc);
2164 #endif
2165 	}
2166 	close(nat_fd);
2167 
2168 	if(rc < 0) {
2169 		if(errno != ESRCH) {
2170 			syslog_error("can't get ipnat transparent destination");
2171 		}
2172 		return -1;
2173 	}
2174 
2175 	if((natlook.nl_realport == name.sin_port) &&
2176 	   (natlook.nl_realip.s_addr == name.sin_addr.s_addr))
2177 	{
2178 		syslog_write(T_DBG,
2179 		       "ipnat transparent destination %s:%d is local",
2180 		       socket_addr2str(ntohl(natlook.nl_realip.s_addr)),
2181 		       ntohs(natlook.nl_realport));
2182 		return -1;
2183 	}
2184 	syslog_write(T_DBG, "ipnat transparent destination: %s:%d",
2185 		socket_addr2str(ntohl(natlook.nl_realip.s_addr)),
2186 		ntohs(natlook.nl_realport));
2187 
2188 	*addr = natlook.nl_realip.s_addr;
2189 	*port = natlook.nl_realport;
2190 	return 0;
2191 
2192 #else /* !BSD-IPNAT */
2193 
2194 	/*
2195 	** IP-Chains uses getsockname, as "transparent address"
2196 	*/
2197 	syslog_write(T_DBG,
2198 			"ipchains transparent destination: %s:%d",
2199 			socket_addr2str(ntohl(name.sin_addr.s_addr)),
2200 			ntohs(name.sin_port));
2201 
2202 	*addr = name.sin_addr.s_addr;
2203 	*port = name.sin_port;
2204 #endif
2205 	return 0;
2206 }
2207 
2208 
2209 /* ------------------------------------------------------------ **
2210 **
2211 **	Function......:	getfqhostname
2212 **
2213 **	Parameters....:	fqhost	buffer to store the host name
2214 **			n	size of the buffer
2215 **
2216 **	Return........:	0 on success, -1 on error
2217 **
2218 **	Purpose.......: get the full qualified (resolved)
2219 **                      host name of the current/local host
2220 **
2221 ** ------------------------------------------------------------ */
2222 
getfqhostname(char * fqhost,size_t n)2223 int getfqhostname(char *fqhost, size_t n)
2224 {
2225 	char           hname[MAXHOSTNAMELEN];
2226 	struct hostent *hp;
2227 
2228 	if( !(n > 0 && fqhost))
2229 		return -1;
2230 
2231 	memset(hname, 0, sizeof(hname));
2232 	if( gethostname(hname, sizeof(hname)-1))
2233 		return -1;
2234 
2235 	if( !(hp = gethostbyname(hname)))
2236 		return -1;
2237 
2238 	misc_strncpy(fqhost, hp->h_name, n);
2239 
2240 	return 0;
2241 }
2242 
2243 /* ------------------------------------------------------------ **
2244 **
2245 **	Function......:	getfqdomainname
2246 **
2247 **	Parameters....:	fqhost	buffer to store the domain name
2248 **			n	size of the buffer
2249 **
2250 **	Return........:	0 on success, -1 on error
2251 **
2252 **	Purpose.......: get the full qualified (resolved)
2253 **                      domain name of the current/local host
2254 **
2255 ** ------------------------------------------------------------ */
2256 
getfqdomainname(char * fqdomain,size_t n)2257 int getfqdomainname(char *fqdomain, size_t n)
2258 {
2259 	char hname[MAXHOSTNAMELEN], *p;
2260 
2261 	if( !(n > 0 && fqdomain))
2262 		return -1;
2263 
2264 	if(getfqhostname(hname, sizeof(hname)))
2265 		return -1;
2266 
2267 	p = strchr(hname, (int)'.');
2268 	if(p && *(p+1)) {
2269 		misc_strncpy(fqdomain, p+1, n);
2270 		return 0;
2271 	}
2272 
2273 	return -1;
2274 }
2275 
2276 /* ------------------------------------------------------------
2277  * $Log: com-socket.c,v $
2278  * Revision 1.7.2.2  2005/01/10 11:37:36  mt
2279  * added sys/param.h inclusion
2280  *
2281  * Revision 1.7.2.1  2003/05/07 11:14:08  mt
2282  * added OpenBSD pf-nat transparent proxy support
2283  * fixed to use hls->retr instead of a static retry counter
2284  *
2285  * Revision 1.7  2002/05/02 13:01:08  mt
2286  * merged with v1.8.2.2
2287  *
2288  * Revision 1.6.2.2  2002/04/04 14:44:30  mt
2289  * added waiting and retrying on "no data" but no EOF in I_NREAD
2290  * added check for buffer len difference on ioctl and recv
2291  * added remembering of i/o failures in hls->ernr for loging
2292  * added and improved transparent proxy log messages
2293  *
2294  * Revision 1.6.2.1  2002/01/28 01:51:21  mt
2295  * replaced question marks sequences that may be misinterpreted as trigraphs
2296  *
2297  * Revision 1.6  2002/01/14 18:26:55  mt
2298  * implemented socket_orgdst to read transparent proxying destinations
2299  * implemented a MaxRecvBufSize option limiting max recv buffer size
2300  * implemented workarround for Netscape (4.x) directory symlink handling
2301  * extended log messages to provide basic transfer statistics data
2302  * fixed socket_gets to wait for a complete line if no EOL found
2303  * added snprintf usage, replaced strcpy/strncpy with misc_strncpy
2304  *
2305  * Revision 1.5  2001/11/06 23:04:43  mt
2306  * applied / merged with transparent proxy patches v8
2307  * see ftp-proxy/NEWS for more detailed release news
2308  *
2309  * Revision 1.4  1999/09/21 05:42:28  wiegand
2310  * syslog / abort review
2311  *
2312  * Revision 1.3  1999/09/17 06:32:28  wiegand
2313  * buffer length and overflow protection review
2314  *
2315  * Revision 1.2  1999/09/16 14:26:33  wiegand
2316  * minor code review and cleanup
2317  *
2318  * Revision 1.1  1999/09/15 14:05:38  wiegand
2319  * initial checkin
2320  *
2321  * ------------------------------------------------------------ */
2322 
2323