aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorSimon Busch <morphis@gravedo.de>2012-01-24 18:07:09 +0100
committerSimon Busch <morphis@gravedo.de>2012-01-24 18:07:09 +0100
commit1122ae786d5f51fc6f7cf367306e1c1493ded7c3 (patch)
treec7a73f89102173dd23c590ce1ae773eb7a5481ed /tools
parentb469707433b2e306fe80b7da844fa87d284fa571 (diff)
downloadexternal_libsamsung-ipc-1122ae786d5f51fc6f7cf367306e1c1493ded7c3.zip
external_libsamsung-ipc-1122ae786d5f51fc6f7cf367306e1c1493ded7c3.tar.gz
external_libsamsung-ipc-1122ae786d5f51fc6f7cf367306e1c1493ded7c3.tar.bz2
tools: add first and untested version of a simple forward utility
Signed-off-by: Simon Busch <morphis@gravedo.de>
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile.am16
-rw-r--r--tools/forward.c178
2 files changed, 188 insertions, 6 deletions
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 5c98119..732d27f 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -4,12 +4,6 @@ AM_CFLAGS = \
-I$(top_srcdir)/include \
$(NULL)
-bin_PROGRAMS = modemctrl
-
-modemctrl_SOURCES = \
- modemctrl.c \
- $(NULL)
-
if WANT_PROTOCOL_VERISON_CRESPO
AM_CFLAGS += -DDEVICE_CRESPO
endif
@@ -18,5 +12,15 @@ if WANT_PROTOCOL_VERISON_H1
AM_CFLAGS += -DDEVICE_H1
endif
+bin_PROGRAMS = \
+ modemctrl \
+ samsung_ipc_forward \
+ $(NULL)
+
+modemctrl_SOURCES = modemctrl.c
modemctrl_LDADD = $(top_srcdir)/samsung-ipc/libsamsung-ipc.la
modemctrl_LDFLAGS =
+
+samsung_ipc_forward_SOURCES = forward.c
+samsung_ipc_forward_LDADD = $(top_srcdir)/samsung-ipc/libsamsung-ipc.la
+modemctrl_LDFLAGS =
diff --git a/tools/forward.c b/tools/forward.c
new file mode 100644
index 0000000..822d986
--- /dev/null
+++ b/tools/forward.c
@@ -0,0 +1,178 @@
+/**
+ * This file is part of libsamsung-ipc.
+ *
+ * Copyright (C) 2012 Simon Busch <morphis@gravedo.de>
+ *
+ * libsamsung-ipc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libsamsung-ipc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <termios.h>
+#include <strings.h>
+#include <getopt.h>
+
+#define IOCTL_MODEM_SEND _IO('o', 0x23)
+#define IOCTL_MODEM_RECV _IO('o', 0x24)
+
+void forward_data(int modem_fd, int remote_fd)
+{
+ fd_set rfds;
+ int rc, max_fd;
+ unsigned char buf[4096];
+
+ max_fd = modem_fd > remote_fd ? modem_fd + 1 : remote_fd + 1;
+
+ while(1) {
+ FD_ZERO(&rfds);
+ FD_SET(modem_fd, &rfds);
+ FD_SET(remote_fd, &rfds);
+
+ rc = select(max_fd, &rfds, NULL, NULL, NULL);
+ if (rc == -1) {
+ perror("select()");
+ break;
+ }
+ else if (rc) {
+ if (FD_ISSET(modem_fd, &rfds)) {
+ ssize_t size = ioctl(modem_fd, IOCTL_MODEM_RECV, &buf);
+ if (rc < 0)
+ break;
+ printf("Sending from modem %ld\n", size);
+ ssize_t written = write(remote_fd, &buf, size);
+ }
+ else if (FD_ISSET(remote_fd, &rfds)) {
+ ssize_t size = read(remote_fd, &buf, sizeof(buf));
+ if (size <= 0)
+ break;
+ printf("Sending from destination %ld\n", size);
+ ssize_t written = ioctl(modem_fd, IOCTL_MODEM_SEND, &buf);
+ }
+ }
+ }
+}
+
+int init_network_connection(int port)
+{
+ int socket_fd = socket(PF_INET, SOCK_STREAM, 0);
+ if (socket_fd < 0) {
+ perror("Failed to create network socket");
+ return EXIT_FAILURE;
+ }
+
+ int opt = 1;
+ if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt)) == -1) {
+ perror("Warning: can't set SO_REUSEADDR");
+ }
+
+ struct sockaddr_in addr = { 0, };
+ addr.sin_family = PF_INET;
+ addr.sin_port = htons(port);
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ if (bind(socket_fd, (struct sockaddr*) &addr, sizeof(addr)) == -1) {
+ perror("Error while binding socket");
+ goto socket_init_failed;
+ }
+
+ if (listen(socket_fd, 1) == -1) {
+ perror("Error while started listing on socket");
+ goto socket_init_failed;
+ }
+
+ return socket_fd;
+
+socket_init_failed:
+ close(socket_fd);
+ return -1;
+}
+
+int main(int argc, char **argv)
+{
+ opterr = 0;
+ int option_index;
+ int chr;
+ char serial_node[30] = "\0";
+ int network_port;
+ int show_help = 0;
+ int modem_fd = 0, socket_fd = 0;
+
+ struct option opts[] = {
+ { "node", required_argument, 0, 'n' },
+ { "port", required_argument, 0, 'p' },
+ { "help", no_argument, 0, 'h' },
+ };
+
+ while (1) {
+ option_index = 0;
+ chr = getopt_long(argc, argv, "n:p:h", opts, &option_index);
+
+ if (chr == -1)
+ break;
+
+ switch (chr) {
+ case 'h':
+ show_help = 1;
+ break;
+ case 'n':
+ snprintf(serial_node, 30, "%s", optarg);
+ break;
+ case 'p':
+ network_port = atoi(optarg);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (show_help || network_port == 0 || serial_node[0] == 0) {
+ printf("usage: samsung_ipc_forward -n <device node> -p <network port>\n");
+ exit(1);
+ }
+
+ socket_fd = init_network_connection(network_port);
+ if (socket_fd < 0)
+ return EXIT_FAILURE;
+
+ modem_fd = open(serial_node, O_RDWR | O_NOCTTY | O_NONBLOCK);
+
+ int connection_fd = -1;
+ struct sockaddr_in addr = { 0, };
+ socklen_t length = sizeof(addr);
+ while ((connection_fd = accept(socket_fd, (struct sockaddr*) &addr, &length)) >= 0) {
+ printf("New connection from: '%s'\n", inet_ntoa(addr.sin_addr));
+ forward_data(modem_fd, connection_fd);
+ close(connection_fd);
+ }
+
+ close(modem_fd);
+ close(socket_fd);
+
+ return 0;
+
+socket_init_failed:
+ close(socket_fd);
+ return EXIT_FAILURE;
+}