DHCP Option query - network-programming

I have been looking around and have been trying to figure out how to query the dhcp server I am connected to and get all options available or to at least be able to query with a proper option in mind and get that information in response. Ideally getting all option information from the lease would be great but I really only need it for a specific option that I want to use to package/receive information with.
I have been looking at this in hopes to figure out how to alter it but I am not all that familiar with the D language, making it a cumbersome task. http://blog.thecybershadow.net/2013/01/10/dhcp-test-client/
CODE:
module dhcptest;
import core.thread;
import std.algorithm;
import std.array;
import std.conv;
import std.random;
import std.stdio;
import std.string;
import std.socket;
version(Windows)
import std.c.windows.winsock : ntohs, htons, ntohl, htonl;
else
version(Posix)
import core.sys.posix.netdb : ntohs, htons, ntohl, htonl;
else
static assert(false, "Unsupported platform");
/// Header (part up to the option fields) of a DHCP packet, as on wire.
align(1)
struct DHCPHeader
{
align(1):
/// Message op code / message type. 1 = BOOTREQUEST, 2 = BOOTREPLY
ubyte op;
/// Hardware address type, see ARP section in "Assigned Numbers" RFC; e.g., '1' = 10mb ethernet.
ubyte htype;
/// Hardware address length (e.g. '6' for 10mb ethernet).
ubyte hlen;
/// Client sets to zero, optionally used by relay agents when booting via a relay agent.
ubyte hops;
/// Transaction ID, a random number chosen by the client, used by the client and server to associate messages and responses between a client and a server.
uint xid;
/// Filled in by client, seconds elapsed since client began address acquisition or renewal process.
ushort secs;
/// Flags. (Only the BROADCAST flag is defined.)
ushort flags;
/// Client IP address; only filled in if client is in BOUND, RENEW or REBINDING state and can respond to ARP requests.
uint ciaddr;
/// 'your' (client) IP address.
uint yiaddr;
/// IP address of next server to use in bootstrap; returned in DHCPOFFER, DHCPACK by server.
uint siaddr;
/// Relay agent IP address, used in booting via a relay agent.
uint giaddr;
/// Client hardware address.
ubyte[16] chaddr;
/// Optional server host name, null terminated string.
char[64] sname = 0;
/// Boot file name, null terminated string; "generic" name or null in DHCPDISCOVER, fully qualified directory-path name in DHCPOFFER.
char[128] file = 0;
/// Optional parameters field. See the options documents for a list of defined options.
ubyte[0] options;
static assert(DHCPHeader.sizeof == 236);
}
/*
35 01 02
0F 17 68 6F 6D 65 2E 74 68 65 63 79 62 65 72 73 68 61 64 6F 77 2E 6E 65 74
01 04 FF FF FF 00
06 04 C0 A8 00 01
03 04 C0 A8 00 01
05 04 C0 A8 00 01
36 04 C0 A8 00 01
33 04 00 00 8C A0
FF
*/
struct DHCPOption
{
ubyte type;
ubyte[] data;
}
struct DHCPPacket
{
DHCPHeader header;
DHCPOption[] options;
}
enum DHCPOptionType : ubyte
{
subnetMask = 1,
timeOffset = 2,
router = 3,
timeServer = 4,
nameServer = 5,
domainNameServer = 6,
domainName = 15,
leaseTime = 51,
netbiosNodeType = 46,
dhcpMessageType = 53,
serverIdentifier = 54,
renewalTime = 58,
rebindingTime = 59,
}
enum DHCPMessageType : ubyte
{
discover = 1,
offer ,
request ,
decline ,
ack ,
nak ,
release,
inform
}
enum NETBIOSNodeType : ubyte
{
bNode = 1,
pNode,
mMode,
hNode
}
DHCPPacket parsePacket(ubyte[] data)
{
DHCPPacket result;
enforce(data.length > DHCPHeader.sizeof + 4, "DHCP packet too small");
result.header = *cast(DHCPHeader*)data.ptr;
data = data[DHCPHeader.sizeof..$];
enforce(data[0..4] == [99, 130, 83, 99], "Absent DHCP option magic cookie");
data = data[4..$];
ubyte readByte()
{
enforce(data.length, "Unexpected end of packet");
ubyte result = data[0];
data = data[1..$];
return result;
}
while (true)
{
auto optionType = readByte();
if (optionType==0) // pad option
continue;
if (optionType==255) // end option
break;
auto len = readByte();
DHCPOption option;
option.type = optionType;
foreach (n; 0..len)
option.data ~= readByte();
result.options ~= option;
}
return result;
}
ubyte[] serializePacket(DHCPPacket packet)
{
ubyte[] data;
data ~= cast(ubyte[])((&packet.header)[0..1]);
data ~= [99, 130, 83, 99];
foreach (option; packet.options)
{
data ~= option.type;
data ~= to!ubyte(option.data.length);
data ~= option.data;
}
data ~= 255;
return data;
}
string ip(uint addr) { return format("%(%d.%)", cast(ubyte[])((&addr)[0..1])); }
void printPacket(DHCPPacket packet)
{
auto opNames = [1:"BOOTREQUEST",2:"BOOTREPLY"];
writefln(" op=%s\n chaddr=%(%02X:%)\n hops=%d\n xid=%08X\n secs=%d\n flags=%04X\n ciaddr=%s\n yiaddr=%s\n siaddr=%s\n giaddr=%s\n sname=%s\n file=%s",
opNames.get(packet.header.op, text(packet.header.op)),
packet.header.chaddr[0..packet.header.hlen],
packet.header.hops,
packet.header.xid,
ntohs(packet.header.secs),
ntohs(packet.header.flags),
ip(packet.header.ciaddr),
ip(packet.header.yiaddr),
ip(packet.header.siaddr),
ip(packet.header.giaddr),
to!string(packet.header.sname.ptr),
to!string(packet.header.file.ptr),
);
writefln(" %d options:", packet.options.length);
foreach (option; packet.options)
{
auto type = cast(DHCPOptionType)option.type;
writef(" %s: ", type);
switch (type)
{
case DHCPOptionType.dhcpMessageType:
enforce(option.data.length==1, "Bad dhcpMessageType data length");
writeln(cast(DHCPMessageType)option.data[0]);
break;
case DHCPOptionType.netbiosNodeType:
enforce(option.data.length==1, "Bad netbiosNodeType data length");
writeln(cast(NETBIOSNodeType)option.data[0]);
break;
case DHCPOptionType.subnetMask:
case DHCPOptionType.router:
case DHCPOptionType.timeServer:
case DHCPOptionType.nameServer:
case DHCPOptionType.domainNameServer:
case DHCPOptionType.serverIdentifier:
enforce(option.data.length % 4 == 0, "Bad IP option data length");
writefln("%(%s, %)", map!ip(cast(uint[])option.data).array());
break;
case DHCPOptionType.domainName:
writeln(cast(string)option.data);
break;
case DHCPOptionType.timeOffset:
case DHCPOptionType.leaseTime:
case DHCPOptionType.renewalTime:
case DHCPOptionType.rebindingTime:
enforce(option.data.length % 4 == 0, "Bad integer option data length");
writefln("%(%d, %)", map!ntohl(cast(uint[])option.data).array());
break;
default:
writefln("%(%02X %)", option.data);
}
}
}
enum SERVER_PORT = 67;
enum CLIENT_PORT = 68;
__gshared UdpSocket socket;
void listenThread()
{
try
{
static ubyte[0x10000] buf;
ptrdiff_t received;
Address address;
while ((received = socket.receiveFrom(buf[], address)) > 0)
{
auto receivedData = buf[0..received].dup;
try
{
auto packet = parsePacket(receivedData);
writefln("Received packet from %s:", address);
printPacket(packet);
}
catch (Exception e)
writefln("Error while parsing packet [%(%02X %)]: %s", receivedData, e.toString());
}
throw new Exception(format("socket.receiveFrom returned %d.", received));
}
catch (Exception e)
{
writeln("Error on listening thread:");
writeln(e.toString());
}
}
void sendPacket()
{
DHCPPacket packet;
packet.header.op = 1; // BOOTREQUEST
packet.header.htype = 1;
packet.header.hlen = 6;
packet.header.hops = 0;
packet.header.xid = uniform!uint();
packet.header.flags = htons(0x8000); // Set BROADCAST flag - required to be able to receive a reply to an imaginary hardware address
foreach (ref b; packet.header.chaddr[0..packet.header.hlen])
b = uniform!ubyte();
packet.options ~= DHCPOption(DHCPOptionType.dhcpMessageType, [DHCPMessageType.discover]);
writefln("Sending packet:");
printPacket(packet);
socket.sendTo(serializePacket(packet), new InternetAddress("255.255.255.255", SERVER_PORT));
}
void main()
{
socket = new UdpSocket();
socket.setOption(SocketOptionLevel.SOCKET, SocketOption.BROADCAST, 1);
try
{
socket.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, 1);
socket.bind(getAddress("0.0.0.0", CLIENT_PORT)[0]);
writefln("Listening for DHCP replies on port %d.", CLIENT_PORT);
}
catch (Exception e)
{
writeln("Error while attempting to bind socket:");
writeln(e);
writeln("Replies will not be visible. Use a packet capture tool to see replies,\nor try re-running the program with more permissions.");
}
(new Thread(&listenThread)).start();
writeln("Type \"d\" to broadcast a DHCP discover packet.");
while (true)
{
auto line = readln().strip().split();
if (!line.length)
{
writeln("Enter a command.");
continue;
}
switch (line[0].toLower())
{
case "d":
case "discover":
sendPacket();
break;
default:
writeln("Unrecognized command.");
}
}
}
From my understanding I will have to send a BOOTP vendor extension if I want to query for a specific option. I am not a networking guru and am looking for as much help as possible thank you.
DHCP OPTIONS DOCUMENTATION:
http://www.networksorcery.com/enp/protocol/bootp/options.htm

If you only need a one-off experiment, you can modify the sendPacket function to include the DHCP option you need. Notice the line:
packet.options ~= DHCPOption(DHCPOptionType.dhcpMessageType, [DHCPMessageType.discover]);
You can copy and edit it to add more options to the DHCP packet.
As for decoding, the program will already print all the data it receives, but it may not know how to decode every option. You may need to add more options to the respective enumerations, and to the switch statement that controls how these options are parsed and printed.

Related

http.GET() sends false (-1) in esp8266 (arduino)

I am trying to fetch some details from an API endpoint (https://bitcoin-ethereum-price-test.vercel.app/btc). But everytime it is returning false (-1). When I GET the endpoint on my browser it is just workign fin, returning 200.
http.GET() returns -1
serial monitor putput
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#include <Wire.h>
WiFiClient wifiClient;
void setup() {
Serial.begin(9600);
WiFi.begin("56", "emayush56");
while(WiFi.status() != WL_CONNECTED)
{
delay(200);
Serial.print("..");
}
Serial.println();
Serial.println("NodeMCU is connected!");
Serial.println(WiFi.localIP());
}
void loop() {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
http.begin(wifiClient, "https://bitcoin-ethereum-price-test.vercel.app/btc");
int httpCode = http.GET();
Serial.println("*** RESPONSE STATUS ***");
Serial.println(httpCode);
if (httpCode > 0) {
String payload = http.getString();
Serial.println(payload);
}
http.end();
}
delay(3000);
}
I think either I am doing something wrong with http.begin() or something else. http.begin() can be called in two different ways:
type1:
bool begin(WiFiClient &client, const String& url);
type2:
bool begin(WiFiClient &client, const String& host, uint16_t port, const String& uri = "/", bool https = false);
I have tried with both of them - first by passing directly the WifiClient object and the URL (type 1), and then (type2) by passing the WiFiClient object and other parameters.
If my main api endpoint (https://bitcoin-ethereum-price-test.vercel.app/btc) is returnig 200 then why http.GET() is returning false? Please help me identify the issue.
You're making an HTTP request to an HTTPS API. You will need to use a certificate's sha1 fingerprint. You can get the fingerprint in chrome by clicking on the little lock by the beginning of the URL, go to "Connection is secure" option then "Certificate is valid" and it'll show you some info about the certificate with the keys at the bottom.
Here is some example code I found which uses HTTPS with the HTTPClient library:\
void loop() {
// wait for WiFi connection
if ((WiFiMulti.run() == WL_CONNECTED)) {
HTTPClient http;
Serial.print("[HTTPS] begin...\n");
http.begin("https://some.secure_server.com/auth/authorise", "2F 2A BB 23 6B 03 89 76 E6 4C B8 36 E4 A6 BF 84 3D DA D3 9F");
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
int httpCode = http.POST("user_id=mylogin&user_password=this%20is%20my%20%24ecret%20pa%24%24word");
if (httpCode > 0) {
http.writeToStream(&Serial);
// HTTP header has been send and Server response header has been handled
Serial.printf("[HTTP] ... code: %d\n", httpCode);
// file found at server
if (httpCode == HTTP_CODE_OK) {
String payload = http.getString();
Serial.println(payload);
}
} else {
Serial.printf("[HTTP] ... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
}
delay(10000);
}

dart query Steam Master Server

I am trying to get the server IPs from a steam master server via a query and later query the game servers.
https://developer.valvesoftware.com/wiki/Master_Server_Query_Protocol#
There are plenty of examples in different programming languages but not dart.
https://gist.github.com/koenbollen/645947/09241258c0d2dd8d5a4e647865730ab83955f68b#file-mastersteam-py-L18
My problem is: i don't even understand why the address "hl2master.steampowered.com" is an invalid internet address. It says so on the official valve Master Server Query (link at top of the post).
This is the error i get trying to run the code:
[ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: Invalid argument(s): Invalid internet address hl2master.steampowered.com
import 'dart:io';
import 'dart:convert';
// Master server:
const GOLD_SRC = "hl1master.steampowered.com";
const GOLD_SRC_PORT = 27010;
const SOURCE = "hl2master.steampowered.com";
const SOURCE_PORT = 27011;
// Regions:
const US_EAST_COAST = 0x00;
const US_WEST_COAST = 0x01;
const SOUTH_AMERICA = 0x02;
const EUROPE = 0x03;
const ASIA = 0x04;
const AUSTRALIA = 0x05;
const MIDDLE_EAST = 0x06;
const AFRICA = 0x07;
const ALL = 0xFF;
class MasterServerQuery {
connectSocket01() async {
var message = "31 FF 30 2E 30 2E 30 2E";
InternetAddress master = InternetAddress(SOURCE);
var masterPort = SOURCE_PORT;
RawDatagramSocket.bind(InternetAddress.anyIPv4, 4096).then((
RawDatagramSocket socket) {
print('UDP Echo ready to receive');
print('${socket.address.address}:${socket.port}');
socket.listen((RawSocketEvent e) {
Datagram d = socket.receive();
if (d == null) return;
String message = "31 FF 30 2E 30 2E 30 2E";
print(
'Datagram from ${d.address.address}:${d.port}: ${message.trim()}');
socket.send(message.codeUnits, master, masterPort);
});
});
}
}
The address is not valid, since it expects a valid ip address and not an hostname, you can provide the ip address or use InternetAddress.lookup.
You code is also wrong in the way that you pass the message you shouldn't pass the codeUnits but the bytes in a way as such:
final byteData = ByteData(8);
byteData.setUint8(0, 0x31);
byteData.setUint8(1, 0xFF);
byteData.setUint8(2, 0x30);
byteData.setUint8(3, 0x2E);
byteData.setUint8(4, 0x30);
byteData.setUint8(5, 0x2E);
byteData.setUint8(6, 0x30);
byteData.setUint8(7, 0x2E);
byteData.buffer.asUint8List() //Pass this.

RSS (Receive Side Scaling) on Intel XL710 Per port

I struggle with Intel XL710 card using DPDK to make it compute RSS hash using only SRC IPV4 or DST IPV4 on per port basis.
The card has 4 10GE ports and RSS config is global for them whatever i do. I tried to set SRC/DST IPV4 fields in PCTYPE and the configuration applied last only takes action.
So the behavior i want to achieve.
Let's say i have upstream packet arrived on port 0:
SRC: 10.10.10.1 and DST:10.10.10.2
And reply downstream packet arrived on port 1:
SRC: 10.10.10.2 and DST:10.10.10.1
I want port 0 (which in our case is upstream) on the card to compute RSS hash based on SRC address 10.10.10.1 and for, port 1 (which is downstream) to compute the hash using DST address which in our case also will be 10.10.10.1. So the idea is to distribute packets between RX queues in a way that only SRC/DST address respectively affects this distribution.
I'm not bound specifically to RSS. Whatever tech will do if it allows to achieve this.
The configuration i used:
void setFilter(uint16_t portId, uint32_t value){
//Value = RTE_ETH_FLOW_NONFRAG_IPV4_TCP in that case
struct rte_eth_hash_filter_info info;
uint32_t ftype, idx, offset;
int ret;
if (rte_eth_dev_filter_supported(portId,
RTE_ETH_FILTER_HASH) < 0) {
printf("RTE_ETH_FILTER_HASH not supported on port %d\n",
portId);
return;
}
memset(&info, 0, sizeof(info));
info.info_type = RTE_ETH_HASH_FILTER_GLOBAL_CONFIG;
info.info.global_conf.hash_func =
RTE_ETH_HASH_FUNCTION_DEFAULT;
ftype = value;
idx = ftype / UINT64_BIT;
offset = ftype % UINT64_BIT;
info.info.global_conf.valid_bit_mask[idx] |= (1ULL << offset);
info.info.global_conf.sym_hash_enable_mask[idx] |=
(1ULL << offset);
ret = rte_eth_dev_filter_ctrl(portId, RTE_ETH_FILTER_HASH,
RTE_ETH_FILTER_SET, &info);
if (ret < 0)
printf("Cannot set global hash configurations by port %d\n",
portId);
else
printf("Global hash configurations have been set "
"succcessfully by port %d\n", portId);
}
void setPctypeRss(uint16_t portId, uint16_t fieldIdx) {
/* Note that AVF_FILTER_PCTYPE_NONF_IPV4_TCP is define for
* Virtual Function. Defines are the same for Physical Functions
*/
int ret = -ENOTSUP;
enum rte_pmd_i40e_inset_type inset_type = INSET_HASH;
struct rte_pmd_i40e_inset inset;
ret = rte_pmd_i40e_inset_get(portId, AVF_FILTER_PCTYPE_NONF_IPV4_TCP,
&inset, inset_type);
if (ret) {
printf("Failed to get input set.\n");
return;
}
memset(&inset, 0, sizeof(inset));
ret = rte_pmd_i40e_inset_set(portId, AVF_FILTER_PCTYPE_NONF_IPV4_TCP,
&inset, inset_type);
if (ret) {
printf("Failed to CLEAR input set.\n");
return;
}
else
{
printf("Successfull cleared input set\n");
}
ret = rte_pmd_i40e_inset_get(portId, AVF_FILTER_PCTYPE_NONF_IPV4_TCP,
&inset, inset_type);
if (ret) {
printf("Failed to get input set.\n");
return;
}
ret = rte_pmd_i40e_inset_field_set(&inset.inset, fieldIdx);
if (ret) {
printf("Failed to configure input set field.\n");
return;
}
ret = rte_pmd_i40e_inset_set(portId, AVF_FILTER_PCTYPE_NONF_IPV4_TCP,
&inset, inset_type);
if (ret) {
printf("Failed to set input set.\n");
return;
}
if (ret == -ENOTSUP)
printf("Function not supported\n");
}
IMO it is worth trying a bit simpler solution. We can simply use rte_eth_dev_configure():
https://doc.dpdk.org/api/rte__ethdev_8h.html#a1a7d3a20b102fee222541fda50fd87bd
And just set eth_conf.rss_conf.rss_hf to ETH_RSS_IP as described here:
https://doc.dpdk.org/api/structrte__eth__rss__conf.html#ad70f17882a835e5d4e38c64a9f872fdc
There are few examples in DPDK using this functionality. and most of them work fine ;)

How do I determine an expired access token?

I am interfacing with the Microsoft Health Cloud API and have successfully requested an access token and refresh token. Communication with the RESTful API works as intended, although I am having a hard time figuring out, how to reliably determine an expired access token.
I have the following code in place:
fire_and_forget read_profile()
{
HttpClient httpClient{};
httpClient.DefaultRequestHeaders().Authorization({ L"bearer", access_token_ });
try
{
auto const response{ co_await httpClient.GetStringAsync({ L"https://api.microsofthealth.net/v1/me/Profile" }) };
// Raise event passing the response along.
// Code left out for brevity.
co_return;
}
catch (hresult_error const& e)
{
if (e.code() != 0x80190191) // Magic value for "unauthorized access (401)"
{
throw;
}
// This is an "unauthorized access (401)" error. Continue with requesting a new
// access token from the refresh token.
// Code left out for brevity.
}
Although it appears to work, it feels wrong for so many reasons. It's not just the magic value, but also the fact, that this particular error code may be used for other error modes.
Is there a more robust way of determining, whether an access token has expired?
Note: I understand, that I could use the expiration interval, and check against the system time. I'd rather not go down that route, as it isn't entirely reliable either, and introduces additional complexity for roaming that information across devices.
I understand, that I could use the expiration interval, and check against the system time.
Microsoft Health Cloud API has provided expires_in field to verify the token is valid. In general, we could check against the system time, and if the system time was artificially modified, it isn't entirely reliable. So we could use NTP server time, rather than use system time.
public async static Task<DateTime> GetNetworkTime()
{
//default Windows time server
const string ntpServer = "time.windows.com";
// NTP message size - 16 bytes of the digest (RFC 2030)
var ntpData = new byte[48];
//Setting the Leap Indicator, Version Number and Mode values
ntpData[0] = 0x1B; //LI = 0 (no warning), VN = 3 (IPv4 only), Mode = 3 (Client Mode)
var addresses = await Dns.GetHostAddressesAsync(ntpServer);
//The UDP port number assigned to NTP is 123
var ipEndPoint = new IPEndPoint(addresses[0], 123);
//NTP uses UDP
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
{
socket.Connect(ipEndPoint);
//Stops code hang if NTP is blocked
socket.ReceiveTimeout = 3000;
socket.Send(ntpData);
socket.Receive(ntpData);
socket.Dispose();
}
//Offset to get to the "Transmit Timestamp" field (time at which the reply
//departed the server for the client, in 64-bit timestamp format."
const byte serverReplyTime = 40;
//Get the seconds part
ulong intPart = BitConverter.ToUInt32(ntpData, serverReplyTime);
//Get the seconds fraction
ulong fractPart = BitConverter.ToUInt32(ntpData, serverReplyTime + 4);
//Convert From big-endian to little-endian
intPart = SwapEndianness(intPart);
fractPart = SwapEndianness(fractPart);
var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);
//**UTC** time
var networkDateTime = (new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc)).AddMilliseconds((long)milliseconds);
return networkDateTime.ToLocalTime();
}
// stackoverflow.com/a/3294698/162671
static uint SwapEndianness(ulong x)
{
return (uint)(((x & 0x000000ff) << 24) +
((x & 0x0000ff00) << 8) +
((x & 0x00ff0000) >> 8) +
((x & 0xff000000) >> 24));
}

How to write a standalone URL logger for Windows?

I want to write a program to log all the URLs visited on a computer, but standalone, so not as a Fiddler2 extension. Are there any libraries out there that do this already that I could include in my application (which I was intending to write in C# .Net, but I'm flexible as long as it's for Windows)? If not are there any that could at least facilitate reading information from HTTP packets? I want to analyse the urls on the fly. Thanks.
For that, you would have to sniff the traffic on the computer under analysis.
To achieve this, use pcap library. As you may want to use a higher level programming language as C# (or Java), there are a lot of wrappers available to facilitate the usage of pcap library. In Java (since I am more used to it), there is one wrapper called jNetPcap. It is open source and has a good documentation. See the example below to sniff the traffic of any of our NICs:
package org.jnetpcap.examples;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.jnetpcap.Pcap;
import org.jnetpcap.PcapIf;
import org.jnetpcap.packet.PcapPacket;
import org.jnetpcap.packet.PcapPacketHandler;
/**
* Here is the output generated by this example :
*
* Network devices found:
* #0: \Device\NPF_{BC81C4FC-242F-4F1C-9DAD-EA9523CC992D} [Intel(R) PRO/100 VE]
* #1: \Device\NPF_{E048DA7F-D007-4EEF-909D-4238F6344971} [VMware Virtual Ethernet Adapter]
* #2: \Device\NPF_{5B62B373-3EC1-460D-8C71-54AA0BF761C7} [VMware Virtual Ethernet Adapter]
* #3: \Device\NPF_GenericDialupAdapter [Adapter for generic dialup and VPN capture]
*
* Choosing 'Intel(R) PRO/100 VE) ' on your behalf:
* Received packet at Tue Nov 03 18:52:42 EST 2009 caplen=1362 len=1362 jNetPcap rocks!
* Received packet at Tue Nov 03 18:52:45 EST 2009 caplen=82 len=82 jNetPcap rocks!
* Received packet at Tue Nov 03 18:52:45 EST 2009 caplen=145 len=145 jNetPcap rocks!
* Received packet at Tue Nov 03 18:52:45 EST 2009 caplen=62 len=62 jNetPcap rocks!
* Received packet at Tue Nov 03 18:52:45 EST 2009 caplen=164 len=164 jNetPcap rocks!
* Received packet at Tue Nov 03 18:52:45 EST 2009 caplen=62 len=62 jNetPcap rocks!
* Received packet at Tue Nov 03 18:52:45 EST 2009 caplen=54 len=54 jNetPcap rocks!
* Received packet at Tue Nov 03 18:52:45 EST 2009 caplen=1073 len=1073 jNetPcap rocks!
* Received packet at Tue Nov 03 18:52:45 EST 2009 caplen=1514 len=1514 jNetPcap rocks!
* Received packet at Tue Nov 03 18:52:45 EST 2009 caplen=279 len=279 jNetPcap rocks!
*/
public class ClassicPcapExample {
/**
* Main startup method
*
* #param args
* ignored
*/
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;
for (PcapIf device : alldevs) {
String description =
(device.getDescription() != null) ? device.getDescription()
: "No description available";
System.out.printf("#%d: %s [%s]\n", i++, device.getName(), description);
}
PcapIf device = alldevs.get(0); // We know we have atleast 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
**************************************************************************/
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;
}
/***************************************************************************
* 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
);
}
};
/***************************************************************************
* 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();
}
}
This example was extracted from the jNetPcap website. As you can see, you just have to customize the nextPacket() method to make what you are intending.
That would simply be:
public void nextPacket(PcapPacket packet, String user) {
Http http = new Http();
if (packet.hasHeader(http)) {
System.out.printf("Received packet at %s: %s\n",
new Date(packet.getCaptureHeader().timestampInMillis()),
http.Request.valueOf("Host")
);
}
Hope I've helped.

Resources