net-snmp 5.7
|
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 <net-snmp/net-snmp-config.h> 00036 #include <net-snmp/types.h> 00037 #include <net-snmp/library/snmp_assert.h> 00038 #include <net-snmp/library/winpipe.h> 00039 #include <io.h> 00040 00041 static int InitUPDSocket(SOCKET *sock, struct sockaddr_in *socketaddress) 00042 { 00043 *sock = 0; 00044 memset(socketaddress, 0, sizeof(struct sockaddr_in)); 00045 00046 if( (*sock = socket(AF_INET, SOCK_DGRAM, 0)) == SOCKET_ERROR) 00047 { 00048 netsnmp_assert(GetLastError() != WSANOTINITIALISED); 00049 return -1; 00050 } 00051 socketaddress->sin_family = AF_INET; 00052 socketaddress->sin_addr.S_un.S_addr = htonl(INADDR_LOOPBACK); 00053 socketaddress->sin_port = 0; 00054 00055 if(bind(*sock, (struct sockaddr *) socketaddress, sizeof(struct sockaddr)) == SOCKET_ERROR) 00056 { 00057 return -1; 00058 } 00059 00060 return 0; 00061 } 00062 00063 static int ConnectUDPSocket(SOCKET *sock, struct sockaddr_in *socketaddress, SOCKET *remotesocket) 00064 { 00065 int size = sizeof(struct sockaddr); 00066 if (getsockname(*sock, (struct sockaddr *) socketaddress, &size) == SOCKET_ERROR) 00067 { 00068 return -1; 00069 } 00070 00071 if(size != sizeof(struct sockaddr)) 00072 { 00073 return -1; 00074 } 00075 00076 if (connect(*remotesocket, (struct sockaddr *) socketaddress, sizeof(struct sockaddr)) == SOCKET_ERROR) 00077 { 00078 return -1; 00079 } 00080 00081 return 0; 00082 } 00083 00084 static int TestUDPSend(SOCKET *sock, struct sockaddr_in *socketaddress) 00085 { 00086 unsigned short port = socketaddress->sin_port; 00087 00088 int bytessent = sendto(*sock, (char *) &port, sizeof(port), 0, NULL, 0); 00089 if(bytessent != sizeof(port)) 00090 { 00091 return -1; 00092 } 00093 00094 return 0; 00095 } 00096 00097 static int TestUDPReceive(SOCKET *sock, SOCKET *remotesocket, struct sockaddr_in *remotesocketaddress) 00098 { 00099 struct sockaddr_in recvfromaddress; 00100 unsigned short readbuffer[2]; 00101 int size = sizeof(struct sockaddr); 00102 00103 int bytesreceived = recvfrom(*sock,(char *) &readbuffer, sizeof(readbuffer), 0, (struct sockaddr *) &recvfromaddress, &size) ; 00104 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) 00105 { 00106 return -1; 00107 } 00108 00109 return 0; 00110 } 00111 00112 static void CloseUDPSocketPair(SOCKET *socketpair) 00113 { 00114 if(socketpair[0] != INVALID_SOCKET) 00115 { 00116 closesocket(socketpair[0]); 00117 } 00118 if(socketpair[1] != INVALID_SOCKET) 00119 { 00120 closesocket(socketpair[1]); 00121 } 00122 } 00123 00124 /* 00125 Windows unnamed pipe emulation, used to enable select() 00126 on a Windows machine for the CALLBACK (pipe-based) transport domain. 00127 */ 00128 int create_winpipe_transport(int *pipefds) 00129 { 00130 SOCKET socketpair[2]; 00131 struct sockaddr_in socketaddress[2]; 00132 00133 struct timeval waittime = {0, 200000}; 00134 fd_set readset; 00135 00136 if (InitUPDSocket(&socketpair[0], &socketaddress[0])) 00137 { 00138 CloseUDPSocketPair(socketpair); 00139 return -1; 00140 } 00141 if (InitUPDSocket(&socketpair[1], &socketaddress[1])) 00142 { 00143 CloseUDPSocketPair(socketpair); 00144 return -1; 00145 } 00146 00147 /* 00148 I have two UDP sockets - now lets connect them to each other. 00149 */ 00150 00151 if (ConnectUDPSocket(&socketpair[0], &socketaddress[0], &socketpair[1])) 00152 { 00153 CloseUDPSocketPair(socketpair); 00154 return -1; 00155 } 00156 if(ConnectUDPSocket(&socketpair[1], &socketaddress[1], &socketpair[0])) 00157 { 00158 CloseUDPSocketPair(socketpair); 00159 return -1; 00160 } 00161 00162 /* 00163 The two sockets are connected to each other, now lets test the connection 00164 by sending the own port number. 00165 */ 00166 if(TestUDPSend(&socketpair[0], &socketaddress[0])) 00167 { 00168 CloseUDPSocketPair(socketpair); 00169 return -1; 00170 } 00171 if(TestUDPSend(&socketpair[1], &socketaddress[1])) 00172 { 00173 CloseUDPSocketPair(socketpair); 00174 return -1; 00175 } 00176 00177 /* 00178 Port numbers sent, now lets select() on the socketpair and check that 00179 both messages got through 00180 */ 00181 FD_ZERO(&readset); 00182 FD_SET(socketpair[0], &readset); 00183 FD_SET(socketpair[1], &readset); 00184 00185 /* 00186 For some unknown reason the timeout setting in the select call does not have 00187 the desired effect, and for yet another unknown reason a Sleep(1) solves this 00188 problem. 00189 */ 00190 Sleep(1); 00191 if(select(0, &readset, NULL, NULL, &waittime) != 2 || !FD_ISSET(socketpair[0], &readset) || !FD_ISSET(socketpair[1], &readset)) 00192 { 00193 CloseUDPSocketPair(socketpair); 00194 return -1; 00195 } 00196 00197 /* 00198 Check if the packets I receive were really sent by me, and nobody else 00199 tried to sneak. 00200 */ 00201 if(TestUDPReceive(&socketpair[0], &socketpair[1], &socketaddress[1])) 00202 { 00203 CloseUDPSocketPair(socketpair); 00204 return -1; 00205 } 00206 if(TestUDPReceive(&socketpair[1], &socketpair[0], &socketaddress[0])) 00207 { 00208 CloseUDPSocketPair(socketpair); 00209 return -1; 00210 } 00211 00212 /* 00213 All sanity checks passed, I can return a "UDP pipe" 00214 */ 00215 pipefds[0] = (int) socketpair[0]; 00216 pipefds[1] = (int) socketpair[1]; 00217 00218 return 0; 00219 } 00220 00221 #endif /* WIN32 */ 00222