Windows Printer Discovery
I was surprised to find that Windows had automatically detected my printer, even though the printer doesn't talk SMB/NMB and Windows doesn't talk DNS-SD. It turns out that a printer communication protocol called WS-print has been available since Windows Vista.
Trigger warning: Web Services. XML and SOAP. It's all very 2006.
Discovery
WS-Discovery uses SOAP-over-UDP to discover devices on the network. Thanks to Wireshark, we can see the service transmites a UDP packet to 239.255.255.250 (or ff02::c for IPv6), port 3702:
1 <?xml version="1.0" encoding="utf-8"?> 2 <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:wsd="http://schemas.xmlsoap.org/ws/2005/04/discovery" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsdp="http://schemas.xmlsoap.org/ws/2006/02/devprof" xmlns:nprt="http://schemas.microsoft.com/windows/2006/08/wdp/print"> 3 <soap:Header> 4 <wsa:Action>http://schemas.xmlsoap.org/ws/2005/04/discovery/Hello</wsa:Action> 5 <wsa:MessageID>urn:uuid:3af4b6f3-50bc-49cc-b9f6-4e37e9d875af</wsa:MessageID> 6 <wsa:To>urn:schemas-xmlsoap-org:ws:2005:04:discovery</wsa:To> 7 <wsd:AppSequence InstanceId="53" MessageNumber="2"/> 8 </soap:Header> 9 <soap:Body> 10 <wsd:Hello> 11 <wsa:EndpointReference> 12 <wsa:Address>uuid:f6fe2f0a-325f-4454-aa07-0888d60ffa64</wsa:Address> 13 </wsa:EndpointReference> 14 <wsd:Types>wsdp:Device nprt:PrintDeviceType</wsd:Types> 15 <wsd:XAddrs>http://[fe80::221:b7ff:fe88:ced0]:50000/lxkWSdevice</wsd:XAddrs> 16 <wsd:MetadataVersion>8</wsd:MetadataVersion> 17 </wsd:Hello> 18 </soap:Body> 19 </soap:Envelope>
Already the XML is flying thick and fast. We have to deal with WS-Addressing and Devices Profile for Web Services, not to mention WS-Print itself. Of note are:
- uuid
within the wsa:Address element, which is the printer's 'Unique identifier' as displayed within Devices and Printers → dell2330 → Properties → Web Services → Troubleshooting Information.
- types
- identify this as a printer
- transport address
within the xsd:Xaddrs element, which shows upin Devices and Printers → dell2330 → Properties → Hardware → dell2330: WSD Print Provider → Location
Wireshark also shows the client broadcasts a Resolve message for the UUID (to the multicast address), and the client responds with a ResolveMatch packet (to the client's address) containing much the same information as the original broadcast. There is actually a slight difference: the transport address in this response doesn't include the /lxkWSdevice path. Probably just a quirk of the printer's code?
Clients can also initiate a search for a device. python-ws-discovery reveals that the client transmits a Probe message, and the service responds with a ProbeMatches message containing the EndpointReference as above (but again without /lxkWSdevice).
Printing
Back to Wireshark, the client does a HTTP POST to the transport address:
1 <?xml version="1.0" encoding="utf-8"?> 2 <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"> 3 <soap:Header> 4 <wsa:To>uuid:f6fe2f0a-325f-4454-aa07-0888d60ffa64</wsa:To> 5 <wsa:Action>http://schemas.xmlsoap.org/ws/2004/09/transfer/Get</wsa:Action> 6 <wsa:MessageID>urn:uuid:4ab98165-5095-499d-8222-cd55690eb4c8</wsa:MessageID> 7 <wsa:ReplyTo> 8 <wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address> 9 </wsa:ReplyTo> 10 <wsa:From> 11 <wsa:Address>urn:uuid:8570035b-a8b5-45c0-b0f8-89d70974e534</wsa:Address> 12 </wsa:From> 13 </soap:Header> 14 <soap:Body/> 15 </soap:Envelope>
to which the printer responds:
1 <?xml version="1.0" encoding="utf-8"?> 2 <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:wsdp="http://schemas.xmlsoap.org/ws/2006/02/devprof" xmlns:nprt="http://schemas.microsoft.com/windows/2006/08/wdp/print" xmlns:PNPX="http://schemas.microsoft.com/windows/pnpx/2005/10" xmlns:UNS1="http://www.microsoft.com/windows/test/testdevice/11/2005"> 3 <soap:Header> 4 <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> 5 <wsa:MessageID>urn:uuid:02191325-8505-40a1-97fd-c732fbdbc59a</wsa:MessageID> 6 <wsa:RelatesTo>urn:uuid:9f6331b5-cdf9-44ba-b819-d99364bf9bad</wsa:RelatesTo> 7 <wsa:Action>http://schemas.xmlsoap.org/ws/2004/09/transfer/GetResponse</wsa:Action> 8 </soap:Header> 9 <soap:Body> 10 <wsx:Metadata> 11 <wsx:MetadataSection Dialect="http://schemas.xmlsoap.org/ws/2006/02/devprof/ThisDevice"> 12 <wsdp:ThisDevice> 13 <wsdp:FriendlyName xml:lang="en">dell2330</wsdp:FriendlyName> 14 <wsdp:FirmwareVersion>NR.APS.N310</wsdp:FirmwareVersion> 15 <wsdp:SerialNumber>7218W78</wsdp:SerialNumber> 16 </wsdp:ThisDevice> 17 </wsx:MetadataSection> 18 <wsx:MetadataSection Dialect="http://schemas.xmlsoap.org/ws/2006/02/devprof/ThisModel"> 19 <wsdp:ThisModel> 20 <wsdp:Manufacturer xml:lang="en">Dell</wsdp:Manufacturer> 21 <wsdp:ManufacturerUrl>http://www.dell.com</wsdp:ManufacturerUrl> 22 <wsdp:ModelName xml:lang="en">Dell 2330dn Laser Printer</wsdp:ModelName> 23 <wsdp:ModelNumber>Dell 2330dn Laser Printer</wsdp:ModelNumber> 24 <wsdp:ModelUrl>http://www.lexmark.com/MD/?func=producthome</wsdp:ModelUrl> 25 <wsdp:PresentationUrl>http://[fe80::221:b7ff:fe88:ced0]</wsdp:PresentationUrl> 26 <PNPX:DeviceCategory>Printers</PNPX:DeviceCategory> 27 </wsdp:ThisModel> 28 </wsx:MetadataSection> 29 <wsx:MetadataSection Dialect="http://schemas.xmlsoap.org/ws/2006/02/devprof/Relationship"> 30 <wsdp:Relationship Type="http://schemas.xmlsoap.org/ws/2006/02/devprof/host"> 31 <wsdp:Hosted> 32 <wsa:EndpointReference> 33 <wsa:Address>http://[fe80::221:b7ff:fe88:ced0]:4033/Printer1/WebServices</wsa:Address> 34 <wsa:ReferenceProperties> 35 <UNS1:ServiceIdentifier>uri:prn</UNS1:ServiceIdentifier> 36 </wsa:ReferenceProperties> 37 </wsa:EndpointReference> 38 <wsdp:Types>nprt:PrinterServiceType</wsdp:Types> 39 <wsdp:ServiceId>uri:f6fe2f0a-325f-4454-aa07-0888d60ffa64/Printer1/WebServices</wsdp:ServiceId> 40 <PNPX:CompatibleId>http://schemas.microsoft.com/windows/2006/08/wdp/print/PrinterServiceType</PNPX:CompatibleId> 41 </wsdp:Hosted> 42 </wsdp:Relationship> 43 </wsx:MetadataSection> 44 </wsx:Metadata> 45 </soap:Body> 46 </soap:Envelope>
Of interest are the references to Lexmark. It seems they manufactured this printer for Dell! This also explains the origin of /lxkWSdevice in the transport address.
Further communication takes place using a new URL, given for the uri:prn endpoint in this message. (Weirdly, Windows uses IPv4 from this point onwards, but I'll assume that communication over IPv6 would produce similar results. Here's an example:
1 <?xml version="1.0" encoding="utf-8"?> 2 <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:UNS1="http://www.microsoft.com/windows/test/testdevice/11/2005" xmlns:pri="http://schemas.microsoft.com/windows/2006/08/wdp/print"> 3 <soap:Header> 4 <wsa:To>http://192.168.0.6:4033/Printer1/WebServices</wsa:To> 5 <wsa:Action>http://schemas.microsoft.com/windows/2006/08/wdp/print/GetPrinterElements</wsa:Action> 6 <wsa:MessageID>urn:uuid:a74b1759-ac13-4482-a332-46226111e174</wsa:MessageID> 7 <wsa:ReplyTo> 8 <wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address> 9 </wsa:ReplyTo> 10 <wsa:From> 11 <wsa:Address>urn:uuid:ba7cf5a6-a324-4b3e-bd51-48b34dba6d76</wsa:Address> 12 </wsa:From> 13 <UNS1:ServiceIdentifier>uri:prn</UNS1:ServiceIdentifier> 14 </soap:Header> 15 <soap:Body> 16 <pri:GetPrinterElementsRequest> 17 <pri:RequestedElements> 18 <pri:Name>pri:PrinterDescription</pri:Name> 19 <pri:Name>pri:PrinterConfiguration</pri:Name> 20 <pri:Name>pri:PrinterCapabilities</pri:Name> 21 <pri:Name>pri:DefaultPrintTicket</pri:Name> 22 <pri:Name>pri:PrinterStatus</pri:Name> 23 </pri:RequestedElements> 24 </pri:GetPrinterElementsRequest> 25 </soap:Body> 26 </soap:Envelope>
1 <?xml version="1.0"?> 2 <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:UNS1="http://www.microsoft.com/windows/test/testdevice/11/2005" xmlns:c14n="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:wsdp="http://schemas.xmlsoap.org/ws/2006/02/devprof" xmlns:lxk1="urn:lxk_ws_demo" xmlns:wse="http://schemas.xmlsoap.org/ws/2004/08/eventing" xmlns:xop="http://www.w3.org/2004/08/xop/include" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wprt="http://schemas.microsoft.com/windows/2006/08/wdp/print"> 3 <SOAP-ENV:Header> 4 <wsa:MessageID SOAP-ENV:mustUnderstand="true">uuid:3de53c9e-1694-49ac-a66c-33e6f32e65e6</wsa:MessageID> 5 <wsa:RelatesTo SOAP-ENV:mustUnderstand="true">urn:uuid:a74b1759-ac13-4482-a332-46226111e174</wsa:RelatesTo> 6 <wsa:To SOAP-ENV:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> 7 <wsa:Action SOAP-ENV:mustUnderstand="true">http://schemas.microsoft.com/windows/2006/08/wdp/print/GetPrinterElementsResponse</wsa:Action> 8 <UNS1:ServiceIdentifier SOAP-ENV:mustUnderstand="true">uri:prn</UNS1:ServiceIdentifier> 9 </SOAP-ENV:Header> 10 <SOAP-ENV:Body> 11 <wprt:GetPrinterElementsResponse> 12 <wprt:PrinterElements> 13 <wprt:ElementData Valid="true" Name="wprt:PrinterDescription"> 14 <wprt:PrinterDescription> 15 <wprt:ColorSupported>false</wprt:ColorSupported> 16 <wprt:DeviceId>MANUFACTURER:Dell;COMMAND SET:PCL 6 Emulation, PostScript Level 3 Emulation, NPAP, PJL;MODEL:Dell 2330dn Laser Printer;CLS:PRINTER;DES:Dell 2330dn Laser Printer;CID:;COMMENT:ECP1.0, LV_043D, LP_5231, LF_0056;</wprt:DeviceId> 17 <wprt:MultipleDocumentJobsSupported>false</wprt:MultipleDocumentJobsSupported> 18 <wprt:PagesPerMinute>35</wprt:PagesPerMinute> 19 <wprt:PrinterName xml:lang="en">dell2330</wprt:PrinterName> 20 <wprt:PrinterInfo xml:lang="en">DefContact and DefLocation</wprt:PrinterInfo> 21 <wprt:PrinterLocation xml:lang="en">DefLocation</wprt:PrinterLocation> 22 </wprt:PrinterDescription> 23 </wprt:ElementData> 24 <wprt:ElementData Valid="true" Name="wprt:PrinterConfiguration"> 25 <wprt:PrinterConfiguration> 26 <wprt:PrinterEventRate>1</wprt:PrinterEventRate> 27 <wprt:Storage> 28 <wprt:StorageEntry Name="RAM"> 29 <wprt:Type>RAM</wprt:Type> 30 <wprt:Size>33554432</wprt:Size> 31 <wprt:Free>-1</wprt:Free> 32 </wprt:StorageEntry> 33 </wprt:Storage> 34 <wprt:Consumables> 35 <wprt:ConsumableEntry Name="Black Toner"> 36 <wprt:Type>Toner</wprt:Type> 37 <wprt:Color>Black</wprt:Color> 38 <wprt:Level>90</wprt:Level> 39 </wprt:ConsumableEntry> 40 <wprt:ConsumableEntry Name="Fuser"> 41 <wprt:Type>Fuser</wprt:Type> 42 <wprt:Color>Other</wprt:Color> 43 <wprt:Level>93</wprt:Level> 44 </wprt:ConsumableEntry> 45 <wprt:ConsumableEntry Name="Photo Drum"> 46 <wprt:Type>PC-Drum</wprt:Type> 47 <wprt:Color>Black</wprt:Color> 48 <wprt:Level>70</wprt:Level> 49 </wprt:ConsumableEntry> 50 </wprt:Consumables> 51 <wprt:InputBins> 52 <wprt:InputBinEntry Name="Tray 1"> 53 <wprt:FeedDirection>LongEdgeFirst</wprt:FeedDirection> 54 <wprt:MediaSize>iso_a4_210x297mm</wprt:MediaSize> 55 <wprt:MediaType>other</wprt:MediaType> 56 <wprt:Capacity>250</wprt:Capacity> 57 <wprt:Level>-1</wprt:Level> 58 </wprt:InputBinEntry> 59 <wprt:InputBinEntry Name="MP Tray"> 60 <wprt:FeedDirection>LongEdgeFirst</wprt:FeedDirection> 61 <wprt:MediaSize>iso_a4_210x297mm</wprt:MediaSize> 62 <wprt:MediaType>other</wprt:MediaType> 63 <wprt:Capacity>50</wprt:Capacity> 64 <wprt:Level>-1</wprt:Level> 65 </wprt:InputBinEntry> 66 <wprt:InputBinEntry Name="Manual Paper"> 67 <wprt:FeedDirection>LongEdgeFirst</wprt:FeedDirection> 68 <wprt:MediaSize>iso_a4_210x297mm</wprt:MediaSize> 69 <wprt:MediaType>other</wprt:MediaType> 70 <wprt:Capacity>-1</wprt:Capacity> 71 <wprt:Level>-1</wprt:Level> 72 </wprt:InputBinEntry> 73 <wprt:InputBinEntry Name="Manual Envelope"> 74 <wprt:FeedDirection>LongEdgeFirst</wprt:FeedDirection> 75 <wprt:MediaSize>pwg_letter-or-a4_choice</wprt:MediaSize> 76 <wprt:MediaType>envelope</wprt:MediaType> 77 <wprt:Capacity>-1</wprt:Capacity> 78 <wprt:Level>-1</wprt:Level> 79 </wprt:InputBinEntry> 80 </wprt:InputBins> 81 <wprt:Finishings> 82 <wprt:CollationSupported>true</wprt:CollationSupported> 83 <wprt:DuplexerInstalled>true</wprt:DuplexerInstalled> 84 </wprt:Finishings> 85 <wprt:OutputBins> 86 <wprt:OutputBinEntry Name="Standard Bin"> 87 <wprt:Capacity>150</wprt:Capacity> 88 <wprt:Level>-1</wprt:Level> 89 </wprt:OutputBinEntry> 90 </wprt:OutputBins> 91 </wprt:PrinterConfiguration> 92 </wprt:ElementData> 93 <wprt:ElementData Valid="true" Name="wprt:PrinterCapabilities"> 94 <wprt:PrinterCapabilities> 95 <wprt:JobValues> 96 <wprt:JobProcessing> 97 <wprt:Copies> 98 <wprt:MaxValue>999</wprt:MaxValue> 99 </wprt:Copies> 100 <wprt:Priority> 101 <wprt:MaxValue>50</wprt:MaxValue> 102 </wprt:Priority> 103 </wprt:JobProcessing> 104 <wprt:DocumentProcessing> 105 <wprt:MediaSizeName> 106 <wprt:AllowedValue>na_letter_8.5x11in</wprt:AllowedValue> 107 </wprt:MediaSizeName> 108 <wprt:MediaType> 109 <wprt:AllowedValue>unknown</wprt:AllowedValue> 110 </wprt:MediaType> 111 <wprt:MediaColor> 112 <wprt:AllowedValue>unknown</wprt:AllowedValue> 113 </wprt:MediaColor> 114 <wprt:NumberUp> 115 <wprt:PagesPerSheet> 116 <wprt:AllowedValue>1</wprt:AllowedValue> 117 </wprt:PagesPerSheet> 118 <wprt:Direction> 119 <wprt:AllowedValue>RightDown</wprt:AllowedValue> 120 </wprt:Direction> 121 </wprt:NumberUp> 122 <wprt:Orientation> 123 <wprt:AllowedValue>Portrait</wprt:AllowedValue> 124 </wprt:Orientation> 125 <wprt:Resolution> 126 <wprt:AllowedValue> 127 <wprt:Width>1200</wprt:Width> 128 </wprt:AllowedValue> 129 </wprt:Resolution> 130 <wprt:PrintQuality> 131 <wprt:AllowedValue>Normal</wprt:AllowedValue> 132 </wprt:PrintQuality> 133 <wprt:Sides> 134 <wprt:AllowedValue>OneSided</wprt:AllowedValue> 135 </wprt:Sides> 136 </wprt:DocumentProcessing> 137 </wprt:JobValues> 138 <wprt:DocumentValues> 139 <wprt:DocumentDescription> 140 <wprt:Compression> 141 <wprt:AllowedValue>gzip</wprt:AllowedValue> 142 </wprt:Compression> 143 <wprt:Format> 144 <wprt:AllowedValue>application/octet-stream</wprt:AllowedValue> 145 </wprt:Format> 146 </wprt:DocumentDescription> 147 </wprt:DocumentValues> 148 </wprt:PrinterCapabilities> 149 </wprt:ElementData> 150 <wprt:ElementData Valid="true" Name="wprt:DefaultPrintTicket"> 151 <wprt:DefaultPrintTicket> 152 <wprt:JobDescription> 153 <wprt:JobName>Default job</wprt:JobName> 154 <wprt:JobOriginatingUserName>Unknown</wprt:JobOriginatingUserName> 155 </wprt:JobDescription> 156 </wprt:DefaultPrintTicket> 157 </wprt:ElementData> 158 <wprt:ElementData Valid="true" Name="wprt:PrinterStatus"> 159 <wprt:PrinterStatus> 160 <wprt:PrinterCurrentTime>1970-01-01T00:00:32Z</wprt:PrinterCurrentTime> 161 <wprt:PrinterState>Idle</wprt:PrinterState> 162 <wprt:QueuedJobCount>0</wprt:QueuedJobCount> 163 </wprt:PrinterStatus> 164 </wprt:ElementData> 165 </wprt:PrinterElements> 166 </wprt:GetPrinterElementsResponse> 167 </SOAP-ENV:Body> 168 </SOAP-ENV:Envelope>
If you squint, you can just about make out the IEE 1284 Device ID string in the DeviceId element (line 16).
I think that's enough XML for today.
In theory a CUPS backend could be written to discover and print to printers using WS-Print. In practice there's no point since the printers probably all implement IPP anyway.