RadioTap headers in scapy - wifi

I'm trying to send and receive packets with scapy and read the RadioTap Header. The wireless adapter (and driver) is able to handle those headers, but I can't seem to get them.
Whenever I send a normal packet in scapy, is does not contain such a header (thus, sniffing packets and checking one with pkt.haslayer(RadioTap) returns 0, and I am not able to display the header like with pkt[RadioTap].show() ).
If I explicitly construct my packets with a RadioTap header (like in a
pkt = RadioTap() and view it, I can get a RadioTap header, but it is empty. After sending it and receiving it, I can get still nothing.
I read posts like this one. But I don't have the problem that the RadioTap header doesn't get decoded, it's simply not filled with anything.
I'm using scapy 2.3.1, if this makes any difference. Any ideas?

Please make sure that your wireless interface and the driver support monitor mode.
$ iw list
...
Supported interface modes:
* IBSS
* managed
* AP
* AP/VLAN
* monitor <-- here
* P2P-client
* P2P-GO
* P2P-device
And your interface is configured to monitor mode with a specific channel (e.g. ch=6).
$ sudo ip link set wlan0 down
$ sudo iw dev wlan0 set type monitor
$ sudo ip link set wlan0 up
$ sudo iw dev wlan0 set channel 6
It is also good idea to try with tools like wireshark first to see if RadioTap is visible.

Related

How to force rerouting of a packet after return to netfilter from NFQUEUE

I have a caching application that runs in userspace. Normally, it uses DPDK to interact with the NICs directly without kernel interaction, grabbing packets off of the wire, and either passing them through, generating a response from cache, or in some occasions blocking them. It's transparent to the endpoints, and is written to work on raw packet data straight from the NIC. Notably, I'm not doing normal socket programming here - everything's handled at the packet level, without interaction with the TCP/IP stack.
For reasons that are long and boring, I wanted to add some NAT functionality. As a proof of concept, I was hoping to put a front end on my application using iptables/netfilter. So I did the NAT parts with commands like these:
sudo iptables --table nat --append PREROUTING --in-interface seg1a -j DNAT --to-destination $SERVERIP
sudo iptables --table nat --append POSTROUTING --out-interface seg1b -j MASQUERADE
sudo route add $SERVERIP seg1b
This works well for my purposes. The clients now attach to an interface on my system, but their traffic gets redirected to the server. I'm guaranteed that their traffic passes through my system, so all's good.
But to be useful as a cache, I need to be able to respond to some requests that I get from clients. I had thought I could use NFQUEUE for this, with a small application that reads from the netfilter queue and passes packets to and from my application via IPC. I used an iptables rule like this:
sudo iptables --table mangle --append FORWARD -j NFQUEUE
This works OK as long as my application doesn't respond to anything. But when my cache attempts to respond to something from one of the endpoints, things go wrong. The cache reverses all of the L2-4 headers, manages sequence and ack numbers, etc. But the packets don't get back to the client.
I think what's happening is that routing decisions for the packet were made before it was sent to NFQUEUE. So even though the cache returns something whose source and destination IP addresses are reversed, that's irrelevant for the routing of the packet.
I've tried a number of things to change the routing of my response packets, but nothing seems to work. How does one go about changing the routing on a packet read from netfilter queues? Failing that, is there a good way to just inject packets onto the wire from netfilter queues? If that were doable, I could block the original request and then send the cache's reply as an entirely new thing.
Thanks in advance for any suggestions.
The best answer I came up with for this problem was to open a raw socket and feed it my pre-built packets. Critically, you must create an iptables rule that matches your generated packets and tells netfilter not to do connection tracking. Otherwise, netfilter sees the injected packets and thinks there's a connection collision. It then does port forwarding, so the packets come out with a different port than you put in there!
I built the socket like this:
sid = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
Then, I turned on a couple of options (leaving failure handling out for brevity):
int one = 1;
const int *val = &one;
retval = setsockopt(sid, IPPROTO_IP, IP_HDRINCL, val, sizeof(one));
retval = setsockopt(sid, SOL_SOCKET, SO_MARK, val, sizeof(one));
The first of these tells the kernel that I have the headers already, so no need to try and create them. The second tells the kernel to put a mark value of 1 on every packet sent via the socket, which I can match against in routing or iptables rules.
Later, I built a destination address and used sendto() to send the packet:
retval = sendto(sid, pL3, len, 0, (struct sockaddr *)&daddr, sizeof(daddr));
Finally, I installed a rule telling netfilter not to do connection tracking on TCP packets marked with a 1. Since I had added the sockopt above so that all of my generated packets had this mark, this worked well:
sudo iptables -t raw -I OUTPUT -p tcp -m mark --mark 1 -j CT --notrack

import ip packet via hex dump

I have a hex dump generated using gdb. I have generated the dump that wireshark can understand using "od -Ax -tx1 -v". But when I open in the wireshark tool the packet doesn't get recognized properly. I think wireshark is trying to read the ethernet frame while the buffer has data from IP header. Is there a way to indicate wireshark to parse hexdump assuming fro IP header.
Have a look at text2pcap. There are 2 basic approaches you can take:
Add a dummy Ethernet header using the -e <l3pid> option, or
Set the encapsulation type of the converted pcap file to link-layer type LINKTYPE_RAW using the -l 101 option.

CUPS returns 'complete' on jobs which are still printing

I am communicating with CUPS using IPP protocol. I have all drivers for my printers installed in CUPS (using .ppd file) and printers got latest firmware.
When I query a job which a printer printing right now it says that the job's state is 'complete' before the printer even finish printing. It seems that the CUPS marks the job as 'complete' when it finish 'uploading' the file.
I would not expect this behaviour and I basically need to know when exactly the printer printed last paper for a job.
The code looks as follow. The self.printer().ippPrinter() is an instance of node-ipp and it points to a printer. To read the the state of the job I am using attribute 'job-state'.
var msg = {
"operation-attributes-tag": {
'job-id': id
}
};
self.printer().ippPrinter().execute("Get-Job-Attributes", msg, function(err, res){
var attributes = res['job-attributes-tag'];
self.setAttributes = attributes;
callback.call(self, attributes);
});
Does anyone know why I am having this issue or .. how to make it working?
Thank you!
CUPS can only forward job-states received from the printer. A lot of printer drivers and protocols work like 'fire and forget'.
Usually IPP printers allow CUPS and other clients to monitor the current job-state until it's finished/printed. Some manufacturers don't implement IPP properly and classify submitted jobs as printed - even if the printer has a paper jam!
Conclusion:
If your printer does not fully support IPP you probably won't be able to check for 'printed successfully'.
RFC 8011 5.3.7.1
If the implementation is a gateway to a printing system that never provides detailed status about the Print Job, the implementation MAY set the IPP Job’s state to ’completed’, provided that it also sets the ’queued-in-device’ value in the Job’s "job-state-reasons" attribute
#Jakub, you may well be communicating with CUPS using IPP... But are you sure that CUPS is communicating with the print device via IPP?
You can check this by running
lpstat -h cupsservername -v
This should return the device URI assigned to each print queue, which CUPS uses to address the actual printing device:
If that URI does contain ipp://, ipps://, http:// or https:// CUPS indeed talks IPP to the print device and you should be able to get actually correct status messages.
But if you see socket:// then CUPS is configured to use the AppSocket method (sometimes also called 'HP Jet Direct' or 'IP Direct Printing') to forward jobs. This is a "fire and forget" protocol. Basically it is the same as if you did run netcat print-device 9100 < myprintfile to shovel the printable data to port 9100 of the printer. The CUPS socket backend handling this spooling to the printer will not get any other acknoledgement from the printer than what TCP/IP provides confirming that the last packet was transfered. Hence it has to close down its process and report to the CUPS daemon successful-ok, even if the printer is still busy spitting out lots paper and will maybe never complete the full job because it runs into a paper jam...
If you see lpd:// the situation is similar (but uses port 515).
You may have success with a full status reporting by switching the CUPS-to-printdevice path from AppSocket or LPD to IPP like so:
sudo lpadmin -p printername ipp://ipaddress-of-printer
or
sudo lpadmin -p printername http://ipaddress-of-printer:631

ndisproto sample not reading any traffic

i was trying to get familiar with ndisproto samples in wdk. As per the doc, the -r -n 10 option should read 10 packets off the interface, but nothing in result even if I ping to the interface! The only time it reads traffic is when we use write option.
The sample is same, without any modification other than altering to #define NPROTO_PACKET_FILTER (NDIS_PACKET_TYPE_ALL_LOCAL|NDIS_PACKET_TYPE_PROMISCUOUS).
Is the driver really wired to read traffic originating from other sources?
What am I missing? Any idea how to read/sniff the traffic using ndisproto?
C:\Users\Administrator\Desktop\ndisprot>prottest.exe -r -n 10 \DEVICE\{17152850-6288-471A-9708-2889E7F55EE8}
Option: NumberOfPackets = 10
Trying to access NDIS Device: \DEVICE\{17152850-6288-471A-9708-2889E7F55EE8}
Opened device \DEVICE\{17152850-6288-471A-9708-2889E7F55EE8} successfully!
Trying to get src mac address
GetSrcMac: IoControl success, BytesReturned = 14
Got local MAC: 00:0c:29:23:b1:09
DoReadProc
C:\Users\Administrator\Desktop\ndisprot>prottest.exe -w -n 1 \DEVICE\{17152850-6288-471A-9708-2889E7F55EE8}
Option: NumberOfPackets = 1
Trying to access NDIS Device: \DEVICE\{17152850-6288-471A-9708-2889E7F55EE8}
Opened device \DEVICE\{17152850-6288-471A-9708-2889E7F55EE8} successfully!
Trying to get src mac address
GetSrcMac: IoControl success, BytesReturned = 14
Got local MAC: 00:0c:29:23:b1:09
DoWriteProc
DoWriteProc: sent 100 bytes
DoWriteProc: finished sending 1 packets of 100 bytes each
DoReadProc
DoReadProc: read pkt # 1, 100 bytes
DoReadProc finished: read 1 packets
Got the answer at last. The reason is, the driver sample is specifically designed to send/receive EAP over LAN frames, not all. There are a couple of break statements in NdisprotReceiveNetBufferLists that prevents any other packets other than frames of ethertype 0x888E from reaching the client app.
Same is the case for send.

Zebra Printing with CUPS no print ZPL or EPL

I have a Zebra GK420d connect to OS X via CUPS. However, when I send files to it that are written in ZPL or EPL they are only printed in plain text.
Am I required to change to mode on the printer?
Contrary to what others said, you don't need to specially add a raw queue.
Instead, you can submit raw files into any queue using -o raw switch:
lpr -P CupsPrinterName -o raw path/to/label.zpl
Printer name can be found over that link in CUPS:
http://localhost:631/printers/
This also works on other platforms that use CUPS, like Linux.
You can create a raw CUPS queue with lpadmin. Here's the command line I used:
lpadmin -p Zebra -E -v usb://Zebra%20Technologies/ZTC%20LP%202824%20Plus?serial=XXXXXX -m raw
You can also set up a raw queue using the CUPS web admin at
http://127.0.0.1:631/
This is a bit more comprehensive answer since I seem to be returning to this question every couple of years. To print with a Zebra or other barcode printers in Linux from command line follow these steps:
List all printer targets and find the printer you want to use:
$ lpinfo -v
network https
serial serial:/dev/ttyS0?baud=115200
serial serial:/dev/ttyS1?baud=115200
network lpd
direct hp
direct usb://GODEX/G500?serial=162203C6
network smb
...
Add new queue:
$ lpadmin -p godex -E -v usb://GODEX/G500?serial=162203C6 -m raw -o usb-unidir-default=true
If your printing is slow (takes long to start), please make sure you added -o usb-unidir-default=true.
Check available queues:
$ lpstat -v
device for godex: usb://GODEX/G500?serial=162203C6
Create a label (text file):
Create a file according to your printer's requirements in EPL (Zebra), ZPL (Zebra), EZPL (Godex).
Warning, certain CUPS versions might have an issue with raw files if they are under 512 bytes of length - longer files will print, while shorter will print once and then stall for a couple of minutes (looks like there is a timeout built in). A workaround is to add comments to extend it over 512 byte limit.
Example Zebra file (test.epl):
N
A20,20,0,2,1,1,N,"text"
B20,40,0,1,1,1,30,N,"aaaa-bbbb-cccc"
P1
Example Godex file (test.ezpl):
;set portrait orientation
^XSET,ROTATION,0
;set height 20mm
^Q20,1
;set width 64mm
^W64
;start label
^L
;AA=print out text with smallest font, x=20dots, y=20dots, magnificationx=0, magnificationy=0, gap=1dot, rotationInverse=0 (no)
AA,20,20,0,0,1,0,Some sample text
;BQ=code128, x=20dots,y=40dots,narrow_bar_width=1,wide_bar_width:2,height=30dots,rotation=0deg,readable=0(no)
BQ,20,40,1,2,30,0,0,1234-1243-43214-432141
;end label
E
Push to printer:
$ lpr -P godex test.ezpl
You would need to avoid any filtering. Print using a RAW filter, as configured in the CUPS interface, or by default in your lpadmin statement. You did not state how the printer was connected, but if IP, your destination would most-likely be socket://ip.addr.ess:9100.
I am a PC guy so I don't know CUPS well, but I have used zpl and epl on PC's and found that they really like to get the raw print files. I always do a :
filecopy "c:\zplfile.txt" "\computername\printershare" type command.
I have used wordpad too, if I just want to do some text. But for labels and barcodes I would see if there is a way for you to send the raw zpl or epl to the printer port. Hope this helps.
Thanks. I have looked at it some more. It seems that while using cups you cannot send raw ZPL commands to the printer. Like what I did was create the printer in cups as a socket and started a netcat listener on 9100 and then issued some sort of command to the printer
nc -l localhost 9100
zpl_mine="^XA ~SD10 ^PW 850 ^MM T ^MN W ^JUS ^XZ,";echo $zpl_mine | nc localhost 9100 -w 1
and this does not send the information to the printer, but I have seen on some forums that you have to use some form of language like C to parse the information

Resources