Changeset 20170 in vbox for trunk/src/VBox/Devices/Network
- Timestamp:
- Jun 2, 2009 2:05:34 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/slirp/slirp.c
r20164 r20170 1061 1061 * Check sockets 1062 1062 */ 1063 if ( link_up)1064 {1063 if (!link_up) 1064 goto done; 1065 1065 #if defined(RT_OS_WINDOWS) 1066 /*XXX: before renaming please make see define 1067 * fIcmp in slirp_state.h 1066 /*XXX: before renaming please make see define 1067 * fIcmp in slirp_state.h 1068 */ 1069 if (fIcmp) 1070 sorecvfrom(pData, &pData->icmp_socket); 1071 #else 1072 if ( (pData->icmp_socket.s != -1) 1073 && CHECK_FD_SET(&pData->icmp_socket, ignored, readfds)) 1074 sorecvfrom(pData, &pData->icmp_socket); 1075 #endif 1076 /* 1077 * Check TCP sockets 1078 */ 1079 QSOCKET_FOREACH(so, so_next, tcp) 1080 /* { */ 1081 1082 #ifdef VBOX_WITH_SLIRP_MT 1083 if ( so->so_state & SS_NOFDREF 1084 && so->so_deleted == 1) 1085 { 1086 struct socket *son, *sop = NULL; 1087 QSOCKET_LOCK(tcb); 1088 if (so->so_next != NULL) 1089 { 1090 if (so->so_next != &tcb) 1091 SOCKET_LOCK(so->so_next); 1092 son = so->so_next; 1093 } 1094 if ( so->so_prev != &tcb 1095 && so->so_prev != NULL) 1096 { 1097 SOCKET_LOCK(so->so_prev); 1098 sop = so->so_prev; 1099 } 1100 QSOCKET_UNLOCK(tcb); 1101 remque(pData, so); 1102 NSOCK_DEC(); 1103 SOCKET_UNLOCK(so); 1104 SOCKET_LOCK_DESTROY(so); 1105 RTMemFree(so); 1106 so_next = son; 1107 if (sop != NULL) 1108 SOCKET_UNLOCK(sop); 1109 CONTINUE_NO_UNLOCK(tcp); 1110 } 1111 #endif 1112 /* 1113 * FD_ISSET is meaningless on these sockets 1114 * (and they can crash the program) 1068 1115 */ 1069 if (fIcmp) 1070 sorecvfrom(pData, &pData->icmp_socket); 1071 #else 1072 if ( (pData->icmp_socket.s != -1) 1073 && CHECK_FD_SET(&pData->icmp_socket, ignored, readfds)) 1074 sorecvfrom(pData, &pData->icmp_socket); 1075 #endif 1116 if (so->so_state & SS_NOFDREF || so->s == -1) 1117 CONTINUE(tcp); 1118 1119 POLL_TCP_EVENTS(rc, error, so, &NetworkEvents); 1120 1121 LOG_NAT_SOCK(so, TCP, &NetworkEvents, readfds, writefds, xfds); 1122 1123 1076 1124 /* 1077 * Check TCP sockets 1125 * Check for URG data 1126 * This will soread as well, so no need to 1127 * test for readfds below if this succeeds 1078 1128 */ 1079 QSOCKET_FOREACH(so, so_next, tcp) 1080 /* { */ 1081 1082 #ifdef VBOX_WITH_SLIRP_MT 1083 if ( so->so_state & SS_NOFDREF 1084 && so->so_deleted == 1) 1085 { 1086 struct socket *son, *sop = NULL; 1087 QSOCKET_LOCK(tcb); 1088 if (so->so_next != NULL) 1089 { 1090 if (so->so_next != &tcb) 1091 SOCKET_LOCK(so->so_next); 1092 son = so->so_next; 1093 } 1094 if ( so->so_prev != &tcb 1095 && so->so_prev != NULL) 1096 { 1097 SOCKET_LOCK(so->so_prev); 1098 sop = so->so_prev; 1099 } 1100 QSOCKET_UNLOCK(tcb); 1101 remque(pData, so); 1102 NSOCK_DEC(); 1103 SOCKET_UNLOCK(so); 1104 SOCKET_LOCK_DESTROY(so); 1105 RTMemFree(so); 1106 so_next = son; 1107 if (sop != NULL) 1108 SOCKET_UNLOCK(sop); 1109 CONTINUE_NO_UNLOCK(tcp); 1110 } 1111 #endif 1129 1130 /* out-of-band data */ 1131 if (CHECK_FD_SET(so, NetworkEvents, xfds)) 1132 { 1133 sorecvoob(pData, so); 1134 } 1135 1136 /* 1137 * Check sockets for reading 1138 */ 1139 else if ( CHECK_FD_SET(so, NetworkEvents, readfds) 1140 || WIN_CHECK_FD_SET(so, NetworkEvents, acceptds)) 1141 { 1112 1142 /* 1113 * FD_ISSET is meaningless on these sockets 1114 * (and they can crash the program) 1143 * Check for incoming connections 1115 1144 */ 1116 if (so->so_state & SS_NOFDREF || so->s == -1) 1117 CONTINUE(tcp); 1118 1119 POLL_TCP_EVENTS(rc, error, so, &NetworkEvents); 1120 1121 LOG_NAT_SOCK(so, TCP, &NetworkEvents, readfds, writefds, xfds); 1122 1123 1145 if (so->so_state & SS_FACCEPTCONN) 1146 { 1147 TCP_CONNECT(pData, so); 1148 #if defined(RT_OS_WINDOWS) 1149 if (!(NetworkEvents.lNetworkEvents & FD_CLOSE)) 1150 #endif 1151 CONTINUE(tcp); 1152 } 1153 1154 ret = soread(pData, so); 1155 /* Output it if we read something */ 1156 if (ret > 0) 1157 TCP_OUTPUT(pData, sototcpcb(so)); 1158 } 1159 1160 #if defined(RT_OS_WINDOWS) 1161 /* 1162 * Check for FD_CLOSE events. 1163 * in some cases once FD_CLOSE engaged on socket it could be flashed latter (for some reasons) 1164 */ 1165 if ( (NetworkEvents.lNetworkEvents & FD_CLOSE) 1166 || (so->so_close == 1)) 1167 { 1168 so->so_close = 1; /* mark it */ 1124 1169 /* 1125 * Check for URG data 1126 * This will soread as well, so no need to 1127 * test for readfds below if this succeeds 1170 * drain the socket 1128 1171 */ 1129 1130 /* out-of-band data */ 1131 if (CHECK_FD_SET(so, NetworkEvents, xfds)) 1132 { 1133 sorecvoob(pData, so); 1134 } 1135 1136 /* 1137 * Check sockets for reading 1138 */ 1139 else if ( CHECK_FD_SET(so, NetworkEvents, readfds) 1140 || WIN_CHECK_FD_SET(so, NetworkEvents, acceptds)) 1141 { 1142 /* 1143 * Check for incoming connections 1144 */ 1145 if (so->so_state & SS_FACCEPTCONN) 1146 { 1147 TCP_CONNECT(pData, so); 1148 #if defined(RT_OS_WINDOWS) 1149 if (!(NetworkEvents.lNetworkEvents & FD_CLOSE)) 1150 #endif 1151 CONTINUE(tcp); 1152 } 1153 1172 for (;;) 1173 { 1154 1174 ret = soread(pData, so); 1155 /* Output it if we read something */1156 1175 if (ret > 0) 1157 1176 TCP_OUTPUT(pData, sototcpcb(so)); 1158 } 1159 1160 #if defined(RT_OS_WINDOWS) 1177 else 1178 break; 1179 } 1180 CONTINUE(tcp); 1181 } 1182 #endif 1183 1184 /* 1185 * Check sockets for writing 1186 */ 1187 if (CHECK_FD_SET(so, NetworkEvents, writefds)) 1188 { 1161 1189 /* 1162 * Check for FD_CLOSE events. 1163 * in some cases once FD_CLOSE engaged on socket it could be flashed latter (for some reasons) 1190 * Check for non-blocking, still-connecting sockets 1164 1191 */ 1165 if ( (NetworkEvents.lNetworkEvents & FD_CLOSE) 1166 || (so->so_close == 1)) 1167 { 1168 so->so_close = 1; /* mark it */ 1192 if (so->so_state & SS_ISFCONNECTING) 1193 { 1194 Log2(("connecting %R[natsock] catched\n", so)); 1195 /* Connected */ 1196 so->so_state &= ~SS_ISFCONNECTING; 1197 1169 1198 /* 1170 * drain the socket 1199 * This should be probably guarded by PROBE_CONN too. Anyway, 1200 * we disable it on OS/2 because the below send call returns 1201 * EFAULT which causes the opened TCP socket to close right 1202 * after it has been opened and connected. 1171 1203 */ 1172 for (;;) 1204 #ifndef RT_OS_OS2 1205 ret = send(so->s, (const char *)&ret, 0, 0); 1206 if (ret < 0) 1173 1207 { 1174 ret = soread(pData, so); 1175 if (ret > 0) 1176 TCP_OUTPUT(pData, sototcpcb(so)); 1177 else 1178 break; 1208 /* XXXXX Must fix, zero bytes is a NOP */ 1209 if ( errno == EAGAIN 1210 || errno == EWOULDBLOCK 1211 || errno == EINPROGRESS 1212 || errno == ENOTCONN) 1213 CONTINUE(tcp); 1214 1215 /* else failed */ 1216 so->so_state = SS_NOFDREF; 1179 1217 } 1180 CONTINUE(tcp); 1181 } 1182 #endif 1183 1218 /* else so->so_state &= ~SS_ISFCONNECTING; */ 1219 #endif 1220 1221 /* 1222 * Continue tcp_input 1223 */ 1224 TCP_INPUT(pData, (struct mbuf *)NULL, sizeof(struct ip), so); 1225 /* continue; */ 1226 } 1227 else 1228 SOWRITE(ret, pData, so); 1184 1229 /* 1185 * Check sockets for writing 1230 * XXX If we wrote something (a lot), there could be the need 1231 * for a window update. In the worst case, the remote will send 1232 * a window probe to get things going again. 1186 1233 */ 1187 if (CHECK_FD_SET(so, NetworkEvents, writefds)) 1188 { 1189 /* 1190 * Check for non-blocking, still-connecting sockets 1191 */ 1192 if (so->so_state & SS_ISFCONNECTING) 1234 } 1235 1236 /* 1237 * Probe a still-connecting, non-blocking socket 1238 * to check if it's still alive 1239 */ 1240 #ifdef PROBE_CONN 1241 if (so->so_state & SS_ISFCONNECTING) 1242 { 1243 ret = recv(so->s, (char *)&ret, 0, 0); 1244 1245 if (ret < 0) 1246 { 1247 /* XXX */ 1248 if ( errno == EAGAIN 1249 || errno == EWOULDBLOCK 1250 || errno == EINPROGRESS 1251 || errno == ENOTCONN) 1193 1252 { 1194 Log2(("connecting %R[natsock] catched\n", so)); 1195 /* Connected */ 1196 so->so_state &= ~SS_ISFCONNECTING; 1197 1198 /* 1199 * This should be probably guarded by PROBE_CONN too. Anyway, 1200 * we disable it on OS/2 because the below send call returns 1201 * EFAULT which causes the opened TCP socket to close right 1202 * after it has been opened and connected. 1203 */ 1204 #ifndef RT_OS_OS2 1205 ret = send(so->s, (const char *)&ret, 0, 0); 1206 if (ret < 0) 1207 { 1208 /* XXXXX Must fix, zero bytes is a NOP */ 1209 if ( errno == EAGAIN 1210 || errno == EWOULDBLOCK 1211 || errno == EINPROGRESS 1212 || errno == ENOTCONN) 1213 CONTINUE(tcp); 1214 1215 /* else failed */ 1216 so->so_state = SS_NOFDREF; 1217 } 1218 /* else so->so_state &= ~SS_ISFCONNECTING; */ 1219 #endif 1220 1221 /* 1222 * Continue tcp_input 1223 */ 1224 TCP_INPUT(pData, (struct mbuf *)NULL, sizeof(struct ip), so); 1225 /* continue; */ 1253 CONTINUE(tcp); /* Still connecting, continue */ 1226 1254 } 1227 else 1228 SOWRITE(ret, pData, so); 1229 /* 1230 * XXX If we wrote something (a lot), there could be the need 1231 * for a window update. In the worst case, the remote will send 1232 * a window probe to get things going again. 1233 */ 1234 } 1235 1236 /* 1237 * Probe a still-connecting, non-blocking socket 1238 * to check if it's still alive 1239 */ 1240 #ifdef PROBE_CONN 1241 if (so->so_state & SS_ISFCONNECTING) 1242 { 1243 ret = recv(so->s, (char *)&ret, 0, 0); 1244 1255 1256 /* else failed */ 1257 so->so_state = SS_NOFDREF; 1258 1259 /* tcp_input will take care of it */ 1260 } 1261 else 1262 { 1263 ret = send(so->s, &ret, 0, 0); 1245 1264 if (ret < 0) 1246 1265 { … … 1251 1270 || errno == ENOTCONN) 1252 1271 { 1253 CONTINUE(tcp); /* Still connecting, continue */1272 CONTINUE(tcp); 1254 1273 } 1255 1256 1274 /* else failed */ 1257 1275 so->so_state = SS_NOFDREF; 1258 1259 /* tcp_input will take care of it */1260 1276 } 1261 1277 else 1262 { 1263 ret = send(so->s, &ret, 0, 0); 1264 if (ret < 0) 1265 { 1266 /* XXX */ 1267 if ( errno == EAGAIN 1268 || errno == EWOULDBLOCK 1269 || errno == EINPROGRESS 1270 || errno == ENOTCONN) 1271 { 1272 CONTINUE(tcp); 1273 } 1274 /* else failed */ 1275 so->so_state = SS_NOFDREF; 1276 } 1277 else 1278 so->so_state &= ~SS_ISFCONNECTING; 1279 1280 } 1281 TCP_INPUT((struct mbuf *)NULL, sizeof(struct ip),so); 1282 } /* SS_ISFCONNECTING */ 1278 so->so_state &= ~SS_ISFCONNECTING; 1279 1280 } 1281 TCP_INPUT((struct mbuf *)NULL, sizeof(struct ip),so); 1282 } /* SS_ISFCONNECTING */ 1283 1283 #endif 1284 1284 #ifndef RT_OS_WINDOWS 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1285 if ( UNIX_CHECK_FD_SET(so, NetworkEvents, rdhup) 1286 || UNIX_CHECK_FD_SET(so, NetworkEvents, rderr)) 1287 { 1288 int err; 1289 int inq, outq; 1290 int status; 1291 socklen_t optlen = sizeof(int); 1292 inq = outq = 0; 1293 status = getsockopt(so->s, SOL_SOCKET, SO_ERROR, &err, &optlen); 1294 if (status != 0) 1295 Log(("NAT: can't get error status from %R[natsock]\n", so)); 1296 1296 #ifndef RT_OS_SOLARIS 1297 1298 1299 1300 1301 1302 1303 1304 1305 1297 status = ioctl(so->s, FIONREAD, &inq); /* tcp(7) recommends SIOCINQ which is Linux specific */ 1298 if (status != 0 || status != EINVAL) 1299 { 1300 /* EINVAL returned if socket in listen state tcp(7)*/ 1301 Log(("NAT: can't get depth of IN queue status from %R[natsock]\n", so)); 1302 } 1303 status = ioctl(so->s, TIOCOUTQ, &outq); /* SIOCOUTQ see previous comment */ 1304 if (status != 0) 1305 Log(("NAT: can't get depth of OUT queue from %R[natsock]\n", so)); 1306 1306 #else 1307 1307 /* … … 1310 1310 */ 1311 1311 #endif 1312 if ( so->so_state & SS_ISFCONNECTING 1313 || UNIX_CHECK_FD_SET(so, NetworkEvents, readfds)) 1312 if ( so->so_state & SS_ISFCONNECTING 1313 || UNIX_CHECK_FD_SET(so, NetworkEvents, readfds)) 1314 { 1315 /** 1316 * Check if we need here take care about gracefull connection 1317 * @todo try with proxy server 1318 */ 1319 if (UNIX_CHECK_FD_SET(so, NetworkEvents, readfds)) 1314 1320 { 1315 /** 1316 * Check if we need here take care about gracefull connection 1317 * @todo try with proxy server 1321 /* 1322 * Never meet inq != 0 or outq != 0, anyway let it stay for a while 1323 * in case it happens we'll able to detect it. 1324 * Give TCP/IP stack wait or expire the socket. 1318 1325 */ 1319 if (UNIX_CHECK_FD_SET(so, NetworkEvents, readfds)) 1320 { 1321 /* 1322 * Never meet inq != 0 or outq != 0, anyway let it stay for a while 1323 * in case it happens we'll able to detect it. 1324 * Give TCP/IP stack wait or expire the socket. 1325 */ 1326 Log(("NAT: %R[natsock] err(%d:%s) s(in:%d,out:%d)happens on read I/O, " 1327 "other side close connection \n", so, err, strerror(err), inq, outq)); 1328 CONTINUE(tcp); 1329 } 1330 goto tcp_input_close; 1326 Log(("NAT: %R[natsock] err(%d:%s) s(in:%d,out:%d)happens on read I/O, " 1327 "other side close connection \n", so, err, strerror(err), inq, outq)); 1328 CONTINUE(tcp); 1331 1329 } 1332 if ( !UNIX_CHECK_FD_SET(so, NetworkEvents, readfds) 1333 && !UNIX_CHECK_FD_SET(so, NetworkEvents, writefds) 1334 && !UNIX_CHECK_FD_SET(so, NetworkEvents, xfds)) 1335 { 1336 Log(("NAT: system expires the socket %R[natsock] err(%d:%s) s(in:%d,out:%d) happens on non-I/O. ", 1337 so, err, strerror(err), inq, outq)); 1338 goto tcp_input_close; 1339 } 1340 Log(("NAT: %R[natsock] we've met(%d:%s) s(in:%d, out:%d) unhandled combination hup (%d) " 1341 "rederr(%d) on (r:%d, w:%d, x:%d)\n", 1342 so, err, strerror(err), 1343 inq, outq, 1344 UNIX_CHECK_FD_SET(so, ign, rdhup), 1345 UNIX_CHECK_FD_SET(so, ign, rderr), 1346 UNIX_CHECK_FD_SET(so, ign, readfds), 1347 UNIX_CHECK_FD_SET(so, ign, writefds), 1348 UNIX_CHECK_FD_SET(so, ign, xfds))); 1349 /* 1350 * Give OS's TCP/IP stack a chance to resolve an issue or expire the socket. 1351 */ 1352 CONTINUE(tcp); 1330 goto tcp_input_close; 1331 } 1332 if ( !UNIX_CHECK_FD_SET(so, NetworkEvents, readfds) 1333 && !UNIX_CHECK_FD_SET(so, NetworkEvents, writefds) 1334 && !UNIX_CHECK_FD_SET(so, NetworkEvents, xfds)) 1335 { 1336 Log(("NAT: system expires the socket %R[natsock] err(%d:%s) s(in:%d,out:%d) happens on non-I/O. ", 1337 so, err, strerror(err), inq, outq)); 1338 goto tcp_input_close; 1339 } 1340 Log(("NAT: %R[natsock] we've met(%d:%s) s(in:%d, out:%d) unhandled combination hup (%d) " 1341 "rederr(%d) on (r:%d, w:%d, x:%d)\n", 1342 so, err, strerror(err), 1343 inq, outq, 1344 UNIX_CHECK_FD_SET(so, ign, rdhup), 1345 UNIX_CHECK_FD_SET(so, ign, rderr), 1346 UNIX_CHECK_FD_SET(so, ign, readfds), 1347 UNIX_CHECK_FD_SET(so, ign, writefds), 1348 UNIX_CHECK_FD_SET(so, ign, xfds))); 1349 /* 1350 * Give OS's TCP/IP stack a chance to resolve an issue or expire the socket. 1351 */ 1352 CONTINUE(tcp); 1353 1353 tcp_input_close: 1354 1355 1356 1357 1358 #endif 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1354 so->so_state = SS_NOFDREF; /*cause connection valid tcp connection termination and socket closing */ 1355 TCP_INPUT(pData, (struct mbuf *)NULL, sizeof(struct ip), so); 1356 CONTINUE(tcp); 1357 } 1358 #endif 1359 LOOP_LABEL(tcp, so, so_next); 1360 } 1361 1362 /* 1363 * Now UDP sockets. 1364 * Incoming packets are sent straight away, they're not buffered. 1365 * Incoming UDP data isn't buffered either. 1366 */ 1367 QSOCKET_FOREACH(so, so_next, udp) 1368 /* { */ 1369 1369 #ifdef VBOX_WITH_SLIRP_MT 1370 if ( so->so_state & SS_NOFDREF 1371 && so->so_deleted == 1) 1372 { 1373 struct socket *son, *sop = NULL; 1374 QSOCKET_LOCK(udb); 1375 if (so->so_next != NULL) 1376 { 1377 if (so->so_next != &udb) 1378 SOCKET_LOCK(so->so_next); 1379 son = so->so_next; 1380 } 1381 if ( so->so_prev != &udb 1382 && so->so_prev != NULL) 1383 { 1384 SOCKET_LOCK(so->so_prev); 1385 sop = so->so_prev; 1386 } 1387 QSOCKET_UNLOCK(udb); 1388 remque(pData, so); 1389 NSOCK_DEC(); 1390 SOCKET_UNLOCK(so); 1391 SOCKET_LOCK_DESTROY(so); 1392 RTMemFree(so); 1393 so_next = son; 1394 if (sop != NULL) 1395 SOCKET_UNLOCK(sop); 1396 CONTINUE_NO_UNLOCK(udp); 1397 } 1398 #endif 1399 POLL_UDP_EVENTS(rc, error, so, &NetworkEvents); 1400 1401 LOG_NAT_SOCK(so, UDP, &NetworkEvents, readfds, writefds, xfds); 1402 1403 if (so->s != -1 && CHECK_FD_SET(so, NetworkEvents, readfds)) 1404 { 1405 SORECVFROM(pData, so); 1406 } 1407 LOOP_LABEL(udp, so, so_next); 1408 } 1409 1410 } 1411 1370 if ( so->so_state & SS_NOFDREF 1371 && so->so_deleted == 1) 1372 { 1373 struct socket *son, *sop = NULL; 1374 QSOCKET_LOCK(udb); 1375 if (so->so_next != NULL) 1376 { 1377 if (so->so_next != &udb) 1378 SOCKET_LOCK(so->so_next); 1379 son = so->so_next; 1380 } 1381 if ( so->so_prev != &udb 1382 && so->so_prev != NULL) 1383 { 1384 SOCKET_LOCK(so->so_prev); 1385 sop = so->so_prev; 1386 } 1387 QSOCKET_UNLOCK(udb); 1388 remque(pData, so); 1389 NSOCK_DEC(); 1390 SOCKET_UNLOCK(so); 1391 SOCKET_LOCK_DESTROY(so); 1392 RTMemFree(so); 1393 so_next = son; 1394 if (sop != NULL) 1395 SOCKET_UNLOCK(sop); 1396 CONTINUE_NO_UNLOCK(udp); 1397 } 1398 #endif 1399 POLL_UDP_EVENTS(rc, error, so, &NetworkEvents); 1400 1401 LOG_NAT_SOCK(so, UDP, &NetworkEvents, readfds, writefds, xfds); 1402 1403 if (so->s != -1 && CHECK_FD_SET(so, NetworkEvents, readfds)) 1404 { 1405 SORECVFROM(pData, so); 1406 } 1407 LOOP_LABEL(udp, so, so_next); 1408 } 1409 1410 done: 1412 1411 #ifndef VBOX_WITH_SLIRP_MT 1413 1412 /*
Note:
See TracChangeset
for help on using the changeset viewer.