Will my AirPrint Code connect to an IPv6-only Printer? - printing

Below is my code to connect to an IPv4 Printer. Everything is OK.
NSString *printerURL = #"ipp://192.168.1.3:631/ipp/print" //IPv4 : OK
UIPrinter *myPrint = [UIPrinter printerWithURL:[NSURL URLWithString:printerURL]];
[myPrint contactPrinter:^(BOOL available) {
if(!available){
// Show error
}
[printInteraction printToPrinter:myPrint completionHandler:^(UIPrintInteractionController * _Nonnull printInteractionController, BOOL completed, NSError * _Nullable error) {
// Print
}];
}];
Because I do not have the IpV6 printer, I do not know what will happen with the code below:
NSString *printerURL = #"ipp://FE80::FE3F:DBFF:FE51:6BA:631/ipp/print" //IPv6 : ????
Will it connect to an IPv6 printer?

I don't have an IPv6 printer neither, nor an AirPrint-capable device.
But I have a suggestion for you, how you could test if your code works for IPv6 connections:
Use a MacBook to fake an environment which makes a iOS device in your LAN/WLAN think that they "see" and can connect to an AirPrint device.
Here are the detailed steps:
Make sure an IPv6 address is assigned to your MacBook. (How you do that is beyond the scope of this answer.)
Make sure that your MacBook's CUPS services is allowing only IPv6 connections by adding a line to cupsd.conf:
Listen [xxxx::xxxx:xxxx:xxxx:xxxx]:631
Listen /private/var/run/cupsd
# Port 631
Make sure that your cupsd.conf has also this line:
DefaultAuthType None
This makes sure you'll not need to debug Authentication or Authorization problems on top of your IPv6 and AirPrint functionality. (You can change that back later, once your current problem is solved.)
Create a shared print queue on your MacBook and name it, say, abcd. The queue does not need to connect to an AirPrint device -- any other printer will be "good enough". Also, the printer can also be IPv4-only, or USB, or Bluetooth -- as long as your MacBook can connect to it. (How you do that is beyond the scope of this answer.)
Test your printer: make sure your MacBook prints to it, and make sure that other clients are able to print to the shared queue.
Your Mac clients will now be able to "see" and use your abcd print queue -- but your iOS clients will not (yet) see an AirPrint device.
Now use the dns-sd utility to announce a fake AirPrint device to your local network, pointing to the real print queue named abcd. The general syntax for the command is this:
dns-sd -P <Name> <Type> <Domain> <Port> <Hostname> <IP> [<TXT>...]
Now to run the real command, open a Terminal.app window and type this:
dns-sd \
-P AirPrint-abcd \
_ipp._tcp,_universal \
local. \
631 \
mymacbook.local. \
xxxx::xxxx:xxxx:xxxx:xxxx \
pdl="application/pdf,image/urf" \
kind="document" \
priority="1" \
product="Model Name of my Printer" \
rp="printers/abcd" \
URF="DM3" \
Duplex="T" \
Color="T" \
note="Testing AirPrint on MacBook" \
txtvers="1" \
qtotal="1" \
printer-type="0x0480FFFC" \
printer-state="3" \
air="none" \
UUID="54321abc-1234-1234-abcd-ffa8e4bdcbf8"
Here,
xxxx::xxxx:xxxx:xxxx:xxxx is the IPv6 address of your MacBook
mymacbook is the hostname of your MacBook
Now your iOS client should be able to see and use an AirPrint device named AirPrint-abcd. The service announcement also tells them that the connection path to this AirPrinter is the IPv6 address of your MacBook and the port to use is 631.
Additional Explanation:
The -P parameter to the dns-sd utility will make a Bonjour "proxy announcement" to your local LAN/WLAN. For details about this utility see man dns-sd. For more background, see dns-sd.org and these other answers.

Related

smartcard + configfile: how to avoid error "File name too long"?

I am trying to change my openconnect usage from command line to configfile.
I need to use a smartcard (StarSign CUT S, from Giesecke & Devrient GmbH) in order to access my VPN.
My current command line works fine and I can connect to the VPN:
$ openconnect \
--authgroup=<my_gateway> \
--protocol=gp \
--servercert <...> \
--disable-ipv6 \
--cafile <file.pem> \
<my_server_url> \
-c "pkcs11:model=XXXXXXXXXXXXXXXX;manufacturer=A.E.T.%20Europe%20B.V.;serial=XXXXXXXXXXXXXXXX;token=XXXXXXXXX;id=<...>;object=<...>;type=cert"
But when I try this configfile:
(All arguments are exactly the same!)
# vpn.config
authgroup = <my_gateway>
protocol = gp
servercert = <...>
disable-ipv6
cafile = <file.pem>
server = <my_server_url>
certificate = "pkcs11:model=XXXXXXXXXXXXXXXX;manufacturer=A.E.T.%20Europe%20B.V.;serial=XXXXXXXXXXXXXXXX;token=XXXXXXXXX;id=<...>;object=<...>;type=cert"
I get this error:
$ openconnect --config=vpn.config
Failed to open key/certificate file <...>: File name too long
Loading certificate failed. Aborting.
Failed to open HTTPS connection to <...>
Failed to complete authentication
Any idea on how to make it work? Or is it a bug in openconnect?
Thanks.
PS 1:
$ openconnect --version
OpenConnect version v9.01
Using GnuTLS 3.7.7. Features present: PKCS#11, HOTP software token, TOTP software token, System keys, DTLS, ESP
Supported protocols: anyconnect (default), nc, gp, pulse, f5, fortinet, array
Default vpnc-script (override with --script): /etc/vpnc/vpnc-script
PS 2: All commands executed as root.
Remove the double quotes from the configuration file:
# vpn.config
...
certificate = pkcs11:model=XXXXXXXXXXXXXXXX;manufacturer=A.E.T.%20Europe%20B.V.;serial=XXXXXXXXXXXXXXXX;token=XXXXXXXXX;id=<...>;object=<...>;type=cert

Xorg/xinput does not recognise evdev devices in Docker (Alpine base image)

I'm trying to run an Xorg server in Docker, due to the host OS not having any X installed, nor can it preserve installed packages between updates (however, Docker containers are preserved).
My goal is to run an X app in "kiosk" mode (no desktop environment, no window manager, just a single X app taking up the whole display), confined to the Docker container - specifically, Chromium to open the web management interface of the host (which is embedded in the distro).
After reading a swathe of Xorg/Xinput articles, setup guides, manuals and whatnot, and I'm still not sure what's going wrong.
This is my current Dockerfile:
FROM alpine:3.16
# Install Xorg
RUN \
apk add --no-cache \
xorg-server eudev mesa \
xinput xinit xhost evtest \
xf86-input-libinput xf86-video-fbdev xf86-input-evdev \
dbus xrandr xset xsetroot \
xeyes libinput mesa-dri-swrast mesa-dri-gallium mesa-egl
# Install Chromium
RUN \
apk add --no-cache \
chromium
CMD [ "/usr/bin/xinit", "/usr/bin/chromium-browser", "--no-sandbox", "--kiosk" ]
Then run it by passing in all the necessary udev entries:
docker run --rm -it \
--device=/dev/input \
--device=/dev/console \
--device=/dev/dri \
--device=/dev/fb0 \
--device=/dev/tty \
--device=/dev/tty1 \
--device=/dev/vga_arbiter \
--device=/dev/snd \
--cap-add=SYS_TTY_CONFIG \
alpine-xorg:latest http://172.17.0.1:8123/
In my case, I'm trying to use a 7" touchscreen HDMI display, designed for Raspberry Pis (however, I'm not using a Pi, but an Intel based mini PC).
Xorg logs aren't much help, they contain just init information about Xinput, no devices identified or anything.
Here's the log: https://paste-bin.xyz/65152
I've also fiddled around with evtest - in my case, /dev/input/event3 corresponds to the touchscreen's input, and evtest successfully recognises them: https://paste-bin.xyz/65154
However xinput doesn't even see these as a possible device:
a369b238e0f1:/var/log# xinput list
⎡ Virtual core pointer id=2 [master pointer (3)]
⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)]
⎣ Virtual core keyboard id=3 [master keyboard (2)]
↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)]
According to the Xorg logs, the appropriate init scripts have been loaded:
[ 3724.820] (==) Using system config directory "/usr/share/X11/xorg.conf.d"
/usr/share/X11/xorg.conf.d/10-evdev.conf exists, and contains all the needed entries:
#
# Catch-all evdev loader for udev-based systems
# We don't simply match on any device since that also adds accelerometers
# and other devices that we don't really want to use. The list below
# matches everything but joysticks.
Section "InputClass"
Identifier "evdev pointer catchall"
MatchIsPointer "on"
MatchDevicePath "/dev/input/event*"
Driver "evdev"
EndSection
Section "InputClass"
Identifier "evdev keyboard catchall"
MatchIsKeyboard "on"
MatchDevicePath "/dev/input/event*"
Driver "evdev"
EndSection
Section "InputClass"
Identifier "evdev touchpad catchall"
MatchIsTouchpad "on"
MatchDevicePath "/dev/input/event*"
Driver "evdev"
EndSection
Section "InputClass"
Identifier "evdev tablet catchall"
MatchIsTablet "on"
MatchDevicePath "/dev/input/event*"
Driver "evdev"
EndSection
Section "InputClass"
Identifier "evdev touchscreen catchall"
MatchIsTouchscreen "on"
MatchDevicePath "/dev/input/event*"
Driver "evdev"
EndSection
Where is this setup going wrong, why can't xinput register the evdev devices when the necessary events are clearly there and usable?

How to get Serial number or Mac address of Airprint printer from iOS application programatically

I implemented printing functionality in my iOS app. My iPad is connected to AirPrint Printer on same wi-fi. Is it possible to get Serial number or Mac address of printer in iOS application before giving print command?
You could use a two stage approach:
Query for the IP address of the printer, using standard Bonjour methods.
Find the MAC address of the printer using arp.
I cannot provide you the code... but the command line utility dns-sd will do to demo the first step.
Whatever info this command line can return to you, the dns-sd library API can also do. See /usr/include/dns_sd.h for more details....
The following outlines the steps to follow for the first stage.
1a.
Assuming that you want to find out the instance names for all AirPrint-capable devices in domain dns-sd.org....
You'd then use:
dns-sd -B _ipp._tcp.,_universal dns-sd.org.
Browsing for _ipp._tcp.,_universal.dns-sd.org.
DATE: ---Sat 02 Jul 2016---
14:20:07.190 ...STARTING...
Timestamp A/R Flags if Domain Service Type Instance Name
14:20:07.626 Add 2 0 dns-sd.org. _ipp._tcp. Stuart's Home AirPrint Printer
^C
(Note the ,_universal suffix [requesting the AirPrint subset] to the standard query of _ipp._tcp. which requests the list of all generic IPP-capable print devices...)
You've now found one instance with the name "Stuart's Home AirPrint Printer".
1b.
You can now query for the hostname of the network node which is hosting service instance "Stuart's Home AirPrint Printer":
dns-sd -L "Stuart's Home AirPrint Printer" _ipp._tcp. dns-sd.org.
Lookup Stuart's Home AirPrint Printer._ipp._tcp..dns-sd.org.
DATE: ---Sat 02 Jul 2016---
14:37:44.436 ...STARTING...
14:37:44.813 Stuart's\032Home\032AirPrint\032Printer._ipp._tcp.dns-sd.org. can be reached at airprint.dns-sd.org.:631 (interface 0)
txtvers=1 \
qtotal=1 \
pdl=application/postscript,application/vnd.hp-PCL,application/vnd.hp-PCLXL,application/pdf,image/urf \
rp=ipp/printer \
URF=CP99,W8,OB10,PQ3-4-5,ADOBERGB24,DEVRGB24,DEVW8,SRGB24,IS1-2-4,MT1-2-3-5-12,MT1-2-3-5-12,RS600 \
ty=HP\ LaserJet\ 400\ color\ M451nw \
product=\(HP\ LaserJet\ 400\ color\ M451nw\) \
priority=10 \
adminurl=http://www.dns-sd.org/ServerStaticSetup.html \
note=At\ Stuart\'s\ house \
Color=T \
Duplex=F \
Scan=F
^C
Note the line "...can be reached at airprint.dns-sd.org.:631". This gives you the hostname you are looking for.
1c.
You can now ask for the IP addresses (IPv4 as well as IPv6) where this AirPrint instance is hosted:
dns-sd -Gv4v6 airprint.dns-sd.org.
DATE: ---Sat 02 Jul 2016---
14:19:12.040 ...STARTING...
Timestamp A/R Flags if Hostname Address TTL
14:19:12.426 Add 2 0 airprint.dns-sd.org. 50.197.138.101 75
14:19:12.544 Add 2 0 airprint.dns-sd.org. 0000:0000:0000:0000:0000:0000:0000:0000% 77 No Such Record
^C
So this AirPrinter does have an IPv4 (50.197.138.101) but no IPv6 address.
2.
To find the respective MAC address, just use ARP.

LPQ on Windows 8 doesn't find my printer

I have enabled the LPD and LPR on a Windows 8.
I want to print some files using the LPR command, but i can't even find the printer with the LPQ.
I can print normally with the printer through (ctrl + p), but i can't find it with the LPQ command.
C:\>lpq -S localhost -P HiTi_P510L
Servidor LPD do WindowsErro: the specified printer doesn't exists.
If i try to run the LPR directly i have the same error saying that the printer doesn't exists.
C:\>lpr -S 127.0.0.1 -P HiTi_P510L camila.jpg
Erro: o servidor de impressão não aceitou a requisição. Trabalho interrompido.
The event log:
LPD refused the job \\127.0.0.1\HiTi_P510L because the specified printer doens't exist on this computer.
net view:
C:\Windows\system32>net view \\myserver
Recursos compartilhados em \\myserver
Nome do compartilhamento Tipo Usado como Comentário
--------------------------------------------------------------
HiTi_P510L Impressão P510L
Comando concluído com êxito.
C:\Windows\system32>
update: port 515 is listening.
C:\>netstat -an
Conexões ativas
Proto Endereço local Endereço externo Estado
TCP 0.0.0.0:80 0.0.0.0:0 LISTENING
TCP 0.0.0.0:135 0.0.0.0:0 LISTENING
TCP 0.0.0.0:445 0.0.0.0:0 LISTENING
TCP 0.0.0.0:515 0.0.0.0:0 LISTENING
TCP 0.0.0.0:2869 0.0.0.0:0 LISTENING
TCP 0.0.0.0:49152 0.0.0.0:0 LISTENING
...
I can also telnet localhost 515 which gives me a black screen, and after i press ENTER i have this:
☺
Conexão ao host perdida.
C:\Windows\system32>
Any suggestion?
UPDATE: There are two issues here. The answer to the question regarding LPR/LPD is resolved here while the other issue was relating to the actual print stream is answered at the bottom of this response.
Ensure your firewall is off (or at least allowing 515 to pass through). Also, ensure you are using the IP of your network adapter and not local host as LPD tends to bind to an actual IP address.
If you want to ensure that your data is passed through without modification / encoding then use -o l in the command line. For example:
lpr -S <workstation_ip> -P <printer_share> -o l test.ps
lpr -S 192.168.1.6 -P P510L -o l test.ps
Also ensure the file you are sending is actually supported by the print device. While some printers support graphic formats most are expecting PCL, PS, XPS, PDF etc. Some support TIF and other JPG etc. Ensure the file you are sending is supported by the device.
In the end the issue appears to be the proprietary nature of the device and as such, the requirement is there to push the file through the print driver. One simple way is to use a graphics application that supports command line printing. One option is MS Paint.
mspaint /pt IMG_1234.jpg "Hiti P510L"
The printer name (Hiti P510L) is the name that appears in the devices and printers screen in Windows.

Plot RTT histogram using wireshark or other tool

I have a little office network and I'm experiencing a huge internet link latency. We have a simple network topology: a computer configured as router running ubuntu server 10.10, 2 network cards (one to internet link, other to office network) and a switch connecting 20 computers. I have a huge tcpdump log collected at the router and I would like to plot a histogram with the RTT time of all TCP streams to try to find out the best solution to this latency problem. So, could somebody tell me how to do it using wireshark or other tool?
Wireshark or tshark can give you the TCP RTT for each received ACK packet using tcp.analysis.ack_rtt which measures the time delta between capturing a TCP packet and the ACK for that packet.
You need to be careful with this as most of your ACK packets will be from your office machines ACKing packets received from the internet, so you will be measuring the RTT between your router seeing the packet from the internet and seeing the ACK from your office machine.
To measure your internet RTT you need to look for ACKS from the internet (ACKing data sent from your network). Assuming your office machines have IP addresses like 192.168.1.x and you have logged all the data on the LAN port of your router you could use a display filter like so:
tcp.analysis.ack_rtt and ip.dst==192.168.1.255/24
To dump the RTTs into a .csv for analysis you could use a tshark command like so;
tshark -r router.pcap -Y "tcp.analysis.ack_rtt and ip.dst==192.168.1.255/24" -e tcp.analysis.ack_rtt -T fields -E separator=, -E quote=d > rtt.csv
The -r option tells tshark to read from your .pcap file
The -Y option specifies the display filter to use (-R without -2 is deprecated)
The -e option specifies the field to output
The -T options specify the output formatting
You can use the mergecap utility to merge all your pcap files into one one file before running this command. Turning this output into a histogram should be easy!
Here's the 5-min perlscript inspired by rupello's answer:
#!/usr/bin/perl
# For a live histogram of rtt latencies, save this file as /tmp/hist.pl and chmod +x /tmp/hist.pl, then run:
# tshark -i wlp2s0 -Y "tcp.analysis.ack_rtt and ip.dst==192.168.0.0/16" -e tcp.analysis.ack_rtt -T fields -E separator=, -E quote=d | /tmp/hist.pl
# Don't forget to update the interface "wlp2s0" and "and ip.dst==..." bits as appropriate, type "ip addr" to get those.
#t[$m=0]=20;
#t[++$m]=10;
#t[++$m]=5;
#t[++$m]=2;
#t[++$m]=1;
#t[++$m]=0.9;
#t[++$m]=0.8;
#t[++$m]=0.7;
#t[++$m]=0.6;
#t[++$m]=0.5;
#t[++$m]=0.4;
#t[++$m]=0.3;
#t[++$m]=0.2;
#t[++$m]=0.1;
#t[++$m]=0.05;
#t[++$m]=0.04;
#t[++$m]=0.03;
#t[++$m]=0.02;
#t[++$m]=0.01;
#t[++$m]=0.005;
#t[++$m]=0.001;
#t[++$m]=0;
#h[0]=0;
while (<>) {
s/\"//g; $n=$_; chomp($n); $o++;
for ($i=$m;$i>=0;$i--) { if ($n<=$t[$i]) { $h[$i]++; $i=-1; }; };
if ($i==-1) { $h[0]++; };
print "\033c";
for (0..$m) { printf "%6s %6s %8s\n",$t[$_],sprintf("%3.2f",$h[$_]/$o*100),$h[$_]; };
}
The newer versions of tshark seem to work better with a "stdbuf -i0 -o0 -e0 " in front of the "tshark".
PS Does anyone know if wireshark has DNS and ICMP rtt stats built in or how to easily get those?
2018 Update: See https://github.com/dagelf/pping

Resources