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