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