1 /* 2 * Mozilla Test 3 * Copyright (C) 2004 Filip Navara 4 */ 5 6 #include <winsock.h> 7 #include <stdio.h> 8 9 ULONG DbgPrint(PCH Format,...); 10 11 #undef DBG 12 #define DBG(x) \ 13 printf("%s:%i - %s", __FILE__, __LINE__, x); \ 14 DbgPrint("%s:%i - %s", __FILE__, __LINE__, x); 15 16 int SocketTest() 17 { 18 /* 19 * A socket pair is often used for interprocess communication, 20 * so we need to make sure neither socket is associated with 21 * the I/O completion port; otherwise it can't be used by a 22 * child process. 23 * 24 * The default implementation below cannot be used for NT 25 * because PR_Accept would have associated the I/O completion 26 * port with the listening and accepted sockets. 27 */ 28 SOCKET listenSock; 29 SOCKET osfd[2]; 30 struct sockaddr_in selfAddr, peerAddr; 31 int addrLen; 32 WORD wVersionRequested; 33 WSADATA wsaData; 34 int err; 35 36 /* 37 * Initialization. 38 */ 39 40 wVersionRequested = MAKEWORD( 2, 2 ); 41 42 DBG("Calling WSAStartup\n"); 43 err = WSAStartup( wVersionRequested, &wsaData ); 44 if ( err != 0 ) { 45 /* Tell the user that we could not find a usable */ 46 /* WinSock DLL. */ 47 DBG("WSAStartup failed\n"); 48 return 1; 49 } 50 51 /* Confirm that the WinSock DLL supports 2.2.*/ 52 /* Note that if the DLL supports versions greater */ 53 /* than 2.2 in addition to 2.2, it will still return */ 54 /* 2.2 in wVersion since that is the version we */ 55 /* requested. */ 56 57 if ( LOBYTE( wsaData.wVersion ) != 2 || 58 HIBYTE( wsaData.wVersion ) != 2 ) { 59 /* Tell the user that we could not find a usable */ 60 /* WinSock DLL. */ 61 DBG("WSAStartup version unacceptable\n"); 62 WSACleanup( ); 63 return 1; 64 } 65 66 /* The WinSock DLL is acceptable. Proceed. */ 67 68 DBG("Calling socket\n"); 69 osfd[0] = osfd[1] = INVALID_SOCKET; 70 listenSock = socket(AF_INET, SOCK_STREAM, 0); 71 if (listenSock == INVALID_SOCKET) { 72 DBG("socket failed\n"); 73 goto failed; 74 } 75 76 selfAddr.sin_family = AF_INET; 77 selfAddr.sin_port = 0; 78 selfAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* BugZilla: 35408 */ 79 addrLen = sizeof(selfAddr); 80 DBG("Calling bind\n"); 81 if (bind(listenSock, (struct sockaddr *) &selfAddr, 82 addrLen) == SOCKET_ERROR) { 83 DBG("bind failed\n"); 84 goto failed; 85 } 86 87 DBG("Calling getsockname\n"); 88 if (getsockname(listenSock, (struct sockaddr *) &selfAddr, 89 &addrLen) == SOCKET_ERROR) { 90 DBG("getsockname failed\n"); 91 goto failed; 92 } 93 94 DBG("Calling listen\n"); 95 if (listen(listenSock, 5) == SOCKET_ERROR) { 96 DBG("listen failed\n"); 97 goto failed; 98 } 99 100 DBG("Calling socket\n"); 101 osfd[0] = socket(AF_INET, SOCK_STREAM, 0); 102 if (osfd[0] == INVALID_SOCKET) { 103 DBG("socket failed\n"); 104 goto failed; 105 } 106 selfAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 107 108 /* 109 * Only a thread is used to do the connect and accept. 110 * I am relying on the fact that connect returns 111 * successfully as soon as the connect request is put 112 * into the listen queue (but before accept is called). 113 * This is the behavior of the BSD socket code. If 114 * connect does not return until accept is called, we 115 * will need to create another thread to call connect. 116 */ 117 DBG("Calling connect\n"); 118 if (connect(osfd[0], (struct sockaddr *) &selfAddr, 119 addrLen) == SOCKET_ERROR) { 120 DBG("connect failed\n"); 121 goto failed; 122 } 123 124 /* 125 * A malicious local process may connect to the listening 126 * socket, so we need to verify that the accepted connection 127 * is made from our own socket osfd[0]. 128 */ 129 DBG("Calling getsockname\n"); 130 if (getsockname(osfd[0], (struct sockaddr *) &selfAddr, 131 &addrLen) == SOCKET_ERROR) { 132 DBG("getsockname failed\n"); 133 goto failed; 134 } 135 136 DBG("Calling accept\n"); 137 osfd[1] = accept(listenSock, (struct sockaddr *) &peerAddr, &addrLen); 138 if (osfd[1] == INVALID_SOCKET) { 139 DBG("accept failed\n"); 140 goto failed; 141 } 142 if (peerAddr.sin_port != selfAddr.sin_port) { 143 /* the connection we accepted is not from osfd[0] */ 144 DBG("peerAddr.sin_port != selfAddr.sin_port\n"); 145 goto failed; 146 } 147 148 DBG("Hurray!\n"); 149 150 closesocket(listenSock); 151 152 closesocket(osfd[0]); 153 closesocket(osfd[1]); 154 155 WSACleanup(); 156 157 return 0; 158 159 failed: 160 if (listenSock != INVALID_SOCKET) { 161 closesocket(listenSock); 162 } 163 if (osfd[0] != INVALID_SOCKET) { 164 closesocket(osfd[0]); 165 } 166 if (osfd[1] != INVALID_SOCKET) { 167 closesocket(osfd[1]); 168 } 169 170 WSACleanup(); 171 172 return 1; 173 } 174 175 int VirtualTest() 176 { 177 DWORD dwErr; 178 SYSTEM_INFO si; 179 HANDLE hMap; 180 PBYTE pBufferStart; 181 PCHAR pszFileName = "test.txt"; 182 ULONG dwMaxSize = strlen(pszFileName); 183 184 DBG("Calling CreateFileMappingA\n"); 185 hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, 186 PAGE_READWRITE | SEC_RESERVE, 0, dwMaxSize, pszFileName); 187 if (!hMap) 188 { 189 DBG("CreateFileMappingA failed\n"); 190 return 1; 191 } 192 193 dwErr = GetLastError(); 194 DBG("Calling MapViewOfFile\n"); 195 pBufferStart = (BYTE *)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); 196 if (!pBufferStart) 197 { 198 DBG("MapViewOfFile failed\n"); 199 return 1; 200 } 201 202 GetSystemInfo(&si); 203 204 if (dwErr == ERROR_ALREADY_EXISTS) 205 { 206 DBG("MapViewOfFile returned ERROR_ALREADY_EXISTS\n"); 207 DBG("This really shouldn't happen, but it's not fatal.\n"); 208 UnmapViewOfFile(pBufferStart); 209 CloseHandle(hMap); 210 return 1; 211 } 212 else 213 { 214 DBG("Calling VirtualAlloc\n"); 215 if (!VirtualAlloc(pBufferStart, si.dwPageSize, MEM_COMMIT, PAGE_READWRITE)) 216 { 217 DBG("VirtualAlloc failed\n"); 218 UnmapViewOfFile(pBufferStart); 219 CloseHandle(hMap); 220 return 1; 221 } 222 } 223 224 DBG("Hurray!\n"); 225 226 UnmapViewOfFile(pBufferStart); 227 CloseHandle(hMap); 228 229 return 0; 230 } 231 232 int main(int argc, char **argv) 233 { 234 if (argc != 2) 235 { 236 printf("Usage: %s test_name\n\n", argv[0]); 237 printf("Valid test names:\n"); 238 printf("\tsocket\n"); 239 printf("\tvirtual\n"); 240 return 0; 241 } 242 243 if (!_stricmp(argv[1], "socket")) 244 return SocketTest(); 245 if (!_stricmp(argv[1], "virtual")) 246 return VirtualTest(); 247 248 printf("Test '%s' doesn't exist\n", argv[1]); 249 250 return 0; 251 } 252