3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include <netinet/in.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
32 #include <arpa/inet.h>
40 /* baudrate settings are defined in <asm/termbits.h>, which is
41 included by <termios.h> */
42 #define BAUDRATE B9600
43 /* change this definition for the correct port */
44 #define MODEMDEVICE "/dev/ttyS0"
45 #define _POSIX_SOURCE 1 /* POSIX compliant source */
47 #define IPS_PROTO_CONNECT 'c'
48 #define IPS_PROTO_CONNECTED 'k'
49 #define IPS_PROTO_RECV 'r'
50 #define IPS_PROTO_EOF 'e'
51 #define IPS_PROTO_CLOSE 'q'
52 #define IPS_PROTO_SOCKET 's'
53 #define IPS_PROTO_ACCEPT 'a'
54 #define IPS_PROTO_BIND 'b'
55 #define IPS_PROTO_LISTEN 'l'
56 #define IPS_PROTO_FCNTL 'f'
58 #define IPS_PROTO "/#ips#"
62 int serial_write (char *data
, unsigned len
);
65 struct termios oldtio
, newtio
;
67 bool connected
= false;
70 hostent
*host
; // Vzdálený poèítaè;
71 sockaddr_in serverSock
; // Vzdálený "konec potrubí"
72 int mySocket
; // Soket
73 int port
; // Èíslo portu
74 char buf
[BUFSIZE
]; // Pøijímací buffer
75 int size
; // Poèet pøijatých a odeslaných bytù
79 struct sockaddr_un serv_addr
;
81 sockaddr_in sockName
; // "Jméno" portu
82 sockaddr_in clientInfo
; // Klient, který se pøipojil
83 socklen_t addrlen
; // Velikost adresy vzdáleného poèítaèe
85 int unixsock_init (char *path
)
89 bzero ((char *) &serv_addr
, sizeof(serv_addr
));
91 serv_addr
.sun_family
= AF_UNIX
;
92 strcpy (serv_addr
.sun_path
, path
);
93 servlen
= strlen (serv_addr
.sun_path
) + sizeof (serv_addr
.sun_family
);
95 if ((fd
= socket (AF_UNIX
, SOCK_STREAM
, 0)) < 0) {
96 puts ("socket () < 0 - unix domain socket cant be created !");
101 if (connect (fd
, (struct sockaddr
*) &serv_addr
, servlen
) < 0) {
102 printf ("connect () < 0 - cant connect to socket '%s'\n", path
);
107 printf ("unix domain socket - connected :P\n");
115 Open modem device for reading and writing and not as controlling tty
116 because we don't want to get killed if linenoise sends CTRL-C.
118 fd
= open (MODEMDEVICE
, O_RDWR
| O_NOCTTY
);
121 perror(MODEMDEVICE
); exit(-1);
123 tcgetattr (fd
, &oldtio
); /* save current serial port settings */
124 bzero (&newtio
, sizeof(newtio
)); /* clear struct for new port settings */
127 BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
128 CRTSCTS : output hardware flow control (only used if the cable has
129 all necessary lines. See sect. 7 of Serial-HOWTO)
130 CS8 : 8n1 (8bit,no parity,1 stopbit)
131 CLOCAL : local connection, no modem contol
132 CREAD : enable receiving characters
135 newtio
.c_cflag
= BAUDRATE
| CS8
| /*CLOCAL | */CREAD
;
138 IGNPAR : ignore bytes with parity errors
139 ICRNL : map CR to NL (otherwise a CR input on the other computer
140 will not terminate input)
141 otherwise make device raw (no other input processing)
143 // newtio.c_iflag = /*IGNPAR | ICRNL;*/
151 ICANON : enable canonical input
152 disable all echo functionality, and don't send signals to calling program
154 // newtio.c_lflag = ICANON;
157 initialize all control characters
158 default values can be found in /usr/include/termios.h, and are given
159 in the comments, but we don't need them here
161 newtio
.c_cc
[VINTR
] = 0; /* Ctrl-c */
162 newtio
.c_cc
[VQUIT
] = 0; /* Ctrl-\ */
163 newtio
.c_cc
[VERASE
] = 0; /* del */
164 newtio
.c_cc
[VKILL
] = 0; /* @ */
165 newtio
.c_cc
[VEOF
] = 4; /* Ctrl-d */
166 newtio
.c_cc
[VTIME
] = 0; /* inter-character timer unused */
167 newtio
.c_cc
[VMIN
] = 1; /* blocking read until 1 character arrives */
168 newtio
.c_cc
[VSWTC
] = 0; /* '\0' */
169 newtio
.c_cc
[VSTART
] = 0; /* Ctrl-q */
170 newtio
.c_cc
[VSTOP
] = 0; /* Ctrl-s */
171 newtio
.c_cc
[VSUSP
] = 0; /* Ctrl-z */
172 newtio
.c_cc
[VEOL
] = 0; /* '\0' */
173 newtio
.c_cc
[VREPRINT
] = 0; /* Ctrl-r */
174 newtio
.c_cc
[VDISCARD
] = 0; /* Ctrl-u */
175 newtio
.c_cc
[VWERASE
] = 0; /* Ctrl-w */
176 newtio
.c_cc
[VLNEXT
] = 0; /* Ctrl-v */
177 newtio
.c_cc
[VEOL2
] = 0; /* '\0' */
180 now clean the modem line and activate the settings for the port
183 tcflush(fd
, TCIFLUSH
);
184 tcsetattr(fd
, TCSANOW
,&newtio
);
189 void irs_proto_sendheader (int ret
)
192 num
[0] = (unsigned char) ret
;
193 num
[1] = (unsigned char) (ret
>> 8);
194 num
[2] = (unsigned char) (ret
>> 16);
195 num
[3] = (unsigned char) (ret
>> 24);
197 serial_write (num
, 4);
200 int ips_proto_parse (int sock
, char *data
, unsigned len
)
202 if (strncmp (data
, IPS_PROTO
, 6)) {
211 int ret
= send (sock
, data
, len
, 0);
213 printf ("send (%d/%d): %s\n", ret
, len
, data
);
217 // printf ("dta: %s\n", data);
218 if (data
[6] == IPS_PROTO_RECV
) {
226 sscanf (data
, "%s %d", s
, &buf_len
);
229 printf ("recv (): buf_len ! %d\n", buf_len
);
230 irs_proto_sendheader (-1);
235 memset (buf
, 0, buf_len
);
237 usleep (80); // prevent for fragmentation
239 int ret
= recv (sock
, buf
, buf_len
, 0);
241 // printf ("len: %d\n", len);
242 //if (ret == -1) //to vymaz pak -- test
243 // irs_proto_sendheader (0);
246 irs_proto_sendheader (ret
);
249 serial_write (buf
, ret
);
251 printf ("recv(%d): %d: %s\n", sock
, ret
, buf
);
257 if (data
[6] == IPS_PROTO_ACCEPT
) {
258 // Poznaèím si velikost struktury clientInfo.
259 // Pøedám to funkci accept.
260 addrlen
= sizeof (clientInfo
);
261 // Vyberu z fronty po¾adavek na spojení.
262 // "client" je nový soket spojující klienta se serverem.
263 int client
= accept (sock
, (sockaddr
*) &clientInfo
, &addrlen
);
265 irs_proto_sendheader (client
);
266 // TODO: dodelat vraceni clientInfo structury .. nebo spis jen ip ktera se pripojila
270 // printf ("accept (%d)\n", client);
275 if (data
[6] == IPS_PROTO_SOCKET
) {
277 if ((sock
= socket (AF_INET
, SOCK_STREAM
, IPPROTO_TCP
)) == -1)
279 cerr
<< "Nelze vytvoøit soket" << endl
;
280 irs_proto_sendheader (sock
);
284 printf ("socket (%d)\n", sock
);
286 irs_proto_sendheader (sock
);
289 if (data
[6] == IPS_PROTO_CONNECT
) {
292 irs_proto_sendheader (-1);
296 char s
[10], addr
[32];
298 sscanf (data
, "%s %s %d", s
, addr
, &port
);
300 // Zjistíme info o vzdáleném poèítaèi
301 if ((host
= gethostbyname (addr
)) == NULL
)
303 printf ("connect () -> wrong address: %s\n", addr
);
304 irs_proto_sendheader (-1);
308 // Zaplníme strukturu sockaddr_in
309 // 1) Rodina protokolù
310 serverSock
.sin_family
= AF_INET
;
311 // 2) Èíslo portu, ke kterému se pøipojíme
312 serverSock
.sin_port
= htons(port
);
313 // 3) Nastavení IP adresy, ke které se pøipojíme
314 memcpy(&(serverSock
.sin_addr
), host
->h_addr
, host
->h_length
);
319 if ((ret
= connect(sock
, (sockaddr
*)&serverSock
, sizeof(serverSock
))) == -1)
321 if (errno
!= EINPROGRESS
)
323 printf ("ERROR -> Cant resolve - %s:%d\n", addr
, port
);
324 irs_proto_sendheader (ret
);
334 // Zjistím, jestli je ji¾ spojení navázáno. Jestli¾e ne, poèkáme a¾ bude navázáno.
335 if (select (sock
+ 1, NULL
, &set
, NULL
, &tv
) == 0)
337 printf ("ERROR -> Cant connect to %s:%d\n", addr
, port
);
338 irs_proto_sendheader (-1);
346 irs_proto_sendheader (1);
348 printf ("Connected -> %s:%d\n", addr
, port
);
353 if (data
[6] == IPS_PROTO_BIND
) {
356 setsockopt (sock
, SOL_SOCKET
, SO_REUSEADDR
, (char *) &yes
, sizeof (yes
));
358 char s
[10], addr
[32];
360 sscanf (data
, "%s %s %d", s
, addr
, &port
);
361 // Zaplníme strukturu sockaddr_in
362 // 1) Rodina protokolù
363 sockName
.sin_family
= AF_INET
;
364 // 2) Èíslo portu, na kterém èekáme
365 sockName
.sin_port
= htons (port
);
366 // 3) Nastavení IP adresy lokální sí»ové karty, pøes kterou je mo¾no se
367 // pøipojit. Nastavíme mo¾nost pøipojit se odkudkoliv.
368 sockName
.sin_addr
.s_addr
= INADDR_ANY
;
369 // pøiøadíme soketu jméno
372 if ((ret
= bind (sock
, (sockaddr
*)&sockName
, sizeof(sockName
))) == -1)
374 cerr
<< "Problém s pojmenováním soketu." << endl
;
375 irs_proto_sendheader (-1);
379 printf ("bind () on port %d\n", port
);
381 irs_proto_sendheader (ret
);
386 if (data
[6] == IPS_PROTO_LISTEN
) {
388 irs_proto_sendheader (-1);
395 sscanf (data
, "%s %d", s
, &backlog
);
397 int ret
= listen (sock
, backlog
);
399 irs_proto_sendheader (ret
);
404 if (data
[6] == IPS_PROTO_CLOSE
) {
407 //printf ("close (%d)\n", sock);
411 if (data
[6] == IPS_PROTO_FCNTL
) {
413 irs_proto_sendheader (-1);
421 sscanf (data
, "%s %d %ld", s
, &act
, &flag
);
423 /* Set to nonblocking socket mode */
424 int ret
= fcntl (sock
, act
, flag
);
425 /*if (fcntl (sock, F_SETFL, oldFlag | O_NONBLOCK) == -1)
427 cerr << "> ERROR -> Problem with set socket mode" << endl;
428 irs_proto_sendheader (-1);
433 // printf ("socket is nonblock (%d)\n", sock);
435 irs_proto_sendheader (ret
);
443 int serial_read (char *data
)
449 unsigned char num
[5];
450 memset (num
, 0, sizeof (num
));
452 read (fd
, (unsigned char *) &num
[0], 1);
453 read (fd
, (unsigned char *) &num
[1], 1);
454 read (fd
, (unsigned char *) &num
[2], 1);
455 read (fd
, (unsigned char *) &num
[3], 1);
460 len
= num
[0] | (num
[1] << 8) | (num
[2] << 16) | (num
[3] << 24);
462 // printf ("##len: %d\n", len);
465 printf ("oj ! len: %d\n", len
);
469 unsigned char fds
[5];
470 memset (fds
, 0, sizeof (fds
));
472 read (fd
, (unsigned char *) &fds
[0], 1);
473 read (fd
, (unsigned char *) &fds
[1], 1);
474 read (fd
, (unsigned char *) &fds
[2], 1);
475 read (fd
, (unsigned char *) &fds
[3], 1);
477 //if (fds[0] == '\0')
480 int sock
= fds
[0] | (fds
[1] << 8) | (fds
[2] << 16) | (fds
[3] << 24);
482 // printf ("##sock: %d\n", sock);
503 return ips_proto_parse (sock
, data
, len
);
506 int serial_write (char *data
, unsigned len
)
508 write (fd
, data
, len
);
513 int main (int argc
, char *argv
[])
515 puts ("-[ ZeX/OS ips2ip gateway ]-");
519 if (argc
> 1 && argv
[1][0] == 'p')
526 unixsock_init (argv
[2]);
528 unixsock_init ("/tmp/zexos");
530 char *test
= (char *) calloc (sizeof (char), 4096);
533 memset (test
, 0, 4095);
542 /* restore the old port settings */
544 tcsetattr (fd
, TCSANOW
, &oldtio
);
546 puts ("ips2ip -> exit ()");