Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 30 Aug 2000 08:58:45 -0700 (PDT)
From:      agifford@infowest.com
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   kern/20946: UDP use within a jailed environment mistakenly uses the primary interface IP in certain situations
Message-ID:  <20000830155845.D337E37B42C@hub.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         20946
>Category:       kern
>Synopsis:       UDP use within a jailed environment mistakenly uses the primary interface IP in certain situations
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Aug 30 09:00:03 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator:     Aaron Gifford
>Release:        4.1-STABLE as of 15 Aug. 2000
>Organization:
>Environment:
FreeBSD my.host.name 4.1-STABLE FreeBSD 4.1-STABLE #0: Tue Aug 15 17:10:27 MDT 2000     me@my.host.name:/usr/src/sys/compile/LOCAL  i386
>Description:
When using the FreeBSD jail feature, any program that uses UDP (SOCK_DGRAM) to communicate can use the primary interface/host IP instead of the jail IP by omitting the bind() step after using socket() to create the SOCK_DGRAM socket, then proceeding directly to connect() to connect the datagram socket to a remote IP.
>How-To-Repeat:
/*

(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", errno, strerror(errno));
    return;
  }
  printf("Socket name is IP address %s port %d", 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", errno, strerror(errno));
    return;
  }
  if ((bsock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
    printf("socket(): %d %s", 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", errno, strerror(errno));
    return;
  }

  if (connect(asock, (struct sockaddr *)(&remote), sizeof(struct sockaddr_in)) != 0) {
    printf("connect(): %d %s", errno, strerror(errno));
    return;
  }
  if (connect(bsock, (struct sockaddr *)(&remote), sizeof(struct sockaddr_in)) != 0) {
    printf("connect(): %d %s", errno, strerror(errno));
    return;
  }

  printf("The following socket (asock) has NOT been bound to a local address using");
  printf("bind() and so if in a jail this socket will probably show the host`s main");
  printf("IP address instead of the jail IP address:");
  showsockname(asock);
  printf("The following socket (bsock) HAS been bound to a local address (INADDR_ANY)");
  printf("using bind() and so inside of a jail, this should show the proper jail IP");
  printf("address as expected:");
  showsockname(bsock);
}


>Fix:


>Release-Note:
>Audit-Trail:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20000830155845.D337E37B42C>