2 * Routines for LPR and LPRng packet disassembly
3 * Gilbert Ramirez <gram@xiexie.org>
5 * $Id: packet-lpd.c,v 1.19 2000/05/11 08:15:23 gram Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@zing.org>
9 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
40 #define TCP_PORT_PRINTER 515
42 static int proto_lpd = -1;
43 static int hf_lpd_response = -1;
44 static int hf_lpd_request = -1;
46 static gint ett_lpd = -1;
48 enum lpr_type { request, response, unknown };
50 static char* find_printer_string(const u_char *pd, int offset, int frame_length);
53 dissect_lpd(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
57 enum lpr_type lpr_packet_type;
60 /* This information comes from the LPRng HOWTO, which also describes
61 RFC 1179. http://www.astart.com/lprng/LPRng-HOWTO.html */
62 char *lpd_client_code[] = {
64 "LPC: start print / jobcmd: abort",
65 "LPR: transfer a printer job / jobcmd: receive control file",
66 "LPQ: print short form of queue status / jobcmd: receive data file",
67 "LPQ: print long form of queue status",
69 "LPRng lpc: do control operation",
70 "LPRng lpr: transfer a block format print job",
71 "LPRng lpc: secure command transfer",
72 "LPRng lpq: verbose status information"
74 char *lpd_server_code[] = {
75 "Success: accepted, proceed",
76 "Queue not accepting jobs",
77 "Queue temporarily full, retry later",
78 "Bad job format, do not retry"
81 /* rfc1179 states that all responses are 1 byte long */
82 if (END_OF_FRAME == 1) {
83 lpr_packet_type = response;
85 else if (pd[offset] <= 9) {
86 lpr_packet_type = request;
89 lpr_packet_type = unknown;
92 if (check_col(fd, COL_PROTOCOL))
93 col_add_str(fd, COL_PROTOCOL, "LPD");
94 if (check_col(fd, COL_INFO)) {
95 if (lpr_packet_type == request) {
96 col_add_str(fd, COL_INFO, lpd_client_code[pd[offset]]);
98 else if (lpr_packet_type == response) {
99 col_add_str(fd, COL_INFO, "LPD response");
102 col_add_str(fd, COL_INFO, "LPD continuation");
107 ti = proto_tree_add_item(tree, proto_lpd, NullTVB, offset,
109 lpd_tree = proto_item_add_subtree(ti, ett_lpd);
111 if (lpr_packet_type == response) {
112 proto_tree_add_item_hidden(lpd_tree, hf_lpd_response, NullTVB, 0, 0, TRUE);
114 proto_tree_add_item_hidden(lpd_tree, hf_lpd_request, NullTVB, 0, 0, TRUE);
117 if (lpr_packet_type == request) {
118 printer = find_printer_string(pd, offset+1, END_OF_FRAME);
120 if (pd[offset] <= 9 && printer) {
121 proto_tree_add_text(lpd_tree, NullTVB, offset, 1,
122 lpd_client_code[pd[offset]]);
123 proto_tree_add_text(lpd_tree, NullTVB, offset+1,
124 strlen(printer), "Printer/options: %s", printer);
127 dissect_data(pd, offset, fd, tree);
133 else if (lpr_packet_type == response) {
134 int response = pd[offset];
137 proto_tree_add_text(lpd_tree, NullTVB, offset, 1, "Response: %s",
138 lpd_server_code[response]);
141 dissect_data(pd, offset, fd, tree);
145 dissect_data(pd, offset, fd, tree);
152 find_printer_string(const u_char *pd, int offset, int frame_length)
159 final_offset = offset + frame_length;
161 /* try to find end of string, either 0x0a or 0x00 */
162 for (i = offset; i < final_offset; i++) {
164 if (c == '\x00' || c == '\x0a') {
166 string = g_malloc(bytes+1);
167 memcpy(string, &pd[offset], bytes);
178 proto_register_lpd(void)
180 static hf_register_info hf[] = {
182 { "Response", "lpd.response",
183 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
184 "TRUE if LPD response" }},
187 { "Request", "lpd.request",
188 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
189 "TRUE if LPD request" }}
191 static gint *ett[] = {
195 proto_lpd = proto_register_protocol("Line Printer Daemon Protocol", "lpd");
196 proto_register_field_array(proto_lpd, hf, array_length(hf));
197 proto_register_subtree_array(ett, array_length(ett));
201 proto_reg_handoff_lpd(void)
203 dissector_add("tcp.port", TCP_PORT_PRINTER, &dissect_lpd);