b1164b611fe44361bf5f05543b6cb1a709086262
[obnox/wireshark/wip.git] / packet-lpd.c
1 /* packet-lpr.c
2  * Routines for LPR and LPRng packet disassembly
3  * Gilbert Ramirez <gram@verdict.uthscsa.edu>
4  *
5  * $Id: packet-lpd.c,v 1.7 1999/03/23 03:14:39 gram Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@unicom.net>
9  * Copyright 1998 Gerald Combs
10  *
11  * 
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.
16  * 
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.
21  * 
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.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
33 #endif
34
35 #include <string.h>
36
37 #include <glib.h>
38 #include "packet.h"
39
40 enum lpr_type { request, response };
41
42 void
43 dissect_lpd(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
44 {
45         proto_tree      *lpd_tree;
46         proto_item      *ti;
47         enum lpr_type   lpr_packet_type;
48         char            *newline, *printer, *line_pos;
49         int                     substr_len, curr_offset;
50
51         /* This information comes from the LPRng HOWTO, which also describes
52                 RFC 1179. http://www.astart.com/lprng/LPRng-HOWTO.html */
53         char            *lpd_client_code[] = {
54                 "Unknown command",
55                 "LPC: start print",
56                 "LPR: transfer a printer job",
57                 "LPQ: print short form of queue status",
58                 "LPQ: print long form of queue status",
59                 "LPRM: remove jobs",
60                 "LPRng lpc: do control operation",
61                 "LPRng lpr: transfer a block format print job",
62                 "LPRng lpc: secure command transfer",
63                 "LPRng lpq: verbose status information"
64         };
65         char            *lpd_server_code[] = {
66                 "Success: accepted, proceed",
67                 "Queue not accepting jobs",
68                 "Queue temporarily full, retry later",
69                 "Bad job format, do not retry"
70         };
71
72
73         if (pd[offset+1] == '\n') {
74                 lpr_packet_type = response;
75         }
76         else if (pd[offset] <= 9) {
77                 lpr_packet_type = request;
78         }
79         else {
80                 lpr_packet_type = response;
81         }
82
83
84         if (check_col(fd, COL_PROTOCOL))
85                 col_add_str(fd, COL_PROTOCOL, "LPD");
86         if (check_col(fd, COL_INFO)) {
87                 if (lpr_packet_type == request) {
88                         col_add_str(fd, COL_INFO, lpd_client_code[pd[offset]]);
89                 }
90                 else {
91                         col_add_str(fd, COL_INFO, "LPD response");
92                 }
93         }
94
95         if (tree) {
96                 ti = proto_tree_add_item(tree, offset, fd->cap_len - offset,
97                   "Line Printer Daemon Protocol");
98                 lpd_tree = proto_tree_new();
99                 proto_item_add_subtree(ti, lpd_tree, ETT_LPD);
100
101                 if (lpr_packet_type == request) {
102                         if (pd[offset] <= 9) {
103                                 proto_tree_add_item(lpd_tree, offset,           1,
104                                         lpd_client_code[pd[offset]]);
105                         }
106                         else {
107                                 proto_tree_add_item(lpd_tree, offset,           1,
108                                         lpd_client_code[0]);
109                         }
110                         printer = g_strdup(&pd[offset+1]);
111
112                         /* get rid of the new-line so that the tree prints out nicely */
113                         if (printer[fd->cap_len - offset - 2] == 0x0a) {
114                                 printer[fd->cap_len - offset - 2] = 0;
115                         }
116                         proto_tree_add_item(lpd_tree, offset+1, fd->cap_len - (offset+1),
117                                         /*"Printer/options: %s", &pd[offset+1]);*/
118                                         "Printer/options: %s", printer);
119                         g_free(printer);
120                 }
121                 else {
122                         if (pd[offset] <= 3) {
123                                 proto_tree_add_item(lpd_tree, offset, 2, "Response: %s",
124                                         lpd_server_code[pd[offset]]);
125                         }
126                         else {
127                                 printer = strdup(&pd[offset]);
128                                 line_pos = printer;
129                                 curr_offset = offset;
130                                 while (fd->cap_len > curr_offset) {
131                                         newline = strchr(line_pos, '\n');
132                                         if (!newline) {
133                                                 proto_tree_add_item(lpd_tree, curr_offset,
134                                                         fd->cap_len - offset, "Text: %s", line_pos);
135                                                 break;
136                                         }
137                                         *newline = 0;
138                                         substr_len = strlen(line_pos);
139                                         proto_tree_add_item(lpd_tree, curr_offset, substr_len + 1,
140                                                 "Text: %s", line_pos);
141                                         curr_offset += substr_len + 1;
142                                         line_pos = newline + 1;
143                                 }
144                         }
145                 }
146         }
147 }
148