Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Writing to a dump file #291

Open
mondain opened this issue Dec 3, 2021 · 13 comments
Open

Writing to a dump file #291

mondain opened this issue Dec 3, 2021 · 13 comments

Comments

@mondain
Copy link

mondain commented Dec 3, 2021

I want to write some UDP packets to a file, I do not want to hook into any network interfaces or stdin. I've tried a number of different variations of the below logic and I'm stopped at every turn; is this even possible?

        try {
            Path pcapPath = Paths.get(String.format("rtp_%s.pcap", stream.getId()));
            Files.deleteIfExists(pcapPath);
            String pcapPathStr = pcapPath.toString();
            PcapHandle pcapHandle = new PcapHandle.Builder("dumper").build();
            pcapDumper = pcapHandle.dumpOpen(pcapPathStr);
        } catch (Exception e) {
            log.warn("Exception on pcap open", e);
        }

Error for above:

Exception on pcap open
org.pcap4j.core.PcapNativeException: socket: Operation not permitted
	at org.pcap4j.core.PcapHandle.<init>(PcapHandle.java:163)
	at org.pcap4j.core.PcapHandle.<init>(PcapHandle.java:44)
	at org.pcap4j.core.PcapHandle$Builder.build(PcapHandle.java:1412)

I also tried with Pcaps.openOffline(pcapPathStr) but since its a new empty file, it fails...

@rjo
Copy link

rjo commented Jul 22, 2022

Were you ever able to figure this out?

@rjo
Copy link

rjo commented Jul 23, 2022

I seem to have accomplished this with the following:

try {
      PcapHandle handle = Pcaps.openDead(DataLinkType.RAW, 65535);
      PcapDumper dumper = handle.dumpOpen("test.pcap");
      payloads.forEach(payload -> {
          try {
              IpV4Packet p = IpV4Packet.newPacket(payload, 0, payload.length);
              dumper.dump(p);
          } catch(IllegalRawDataException e) {
              logger.error("IllegalRawDataException");
              e.printStackTrace();
          } catch(NotOpenException e) {
              logger.error("IllegalRawDataException");
              e.printStackTrace();
          }
      });
      dumper.close();
} catch(PcapNativeException e) {
    logger.error("PcapNativeException");
    e.printStackTrace();
}

Obviously exception handling is weak ... just a prototype.

@mondain
Copy link
Author

mondain commented Oct 6, 2022

I'm back on this, so I'll let you know how I fare.

@mondain
Copy link
Author

mondain commented Oct 6, 2022

@rjo I gave that a shot with 1.8.2 and this was logged

2022-10-06 14:10:37,558 WARN  o.p.packet.factory.PacketFactories - No PacketFactoryBinder is available. All packets will be captured as UnknownPacket.
2022-10-06 14:10:37,559 ERROR mypackage.MyClass - PcapException
java.lang.IllegalArgumentException: targetClass: interface org.pcap4j.packet.IpV4Packet$IpV4Tos numberClass: class org.pcap4j.packet.namednumber.NotApplicable
	at org.pcap4j.packet.factory.SimplePacketFactoryBinder.getPacketFactory(SimplePacketFactoryBinder.java:35)
	at org.pcap4j.packet.factory.PacketFactories.getFactory(PacketFactories.java:79)
	at org.pcap4j.packet.IpV4Packet$IpV4Header.<init>(IpV4Packet.java:464)
	at org.pcap4j.packet.IpV4Packet$IpV4Header.<init>(IpV4Packet.java:378)
	at org.pcap4j.packet.IpV4Packet.<init>(IpV4Packet.java:61)
	at org.pcap4j.packet.IpV4Packet.newPacket(IpV4Packet.java:57)

@rjo
Copy link

rjo commented Oct 7, 2022

That looks like its coming from someplace deeper in your code that the dump part

@mondain
Copy link
Author

mondain commented Oct 7, 2022

@rjo does the snaplen in PcapHandle handle = Pcaps.openDead(DataLinkType.RAW, 1500); have to be the exact length sent in the IpV4Packet.newPacket call? If yes, I'll have to pad it, since my data arrays are variable "up-to" 1500 max.

@rjo
Copy link

rjo commented Oct 7, 2022

I dont think it does as that would not accomodate variable length packets. The snap length is about capturing anyway. I don't think it would have an impact on what you're doing and I would just set it to 65535.

@mondain
Copy link
Author

mondain commented Oct 7, 2022

Ok, I'll set that back to 65535; I read through some of the unit tests and came up with for my write section; the issue is that the pcap doesn't show the proper sizes for the packets when I view them in wireshark; this is my write section:

      UnknownPacket.Builder rtpPktBuilder = new UnknownPacket.Builder();
      rtpPktBuilder.rawData(p.data);

      UdpPacket.Builder uPktBuilder = new UdpPacket.Builder();
      uPktBuilder.srcAddr(srcAddr).srcPort(srcPort).dstAddr(dstAddr).dstPort(dstPort)
              .payloadBuilder(rtpPktBuilder).correctChecksumAtBuild(true).correctLengthAtBuild(true);

      IpV6Packet.Builder IpV6PktBuilder = new IpV6Packet.Builder();
      IpV6PktBuilder.version(IpVersion.IPV6).trafficClass(IpV6SimpleTrafficClass.newInstance((byte) 0x12))
              .flowLabel(IpV6SimpleFlowLabel.newInstance(0x12345)).nextHeader(IpNumber.UDP).hopLimit((byte) 100)
              .srcAddr(srcAddr).dstAddr(dstAddr).payloadBuilder(uPktBuilder).correctLengthAtBuild(true);

      EthernetPacket.Builder ethPktBuilder = new EthernetPacket.Builder();
      ethPktBuilder.dstAddr(MacAddress.getByName("fe:00:00:00:00:02"))
              .srcAddr(MacAddress.getByName("fe:00:00:00:00:01")).type(EtherType.IPV6)
              .payloadBuilder(IpV6PktBuilder).paddingAtBuild(true);
      EthernetPacket ethPkt = ethPktBuilder.build();
      pcapWriter.dump(ethPkt, Instant.now());

It'd be awesome if there was an RtpPacket class impl instead of having use use Unknown...

@mondain
Copy link
Author

mondain commented Oct 7, 2022

I've now got data that wireshark seems to mostly understand, but my data can't be decoded as RTP, so I'm stuck. Anyone know what might wrong by looking at this image?
Here's updated writer code which writes each new video rtp data byte array:

//init section
  try {
      handle = Pcaps.openDead(DataLinkType.EN10MB, 65535);
      pcapWriter = handle.dumpOpen(String.format("%s/%s.pcap", currentPath.toAbsolutePath().toString(), name));
      srcAddr = (Inet4Address) InetAddress.getByName("192.168.0.1");
      dstAddr = (Inet4Address) InetAddress.getByName("192.168.0.2");
      srcPort = UdpPort.getInstance((short) 49152);
      dstPort = UdpPort.getInstance((short) 49153);
  } catch (Exception e) {
      log.error("PcapException", e);
  }

//write section

  try {
      UnknownPacket rtpPkt = UnknownPacket.newPacket(p.data, 0, p.data.length);
      log.debug("Writing {} rtp bytes pt: {} {}", p.length, p.payloadType, rtpPkt);

      UdpPacket.Builder uPktBuilder = new UdpPacket.Builder();
      uPktBuilder.srcAddr(srcAddr).srcPort(srcPort).dstAddr(dstAddr).dstPort(dstPort)
              .payloadBuilder(rtpPkt.getBuilder()).correctChecksumAtBuild(true).correctLengthAtBuild(true);

      IpV4Packet.Builder IpPktBuilder = new IpV4Packet.Builder();
      IpPktBuilder.version(IpVersion.IPV4).dontFragmentFlag(true).ihl((byte) 9).protocol(IpNumber.UDP)
              .tos(IpV4Rfc1349Tos.newInstance((byte) 0)).ttl((byte) 16).srcAddr(srcAddr).dstAddr(dstAddr)
              .payloadBuilder(uPktBuilder).correctChecksumAtBuild(true).correctLengthAtBuild(true)
              .paddingAtBuild(true);

      EthernetPacket.Builder ethPktBuilder = new EthernetPacket.Builder();
      ethPktBuilder.dstAddr(MacAddress.getByName("fe:00:00:00:00:02"))
              .srcAddr(MacAddress.getByName("fe:00:00:00:00:01")).type(EtherType.IPV4)
              .payloadBuilder(IpPktBuilder).paddingAtBuild(true);
      EthernetPacket ethPkt = ethPktBuilder.build();
      pcapWriter.dump(ethPkt, Instant.now());
  } catch (Exception e) {
      log.error("PcapException", e);
  }

@mondain
Copy link
Author

mondain commented Oct 7, 2022

Is there a way to specify one pcap format vs the other? There appear to be different types covered here: https://wiki.wireshark.org/Development/LibpcapFileFormat

@rjo
Copy link

rjo commented Oct 11, 2022

Regarding your wireshark problem ... perhaps you need to do a manual decode. link

@mondain
Copy link
Author

mondain commented Oct 11, 2022

@rjo that helped a lot, but my "menu" options are different. It certainly sees the proper values now, thanks!

# Packet 0 from /stream1-2323562666.pcap
- 1
- 0.000000
- 192.168.0.1
- 192.168.0.2
- RTP
- 78
- PT=DynamicRTP-Type-126, SSRC=0x8A7EC0AA, Seq=1, Time=873270

@rjo
Copy link

rjo commented Oct 11, 2022

glad i could help!

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

No branches or pull requests

2 participants