summaryrefslogtreecommitdiff
path: root/src/usr.bin/nc/netcat.c
diff options
context:
space:
mode:
authorbeck <>2019-11-13 04:10:38 +0000
committerbeck <>2019-11-13 04:10:38 +0000
commitbb392e46353010e9b8df230389fa7a849f4ec42e (patch)
treeb9dc89ebc1f5efebbaf280c80b0cc30be3db858a /src/usr.bin/nc/netcat.c
parent6c950d6ea19b4cc2844f226bb33a9847cab36f21 (diff)
downloadopenbsd-bb392e46353010e9b8df230389fa7a849f4ec42e.tar.gz
openbsd-bb392e46353010e9b8df230389fa7a849f4ec42e.tar.bz2
openbsd-bb392e46353010e9b8df230389fa7a849f4ec42e.zip
refactor the nc pool loop to not shut down the socket early, and
to handle tls_shutdown correctly if using TLS, doing tls_shutdown correctly if we are using the -N flag ok sthen@
Diffstat (limited to 'src/usr.bin/nc/netcat.c')
-rw-r--r--src/usr.bin/nc/netcat.c100
1 files changed, 64 insertions, 36 deletions
diff --git a/src/usr.bin/nc/netcat.c b/src/usr.bin/nc/netcat.c
index a53fe1c4cd..1dc95e9f36 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.210 2019/11/04 17:33:28 millert Exp $ */ 1/* $OpenBSD: netcat.c,v 1.211 2019/11/13 04:10:38 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> 3 * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
4 * Copyright (c) 2015 Bob Beck. All rights reserved. 4 * Copyright (c) 2015 Bob Beck. All rights reserved.
@@ -1103,13 +1103,14 @@ void
1103readwrite(int net_fd, struct tls *tls_ctx) 1103readwrite(int net_fd, struct tls *tls_ctx)
1104{ 1104{
1105 struct pollfd pfd[4]; 1105 struct pollfd pfd[4];
1106 int gone[4] = { 0 };
1106 int stdin_fd = STDIN_FILENO; 1107 int stdin_fd = STDIN_FILENO;
1107 int stdout_fd = STDOUT_FILENO; 1108 int stdout_fd = STDOUT_FILENO;
1108 unsigned char netinbuf[BUFSIZE]; 1109 unsigned char netinbuf[BUFSIZE];
1109 size_t netinbufpos = 0; 1110 size_t netinbufpos = 0;
1110 unsigned char stdinbuf[BUFSIZE]; 1111 unsigned char stdinbuf[BUFSIZE];
1111 size_t stdinbufpos = 0; 1112 size_t stdinbufpos = 0;
1112 int n, num_fds; 1113 int n, num_fds, shutdown_netin, shutdown_netout;
1113 ssize_t ret; 1114 ssize_t ret;
1114 1115
1115 /* don't read from stdin if requested */ 1116 /* don't read from stdin if requested */
@@ -1132,17 +1133,20 @@ readwrite(int net_fd, struct tls *tls_ctx)
1132 pfd[POLL_STDOUT].fd = stdout_fd; 1133 pfd[POLL_STDOUT].fd = stdout_fd;
1133 pfd[POLL_STDOUT].events = 0; 1134 pfd[POLL_STDOUT].events = 0;
1134 1135
1136 /* used to indicate we wish to shut down the network socket */
1137 shutdown_netin = shutdown_netout = 0;
1138
1135 while (1) { 1139 while (1) {
1136 /* both inputs are gone, buffers are empty, we are done */ 1140 /* both inputs are gone, buffers are empty, we are done */
1137 if (pfd[POLL_STDIN].fd == -1 && pfd[POLL_NETIN].fd == -1 && 1141 if (gone[POLL_STDIN] && gone[POLL_NETIN] &&
1138 stdinbufpos == 0 && netinbufpos == 0) 1142 stdinbufpos == 0 && netinbufpos == 0)
1139 return; 1143 return;
1140 /* both outputs are gone, we can't continue */ 1144 /* both outputs are gone, we can't continue */
1141 if (pfd[POLL_NETOUT].fd == -1 && pfd[POLL_STDOUT].fd == -1) 1145 if (gone[POLL_NETOUT] && gone[POLL_STDOUT])
1142 return; 1146 return;
1143 /* listen and net in gone, queues empty, done */ 1147 /* listen and net in gone, queues empty, done */
1144 if (lflag && pfd[POLL_NETIN].fd == -1 && 1148 if (lflag && gone[POLL_NETIN] && stdinbufpos == 0
1145 stdinbufpos == 0 && netinbufpos == 0) 1149 && netinbufpos == 0)
1146 return; 1150 return;
1147 1151
1148 /* help says -i is for "wait between lines sent". We read and 1152 /* help says -i is for "wait between lines sent". We read and
@@ -1151,6 +1155,12 @@ readwrite(int net_fd, struct tls *tls_ctx)
1151 if (iflag) 1155 if (iflag)
1152 sleep(iflag); 1156 sleep(iflag);
1153 1157
1158 /* If it's gone, take it away from poll */
1159 for (n = 0; n < 4; n++) {
1160 if (gone[n])
1161 pfd[n].events = pfd[n].revents = 0;
1162 }
1163
1154 /* poll */ 1164 /* poll */
1155 num_fds = poll(pfd, 4, timeout); 1165 num_fds = poll(pfd, 4, timeout);
1156 1166
@@ -1165,36 +1175,36 @@ readwrite(int net_fd, struct tls *tls_ctx)
1165 /* treat socket error conditions */ 1175 /* treat socket error conditions */
1166 for (n = 0; n < 4; n++) { 1176 for (n = 0; n < 4; n++) {
1167 if (pfd[n].revents & (POLLERR|POLLNVAL)) { 1177 if (pfd[n].revents & (POLLERR|POLLNVAL)) {
1168 pfd[n].fd = -1; 1178 gone[n] = 1;
1169 } 1179 }
1170 } 1180 }
1171 /* reading is possible after HUP */ 1181 /* reading is possible after HUP */
1172 if (pfd[POLL_STDIN].events & POLLIN && 1182 if (pfd[POLL_STDIN].events & POLLIN &&
1173 pfd[POLL_STDIN].revents & POLLHUP && 1183 pfd[POLL_STDIN].revents & POLLHUP &&
1174 !(pfd[POLL_STDIN].revents & POLLIN)) 1184 !(pfd[POLL_STDIN].revents & POLLIN))
1175 pfd[POLL_STDIN].fd = -1; 1185 gone[POLL_STDIN] = 1;
1176 1186
1177 if (pfd[POLL_NETIN].events & POLLIN && 1187 if (pfd[POLL_NETIN].events & POLLIN &&
1178 pfd[POLL_NETIN].revents & POLLHUP && 1188 pfd[POLL_NETIN].revents & POLLHUP &&
1179 !(pfd[POLL_NETIN].revents & POLLIN)) 1189 !(pfd[POLL_NETIN].revents & POLLIN))
1180 pfd[POLL_NETIN].fd = -1; 1190 gone[POLL_NETIN] = 1;
1181 1191
1182 if (pfd[POLL_NETOUT].revents & POLLHUP) { 1192 if (pfd[POLL_NETOUT].revents & POLLHUP) {
1183 if (Nflag) 1193 if (Nflag)
1184 shutdown(pfd[POLL_NETOUT].fd, SHUT_WR); 1194 shutdown_netout = 1;
1185 pfd[POLL_NETOUT].fd = -1; 1195 gone[POLL_NETOUT] = 1;
1186 } 1196 }
1187 /* if HUP, stop watching stdout */
1188 if (pfd[POLL_STDOUT].revents & POLLHUP)
1189 pfd[POLL_STDOUT].fd = -1;
1190 /* if no net out, stop watching stdin */ 1197 /* if no net out, stop watching stdin */
1191 if (pfd[POLL_NETOUT].fd == -1) 1198 if (gone[POLL_NETOUT])
1192 pfd[POLL_STDIN].fd = -1; 1199 gone[POLL_STDIN] = 1;
1200
1201 /* if stdout HUP's, stop watching stdout */
1202 if (pfd[POLL_STDOUT].revents & POLLHUP)
1203 gone[POLL_STDOUT] = 1;
1193 /* if no stdout, stop watching net in */ 1204 /* if no stdout, stop watching net in */
1194 if (pfd[POLL_STDOUT].fd == -1) { 1205 if (gone[POLL_STDOUT]) {
1195 if (pfd[POLL_NETIN].fd != -1) 1206 shutdown_netin = 1;
1196 shutdown(pfd[POLL_NETIN].fd, SHUT_RD); 1207 gone[POLL_NETIN] = 1;
1197 pfd[POLL_NETIN].fd = -1;
1198 } 1208 }
1199 1209
1200 /* try to read from stdin */ 1210 /* try to read from stdin */
@@ -1206,7 +1216,7 @@ readwrite(int net_fd, struct tls *tls_ctx)
1206 else if (ret == TLS_WANT_POLLOUT) 1216 else if (ret == TLS_WANT_POLLOUT)
1207 pfd[POLL_STDIN].events = POLLOUT; 1217 pfd[POLL_STDIN].events = POLLOUT;
1208 else if (ret == 0 || ret == -1) 1218 else if (ret == 0 || ret == -1)
1209 pfd[POLL_STDIN].fd = -1; 1219 gone[POLL_STDIN] = 1;
1210 /* read something - poll net out */ 1220 /* read something - poll net out */
1211 if (stdinbufpos > 0) 1221 if (stdinbufpos > 0)
1212 pfd[POLL_NETOUT].events = POLLOUT; 1222 pfd[POLL_NETOUT].events = POLLOUT;
@@ -1223,7 +1233,7 @@ readwrite(int net_fd, struct tls *tls_ctx)
1223 else if (ret == TLS_WANT_POLLOUT) 1233 else if (ret == TLS_WANT_POLLOUT)
1224 pfd[POLL_NETOUT].events = POLLOUT; 1234 pfd[POLL_NETOUT].events = POLLOUT;
1225 else if (ret == -1) 1235 else if (ret == -1)
1226 pfd[POLL_NETOUT].fd = -1; 1236 gone[POLL_NETOUT] = 1;
1227 /* buffer empty - remove self from polling */ 1237 /* buffer empty - remove self from polling */
1228 if (stdinbufpos == 0) 1238 if (stdinbufpos == 0)
1229 pfd[POLL_NETOUT].events = 0; 1239 pfd[POLL_NETOUT].events = 0;
@@ -1240,17 +1250,15 @@ readwrite(int net_fd, struct tls *tls_ctx)
1240 else if (ret == TLS_WANT_POLLOUT) 1250 else if (ret == TLS_WANT_POLLOUT)
1241 pfd[POLL_NETIN].events = POLLOUT; 1251 pfd[POLL_NETIN].events = POLLOUT;
1242 else if (ret == -1) 1252 else if (ret == -1)
1243 pfd[POLL_NETIN].fd = -1; 1253 gone[POLL_NETIN] = 1;
1244 /* eof on net in - remove from pfd */ 1254 /* eof on net in - remove from pfd */
1245 if (ret == 0) { 1255 if (ret == 0) {
1246 shutdown(pfd[POLL_NETIN].fd, SHUT_RD); 1256 gone[POLL_NETIN] = 1;
1247 pfd[POLL_NETIN].fd = -1;
1248 } 1257 }
1249 if (recvlimit > 0 && ++recvcount >= recvlimit) { 1258 if (recvlimit > 0 && ++recvcount >= recvlimit) {
1250 if (pfd[POLL_NETIN].fd != -1) 1259 shutdown_netin = 1;
1251 shutdown(pfd[POLL_NETIN].fd, SHUT_RD); 1260 gone[POLL_NETIN] = 1;
1252 pfd[POLL_NETIN].fd = -1; 1261 gone[POLL_STDIN] = 1;
1253 pfd[POLL_STDIN].fd = -1;
1254 } 1262 }
1255 /* read something - poll stdout */ 1263 /* read something - poll stdout */
1256 if (netinbufpos > 0) 1264 if (netinbufpos > 0)
@@ -1272,7 +1280,7 @@ readwrite(int net_fd, struct tls *tls_ctx)
1272 else if (ret == TLS_WANT_POLLOUT) 1280 else if (ret == TLS_WANT_POLLOUT)
1273 pfd[POLL_STDOUT].events = POLLOUT; 1281 pfd[POLL_STDOUT].events = POLLOUT;
1274 else if (ret == -1) 1282 else if (ret == -1)
1275 pfd[POLL_STDOUT].fd = -1; 1283 gone[POLL_STDOUT] = 1;
1276 /* buffer empty - remove self from polling */ 1284 /* buffer empty - remove self from polling */
1277 if (netinbufpos == 0) 1285 if (netinbufpos == 0)
1278 pfd[POLL_STDOUT].events = 0; 1286 pfd[POLL_STDOUT].events = 0;
@@ -1282,14 +1290,34 @@ readwrite(int net_fd, struct tls *tls_ctx)
1282 } 1290 }
1283 1291
1284 /* stdin gone and queue empty? */ 1292 /* stdin gone and queue empty? */
1285 if (pfd[POLL_STDIN].fd == -1 && stdinbufpos == 0) { 1293 if (gone[POLL_STDIN] && stdinbufpos == 0) {
1286 if (pfd[POLL_NETOUT].fd != -1 && Nflag) 1294 if (Nflag) {
1287 shutdown(pfd[POLL_NETOUT].fd, SHUT_WR); 1295 shutdown_netin = 1;
1288 pfd[POLL_NETOUT].fd = -1; 1296 shutdown_netout = 1;
1297 }
1298 gone[POLL_NETOUT] = 1;
1289 } 1299 }
1290 /* net in gone and queue empty? */ 1300 /* net in gone and queue empty? */
1291 if (pfd[POLL_NETIN].fd == -1 && netinbufpos == 0) { 1301 if (gone[POLL_NETIN] && netinbufpos == 0) {
1292 pfd[POLL_STDOUT].fd = -1; 1302 if (Nflag) {
1303 shutdown_netin = 1;
1304 shutdown_netout = 1;
1305 }
1306 gone[POLL_STDOUT] = 1;
1307 }
1308
1309 /* call tls_close if any part of the network socket is closing */
1310 if ((shutdown_netin || shutdown_netout) && usetls) {
1311 timeout_tls(pfd[POLL_NETIN].fd, tls_ctx, tls_close);
1312 shutdown_netout = shutdown_netin = 1;
1313 }
1314 if (shutdown_netin) {
1315 shutdown(pfd[POLL_NETIN].fd, SHUT_RD);
1316 gone[POLL_NETIN] = 1;
1317 }
1318 if (shutdown_netout) {
1319 shutdown(pfd[POLL_NETOUT].fd, SHUT_WR);
1320 gone[POLL_NETOUT] = 1;
1293 } 1321 }
1294 } 1322 }
1295} 1323}