Skip to content

VMNetworkInterface: define IFF_RUNNING if the system does not - #75

Merged
guillerodriguez merged 1 commit into
ingelabs:masterfrom
duncanmcqueen:fix-iff-running
Oct 16, 2026
Merged

guillerodriguez merged 1 commit into
ingelabs:masterfrom
duncanmcqueen:fix-iff-running

Conversation

@duncanmcqueen

@duncanmcqueen duncanmcqueen commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Split from #60.

Problem and fix

Haiku does not define IFF_RUNNING in <net/if.h>. Thus java_net_VMNetworkInterface.c does not compile, and the build of master stops on Haiku.

Now the file defines IFF_RUNNING as 0 when the system does not define it. Then NetworkInterface.isUp() tests IFF_UP only.

Haiku's IFF_LINK is not a replacement for IFF_RUNNING: it tells if the hardware has a link, also when the interface is down (see the tests in the comments).

Note: #60 defined IFF_RUNNING as 0x40. On Haiku, 0x40 is IFF_NOARP, so that value was not correct.

How to reproduce

On Haiku, configure and build master:

../configure --enable-jni ...
make

To test the result, run this program (it also needs #73 and #74 to build and load on Haiku):

javac NetBasics.java
java NetBasics
NetBasics.java
import java.io.*;
import java.net.*;
import java.util.*;

/**
 * Basic network operations: resolve a host name, list the network
 * interfaces, and connect a socket to a server socket on the loopback
 * interface. Each one loads Classpath's java-net JNI library.
 */
public class NetBasics
{
  public static void main(String[] args) throws Exception
  {
    try
      {
        System.out.println("resolve: " + InetAddress.getByName("localhost"));
        for (Enumeration<NetworkInterface> e =
               NetworkInterface.getNetworkInterfaces(); e.hasMoreElements(); )
          {
            NetworkInterface i = e.nextElement();
            System.out.println("interface: " + i.getName() + " up="
                               + i.isUp() + " loopback=" + i.isLoopback());
          }
        ServerSocket ss = new ServerSocket(0, 1, InetAddress.getByName("127.0.0.1"));
        Socket c = new Socket("127.0.0.1", ss.getLocalPort());
        Socket s = ss.accept();
        c.getOutputStream().write(42);
        int b = s.getInputStream().read();
        System.out.println((b == 42 ? "PASS" : "FAIL") + ": socket byte = " + b);
        System.exit(b == 42 ? 0 : 1);
      }
    catch (Throwable t)
      {
        System.out.println("FAIL: " + t);
        t.printStackTrace(System.out);
        System.exit(1);
      }
  }
}

Results

Haiku R1/beta6 x86_64 (hrev59866), javac from OpenJDK 8, Kaffe 1.1.10-pre. I ran autoreconf on Linux (autoconf 2.73, automake 1.19) and built on Haiku out of tree with --enable-jni --disable-examples --disable-plugin --disable-gjdoc --disable-gtk-peer --disable-gconf-peer --disable-alsa --disable-dssi.

Before (master):
../../../../src/native/jni/java-net/java_net_VMNetworkInterface.c:318:33: error: 'IFF_RUNNING' undeclared (first use in this function)
make[3]: *** [Makefile:587: java_net_VMNetworkInterface.lo] Error 1

After (master with this pull request, #73, #74, and #62, #64 and #65 for Kaffe):
resolve: localhost/127.0.0.1
interface: /dev/net/ipro1000/0 up=true loopback=false
interface: loop up=true loopback=true
PASS: socket byte = 42

Platforms

Specific to systems that do not define IFF_RUNNING. Haiku is the system that I know. Linux, macOS and the BSDs define IFF_RUNNING, so the new lines have no effect there.

AI assistance

An AI model (Claude Code, by Anthropic) wrote this change, the test and this text. The repository owner directed the work and checked the results. Please review it as you review other contributions.

🤖 Generated with Claude Code

@guillerodriguez

Copy link
Copy Markdown
Contributor

I am not sure defining IFF_RUNNING as IFF_LINK is correct. Due to the way the IFF_UP and IFF_RUNNING flags are checked in the current implementation, isUp() will return true if either flag is set (instead of returning true if both are set). I believe this is actually a bug, but the impact is limited on existing platforms:

  • On Linux, IFF_RUNNING is never set if IFF_UP is not set, so the test is basically equivalent to checking IFF_UP alone. The result is that isUp() returns true if the interface is administratively up, regardless of whether it is "running".
  • On BSDs and macOS, IFF_RUNNING means "the driver has set up its resources". Drivers normally set it when the interface comes up and clear it when it goes down. "Running" without "up" can at most happen briefly while the interface is changing state. So in practice this is also mostly equivalent to testing IFF_UP alone.

But on Haiku, if I am not wrong (I haven't tested this), IFF_LINK means the hardware has a link (cable connected), regardless of whether the administrator brought the interface up (so, equivalent to Linux's IFF_LOWER_UP). So, it can happen in practice that an interface is down but has IFF_LINK set. With the proposed fix, isUp() would report true for this case, which is wrong.

I think a safe alternative here for Haiku would be to test IFF_UP only, which is equivalent in practice to the current behaviour on other platforms. I suggest doing this now as a short-term fix for Haiku if you agree.

A better long-term fix would be to change the implementation to require "both flags set" instead of "either flag set" on all platforms. Then we could check both IFF_UP and IFF_LINK on Haiku. This is the better fix but requires some more testing (also on other platforms). We can tackle that in a follow-up PR.

Either way it would be useful if you could test the following three cases on Haiku, and paste the output of ifconfig for each one:

  1. Interface down, cable connected:

    ifconfig /dev/net/ipro1000/0 down
    ifconfig /dev/net/ipro1000/0
    

    If you can, also run the NetBasics test here.

  2. Interface up, cable disconnected:

    ifconfig /dev/net/ipro1000/0 up
    # now unplug the cable
    ifconfig /dev/net/ipro1000/0
    
  3. Loopback:

    ifconfig loop
    

Thanks!

@duncanmcqueen

Copy link
Copy Markdown
Contributor Author

Thank you. You are correct. I did the three tests on Haiku (hrev60228 x86_64, QEMU e1000). For case 2, I used the QEMU monitor command set_link e1000.0 off to disconnect the cable. A small C program shows the SIOCGIFFLAGS flags and the result of each test.

1. Interface down, cable connected

MTU: 1500, Metric: 0, broadcast link auto-configured
flags /dev/net/ipro1000/0: 0x3002 UP=0 LINK=1

IFF_LINK is set when the interface is down. Thus, with IFF_RUNNING = IFF_LINK, NetBasics gave up=true, which is not correct.

2. Interface up, cable disconnected

MTU: 1500, Metric: 0, up broadcast auto-configured
flags /dev/net/ipro1000/0: 0x2003 UP=1 LINK=0

(The "Media type" line is also not shown.)

3. Loopback

loop	Hardware type: Local Loopback, Address: none
	inet addr: 127.0.0.1, Mask: 255.0.0.0
	inet6 addr: ::1, Prefix Length: 128
	MTU: 65536, Metric: 0, up loopback link
flags loop: 0x1009 UP=1 LINK=1

I agree with your short-term fix. I changed the commit: when the system does not define IFF_RUNNING, it is now 0, so isUp() tests IFF_UP only. NetBasics with this change:

Case IFF_RUNNING = IFF_LINK (old) IFF_UP only (new)
All up up=true up=true
1. Down, cable connected up=true up=false
2. Up, cable disconnected up=true up=true
Loopback up=true up=true

The socket test passed in all cases. For case 2, "both flags set" with IFF_UP and IFF_LINK would give up=false. I agree to do that in a follow-up pull request.

@guillerodriguez

Copy link
Copy Markdown
Contributor

Perfect, thank you!

Comment thread native/jni/java-net/java_net_VMNetworkInterface.c Outdated
Haiku does not define IFF_RUNNING, so java_net_VMNetworkInterface.c
does not compile. Define it as 0 when the system does not define it,
so that isUp() tests IFF_UP only. Haiku's IFF_LINK is not a
replacement: it tells if the hardware has a link, also when the
interface is down.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: duncanmcqueen <dwmcqueen@gmail.com>
@guillerodriguez
guillerodriguez merged commit c74aac5 into ingelabs:master Oct 16, 2026
3 checks passed
@guillerodriguez

Copy link
Copy Markdown
Contributor

@duncanmcqueen see #78

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants