Re: [OT] ipv4: how to choose src ip?

Richard B. Johnson (root@chaos.analogic.com)
Fri, 6 Dec 2002 10:13:23 -0500 (EST)


On Thu, 5 Dec 2002, Tomas Szepe wrote about choosing a source ip.
If you are writing the application, it is in fact quite trivial.
I found that, although no networking or 'sockets' programming
books I have read ever bind a client's socket to an address, only
a server's, it can be done as the included code shows. It seems
to work fine (although aparently not well documented). I'm not
sure it's 'legal', but it works on Linux-2.4.18 and SunOS 5.5.1.
It does not work with windsock, but who cares.

#ifdef _MSC_VER
#define WINDOWS
#else
#define LINUX
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <time.h>

#ifdef LINUX
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#endif
#ifdef WINDOWS
#include <winsock.h>
#include <io.h>
typedef unsigned long off_t;
#define ENONET 0x100
#define sleep(x) Sleep((x) * 1000L)
#endif

#define FAIL -1
#define ERRORS(s) { \
fprintf(stderr, "Error on line %d, file, %s, call %s (%s)\n", \
__LINE__,__FILE__,(s),strerror(errno)); \
}

int main(int argc, char *argv[]) {
struct sockaddr_in dst, src;
struct hostent *hp;
int s, on;

#ifdef WINDOWS
WSADATA wsadata;
(void)WSAStartup(MAKEWORD(2,0), &wsadata);
#endif

if(argc < 3) {
printf("Usage:\n %s source destination\n", argv[0]);
exit(EXIT_FAILURE);
}
memset(&src, 0x00, sizeof(src));
memset(&dst, 0x00, sizeof(dst));
if((hp = gethostbyname(argv[1])) == NULL)
{
errno = ENONET;
ERRORS("gethostbyname");
}
src.sin_addr.s_addr = *((unsigned long *) *hp->h_addr_list);
src.sin_family = AF_INET;
if((hp = gethostbyname(argv[2])) == NULL) {
errno = ENONET;
ERRORS("gethostbyname");
}
dst.sin_addr.s_addr = *((unsigned long *) *hp->h_addr_list);
dst.sin_family = AF_INET;
dst.sin_port = htons(IPPORT_TELNET);
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == FAIL)
ERRORS("socket");
on = 1;
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == FAIL)
ERRORS("setsockopt");
if(bind(s, &src, sizeof(src)) == FAIL)
ERRORS("bind");
if((connect(s, (struct sockaddr *) &dst, (int) sizeof(dst))) == FAIL)
ERRORS("connect");
fprintf(stdout,"Connected to %s, waiting...", argv[2]);
fflush(stdout);
pause();
(void)close(s);
return 0;
}

Cheers,
Dick Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
Why is the government concerned about the lunatic fringe? Think about it.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/