mirror of
https://repo.or.cz/socat.git
synced 2025-07-11 14:23:23 +00:00
socat V1.6.0.0 (initial GIT commit)
This commit is contained in:
commit
b819572f5e
170 changed files with 59193 additions and 0 deletions
327
fdname.c
Normal file
327
fdname.c
Normal file
|
@ -0,0 +1,327 @@
|
|||
/* $Id: fdname.c,v 1.9 2007/02/08 18:27:00 gerhard Exp $ */
|
||||
/* Copyright Gerhard Rieger 2003-2007 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* the subroutine sockname prints the basic info about the address of a socket
|
||||
NOTE: it works on UNIX (kernel) file descriptors, not on libc files! */
|
||||
|
||||
#include "config.h"
|
||||
#include "xioconfig.h" /* what features are enabled */
|
||||
|
||||
#include "sysincludes.h"
|
||||
|
||||
#include "mytypes.h"
|
||||
#include "compat.h"
|
||||
#include "error.h"
|
||||
#include "sycls.h"
|
||||
#include "sysutils.h"
|
||||
|
||||
#include "filan.h"
|
||||
|
||||
|
||||
struct sockopt {
|
||||
int so;
|
||||
char *name;
|
||||
};
|
||||
|
||||
|
||||
int statname(const char *file, int fd, int filetype, FILE *outfile);
|
||||
int cdevname(int fd, FILE *outfile);
|
||||
int sockname(int fd, FILE *outfile);
|
||||
int unixame(int fd, FILE *outfile);
|
||||
int tcpname(int fd, FILE *outfile);
|
||||
|
||||
|
||||
int fdname(const char *file, int fd, FILE *outfile) {
|
||||
struct stat buf = {0};
|
||||
int filetype;
|
||||
Debug1("checking file descriptor %u", fd);
|
||||
if (fd >= 0) {
|
||||
if (Fstat(fd, &buf) < 0) {
|
||||
if (errno == EBADF) {
|
||||
Debug2("fstat(%d): %s", fd, strerror(errno));
|
||||
return -1;
|
||||
} else {
|
||||
Error2("fstat(%d): %s", fd, strerror(errno));
|
||||
}
|
||||
}
|
||||
filetype = (buf.st_mode&S_IFMT)>>12;
|
||||
return statname(file, fd, filetype, outfile);
|
||||
} else {
|
||||
if (Stat(file, &buf) < 0) {
|
||||
Error2("stat(\"%s\"): %s", file, strerror(errno));
|
||||
}
|
||||
filetype = (buf.st_mode&S_IFMT)>>12;
|
||||
return statname(file, -1, filetype, outfile);
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_PROC_DIR_FD
|
||||
static int procgetfdname(int fd, char *filepath, size_t pathsize) {
|
||||
static pid_t pid = -1;
|
||||
char procpath[PATH_MAX];
|
||||
int len;
|
||||
|
||||
/* even if configure has shown that we have /proc, we must check if it
|
||||
exists at runtime, because we might be in a chroot environment */
|
||||
#if HAVE_STAT64
|
||||
{
|
||||
struct stat64 buf;
|
||||
if (Stat64("/proc", &buf) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (!S_ISDIR(buf.st_mode)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#else /* !HAVE_STAT64 */
|
||||
{
|
||||
struct stat buf;
|
||||
if (Stat("/proc", &buf) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (!S_ISDIR(buf.st_mode)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif /* !HAVE_STAT64 */
|
||||
|
||||
if (pid < 0) pid = Getpid();
|
||||
snprintf(procpath, sizeof(procpath), "/proc/"F_pid"/fd/%d", pid, fd);
|
||||
if ((len = Readlink(procpath, filepath, pathsize-1)) < 0) {
|
||||
Error4("readlink(\"%s\", %p, "F_Zu"): %s",
|
||||
procpath, filepath, pathsize, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
filepath[len] = '\0';
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_PROC_DIR_FD */
|
||||
|
||||
int statname(const char *file, int fd, int filetype, FILE *outfile) {
|
||||
char filepath[PATH_MAX];
|
||||
int result;
|
||||
|
||||
filepath[0] = '\0';
|
||||
#if HAVE_PROC_DIR_FD
|
||||
if (fd >= 0) {
|
||||
procgetfdname(fd, filepath, sizeof(filepath));
|
||||
if (filepath[0] == '/') {
|
||||
file = filepath;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_PROC_DIR_FD */
|
||||
/* now see for type specific infos */
|
||||
switch (filetype) {
|
||||
case (S_IFIFO>>12): /* 1, FIFO */
|
||||
fputs("pipe", outfile);
|
||||
if (file) fprintf(outfile, " %s", file);
|
||||
break;
|
||||
case (S_IFCHR>>12): /* 2, character device */
|
||||
if (cdevname(fd, outfile) == 0) {
|
||||
if (file) fprintf(outfile, " %s", file);
|
||||
}
|
||||
break;
|
||||
case (S_IFDIR>>12): /* 4, directory */
|
||||
fputs("dir", outfile);
|
||||
if (file) fprintf(outfile, " %s", file);
|
||||
break;
|
||||
case (S_IFBLK>>12): /* 6, block device */
|
||||
fputs("blkdev", outfile);
|
||||
if (file) fprintf(outfile, " %s", file);
|
||||
break;
|
||||
case (S_IFREG>>12): /* 8, regular file */
|
||||
fputs("file", outfile);
|
||||
if (file) fprintf(outfile, " %s", file);
|
||||
break;
|
||||
case (S_IFLNK>>12): /* 10, symbolic link */
|
||||
fputs("link", outfile);
|
||||
if (file) fprintf(outfile, " %s", file);
|
||||
break;
|
||||
case (S_IFSOCK>>12): /* 12, socket */
|
||||
#if WITH_SOCKET
|
||||
if (fd >= 0) {
|
||||
result = sockname(fd, outfile);
|
||||
} else if (file) {
|
||||
fprintf(outfile, "socket %s", file);
|
||||
} else {
|
||||
fputs("socket", outfile);
|
||||
}
|
||||
#else
|
||||
Error("SOCKET support not compiled in");
|
||||
return -1;
|
||||
#endif /* !WITH_SOCKET */
|
||||
break;
|
||||
}
|
||||
/* ioctl() */
|
||||
fputc('\n', outfile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* character device analysis */
|
||||
/* return -1 on error, 0 if no name was found, or 1 if it printed ttyname */
|
||||
int cdevname(int fd, FILE *outfile) {
|
||||
int ret;
|
||||
|
||||
if ((ret = Isatty(fd)) < 0) {
|
||||
Error2("isatty(%d): %s", fd, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (ret > 0) {
|
||||
char *name;
|
||||
|
||||
fputs("tty", outfile);
|
||||
if ((name = Ttyname(fd)) != NULL) {
|
||||
fputc(' ', outfile);
|
||||
fputs(name, outfile);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
fputs("chrdev", outfile);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if WITH_SOCKET
|
||||
int sockname(int fd, FILE *outfile) {
|
||||
#define FDNAME_OPTLEN 256
|
||||
#define FDNAME_NAMELEN 256
|
||||
socklen_t optlen;
|
||||
int opttype;
|
||||
#ifdef SO_ACCEPTCONN
|
||||
int optacceptconn;
|
||||
#endif
|
||||
int result /*0, i*/;
|
||||
char namebuff[FDNAME_NAMELEN];
|
||||
char peerbuff[FDNAME_NAMELEN];
|
||||
/* in Linux these optcodes are 'enum', but on AIX they are bits! */
|
||||
union sockaddr_union sockname, peername; /* the longest I know of */
|
||||
socklen_t namelen;
|
||||
#if 0 && defined(SIOCGIFNAME)
|
||||
/*Linux struct ifreq ifc = {{{ 0 }}};*/
|
||||
struct ifreq ifc = {{ 0 }};
|
||||
#endif
|
||||
|
||||
optlen = FDNAME_OPTLEN;
|
||||
|
||||
Getsockopt(fd, SOL_SOCKET, SO_TYPE, &opttype, &optlen);
|
||||
#ifdef SO_ACCEPTCONN
|
||||
Getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &optacceptconn, &optlen);
|
||||
#endif
|
||||
|
||||
namelen = sizeof(sockname);
|
||||
result = Getsockname(fd, &sockname.soa, &namelen);
|
||||
if (result < 0) {
|
||||
Error2("getsockname(%d): %s", fd, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
namelen = sizeof(peername);
|
||||
result = Getpeername(fd, (struct sockaddr *)&peername, &namelen);
|
||||
if (result < 0) {
|
||||
Error2("getpeername(%d): %s", fd, strerror(errno));
|
||||
}
|
||||
|
||||
switch (sockname.soa.sa_family) {
|
||||
#if WITH_UNIX
|
||||
case AF_UNIX:
|
||||
fprintf(outfile, "unix%s%s %s",
|
||||
opttype==SOCK_DGRAM?"datagram":"",
|
||||
#ifdef SO_ACCEPTCONN
|
||||
optacceptconn?"(listening)":
|
||||
#endif
|
||||
"",
|
||||
sockaddr_unix_info(&sockname.un, namelen,
|
||||
namebuff, sizeof(namebuff)));
|
||||
break;
|
||||
#endif
|
||||
#if WITH_IP4
|
||||
case AF_INET:
|
||||
switch (opttype) {
|
||||
#if WITH_TCP
|
||||
case SOCK_STREAM:
|
||||
fprintf(outfile, "tcp%s %s %s",
|
||||
#ifdef SO_ACCEPTCONN
|
||||
optacceptconn?"(listening)":
|
||||
#endif
|
||||
"",
|
||||
sockaddr_inet4_info(&sockname.ip4,
|
||||
namebuff, sizeof(namebuff)),
|
||||
sockaddr_inet4_info(&peername.ip4,
|
||||
peerbuff, sizeof(peerbuff)));
|
||||
break;
|
||||
#endif
|
||||
#if WITH_UDP
|
||||
case SOCK_DGRAM:
|
||||
fprintf(outfile, "udp%s %s %s",
|
||||
#ifdef SO_ACCEPTCONN
|
||||
optacceptconn?"(listening)":
|
||||
#endif
|
||||
"",
|
||||
sockaddr_inet4_info(&sockname.ip4,
|
||||
namebuff, sizeof(namebuff)),
|
||||
sockaddr_inet4_info(&peername.ip4,
|
||||
peerbuff, sizeof(peerbuff)));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(outfile, "ip %s",
|
||||
sockaddr_inet4_info(&sockname.ip4,
|
||||
namebuff, sizeof(namebuff)));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif /* WITH_IP4 */
|
||||
|
||||
#if WITH_IP6
|
||||
case AF_INET6:
|
||||
switch (opttype) {
|
||||
#if WITH_TCP
|
||||
case SOCK_STREAM:
|
||||
fprintf(outfile, "tcp6%s %s %s",
|
||||
#ifdef SO_ACCEPTCONN
|
||||
optacceptconn?"(listening)":
|
||||
#endif
|
||||
"",
|
||||
sockaddr_inet6_info(&sockname.ip6,
|
||||
namebuff, sizeof(namebuff)),
|
||||
sockaddr_inet6_info(&peername.ip6,
|
||||
peerbuff, sizeof(peerbuff)));
|
||||
break;
|
||||
#endif
|
||||
#if WITH_UDP
|
||||
case SOCK_DGRAM:
|
||||
fprintf(outfile, "udp6%s %s %s",
|
||||
#ifdef SO_ACCEPTCONN
|
||||
optacceptconn?"(listening)":
|
||||
#endif
|
||||
"",
|
||||
sockaddr_inet6_info(&sockname.ip6,
|
||||
namebuff, sizeof(namebuff)),
|
||||
sockaddr_inet6_info(&peername.ip6,
|
||||
peerbuff, sizeof(peerbuff)));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(outfile, "ip6 %s",
|
||||
sockaddr_inet6_info(&sockname.ip6,
|
||||
namebuff, sizeof(namebuff)));
|
||||
break;
|
||||
}
|
||||
#endif /* WITH_IP6 */
|
||||
default:
|
||||
fputs("socket", outfile);
|
||||
}
|
||||
|
||||
return result;
|
||||
#undef FDNAME_OPTLEN
|
||||
#undef FDNAME_NAMELEN
|
||||
}
|
||||
#endif /* WITH_SOCKET */
|
||||
|
||||
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue