Mercurial > hg > toybox
annotate toys/netcat.c @ 189:22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
author | Rob Landley <rob@landley.net> |
---|---|
date | Mon, 03 Dec 2007 18:53:00 -0600 |
parents | |
children | 30a6db5a95c2 |
rev | line source |
---|---|
189
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
1 /* vi: set sw=4 ts=4: */ |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
2 /* nc: mini-netcat - Forward stdin/stdout to a file or network connection. |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
3 * |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
4 * Copyright 2007 Rob Landley <rob@landley.net> |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
5 */ |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
6 |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
7 #include "toys.h" |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
8 #include "toynet.h" |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
9 |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
10 #include <sys/socket.h> |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
11 #include <netinet/in.h> |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
12 #include <arpa/inet.h> |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
13 |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
14 #define TT toy.netcat |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
15 |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
16 static void timeout(int signum) |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
17 { |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
18 error_exit("Timeout"); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
19 } |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
20 |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
21 // Translate x.x.x.x numeric IPv4 address, or else DNS lookup an IPv4 name. |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
22 void lookup_name(char *name, uint32_t *result) |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
23 { |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
24 struct hostent *hostbyname; |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
25 |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
26 hostbyname = gethostbyname(*toys.optargs); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
27 if (!hostbyname) error_exit("name lookup failed"); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
28 *result = *(uint32_t *)*hostbyname->h_addr_list; |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
29 } |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
30 |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
31 // Worry about a fancy lookup later. |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
32 void lookup_port(char *str, uint16_t *port) |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
33 { |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
34 *port = SWAP_BE16(atoi(str)); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
35 } |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
36 |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
37 void netcat_main(void) |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
38 { |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
39 int sockfd, pollcount; |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
40 struct pollfd pollfds[2]; |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
41 |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
42 if (TT.wait) { |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
43 signal(SIGALRM, timeout); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
44 alarm(TT.wait); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
45 } |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
46 |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
47 if (TT.filename) pollfds[0].fd = xopen(TT.filename, O_RDWR); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
48 else { |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
49 int temp; |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
50 struct sockaddr_in address; |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
51 |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
52 // The argument parsing logic can't make "<2" conditional on "-f", so... |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
53 if (!*toys.optargs || !toys.optargs[1]) { |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
54 toys.exithelp++; |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
55 error_exit("Need address and port"); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
56 } |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
57 |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
58 // Setup socket |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
59 sockfd = socket(AF_INET, SOCK_STREAM, 0); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
60 if (-1 == sockfd) perror_exit("socket"); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
61 fcntl(sockfd, F_SETFD, FD_CLOEXEC); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
62 temp = 1; |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
63 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &temp, sizeof(temp)); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
64 memset(&address, 0, sizeof(address)); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
65 address.sin_family = AF_INET; |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
66 if (TT.port) { |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
67 address.sin_port = TT.port; |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
68 if (-1 == bind(sockfd, &address, sizeof(address))) |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
69 perror_exit("bind"); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
70 } |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
71 |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
72 // Figure out where to dial out to. |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
73 lookup_name(*toys.optargs, (uint32_t *)&address.sin_addr); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
74 lookup_port(toys.optargs[1], &address.sin_port); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
75 temp = connect(sockfd, (struct sockaddr *)&address, sizeof(address)); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
76 if (temp<0) perror_exit("connect"); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
77 pollfds[0].fd = sockfd; |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
78 } |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
79 |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
80 // We have a connection. Disarm timeout. |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
81 if (TT.wait) { |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
82 alarm(0); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
83 signal(SIGALRM, SIG_DFL); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
84 } |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
85 |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
86 pollcount = 2; |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
87 pollfds[1].fd = 0; |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
88 pollfds[0].events = pollfds[1].events = POLLIN; |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
89 |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
90 // Poll loop copying stdin->socket and socket->stdout. |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
91 for (;;) { |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
92 int i; |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
93 |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
94 if (0>poll(pollfds, pollcount, -1)) perror_exit("poll"); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
95 |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
96 for (i=0; i<pollcount; i++) { |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
97 if (pollfds[i].revents & POLLIN) { |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
98 int len = read(pollfds[i].fd, toybuf, sizeof(toybuf)); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
99 if (len<1) goto dohupnow; |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
100 xwrite(i ? pollfds[0].fd : 1, toybuf, len); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
101 } |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
102 if (pollfds[i].revents & POLLHUP) { |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
103 dohupnow: |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
104 // Close half-connect. This is needed for things like |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
105 // "echo GET / | netcat landley.net 80" to work. |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
106 if (i) { |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
107 shutdown(pollfds[0].fd, SHUT_WR); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
108 pollcount--; |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
109 } else goto cleanup; |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
110 } |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
111 } |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
112 } |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
113 cleanup: |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
114 close(pollfds[0].fd); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
115 // close(sockfd); |
22d22427dec6
Add first pass at netcat. Base applet, -f, and -w implemented.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
116 } |