Date: Tue, 29 Aug 2000 10:48:00 -0600 (MDT) From: "Aaron Gifford" <agifford@infowest.com> To: <questions@freebsd.org>, <freebsd-net@freebsd.org> Subject: Bug in jail with UDP??? Message-ID: <20000829164800.D4D4A20F08@ns1.infowest.com>
next in thread | raw e-mail | index | archive | help
/* (The body of this email message is a C program that demonstrates the bug in the FreeBSD jail system when using UDP. Please save the body of this message with a file name like udpjailtest.c or some other appropriate name if you wish to test this demo.) Hello, While setting up a FreeBSD 4.1-STABLE (as of 15 Aug 2000) jail for running the Jabber instant messaging system inside, including an ICQ transport/gateway, I discovered the following unusual or at least unexpected (by me) behavior of FreeBSD's jail: A UDP datagram socket that uses connect() without first using bind() will end up using the primary interface IP address for the connection instead of the expected jail IP address (which in this case was an alias IP address on that same interface). I wrote this little C program (this message IS the C test program) to demonstrate this. Compile this program, then create an alias IP address, then run this program within a jail using that alias IP address; Assuming a jail environment in /path/to/jail/env and assuming an etheret interface of fxp0 and a primary IP address on that interface of 10.50.23.200/255.255.255.0: cc -o /path/to/jail/env/udpjailtest udpjailtest.c ifconfig fxp0 inet 10.50.23.233 netmask 255.255.255.255 alias jail /path/to/jail/env jail.host.name 10.50.23.233 udpjailtest Then you would see something like: The following socket (asock) has NOT been bound to a local address using bind() and so if in a jail this socket will probably show the host's main IP address instead of the jail IP address: Socket name is IP address 10.50.23.200 port 50189 The following socket (bsock) HAS been bound to a local address (INADDR_ANY) using bind() and so inside of a jail, this should show the proper jail IP address as expected: Socket name is IP address 10.50.23.233 port 49933 Why is this so? Of course I would expect any program worth its salt to bind() the datagram socket before connect()ing to a remote address, but there are cases where programs do not bother with that step. The case in point being the icqtransport program for the Jabber IM system. Can anyone enlighten me as to whether this is a bug in the jail() system, or a feature? Thanks! Aaron out. */ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <errno.h> #include <string.h> /* I use a.root-servers.net, but any remote IP will do */ #define REMOTE_NAMESERVER_IP "198.41.0.4" void showsockname(int sock) { socklen_t len = sizeof(struct sockaddr_in); struct sockaddr_in addr; if (getsockname(sock, (struct sockaddr *)&addr, &len) != 0) { printf("getsockname(): %d %s\n", errno, strerror(errno)); return; } printf("Socket name is IP address %s port %d\n", inet_ntoa(addr.sin_addr), addr.sin_port); } main() { struct sockaddr_in local; struct sockaddr_in remote; int asock, bsock; unsigned long ip; if ((asock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { printf("socket(): %d %s\n", errno, strerror(errno)); return; } if ((bsock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { printf("socket(): %d %s\n", errno, strerror(errno)); return; } bzero(&local, sizeof(struct sockaddr_in)); bzero(&remote, sizeof(struct sockaddr_in)); local.sin_family = remote.sin_family = AF_INET; local.sin_addr.s_addr = INADDR_ANY; remote.sin_addr.s_addr = inet_addr(REMOTE_NAMESERVER_IP); local.sin_port = htons(0); remote.sin_port = htons(53); /* Only bsock gets boundto INADDR_ANY */ if (bind(bsock,(struct sockaddr *)&local, sizeof(struct sockaddr_in)) != 0) { printf("bind(): %d %s\n", errno, strerror(errno)); return; } if (connect(asock, (struct sockaddr *)(&remote), sizeof(struct sockaddr_in)) != 0) { printf("connect(): %d %s\n", errno, strerror(errno)); return; } if (connect(bsock, (struct sockaddr *)(&remote), sizeof(struct sockaddr_in)) != 0) { printf("connect(): %d %s\n", errno, strerror(errno)); return; } printf("The following socket (asock) has NOT been bound to a local address using\n"); printf("bind() and so if in a jail this socket will probably show the host's main\n"); printf("IP address instead of the jail IP address:\n"); showsockname(asock); printf("\nThe following socket (bsock) HAS been bound to a local address (INADDR_ANY)\n"); printf("using bind() and so inside of a jail, this should show the proper jail IP\n"); printf("address as expected:\n"); showsockname(bsock); } To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-questions" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20000829164800.D4D4A20F08>