diff options
Diffstat (limited to 'src/usr.bin/nc/netcat.c')
| -rw-r--r-- | src/usr.bin/nc/netcat.c | 114 |
1 files changed, 103 insertions, 11 deletions
diff --git a/src/usr.bin/nc/netcat.c b/src/usr.bin/nc/netcat.c index 51d2501ccb..f95eb16e09 100644 --- a/src/usr.bin/nc/netcat.c +++ b/src/usr.bin/nc/netcat.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: netcat.c,v 1.41 2002/02/17 02:04:57 ericj Exp $ */ | 1 | /* $OpenBSD: netcat.c,v 1.42 2002/02/17 03:03:06 ericj Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> | 3 | * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> |
| 4 | * | 4 | * |
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <sys/types.h> | 34 | #include <sys/types.h> |
| 35 | #include <sys/socket.h> | 35 | #include <sys/socket.h> |
| 36 | #include <sys/time.h> | 36 | #include <sys/time.h> |
| 37 | #include <sys/un.h> | ||
| 37 | 38 | ||
| 38 | #include <netinet/in.h> | 39 | #include <netinet/in.h> |
| 39 | #include <arpa/telnet.h> | 40 | #include <arpa/telnet.h> |
| @@ -47,6 +48,7 @@ | |||
| 47 | #include <stdlib.h> | 48 | #include <stdlib.h> |
| 48 | #include <string.h> | 49 | #include <string.h> |
| 49 | #include <unistd.h> | 50 | #include <unistd.h> |
| 51 | #include <fcntl.h> | ||
| 50 | 52 | ||
| 51 | #define PORT_MAX 65535 | 53 | #define PORT_MAX 65535 |
| 52 | 54 | ||
| @@ -76,6 +78,8 @@ int local_listen(char *, char *, struct addrinfo); | |||
| 76 | void readwrite(int); | 78 | void readwrite(int); |
| 77 | int remote_connect(char *, char *, struct addrinfo); | 79 | int remote_connect(char *, char *, struct addrinfo); |
| 78 | int udptest(int); | 80 | int udptest(int); |
| 81 | int unix_connect(char *); | ||
| 82 | int unix_listen(char *); | ||
| 79 | void usage(int); | 83 | void usage(int); |
| 80 | 84 | ||
| 81 | int | 85 | int |
| @@ -98,7 +102,7 @@ main(int argc, char *argv[]) | |||
| 98 | endp = NULL; | 102 | endp = NULL; |
| 99 | sv = NULL; | 103 | sv = NULL; |
| 100 | 104 | ||
| 101 | while ((ch = getopt(argc, argv, "46hi:klnp:rs:tuvw:x:z")) != -1) { | 105 | while ((ch = getopt(argc, argv, "46Uhi:klnp:rs:tuvw:x:z")) != -1) { |
| 102 | switch (ch) { | 106 | switch (ch) { |
| 103 | case '4': | 107 | case '4': |
| 104 | family = AF_INET; | 108 | family = AF_INET; |
| @@ -106,6 +110,9 @@ main(int argc, char *argv[]) | |||
| 106 | case '6': | 110 | case '6': |
| 107 | family = AF_INET6; | 111 | family = AF_INET6; |
| 108 | break; | 112 | break; |
| 113 | case 'U': | ||
| 114 | family = AF_UNIX; | ||
| 115 | break; | ||
| 109 | case 'h': | 116 | case 'h': |
| 110 | help(); | 117 | help(); |
| 111 | break; | 118 | break; |
| @@ -161,7 +168,12 @@ main(int argc, char *argv[]) | |||
| 161 | argv += optind; | 168 | argv += optind; |
| 162 | 169 | ||
| 163 | /* Cruft to make sure options are clean, and used properly. */ | 170 | /* Cruft to make sure options are clean, and used properly. */ |
| 164 | if (argv[0] && !argv[1]) { | 171 | if (argv[0] && !argv[1] && family == AF_UNIX) { |
| 172 | if (uflag) | ||
| 173 | errx(1, "cannot use -u and -U"); | ||
| 174 | host = argv[0]; | ||
| 175 | uport = NULL; | ||
| 176 | } else if (argv[0] && !argv[1]) { | ||
| 165 | if (!lflag) | 177 | if (!lflag) |
| 166 | usage(1); | 178 | usage(1); |
| 167 | uport = argv[0]; | 179 | uport = argv[0]; |
| @@ -182,12 +194,15 @@ main(int argc, char *argv[]) | |||
| 182 | errx(1, "must use -l with -k"); | 194 | errx(1, "must use -l with -k"); |
| 183 | 195 | ||
| 184 | /* Initialize addrinfo structure */ | 196 | /* Initialize addrinfo structure */ |
| 185 | memset(&hints, 0, sizeof(struct addrinfo)); | 197 | if (family != AF_UNIX) { |
| 186 | hints.ai_family = family; | 198 | memset(&hints, 0, sizeof(struct addrinfo)); |
| 187 | hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM; | 199 | hints.ai_family = family; |
| 188 | hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP; | 200 | hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM; |
| 189 | if (nflag) | 201 | hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP; |
| 190 | hints.ai_flags |= AI_NUMERICHOST; | 202 | if (nflag) |
| 203 | hints.ai_flags |= AI_NUMERICHOST; | ||
| 204 | } | ||
| 205 | |||
| 191 | 206 | ||
| 192 | if (xflag) { | 207 | if (xflag) { |
| 193 | if (uflag) | 208 | if (uflag) |
| @@ -196,6 +211,9 @@ main(int argc, char *argv[]) | |||
| 196 | if (lflag) | 211 | if (lflag) |
| 197 | errx(1, "no proxy support for listen"); | 212 | errx(1, "no proxy support for listen"); |
| 198 | 213 | ||
| 214 | if (family == AF_UNIX) | ||
| 215 | errx(1, "no proxy support for unix sockets"); | ||
| 216 | |||
| 199 | /* XXX IPv6 transport to proxy would probably work */ | 217 | /* XXX IPv6 transport to proxy would probably work */ |
| 200 | if (family == AF_INET6) | 218 | if (family == AF_INET6) |
| 201 | errx(1, "no proxy support for IPv6"); | 219 | errx(1, "no proxy support for IPv6"); |
| @@ -218,9 +236,14 @@ main(int argc, char *argv[]) | |||
| 218 | int connfd; | 236 | int connfd; |
| 219 | ret = 0; | 237 | ret = 0; |
| 220 | 238 | ||
| 239 | if (family == AF_UNIX) | ||
| 240 | s = unix_listen(host); | ||
| 241 | |||
| 221 | /* Allow only one connection at a time, but stay alive */ | 242 | /* Allow only one connection at a time, but stay alive */ |
| 222 | for (;;) { | 243 | for (;;) { |
| 223 | if ((s = local_listen(host, uport, hints)) < 0) | 244 | if (family != AF_UNIX) |
| 245 | s = local_listen(host, uport, hints); | ||
| 246 | if (s < 0) | ||
| 224 | err(1, NULL); | 247 | err(1, NULL); |
| 225 | /* | 248 | /* |
| 226 | * For UDP, we will use recvfrom() initially | 249 | * For UDP, we will use recvfrom() initially |
| @@ -250,11 +273,23 @@ main(int argc, char *argv[]) | |||
| 250 | 273 | ||
| 251 | readwrite(connfd); | 274 | readwrite(connfd); |
| 252 | close(connfd); | 275 | close(connfd); |
| 253 | close(s); | 276 | if (family != AF_UNIX) |
| 277 | close(s); | ||
| 254 | 278 | ||
| 255 | if (!kflag) | 279 | if (!kflag) |
| 256 | break; | 280 | break; |
| 257 | } | 281 | } |
| 282 | } else if (family == AF_UNIX) { | ||
| 283 | ret = 0; | ||
| 284 | |||
| 285 | if ((s = unix_connect(host)) > 0 && !zflag) { | ||
| 286 | readwrite(s); | ||
| 287 | close(s); | ||
| 288 | } else | ||
| 289 | ret = 1; | ||
| 290 | |||
| 291 | exit(ret); | ||
| 292 | |||
| 258 | } else { | 293 | } else { |
| 259 | int i = 0; | 294 | int i = 0; |
| 260 | 295 | ||
| @@ -311,6 +346,62 @@ main(int argc, char *argv[]) | |||
| 311 | } | 346 | } |
| 312 | 347 | ||
| 313 | /* | 348 | /* |
| 349 | * unix_connect() | ||
| 350 | * Return's a socket connected to a local unix socket. Return's -1 on failure. | ||
| 351 | */ | ||
| 352 | int | ||
| 353 | unix_connect(char *path) | ||
| 354 | { | ||
| 355 | struct sockaddr_un sun; | ||
| 356 | int s; | ||
| 357 | |||
| 358 | if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) | ||
| 359 | return (-1); | ||
| 360 | (void)fcntl(s, F_SETFD, 1); | ||
| 361 | |||
| 362 | memset(&sun, 0, sizeof(struct sockaddr_un)); | ||
| 363 | sun.sun_len = sizeof(path); | ||
| 364 | sun.sun_family = AF_UNIX; | ||
| 365 | strlcpy(sun.sun_path, path, sizeof(sun.sun_path)); | ||
| 366 | |||
| 367 | if (connect(s, (struct sockaddr *)&sun, sizeof(sun)) < 0) { | ||
| 368 | close(s); | ||
| 369 | return (-1); | ||
| 370 | } | ||
| 371 | return (s); | ||
| 372 | |||
| 373 | } | ||
| 374 | |||
| 375 | /* | ||
| 376 | * unix_listen() | ||
| 377 | * create a unix domain socket, and listen on it. | ||
| 378 | */ | ||
| 379 | int | ||
| 380 | unix_listen(char *path) | ||
| 381 | { | ||
| 382 | struct sockaddr_un sun; | ||
| 383 | int s; | ||
| 384 | |||
| 385 | /* create unix domain socket */ | ||
| 386 | if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) | ||
| 387 | return (-1); | ||
| 388 | |||
| 389 | sun.sun_family = AF_UNIX; | ||
| 390 | strlcpy(sun.sun_path, path, sizeof(sun.sun_path)); | ||
| 391 | |||
| 392 | if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) { | ||
| 393 | close(s); | ||
| 394 | return (-1); | ||
| 395 | } | ||
| 396 | |||
| 397 | if (listen(s, 5) < 0) { | ||
| 398 | close(s); | ||
| 399 | return (-1); | ||
| 400 | } | ||
| 401 | return (s); | ||
| 402 | } | ||
| 403 | |||
| 404 | /* | ||
| 314 | * remote_connect() | 405 | * remote_connect() |
| 315 | * Return's a socket connected to a remote host. Properly bind's to a local | 406 | * Return's a socket connected to a remote host. Properly bind's to a local |
| 316 | * port or source address if needed. Return's -1 on failure. | 407 | * port or source address if needed. Return's -1 on failure. |
| @@ -598,6 +689,7 @@ help() | |||
| 598 | fprintf(stderr, "\tCommand Summary:\n\ | 689 | fprintf(stderr, "\tCommand Summary:\n\ |
| 599 | \t-4 Use IPv4\n\ | 690 | \t-4 Use IPv4\n\ |
| 600 | \t-6 Use IPv6\n\ | 691 | \t-6 Use IPv6\n\ |
| 692 | \t-U Use UNIX domain socket\n\ | ||
| 601 | \t-h This help text\n\ | 693 | \t-h This help text\n\ |
| 602 | \t-i secs\t Delay interval for lines sent, ports scanned\n\ | 694 | \t-i secs\t Delay interval for lines sent, ports scanned\n\ |
| 603 | \t-k Keep inbound sockets open for multiple connects\n\ | 695 | \t-k Keep inbound sockets open for multiple connects\n\ |
