net-snmp
5.4.1
|
00001 /* 00002 Copyright (c) Fabasoft R&D Software GmbH & Co KG, 2003 00003 oss@fabasoft.com 00004 Author: Bernhard Penz <bernhard.penz@fabasoft.com> 00005 00006 Redistribution and use in source and binary forms, with or without 00007 modification, are permitted provided that the following conditions are met: 00008 00009 * Redistributions of source code must retain the above copyright notice, 00010 this list of conditions and the following disclaimer. 00011 00012 * Redistributions in binary form must reproduce the above copyright 00013 notice, this list of conditions and the following disclaimer in the 00014 documentation and/or other materials provided with the distribution. 00015 00016 * The name of Fabasoft R&D Software GmbH & Co KG or any of its subsidiaries, 00017 brand or product names may not be used to endorse or promote products 00018 derived from this software without specific prior written permission. 00019 00020 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY 00021 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00022 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00023 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE 00024 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00025 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00026 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 00027 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 00028 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 00029 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 00030 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00031 */ 00032 00033 #ifdef WIN32 00034 00035 #include <io.h> 00036 #include <winsock.h> 00037 00038 static int InitUPDSocket(SOCKET *sock, struct sockaddr_in *socketaddress) 00039 { 00040 *sock = 0; 00041 memset(socketaddress, 0, sizeof(struct sockaddr_in)); 00042 00043 if( (*sock = socket(AF_INET, SOCK_DGRAM, 0)) == SOCKET_ERROR) 00044 { 00045 return -1; 00046 } 00047 socketaddress->sin_family = AF_INET; 00048 socketaddress->sin_addr.S_un.S_addr = htonl(INADDR_LOOPBACK); 00049 socketaddress->sin_port = 0; 00050 00051 if(bind(*sock, (struct sockaddr *) socketaddress, sizeof(struct sockaddr)) == SOCKET_ERROR) 00052 { 00053 return -1; 00054 } 00055 00056 return 0; 00057 } 00058 00059 static int ConnectUDPSocket(SOCKET *sock, struct sockaddr_in *socketaddress, SOCKET *remotesocket) 00060 { 00061 int size = sizeof(struct sockaddr); 00062 if (getsockname(*sock, (struct sockaddr *) socketaddress, &size) == SOCKET_ERROR) 00063 { 00064 return -1; 00065 } 00066 00067 if(size != sizeof(struct sockaddr)) 00068 { 00069 return -1; 00070 } 00071 00072 if (connect(*remotesocket, (struct sockaddr *) socketaddress, sizeof(struct sockaddr)) == SOCKET_ERROR) 00073 { 00074 return -1; 00075 } 00076 00077 return 0; 00078 } 00079 00080 static int TestUDPSend(SOCKET *sock, struct sockaddr_in *socketaddress) 00081 { 00082 unsigned short port = socketaddress->sin_port; 00083 int size = sizeof(struct sockaddr); 00084 00085 int bytessent = send(*sock, (char *) &port, sizeof(port), 0); 00086 if(bytessent != sizeof(port)) 00087 { 00088 return -1; 00089 } 00090 00091 return 0; 00092 } 00093 00094 static int TestUDPReceive(SOCKET *sock, SOCKET *remotesocket, struct sockaddr_in *remotesocketaddress) 00095 { 00096 struct sockaddr_in recvfromaddress; 00097 unsigned short readbuffer[2]; 00098 int size = sizeof(struct sockaddr); 00099 00100 int bytesreceived = recvfrom(*sock,(char *) &readbuffer, sizeof(readbuffer), 0, (struct sockaddr *) &recvfromaddress, &size) ; 00101 if(bytesreceived != sizeof(unsigned short) || size != sizeof(struct sockaddr) || readbuffer[0] != (unsigned short) remotesocketaddress->sin_port || recvfromaddress.sin_family != remotesocketaddress->sin_family || recvfromaddress.sin_addr.S_un.S_addr != remotesocketaddress->sin_addr.S_un.S_addr || recvfromaddress.sin_port != remotesocketaddress->sin_port) 00102 { 00103 return -1; 00104 } 00105 00106 return 0; 00107 } 00108 00109 static void CloseUDPSocketPair(SOCKET *socketpair) 00110 { 00111 int i = WSAGetLastError(); 00112 00113 if(socketpair[0] != INVALID_SOCKET) 00114 { 00115 closesocket(socketpair[0]); 00116 } 00117 if(socketpair[1] != INVALID_SOCKET) 00118 { 00119 closesocket(socketpair[1]); 00120 } 00121 } 00122 00123 /* 00124 Windows unnamed pipe emulation, used to enable select() 00125 on a Windows machine for the CALLBACK (pipe-based) transport domain. 00126 */ 00127 int create_winpipe_transport(int *pipefds) 00128 { 00129 SOCKET socketpair[2]; 00130 struct sockaddr_in socketaddress[2]; 00131 00132 struct timeval waittime = {0, 200000}; 00133 fd_set readset; 00134 00135 if (InitUPDSocket(&socketpair[0], &socketaddress[0])) 00136 { 00137 CloseUDPSocketPair(socketpair); 00138 return -1; 00139 } 00140 if (InitUPDSocket(&socketpair[1], &socketaddress[1])) 00141 { 00142 CloseUDPSocketPair(socketpair); 00143 return -1; 00144 } 00145 00146 /* 00147 I have two UDP sockets - now lets connect them to each other. 00148 */ 00149 00150 if (ConnectUDPSocket(&socketpair[0], &socketaddress[0], &socketpair[1])) 00151 { 00152 CloseUDPSocketPair(socketpair); 00153 return -1; 00154 } 00155 if(ConnectUDPSocket(&socketpair[1], &socketaddress[1], &socketpair[0])) 00156 { 00157 CloseUDPSocketPair(socketpair); 00158 return -1; 00159 } 00160 00161 /* 00162 The two sockets are connected to each other, now lets test the connection 00163 by sending the own port number. 00164 */ 00165 if(TestUDPSend(&socketpair[0], &socketaddress[0])) 00166 { 00167 CloseUDPSocketPair(socketpair); 00168 return -1; 00169 } 00170 if(TestUDPSend(&socketpair[1], &socketaddress[1])) 00171 { 00172 CloseUDPSocketPair(socketpair); 00173 return -1; 00174 } 00175 00176 /* 00177 Port numbers sent, now lets select() on the socketpair and check that 00178 both messages got through 00179 */ 00180 FD_ZERO(&readset); 00181 FD_SET(socketpair[0], &readset); 00182 FD_SET(socketpair[1], &readset); 00183 00184 /* 00185 For some unknown reason the timeout setting in the select call does not have 00186 the desired effect, and for yet another unknown reason a Sleep(1) solves this 00187 problem. 00188 */ 00189 Sleep(1); 00190 if(select(0, &readset, NULL, NULL, &waittime) != 2 || !FD_ISSET(socketpair[0], &readset) || !FD_ISSET(socketpair[1], &readset)) 00191 { 00192 CloseUDPSocketPair(socketpair); 00193 return -1; 00194 } 00195 00196 /* 00197 Check if the packets I receive were really sent by me, and nobody else 00198 tried to sneak. 00199 */ 00200 if(TestUDPReceive(&socketpair[0], &socketpair[1], &socketaddress[1])) 00201 { 00202 CloseUDPSocketPair(socketpair); 00203 return -1; 00204 } 00205 if(TestUDPReceive(&socketpair[1], &socketpair[0], &socketaddress[0])) 00206 { 00207 CloseUDPSocketPair(socketpair); 00208 return -1; 00209 } 00210 00211 /* 00212 All sanity checks passed, I can return a "UDP pipe" 00213 */ 00214 pipefds[0] = (int) socketpair[0]; 00215 pipefds[1] = (int) socketpair[1]; 00216 00217 return 0; 00218 } 00219 00220 #endif /* WIN32 */ 00221