Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Scanner fails when executing Java with admin rights (sudo) in Eclipse in Linux

+1
−0

(Brought over from SE.)


The problem

I have followed this procedure in order to run Java applications as root when needed from Eclipse (as I use Xubuntu, for instance, when using jnetpcap to capture and analyse packets). The problem I have is that any Scanner statement reading from System.in fails with very vague information provided. Otherwise, the program runs fine.

Following is the code I'm using (a modification of the example jnetpcap provides). When compiling this without IDE, it runs fine.

Test code

package pruebas;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Scanner;

import org.jnetpcap.Pcap;
import org.jnetpcap.PcapIf;
import org.jnetpcap.packet.PcapPacket;
import org.jnetpcap.packet.PcapPacketHandler;
import org.jnetpcap.PcapBpfProgram;

public class Captura {

    private static Scanner sc;

    /**
     * Main startup method
     *
     * @param args
     *            ignored
     */
    private static String asString(final byte[] mac) {
        final StringBuilder buf = new StringBuilder();
        for (byte b : mac) {
            if (buf.length() != 0) buf.append(':');
            if (b >= 0 && b < 16) buf.append('0');
            buf.append(Integer.toHexString((b < 0) ? b + 256 : b).toUpperCase());
        }

        return buf.toString();
    }

    private static int readInteger(String msg) {
        int ans = 0;
        boolean validInput = false;
        while (!validInput) {
            System.out.print(msg);
            String buf = sc.nextLine();
            try {
                ans = Integer.parseInt(buf.trim());
                validInput = true;
            }
            catch(NumberFormatException nfe) {
                validInput = false;
                System.out.println("Sorry, this input is incorrect! Please try again.");
            }
        }
        return ans;
    }

    public static void main(String[] args) {
        List<PcapIf> alldevs = new ArrayList<PcapIf>(); // Will be filled with NICs
        StringBuilder errbuf = new StringBuilder(); // For any error msgs

        /***************************************************************************
         * First get a list of devices on this system
         **************************************************************************/
        int r = Pcap.findAllDevs(alldevs, errbuf);
        if (r == Pcap.NOT_OK || alldevs.isEmpty()) {
            System.err.printf("Can't read list of devices, error is %s", errbuf.toString());
            return;
        }

        System.out.println("Network devices found:");

        int i = 0;
        try {
            for (PcapIf device : alldevs) {
                String description = (device.getDescription() != null) ? device.getDescription() : "No description available";
                final byte[] mac = device.getHardwareAddress();
                String dir_mac = (mac == null) ? "No MAC address associated" : asString(mac);
                System.out.printf("#%d: %s [%s] MAC:[%s]\n", i++, device.getName(), description, dir_mac);
            }// for

            sc = new Scanner(System.in);
            int opc = readInteger("\nSelect device [0-" + (alldevs.size() - 1) + "]:\t");

            PcapIf device = alldevs.get(opc); // We know we have at least 1 device
            System.out.printf("\nChoosing '%s' on your behalf:\n", (device
                    .getDescription() != null) ? device.getDescription()
                    : device.getName());

            /***************************************************************************
             * Second we open up the selected device
             **************************************************************************/
            /*
             * "snaplen" is short for 'snapshot length', as it refers to the
             * amount of actual data captured from each packet passing through
             * the specified network interface. 64*1024 = 65536 bytes; campo len
             * en Ethernet(16 bits) tam máx de trama
             */

            int snaplen = 64 * 1024; // Capture all packets, no trucation
            int flags = Pcap.MODE_PROMISCUOUS; // capture all packets
            int timeout = 10 * 1000; // 10 seconds in millis
            Pcap pcap = Pcap.openLive(device.getName(), snaplen, flags,
                    timeout, errbuf);

            if (pcap == null) {
                System.err.printf("Error while opening device for capture: "
                        + errbuf.toString());
                return;
            }// if

            /******** F I L T R O ********/
            PcapBpfProgram filter = new PcapBpfProgram();
            String expression = ""; // "port 80";
            int optimize = 0; // 1 means true, 0 means false
            int netmask = 0;
            int r2 = pcap.compile(filter, expression, optimize, netmask);
            if (r2 != Pcap.OK) {
                System.out.println("Filter error: " + pcap.getErr());
            }// if
            pcap.setFilter(filter);
            /****************/

            /***************************************************************************
             * Third we create a packet handler which will receive packets from
             * the libpcap loop.
             **********************************************************************/
            PcapPacketHandler<String> jpacketHandler = new PcapPacketHandler<String>() {

                public void nextPacket(PcapPacket packet, String user) {

                    System.out.printf(
                            "Received packet at %s caplen=%-4d len=%-4d %s\n",
                            new Date(packet.getCaptureHeader()
                                    .timestampInMillis()), packet
                                    .getCaptureHeader().caplen(),   // Length actually captured
                            packet.getCaptureHeader().wirelen(),    // Original length
                            user                                    // User supplied object
                            );
                    /****** Desencapsulado ********/
                    for (int i = 0; i < packet.size(); i++) {
                        System.out.printf("%02X ", packet.getUByte(i));
                        if (i % 16 == 15)
                            System.out.println("");
                    }
                    System.out.println("\n\nHeader: " + packet.toHexdump());

                }
            };

            /***************************************************************************
             * Fourth we enter the loop and tell it to capture 10 packets. The
             * loop method does a mapping of pcap.datalink() DLT value to
             * JProtocol ID, which is needed by JScanner. The scanner scans the
             * packet buffer and decodes the headers. The mapping is done
             * automatically, although a variation on the loop method exists
             * that allows the programmer to sepecify exactly which protocol ID
             * to use as the data link type for this pcap interface.
             **************************************************************************/
            pcap.loop(10, jpacketHandler, "jNetPcap rocks!");

            /***************************************************************************
             * Last thing to do is close the pcap handle
             **************************************************************************/
            pcap.close();
            sc.close();
        } catch (IOException e) {
            System.out.println(":'(");
            //e.printStackTrace();
        }
    }
}

Output

Select device [0-14]:       at java.util.Scanner.nextLine(Scanner.java:1540)
    at pruebas.Captura.readInteger(Captura.java:50)
    at pruebas.Captura.main(Captura.java:88)

Specs

  • Xubuntu 15.04
  • Eclipse Luna SR2 (4.4.2)
  • Java 8 (Oracle)
History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.
Why should this post be closed?

0 comment threads

1 answer

+1
−0

I've finally managed to get it working without using a wrapper for java. It has to do with filesystem capabilities in Linux.

To let java list and select network interfaces, as well as analyse and capture packets, go to the directory where the executable the IDE uses is (for example, /usr/lib/jvm/java-8-oracle/bin; in Eclipse you can get it by seeing the console titlebar) and run the following command before doing so with your project:

sudo setcap cap_net_raw,cap_net_admin=eip java

Then run your project. Once you have tested your project, run the following command to leave things as they were before:

sudo setcap -r java

You can see if capabilities have been applied/removed by running:

getcap java

See this for more information regarding Linux behaviour when opening interfaces, and here is a complete procedure in case you have to configure something.

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.

0 comment threads

Sign up to answer this question »