Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-lpd.c
blobce05637734f238cd7a461df5c942943e5116aeb8
1 /* packet-lpd.c
2 * Routines for LPR and LPRng packet disassembly
3 * Gilbert Ramirez <gram@alumni.rice.edu>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
14 #include <epan/packet.h>
16 void proto_register_lpd(void);
17 void proto_reg_handoff_lpd(void);
19 static dissector_handle_t lpd_handle;
21 #define TCP_PORT_PRINTER 515
23 static int proto_lpd;
24 static int hf_lpd_response;
25 static int hf_lpd_request;
26 static int hf_lpd_client_code;
27 static int hf_lpd_printer_option;
28 static int hf_lpd_response_code;
30 static int ett_lpd;
32 enum lpr_type { request, response, unknown };
34 static int find_printer_string(tvbuff_t *tvb, int offset);
36 /* This information comes from the LPRng HOWTO, which also describes
37 RFC 1179. http://www.astart.com/lprng/LPRng-HOWTO.html */
38 static const value_string lpd_client_code[] = {
39 { 1, "LPC: start print / jobcmd: abort" },
40 { 2, "LPR: transfer a printer job / jobcmd: receive control file" },
41 { 3, "LPQ: print short form of queue status / jobcmd: receive data file" },
42 { 4, "LPQ: print long form of queue status" },
43 { 5, "LPRM: remove jobs" },
44 { 6, "LPRng lpc: do control operation" },
45 { 7, "LPRng lpr: transfer a block format print job" },
46 { 8, "LPRng lpc: secure command transfer" },
47 { 9, "LPRng lpq: verbose status information" },
48 { 0, NULL }
50 static const value_string lpd_server_code[] = {
51 { 0, "Success: accepted, proceed" },
52 { 1, "Queue not accepting jobs" },
53 { 2, "Queue temporarily full, retry later" },
54 { 3, "Bad job format, do not retry" },
55 { 0, NULL }
58 static int
59 dissect_lpd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
61 proto_tree *lpd_tree;
62 proto_item *ti, *hidden_item;
63 enum lpr_type lpr_packet_type;
64 uint8_t code;
65 int printer_len;
67 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LPD");
68 col_clear(pinfo->cinfo, COL_INFO);
70 /* rfc1179 states that all responses are 1 byte long */
71 code = tvb_get_uint8(tvb, 0);
72 if (tvb_reported_length(tvb) == 1) {
73 lpr_packet_type = response;
75 else if (code <= 9) {
76 lpr_packet_type = request;
78 else {
79 lpr_packet_type = unknown;
82 if (lpr_packet_type == request && code !=0) {
83 col_add_str(pinfo->cinfo, COL_INFO, val_to_str(code, lpd_client_code, "Unknown client code: %u"));
85 else if (lpr_packet_type == response) {
86 col_set_str(pinfo->cinfo, COL_INFO, "LPD response");
88 else {
89 col_set_str(pinfo->cinfo, COL_INFO, "LPD continuation");
92 ti = proto_tree_add_item(tree, proto_lpd, tvb, 0, -1, ENC_NA);
93 lpd_tree = proto_item_add_subtree(ti, ett_lpd);
95 if (lpr_packet_type == response) {
96 hidden_item = proto_tree_add_boolean(lpd_tree, hf_lpd_response,
97 tvb, 0, 0, true);
98 } else {
99 hidden_item = proto_tree_add_boolean(lpd_tree, hf_lpd_request,
100 tvb, 0, 0, true);
102 proto_item_set_hidden(hidden_item);
104 if (lpr_packet_type == request) {
105 printer_len = find_printer_string(tvb, 1);
107 if (code <= 9 && printer_len != -1) {
108 proto_tree_add_uint_format(lpd_tree, hf_lpd_client_code, tvb, 0, 1, code,
109 "%s", val_to_str(code, lpd_client_code, "Unknown client code: %u"));
110 proto_tree_add_item(lpd_tree, hf_lpd_printer_option, tvb, 1, printer_len, ENC_ASCII);
112 else {
113 call_data_dissector(tvb, pinfo, lpd_tree);
116 else if (lpr_packet_type == response) {
117 if (code <= 3) {
118 proto_tree_add_item(lpd_tree, hf_lpd_response_code, tvb, 0, 1, ENC_BIG_ENDIAN);
120 else {
121 call_data_dissector(tvb, pinfo, lpd_tree);
124 else {
125 call_data_dissector(tvb, pinfo, lpd_tree);
128 return tvb_captured_length(tvb);
132 static int
133 find_printer_string(tvbuff_t *tvb, int offset)
135 int i;
137 /* try to find end of string, either '\n' or '\0' */
138 i = tvb_find_uint8(tvb, offset, -1, '\0');
139 if (i == -1)
140 i = tvb_find_uint8(tvb, offset, -1, '\n');
141 if (i == -1)
142 return -1;
143 return i - offset; /* length of string */
147 void
148 proto_register_lpd(void)
150 static hf_register_info hf[] = {
151 { &hf_lpd_response,
152 { "Response", "lpd.response",
153 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
154 "true if LPD response", HFILL }},
156 { &hf_lpd_request,
157 { "Request", "lpd.request",
158 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
159 "true if LPD request", HFILL }},
161 { &hf_lpd_client_code,
162 { "Client code", "lpd.client_code",
163 FT_UINT8, BASE_DEC, VALS(lpd_client_code), 0x0,
164 NULL, HFILL }},
166 { &hf_lpd_printer_option,
167 { "Printer/options", "lpd.printer_option",
168 FT_STRING, BASE_NONE, NULL, 0x0,
169 NULL, HFILL }},
171 { &hf_lpd_response_code,
172 { "Response", "lpd.response_code",
173 FT_UINT8, BASE_DEC, VALS(lpd_server_code), 0x0,
174 NULL, HFILL }},
176 static int *ett[] = {
177 &ett_lpd,
180 proto_lpd = proto_register_protocol("Line Printer Daemon Protocol", "LPD", "lpd");
181 lpd_handle = register_dissector("lpd", dissect_lpd, proto_lpd);
182 proto_register_field_array(proto_lpd, hf, array_length(hf));
183 proto_register_subtree_array(ett, array_length(ett));
186 void
187 proto_reg_handoff_lpd(void)
189 dissector_add_uint_with_preference("tcp.port", TCP_PORT_PRINTER, lpd_handle);
193 * Editor modelines - https://www.wireshark.org/tools/modelines.html
195 * Local variables:
196 * c-basic-offset: 8
197 * tab-width: 8
198 * indent-tabs-mode: t
199 * End:
201 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
202 * :indentSize=8:tabSize=8:noTabs=false: