1 |
|
|
/* $OpenBSD: tcpdrop.c,v 1.17 2015/01/16 06:40:21 deraadt Exp $ */ |
2 |
|
|
|
3 |
|
|
/* |
4 |
|
|
* Copyright (c) 2004 Markus Friedl <markus@openbsd.org> |
5 |
|
|
* |
6 |
|
|
* Permission to use, copy, modify, and distribute this software for any |
7 |
|
|
* purpose with or without fee is hereby granted, provided that the above |
8 |
|
|
* copyright notice and this permission notice appear in all copies. |
9 |
|
|
* |
10 |
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
11 |
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
12 |
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
13 |
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
14 |
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
15 |
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
16 |
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 |
|
|
*/ |
18 |
|
|
|
19 |
|
|
#include <sys/socket.h> |
20 |
|
|
#include <sys/sysctl.h> |
21 |
|
|
#include <sys/queue.h> |
22 |
|
|
#include <sys/timeout.h> |
23 |
|
|
|
24 |
|
|
#include <netinet/in.h> |
25 |
|
|
#include <netinet/tcp.h> |
26 |
|
|
#include <netinet/tcp_timer.h> |
27 |
|
|
#include <netinet/tcp_var.h> |
28 |
|
|
|
29 |
|
|
#include <err.h> |
30 |
|
|
#include <stdio.h> |
31 |
|
|
#include <string.h> |
32 |
|
|
#include <stdlib.h> |
33 |
|
|
#include <netdb.h> |
34 |
|
|
|
35 |
|
|
__dead void usage(void); |
36 |
|
|
|
37 |
|
|
__dead void |
38 |
|
|
usage(void) |
39 |
|
|
{ |
40 |
|
|
extern char *__progname; |
41 |
|
|
|
42 |
|
|
fprintf(stderr, |
43 |
|
|
"usage: %s local-addr local-port remote-addr remote-port\n", |
44 |
|
|
__progname); |
45 |
|
|
fprintf(stderr, |
46 |
|
|
" %s local-addr:local-port remote-addr:remote-port\n", |
47 |
|
|
__progname); |
48 |
|
|
exit(1); |
49 |
|
|
} |
50 |
|
|
|
51 |
|
|
/* |
52 |
|
|
* Drop a tcp connection. |
53 |
|
|
*/ |
54 |
|
|
int |
55 |
|
|
main(int argc, char **argv) |
56 |
|
|
{ |
57 |
|
|
int mib[] = { CTL_NET, PF_INET, IPPROTO_TCP, TCPCTL_DROP }; |
58 |
|
|
struct addrinfo hints, *ail, *aif, *laddr, *faddr; |
59 |
|
|
char fhbuf[NI_MAXHOST], fsbuf[NI_MAXSERV]; |
60 |
|
|
char lhbuf[NI_MAXHOST], lsbuf[NI_MAXSERV]; |
61 |
|
|
char *laddr1, *addr1, *port1, *faddr2, *addr2, *port2; |
62 |
|
|
struct tcp_ident_mapping tir; |
63 |
|
|
int gaierr, rval = 0; |
64 |
|
|
|
65 |
|
|
memset(&hints, 0, sizeof(hints)); |
66 |
|
|
hints.ai_family = AF_UNSPEC; |
67 |
|
|
hints.ai_socktype = SOCK_STREAM; |
68 |
|
|
|
69 |
|
|
if (argc == 3) { |
70 |
|
|
laddr1 = addr1 = strdup(argv[1]); |
71 |
|
|
if (!addr1) |
72 |
|
|
err(1, "strdup"); |
73 |
|
|
port1 = strrchr(addr1, ':'); |
74 |
|
|
if (port1) |
75 |
|
|
*port1++ = '\0'; |
76 |
|
|
else |
77 |
|
|
usage(); |
78 |
|
|
|
79 |
|
|
faddr2 = addr2 = strdup(argv[2]); |
80 |
|
|
if (!addr2) |
81 |
|
|
err(1, "strdup"); |
82 |
|
|
port2 = strrchr(addr2, ':'); |
83 |
|
|
if (port2) |
84 |
|
|
*port2++ = '\0'; |
85 |
|
|
else |
86 |
|
|
usage(); |
87 |
|
|
} else if (argc == 5) { |
88 |
|
|
laddr1 = addr1 = argv[1]; |
89 |
|
|
port1 = argv[2]; |
90 |
|
|
faddr2 = addr2 = argv[3]; |
91 |
|
|
port2 = argv[4]; |
92 |
|
|
} else |
93 |
|
|
usage(); |
94 |
|
|
|
95 |
|
|
if (addr1[0] == '[' && addr1[strlen(addr1) - 1] == ']') { |
96 |
|
|
laddr1 = strdup(addr1); |
97 |
|
|
if (!laddr1) |
98 |
|
|
err(1, "strdup"); |
99 |
|
|
laddr1[strlen(laddr1) - 1] = '\0'; |
100 |
|
|
laddr1++; |
101 |
|
|
} |
102 |
|
|
if (addr2[0] == '[' && addr2[strlen(addr2) - 1] == ']') { |
103 |
|
|
faddr2 = strdup(addr2); |
104 |
|
|
if (!faddr2) |
105 |
|
|
err(1, "strdup"); |
106 |
|
|
faddr2[strlen(faddr2) - 1] = '\0'; |
107 |
|
|
faddr2++; |
108 |
|
|
} |
109 |
|
|
|
110 |
|
|
if ((gaierr = getaddrinfo(laddr1, port1, &hints, &laddr)) != 0) |
111 |
|
|
errx(1, "%s port %s: %s", addr1, port1, |
112 |
|
|
gai_strerror(gaierr)); |
113 |
|
|
|
114 |
|
|
if ((gaierr = getaddrinfo(faddr2, port2, &hints, &faddr)) != 0) |
115 |
|
|
errx(1, "%s port %s: %s", addr2, port2, |
116 |
|
|
gai_strerror(gaierr)); |
117 |
|
|
|
118 |
|
|
rval = 1; |
119 |
|
|
for (ail = laddr; ail; ail = ail->ai_next) { |
120 |
|
|
for (aif = faddr; aif; aif = aif->ai_next) { |
121 |
|
|
if (ail->ai_family != aif->ai_family) |
122 |
|
|
continue; |
123 |
|
|
rval = 0; |
124 |
|
|
memset(&tir, 0, sizeof(tir)); |
125 |
|
|
memcpy(&tir.faddr, aif->ai_addr, aif->ai_addrlen); |
126 |
|
|
memcpy(&tir.laddr, ail->ai_addr, ail->ai_addrlen); |
127 |
|
|
|
128 |
|
|
if ((gaierr = getnameinfo(aif->ai_addr, aif->ai_addrlen, |
129 |
|
|
fhbuf, sizeof(fhbuf), fsbuf, sizeof(fsbuf), |
130 |
|
|
NI_NUMERICHOST | NI_NUMERICSERV)) != 0) |
131 |
|
|
errx(1, "getnameinfo: %s", gai_strerror(gaierr)); |
132 |
|
|
if ((gaierr = getnameinfo(ail->ai_addr, ail->ai_addrlen, |
133 |
|
|
lhbuf, sizeof(lhbuf), lsbuf, sizeof(lsbuf), |
134 |
|
|
NI_NUMERICHOST | NI_NUMERICSERV)) != 0) |
135 |
|
|
errx(1, "getnameinfo: %s", gai_strerror(gaierr)); |
136 |
|
|
|
137 |
|
|
if (sysctl(mib, sizeof (mib) / sizeof (int), NULL, |
138 |
|
|
NULL, &tir, sizeof(tir)) == -1) { |
139 |
|
|
rval = 1; |
140 |
|
|
warn("%s %s %s %s", lhbuf, lsbuf, fhbuf, fsbuf); |
141 |
|
|
} else { |
142 |
|
|
if (aif->ai_family == PF_INET6) |
143 |
|
|
printf("[%s]:%s [%s]:%s dropped\n", |
144 |
|
|
lhbuf, lsbuf, fhbuf, fsbuf); |
145 |
|
|
else |
146 |
|
|
printf("%s:%s %s:%s dropped\n", |
147 |
|
|
lhbuf, lsbuf, fhbuf, fsbuf); |
148 |
|
|
} |
149 |
|
|
} |
150 |
|
|
} |
151 |
|
|
freeaddrinfo(laddr); |
152 |
|
|
freeaddrinfo(faddr); |
153 |
|
|
exit(rval); |
154 |
|
|
} |