2 * Routines for LPR and LPRng packet disassembly
3 * Gilbert Ramirez <gram@xiexie.org>
5 * $Id: packet-lpd.c,v 1.22 2000/08/13 14:08:27 deniel 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 OLD_CHECK_DISPLAY_AS_DATA(proto_lpd, pd, offset, fd, tree);
83 /* rfc1179 states that all responses are 1 byte long */
84 if (END_OF_FRAME == 1) {
85 lpr_packet_type = response;
87 else if (pd[offset] <= 9) {
88 lpr_packet_type = request;
91 lpr_packet_type = unknown;
94 if (check_col(fd, COL_PROTOCOL))
95 col_add_str(fd, COL_PROTOCOL, "LPD");
96 if (check_col(fd, COL_INFO)) {
97 if (lpr_packet_type == request) {
98 col_add_str(fd, COL_INFO, lpd_client_code[pd[offset]]);
100 else if (lpr_packet_type == response) {
101 col_add_str(fd, COL_INFO, "LPD response");
104 col_add_str(fd, COL_INFO, "LPD continuation");
109 ti = proto_tree_add_item(tree, proto_lpd, NullTVB, offset,
110 END_OF_FRAME, FALSE);
111 lpd_tree = proto_item_add_subtree(ti, ett_lpd);
113 if (lpr_packet_type == response) {
114 proto_tree_add_boolean_hidden(lpd_tree, hf_lpd_response, NullTVB, 0, 0, TRUE);
116 proto_tree_add_boolean_hidden(lpd_tree, hf_lpd_request, NullTVB, 0, 0, TRUE);
119 if (lpr_packet_type == request) {
120 printer = find_printer_string(pd, offset+1, END_OF_FRAME);
122 if (pd[offset] <= 9 && printer) {
123 proto_tree_add_text(lpd_tree, NullTVB, offset, 1,
124 lpd_client_code[pd[offset]]);
125 proto_tree_add_text(lpd_tree, NullTVB, offset+1,
126 strlen(printer), "Printer/options: %s", printer);
129 old_dissect_data(pd, offset, fd, tree);
135 else if (lpr_packet_type == response) {
136 int response = pd[offset];
139 proto_tree_add_text(lpd_tree, NullTVB, offset, 1, "Response: %s",
140 lpd_server_code[response]);
143 old_dissect_data(pd, offset, fd, tree);
147 old_dissect_data(pd, offset, fd, tree);
154 find_printer_string(const u_char *pd, int offset, int frame_length)
161 final_offset = offset + frame_length;
163 /* try to find end of string, either 0x0a or 0x00 */
164 for (i = offset; i < final_offset; i++) {
166 if (c == '\x00' || c == '\x0a') {
168 string = g_malloc(bytes+1);
169 memcpy(string, &pd[offset], bytes);
180 proto_register_lpd(void)
182 static hf_register_info hf[] = {
184 { "Response", "lpd.response",
185 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
186 "TRUE if LPD response" }},
189 { "Request", "lpd.request",
190 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
191 "TRUE if LPD request" }}
193 static gint *ett[] = {
197 proto_lpd = proto_register_protocol("Line Printer Daemon Protocol", "lpd");
198 proto_register_field_array(proto_lpd, hf, array_length(hf));
199 proto_register_subtree_array(ett, array_length(ett));
203 proto_reg_handoff_lpd(void)
205 old_dissector_add("tcp.port", TCP_PORT_PRINTER, &dissect_lpd);