2 * Routines for LPR and LPRng packet disassembly
3 * Gilbert Ramirez <gram@xiexie.org>
5 * $Id: packet-lpd.c,v 1.16 2000/01/22 06:22:14 guy 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 static int proto_lpd = -1;
41 static int hf_lpd_response = -1;
42 static int hf_lpd_request = -1;
44 static gint ett_lpd = -1;
46 enum lpr_type { request, response, unknown };
48 static char* find_printer_string(const u_char *pd, int offset, int frame_length);
51 dissect_lpd(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
55 enum lpr_type lpr_packet_type;
58 /* This information comes from the LPRng HOWTO, which also describes
59 RFC 1179. http://www.astart.com/lprng/LPRng-HOWTO.html */
60 char *lpd_client_code[] = {
63 "LPR: transfer a printer job",
64 "LPQ: print short form of queue status",
65 "LPQ: print long form of queue status",
67 "LPRng lpc: do control operation",
68 "LPRng lpr: transfer a block format print job",
69 "LPRng lpc: secure command transfer",
70 "LPRng lpq: verbose status information"
72 char *lpd_server_code[] = {
73 "Success: accepted, proceed",
74 "Queue not accepting jobs",
75 "Queue temporarily full, retry later",
76 "Bad job format, do not retry"
80 if (pd[offset+1] == '\n') {
81 lpr_packet_type = response;
83 else if (pd[offset] <= 9) {
84 lpr_packet_type = request;
87 lpr_packet_type = unknown;
90 if (check_col(fd, COL_PROTOCOL))
91 col_add_str(fd, COL_PROTOCOL, "LPD");
92 if (check_col(fd, COL_INFO)) {
93 if (lpr_packet_type == request) {
94 col_add_str(fd, COL_INFO, lpd_client_code[pd[offset]]);
96 else if (lpr_packet_type == response) {
97 col_add_str(fd, COL_INFO, "LPD response");
100 col_add_str(fd, COL_INFO, "LPD continuation");
105 ti = proto_tree_add_item(tree, proto_lpd, offset,
107 lpd_tree = proto_item_add_subtree(ti, ett_lpd);
109 if (lpr_packet_type == response) {
110 proto_tree_add_item_hidden(lpd_tree, hf_lpd_response, 0, 0, TRUE);
112 proto_tree_add_item_hidden(lpd_tree, hf_lpd_request, 0, 0, TRUE);
115 if (lpr_packet_type == request) {
116 printer = find_printer_string(pd, offset+1, END_OF_FRAME);
118 if (pd[offset] <= 9 && printer) {
119 proto_tree_add_text(lpd_tree, offset, 1,
120 lpd_client_code[pd[offset]]);
121 proto_tree_add_text(lpd_tree, offset+1,
122 strlen(printer), "Printer/options: %s", printer);
125 dissect_data(pd, offset, fd, tree);
131 else if (lpr_packet_type == response) {
132 int response = pd[offset];
135 proto_tree_add_text(lpd_tree, offset, 2, "Response: %s",
136 lpd_server_code[response]);
139 dissect_data(pd, offset, fd, tree);
143 dissect_data(pd, offset, fd, tree);
150 find_printer_string(const u_char *pd, int offset, int frame_length)
157 final_offset = offset + frame_length;
159 /* try to find end of string, either 0x0a or 0x00 */
160 for (i = offset; i < final_offset; i++) {
162 if (c == '\x00' || c == '\x0a') {
164 string = g_malloc(bytes+1);
165 memcpy(string, &pd[offset], bytes);
176 proto_register_lpd(void)
178 static hf_register_info hf[] = {
180 { "Response", "lpd.response",
181 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
182 "TRUE if LPD response" }},
185 { "Request", "lpd.request",
186 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
187 "TRUE if LPD request" }}
189 static gint *ett[] = {
193 proto_lpd = proto_register_protocol("Line Printer Daemon Protocol", "lpd");
194 proto_register_field_array(proto_lpd, hf, array_length(hf));
195 proto_register_subtree_array(ett, array_length(ett));