|
-
January 18th, 2008, 09:25 PM
#16
Re: Bind to a local port that is already in use
I also make the first experiment on Ubuntu Linux. The result is the same as on Windows Vista. I just share this information.
-
January 19th, 2008, 06:26 AM
#17
Re: Bind to a local port that is already in use
 Originally Posted by Cooker
I also make the first experiment on Ubuntu Linux. The result is the same as on Windows Vista. I just share this information.
Are you willing to share the source code so I can try it myself on gentoo?
-
January 19th, 2008, 04:55 PM
#18
Re: Bind to a local port that is already in use
Well, it's only security issue if you do TCP bind to ANY address. If you bind to a specific address, no other TCP server can "steal" that specific address+port.
 Originally Posted by MikeAThon
Yes, it is a security issue, but it's not unique to Windows. The issue arises in all BSD socket implementations that support the SO_REUSEADDR option. AFAIK, all implementations do so, inclusive of Linux, Sun etc.
Windows introduced the SO_EXCLUSIVEADDRUSE option to address this issue. See "Using SO_EXCLUSIVEADDRUSE" at http://msdn2.microsoft.com/en-us/library/ms740618.aspx . Here's a quote:
I am not certain if other socket implementations (i.e., other than that on Windows) also have the SO_EXCLUSIVEADDRUSE option.
Mike
-
January 19th, 2008, 05:32 PM
#19
Re: Bind to a local port that is already in use
 Originally Posted by j0nas
Well, it's only security issue if you do TCP bind to ANY address. If you bind to a specific address, no other TCP server can "steal" that specific address+port.
I don't think I agree. The entire purpose of the SO_EXCLUSIVEADDR option is to prevent a malicious program from "stealing" the addr+port. Without SO_EXCLUSIVEADDR, it's my understanding that a malicious program can do exactly that:
 Originally Posted by http://msdn2.microsoft.com/en-us/library/ms740618.aspx
... such reuse can be executed by malicious applications to disrupt the application
.
-
January 20th, 2008, 05:09 AM
#20
Re: Bind to a local port that is already in use
Still waiting on that source code. I'm either doing something wrong or my OS has some security mechanism such as SO_EXCLUSIVEADDR at kernel level or something.
-
January 20th, 2008, 06:17 AM
#21
Re: Bind to a local port that is already in use
 Originally Posted by ludakot
Are you willing to share the source code so I can try it myself on gentoo?
At first, You can run the following source code on Windows OS.
- UDP Receiver
Code:
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h> // for Winsock
#pragma comment(lib,"Ws2_32.lib") // for Winsock
void ErrExit(SOCKET fd, const char *format, ...);
int main(int argc, char *argv[])
{
WORD wVersionRequested = MAKEWORD(2, 2);
WSADATA wsaData;
int err = 0;
SOCKET sockfd = 0;
struct sockaddr_in local, remote;
int localport = 0;
int nrecvbytes = 0, fromlen = 0;
char recvbuf[128];
BOOL bOptVal = TRUE;
int bOptLen = sizeof(BOOL);
if (argc != 3) {
printf("Usage:\n");
printf(" program local_addr local_port\n");
printf("Description:\n");
printf(" Receive UDP packets from local_addr:local_port\n");
return -1;
}
localport = strtol(argv[2], NULL, 10);
// Initiate use of the Winsock DLL
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
// Could not find a usable WinSock DLL
printf("Couldn't find a usable WinSock DLL.\n");
return -1;
}
// Confirm that the WinSock DLL supports 2.2.
if (LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2)
ErrExit(0, "Bad winsock version.\n");
// Create a socket that is bound to a specific transport service provider
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == INVALID_SOCKET)
ErrExit(0, "Can't open a socket with error code %d\n", WSAGetLastError());
// Contain information about local IP address and port
local.sin_family = AF_INET;
local.sin_port = htons(localport);
local.sin_addr.s_addr = inet_addr(argv[1]);
memset(local.sin_zero, '\0', sizeof local.sin_zero);
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&bOptVal, bOptLen) == SOCKET_ERROR) {
printf("Can't set SO_REUSEADDR option.\n");
}
// Associate a local address with a socket
err = bind(sockfd, (struct sockaddr *)&local, sizeof local);
if (err == SOCKET_ERROR)
ErrExit(sockfd, "Can't bind to a local address and port with error code %d\n", WSAGetLastError());
memset(&remote, 0, sizeof remote);
memset(recvbuf, 0, sizeof recvbuf);
for (;;)
{
fromlen = sizeof remote;
nrecvbytes = recvfrom(sockfd, recvbuf, sizeof recvbuf, 0, (struct sockaddr *)&remote, &fromlen);
if (nrecvbytes == SOCKET_ERROR)
ErrExit(sockfd, "Can't receive messages with error code %d\n", WSAGetLastError());
recvbuf[nrecvbytes] = '\0';
printf("Message [%s] from %s:%d\n", recvbuf, inet_ntoa(remote.sin_addr), ntohs(remote.sin_port));
}
return 0;
}
void ErrExit(SOCKET fd, const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
if (fd != NULL)
closesocket(fd);
WSACleanup();
exit(1);
}
- UDP sender
Code:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
#include <winsock2.h> // for Winsock
#pragma comment(lib,"Ws2_32.lib") // for Winsock
void ErrExit(SOCKET fd, const char *format, ...);
void wait(int seconds);
int main(int argc, char *argv[])
{
WORD wVersionRequested = MAKEWORD(2, 2);
WSADATA wsaData;
int err = 0;
SOCKET sockfd = 0;
struct sockaddr_in local, remote;
int localport = 0, remoteport = 0, cycle = 0;
int nsentbytes = 0;
BOOL bOptVal = TRUE;
int bOptLen = sizeof(BOOL);
if (argc != 7) {
printf("Usage:\n");
printf(" program local_addr local_port cycle message remote_addr remote_port\n");
printf("Description:\n");
printf(" Send a UDP packet to remote_addr:remote_port from local_addr:local_port every cycle seconds\n");
return -1;
}
localport = strtol(argv[2], NULL, 10);
remoteport = strtol(argv[6], NULL, 10);
cycle = strtol(argv[3], NULL, 10);
// Initiate use of the Winsock DLL
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
// Could not find a usable WinSock DLL
printf("Couldn't find a usable WinSock DLL.\n");
return -1;
}
// Confirm that the WinSock DLL supports 2.2.
if (LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2)
ErrExit(0, "Bad winsock version.\n");
// Create a socket that is bound to a specific transport service provider
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == INVALID_SOCKET)
ErrExit(0, "Can't open a socket with error code %d\n", WSAGetLastError());
// Contain information about local IP address and port
local.sin_family = AF_INET;
local.sin_port = htons(localport);
local.sin_addr.s_addr = inet_addr(argv[1]);
memset(local.sin_zero, '\0', sizeof local.sin_zero);
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&bOptVal, bOptLen) == SOCKET_ERROR) {
printf("Can't set SO_REUSEADDR option.\n");
}
// Associate a local address with a socket
err = bind(sockfd, (struct sockaddr *)&local, sizeof local);
if (err == SOCKET_ERROR)
ErrExit(sockfd, "Can't bind to a local address and port with error code %d\n", WSAGetLastError());
// Contain information about remote IP address and port
remote.sin_family = AF_INET;
remote.sin_port = htons(remoteport);
remote.sin_addr.s_addr = inet_addr(argv[5]);
memset(remote.sin_zero, '\0', sizeof remote.sin_zero);
printf("==> Press any key to quit the program. <==\n");
for (;;)
{
if (kbhit())
break;
nsentbytes = sendto(sockfd, argv[4], strlen(argv[4]), 0, (struct sockaddr *)&remote, sizeof remote);
if (nsentbytes == SOCKET_ERROR)
ErrExit(sockfd, "Can't send meesages to remote address with error code%d\n", WSAGetLastError());
wait(cycle);
}
system("pause");
return 0;
}
void ErrExit(SOCKET fd, const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
if (fd != NULL)
closesocket(fd);
WSACleanup();
system("pause");
exit(1);
}
void wait(int seconds)
{
clock_t endwait;
endwait = clock () + seconds * CLK_TCK ;
while (clock() < endwait) {}
}
The source code which runs on Ubuntu Linux isn't in my current PC. I will post later.
-
January 20th, 2008, 06:25 AM
#22
Re: Bind to a local port that is already in use
 Originally Posted by ludakot
Still waiting on that source code. I'm either doing something wrong or my OS has some security mechanism such as SO_EXCLUSIVEADDR at kernel level or something.
This SO_EXCLUSIVEADDR option is available on Microsoft Windows. On a Linux, all the socket information is in the man page for socket in section 7. You can type "man 7 socket" to get all these goodies and find if there exists SO_EXCLUSIVEADDRUSE option. That's my way.
Last edited by Cooker; January 20th, 2008 at 06:38 AM.
-
January 20th, 2008, 08:25 PM
#23
Re: Bind to a local port that is already in use
 Originally Posted by ludakot
Are you willing to share the source code so I can try it myself on gentoo?
Linux version.
The source code of UDP sender
Code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define CLK_TCK CLOCKS_PER_SEC
void ErrExit(int fd, const char *format, ...);
void wait(int seconds);
int main(int argc, char *argv[])
{
int err = 0;
int sockfd = 0;
struct sockaddr_in local, remote;
int localport = 0, remoteport = 0, cycle = 0;
int nsentbytes = 0;
int optval;
if (argc != 7) {
printf("Usage:\n");
printf(" program local_addr local_port cycle message remote_addr remote_port\n");
printf("Description:\n");
printf(" Send a UDP packet to remote_addr:remote_port from local_addr:local_port every cycle seconds\n");
return -1;
}
localport = strtol(argv[2], NULL, 10);
remoteport = strtol(argv[6], NULL, 10);
cycle = strtol(argv[3], NULL, 10);
// Create a socket that is bound to a specific transport service provider
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == INVALID_SOCKET)
ErrExit(0, "Can't open a socket with error %s\n", strerror(errno));
// Contain information about local IP address and port
local.sin_family = AF_INET;
local.sin_port = htons(localport);
local.sin_addr.s_addr = inet_addr(argv[1]);
memset(local.sin_zero, '\0', sizeof local.sin_zero);
optval = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof optval) == SOCKET_ERROR) {
printf("Can't set SO_REUSEADDR option.\n");
}
// Associate a local address with a socket
err = bind(sockfd, (struct sockaddr *)&local, sizeof local);
if (err == SOCKET_ERROR)
ErrExit(sockfd, "Can't bind to a local address and port with error %s\n", strerror(errno));
// Contain information about remote IP address and port
remote.sin_family = AF_INET;
remote.sin_port = htons(remoteport);
remote.sin_addr.s_addr = inet_addr(argv[5]);
memset(remote.sin_zero, '\0', sizeof remote.sin_zero);
for (;;)
{
nsentbytes = sendto(sockfd, argv[4], strlen(argv[4]), 0, (struct sockaddr *)&remote, sizeof remote);
if (nsentbytes == SOCKET_ERROR)
ErrExit(sockfd, "Can't send meesages to remote address with error %s\n", strerror(errno));
wait(cycle);
}
return 0;
}
void ErrExit(int fd, const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
if (fd != NULL)
close(fd);
exit(1);
}
void wait(int seconds)
{
clock_t endwait;
endwait = clock () + seconds * CLK_TCK ;
while (clock() < endwait) {}
}
I use 'tcpdump' to check UDP message at remote PC side.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|