<br><font size=2 face="sans-serif">Hi,</font>
<br>
<br><font size=2 face="sans-serif">I'm using LXC to run Perl scripts that
generate network traffic, using the Net::RawIP package.</font>
<br><font size=2 face="sans-serif">The scripts work perfectly well on a
"real" host, but fail inside an LXC container.</font>
<br>
<br><font size=2 face="sans-serif">After a few hours of testing/debuging,
the origin of the problem is that some basic ioctl calls on socket fails.</font>
<br>
<br><font size=2 face="sans-serif">Net::RawIP relies on SIOCGIFADDR et
SIOCGIFHWADDR to get the IP and MAC addresses of the network interface.</font>
<br>
<br><font size=2 face="sans-serif">My container has 2 interfaces : 1 macvlan
(normally used to generate traffic) and 1 bridged (to dialogue with the
host and the other containers).</font>
<br>
<br><font size=2 face="sans-serif">In the container, these ioctl calls
fail with an "Invalid argument" on every interface, including
the loopback.</font>
<br>
<br>
<br><font size=2 face="sans-serif">I've extracted the failing code from
Net::RawIP to have a simple test program (code at the end of the message).</font>
<br><font size=2 face="sans-serif">It just creates a socket and do the
2 ioctl calls on it.</font>
<br>
<br><font size=2 face="sans-serif">My LXC configuration is based on the
article of Stéphane Graber (http://www.stgraber.org/category/lxc):</font>
<br>
<br><font size=2 face="sans-serif">- host : Ubuntu 9.10 Desktop (2.6.31
kernel)</font>
<br><font size=2 face="sans-serif">- containers : Ubuntu 8.04 </font>
<br>
<br>
<br><font size=2 face="sans-serif">I really don't know what's wrong, because
ifconfig relies on the same basic call to get interface information...</font>
<br>
<br><font size=2 face="sans-serif">If anyone has any idea, I would greatly
appreciate it :-)</font>
<br>
<br>
<br>
<br><font size=2 face="sans-serif">Stéphane.</font>
<br>
<br>
<br>
<br><font size=2 face="sans-serif">------------------</font>
<br><font size=2 face="Courier New">#include <stdio.h></font>
<br><font size=2 face="Courier New">#include <string.h></font>
<br><font size=2 face="Courier New">#include <stdlib.h></font>
<br><font size=2 face="Courier New">#include <netinet/in.h></font>
<br><font size=2 face="Courier New">#include <sys/types.h></font>
<br><font size=2 face="Courier New">#include <sys/ioctl.h></font>
<br><font size=2 face="Courier New">#include <netinet/if_ether.h></font>
<br><font size=2 face="Courier New">#include <net/if.h></font>
<br><font size=2 face="Courier New">#include <errno.h></font>
<br>
<br>
<br><font size=2 face="Courier New">int main(int argc, char* argv[])</font>
<br><font size=2 face="Courier New">{</font>
<br><font size=2 face="Courier New"> unsigned int ip;</font>
<br><font size=2 face="Courier New"> unsigned char mac[256];</font>
<br><font size=2 face="Courier New"> int fd; </font>
<br><font size=2 face="Courier New"> </font>
<br><font size=2 face="Courier New"> if(argc!=2) {</font>
<br><font size=2 face="Courier New"> printf("Usage
: test <device>\n");</font>
<br><font size=2 face="Courier New"> return -1;</font>
<br><font size=2 face="Courier New"> }</font>
<br><font size=2 face="Courier New"> fd = tap(argv[1],&ip,mac);</font>
<br><font size=2 face="Courier New"> </font>
<br><font size=2 face="Courier New"> if(fd>0) {</font>
<br><font size=2 face="Courier New"> printf("Got
IP (%i) and MAC (%s)\n",ip,mac);</font>
<br><font size=2 face="Courier New"> }</font>
<br>
<br><font size=2 face="Courier New">}</font>
<br>
<br><font size=2 face="Courier New">/* Code extracted from Net::RawIP */</font>
<br><font size=2 face="Courier New">int tap(char *dev,unsigned int *my_eth_ip,unsigned
char *my_eth_mac)</font>
<br><font size=2 face="Courier New">{</font>
<br><font size=2 face="Courier New"> </font>
<br><font size=2 face="Courier New"> int fd,v,s;</font>
<br><font size=2 face="Courier New"> struct ifreq ifr;</font>
<br><font size=2 face="Courier New"> </font>
<br><font size=2 face="Courier New"> memset(&ifr,0,sizeof(struct
ifreq));</font>
<br><font size=2 face="Courier New"> (void)strcpy(ifr.ifr_name,
dev);</font>
<br>
<br><font size=2 face="Courier New"> printf("Getting IP
/ MAC info for device (%s)\n",dev);</font>
<br><font size=2 face="Courier New"> if ((fd = socket(AF_INET,
SOCK_PACKET, htons(ETH_P_ALL))) < 0) {</font>
<br><font size=2 face="Courier New"> printf("Socket
creation failed with code (%d) : %s\n",errno, strerror(errno));</font>
<br><font size=2 face="Courier New"> return -1;</font>
<br><font size=2 face="Courier New"> }</font>
<br>
<br><font size=2 face="Courier New"> if (ioctl(fd, SIOCGIFADDR,
&ifr) < 0) {</font>
<br><font size=2 face="Courier New"> close(fd);</font>
<br><font size=2 face="Courier New"> printf("SIOCGIFADDR
failed with code (%d) : %s\n",errno, strerror(errno));</font>
<br><font size=2 face="Courier New"> return
-1;</font>
<br><font size=2 face="Courier New"> }</font>
<br><font size=2 face="Courier New"> </font>
<br><font size=2 face="Courier New"> *my_eth_ip = ntohl(((struct
sockaddr_in*)&ifr.ifr_addr)->sin_addr.s_addr);</font>
<br>
<br><font size=2 face="Courier New"> if (ioctl(fd, SIOCGIFHWADDR,
&ifr) < 0) {</font>
<br><font size=2 face="Courier New"> close(fd);</font>
<br><font size=2 face="Courier New"> printf("SIOCGIFHWADDR
failed with code (%d) : %s\n",errno, strerror(errno));</font>
<br><font size=2 face="Courier New"> return
-1;</font>
<br><font size=2 face="Courier New"> }</font>
<br>
<br><font size=2 face="Courier New"> memcpy(my_eth_mac, ifr.ifr_hwaddr.sa_data,ETH_ALEN);</font>
<br>
<br><font size=2 face="Courier New"> return fd;</font>
<br><font size=2 face="Courier New">}</font>
<br>
<br><font size=2 face="sans-serif">------------</font>