From: Erik Hugne <erik.hu...@gmail.com> Enables bash scripts to read and write data to TIPC RDM/DGRAM sockets.
Signed-off-by: Erik Hugne <erik.hu...@gmail.com> --- Only available/enabled on Linux. config.h.in | 2 ++ configure.ac | 2 ++ doc/bash.1 | 5 +++ doc/bashref.texi | 10 ++++-- externs.h | 2 +- lib/sh/netopen.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ redir.c | 17 ++++++++++ 7 files changed, 134 insertions(+), 3 deletions(-) diff --git a/config.h.in b/config.h.in index 8554aecc..73db32cf 100644 --- a/config.h.in +++ b/config.h.in @@ -950,6 +950,8 @@ /* Define if you have the <arpa/inet.h> header file. */ #undef HAVE_ARPA_INET_H +/* Define if you have the <linux/tipc.h> header file */ +#undef HAVE_TIPC /* Define if you have the <dirent.h> header file. */ #undef HAVE_DIRENT_H diff --git a/configure.ac b/configure.ac index 52b4cdbd..9e80d10d 100644 --- a/configure.ac +++ b/configure.ac @@ -717,6 +717,8 @@ AC_CHECK_HEADERS(sys/pte.h sys/stream.h sys/select.h sys/file.h sys/ioctl.h \ sys/time.h sys/times.h sys/types.h sys/wait.h) AC_CHECK_HEADERS(netinet/in.h arpa/inet.h) +AC_CHECK_HEADER(linux/tipc.h, AC_DEFINE(HAVE_TIPC)) + dnl sys/ptem.h requires definitions from sys/stream.h on systems where it dnl exists AC_CHECK_HEADER(sys/ptem.h, , ,[[ diff --git a/doc/bash.1 b/doc/bash.1 index e6cd08db..91179788 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -3889,6 +3889,11 @@ the corresponding TCP socket. If \fIhost\fP is a valid hostname or Internet address, and \fIport\fP is an integer port number or service name, \fBbash\fP attempts to open the corresponding UDP socket. +.TP +.B /dev/tipc/\fItype\fP/\fIinstance\fP|\fIlow\fP/\fIhigh\fP +if \fItype\fP is a valid TIPC instance integer value, and \fIinstance\fP or +\fIlow\fP/\fIhigh\fP are integer type numbers, Bash attempts to open the corresponding +TIPC RDM socket. Using \fIlow\fP/\fIhigh\fP notation will make the socket multicast. .PD .RE .PP diff --git a/doc/bashref.texi b/doc/bashref.texi index d33cd571..4342b4aa 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -2736,6 +2736,11 @@ the corresponding TCP socket. If @var{host} is a valid hostname or Internet address, and @var{port} is an integer port number or service name, Bash attempts to open the corresponding UDP socket. + +@item /dev/tipc/@var{type}/@var{instance}|@var{low}/@var{high} +If @var{type} is a valid TIPC instance integer value, and @var{instance} or @var{low}/ +@var{high} are integer type numbers, Bash attempts to open the corresponding +TIPC RDM socket. Using @var{low}/@var{high} notation will make the socket multicast. @end table A failure to open or create a file causes the redirection to fail. @@ -8632,8 +8637,9 @@ system provides the necessary support. @item --enable-net-redirections This enables the special handling of filenames of the form -@code{/dev/tcp/@var{host}/@var{port}} and -@code{/dev/udp/@var{host}/@var{port}} +@code{/dev/tcp/@var{host}/@var{port}}, +@code{/dev/udp/@var{host}/@var{port}} and +@code{/dev/tipc/@var{type}/@var{instance}|@var{low}/@var{high}} when used in redirections (@pxref{Redirections}). @item --enable-process-substitution diff --git a/externs.h b/externs.h index 72df33d1..0bd7958c 100644 --- a/externs.h +++ b/externs.h @@ -276,7 +276,7 @@ extern int isnetconn __P((int)); /* declarations for functions defined in lib/sh/netopen.c */ extern int netopen __P((char *)); - +extern int netopen_tipc __P((char *, enum r_instruction)); /* Declarations for functions defined in lib/sh/oslib.c */ #if !defined (HAVE_DUP2) || defined (DUP2_BROKEN) diff --git a/lib/sh/netopen.c b/lib/sh/netopen.c index bc3d8f8a..090756c8 100644 --- a/lib/sh/netopen.c +++ b/lib/sh/netopen.c @@ -31,6 +31,11 @@ # include <unistd.h> #endif +#if defined (HAVE_TIPC) +# include <linux/tipc.h> +# include "command.h" +#endif + #include <stdio.h> #include <sys/types.h> @@ -314,6 +319,91 @@ netopen (path) return fd; } +#if defined (HAVE_TIPC) +static int +_netopen_tipc(uint8_t addrtype, uint32_t addr1, uint32_t addr2, + uint32_t addr3, uint8_t do_bind, uint8_t do_connect) +{ + int fd, e; + + struct sockaddr_tipc sa = { + .family = AF_TIPC, + .addrtype = addrtype + }; + + switch (addrtype) { + case TIPC_ADDR_ID: + sa.addr.id.node = addr1; + sa.addr.id.ref = addr2; + break; + case TIPC_ADDR_NAME: + sa.addrtype = TIPC_ADDR_NAME; + sa.addr.name.name.type = addr1; + sa.addr.name.name.instance = addr2; + break; + case TIPC_ADDR_NAMESEQ: + sa.addrtype = TIPC_ADDR_NAMESEQ; + sa.addr.nameseq.type = addr1; + sa.addr.nameseq.lower = addr2; + sa.addr.nameseq.upper = addr3; + break; + default: + goto err; + } + if ((fd = socket(AF_TIPC, SOCK_RDM, 0)) < 0) { + e = errno; + sys_error("socket"); + goto err; + } + /*Bind the sockaddr if we have input redirection*/ + if (addrtype != TIPC_ADDR_ID && do_bind && + bind(fd, (struct sockaddr*)&sa, sizeof(sa))) { + e = errno; + sys_error("bind"); + goto err; + } + /*Connect the sockaddr if we have output redirection*/ + if (do_connect && connect(fd, (struct sockaddr*)&sa, sizeof(sa))) { + e = errno; + sys_error("connect"); + goto err; + } + return fd; +err: + if (fd > 0) + close(fd); + errno = e; + + return -1; +} +int +netopen_tipc (char *path, enum r_instruction ri) +{ + uint32_t addr1, addr2, addr3; + uint8_t addrtype = TIPC_ADDR_NAME; + uint8_t dummy = 0; + uint8_t do_bind = (ri == r_input_direction || ri == r_input_output); + uint8_t do_connect = (ri == r_output_direction || ri == r_input_output); + + if ((sscanf(path + 10, "%u:%u%c", &addr1, &addr2, &dummy) == 2) && + !dummy) { + addrtype = TIPC_ADDR_ID; + } else + if ((sscanf(path+10, "%u/%u/%u%c", &addr1, &addr2, &addr3, &dummy) == 3) && + !dummy) { + addrtype = TIPC_ADDR_NAMESEQ; + } else + if ((sscanf(path+10, "%u/%u%c", &addr1, &addr2, &dummy) == 2) && + !dummy) { + addrtype = TIPC_ADDR_NAME; + } else { + errno = EINVAL; + return -1; + } + return _netopen_tipc(addrtype, addr1, addr2, addr3, do_bind, do_connect); +} +#endif /* HAVE_TIPC */ + #if 0 /* * Open a TCP connection to host `host' on the port defined for service @@ -348,4 +438,13 @@ netopen (path) return -1; } + +int +netopen_tipc (path) + char *path; +{ + internal_error(_("network operations not supported")); + return -1; +} + #endif /* !HAVE_NETWORK */ diff --git a/redir.c b/redir.c index 0c0c9f2b..989553eb 100644 --- a/redir.c +++ b/redir.c @@ -520,6 +520,7 @@ here_document_to_fd (redirectee, ri) #define RF_DEVSTDOUT 4 #define RF_DEVTCP 5 #define RF_DEVUDP 6 +#define RF_DEVTIPC 7 /* A list of pattern/value pairs for filenames that the redirection code handles specially. */ @@ -535,6 +536,9 @@ static STRING_INT_ALIST _redir_special_filenames[] = { #if defined (NETWORK_REDIRECTIONS) { "/dev/tcp/*/*", RF_DEVTCP }, { "/dev/udp/*/*", RF_DEVUDP }, +#if defined (HAVE_TIPC) + { "/dev/tipc/*", RF_DEVTIPC }, +#endif #endif { (char *)NULL, -1 } }; @@ -592,6 +596,19 @@ redir_special_open (spec, filename, flags, mode, ri) fd = open (filename, flags, mode); #endif break; +#if defined (HAVE_TIPC) + case RF_DEVTIPC: +#if defined (RESTRICTED_SHELL) + if (restricted) + return (RESTRICTED_REDIRECT); +#endif +#if defined (HAVE_NETWORK) + fd = netopen_tipc(filename, ri); +#else + internal_warning(_("/dev/tipc/type/instance not supported without networking")); +#endif /* HAVE_NETWORK */ + break; +#endif /* HAVE_TIPC */ #endif /* NETWORK_REDIRECTIONS */ } -- 2.14.1