Initial revision
[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  * Ethereal - Network traffic analyzer
6  * By Gerald Combs <gerald@unicom.net>
7  * Copyright 1998 Gerald Combs
8  *
9  * 
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  * 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  * 
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <gtk/gtk.h>
30
31 #include <stdio.h>
32 #include <string.h>
33
34 #ifdef HAVE_SYS_TYPES_H
35 # include <sys/types.h>
36 #endif
37
38 #ifdef HAVE_NETINET_IN_H
39 # include <netinet/in.h>
40 #endif
41
42 #include <pcap.h>
43
44 #include "packet.h"
45 #include "ethereal.h"
46 #include "etypes.h"
47
48 enum lpr_type { request, response };
49
50 void
51 dissect_lpd(const u_char *pd, int offset, frame_data *fd, GtkTree *tree)
52 {
53         GtkWidget       *lpd_tree, *ti;
54         enum lpr_type   lpr_packet_type;
55         char            *newline, *printer, *line_pos;
56         int                     substr_len, curr_offset;
57
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[] = {
61                 "Unknown command",
62                 "LPC: start print",
63                 "LPR: transfer a printer job",
64                 "LPQ: print short form of queue status",
65                 "LPQ: print long form of queue status",
66                 "LPRM: remove jobs",
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"
71         };
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"
77         };
78
79
80         if (pd[offset+1] == '\n') {
81                 lpr_packet_type = response;
82         }
83         else if (pd[offset] <= 9) {
84                 lpr_packet_type = request;
85         }
86         else {
87                 lpr_packet_type = response;
88         }
89
90
91         if (fd->win_info[0]) {
92                 strcpy(fd->win_info[3], "LPD");
93                 if (lpr_packet_type == request) {
94                         strcpy(fd->win_info[4], lpd_client_code[pd[offset]]);
95                 }
96                 else {
97                         strcpy(fd->win_info[4], "LPD response");
98                 }
99         }
100
101         if (tree) {
102                 ti = add_item_to_tree(GTK_WIDGET(tree), offset, fd->cap_len - offset,
103                   "Line Printer Daemon Protocol");
104                 lpd_tree = gtk_tree_new();
105                 add_subtree(ti, lpd_tree, ETT_LPD);
106
107                 if (lpr_packet_type == request) {
108                         if (pd[offset] <= 9) {
109                                 add_item_to_tree(lpd_tree, offset,              1,
110                                         lpd_client_code[pd[offset]]);
111                         }
112                         else {
113                                 add_item_to_tree(lpd_tree, offset,              1,
114                                         lpd_client_code[0]);
115                         }
116                         printer = strdup(&pd[offset+1]);
117
118                         /* get rid of the new-line so that the tree prints out nicely */
119                         if (printer[fd->cap_len - offset - 2] == 0x0a) {
120                                 printer[fd->cap_len - offset - 2] = 0;
121                         }
122                         add_item_to_tree(lpd_tree, offset+1, fd->cap_len - (offset+1),
123                                         /*"Printer/options: %s", &pd[offset+1]);*/
124                                         "Printer/options: %s", printer);
125                         free(printer);
126                 }
127                 else {
128                         if (pd[offset] <= 3) {
129                                 add_item_to_tree(lpd_tree, offset, 2, "Response: %s",
130                                         lpd_server_code[pd[offset]]);
131                         }
132                         else {
133                                 printer = strdup(&pd[offset]);
134                                 line_pos = printer;
135                                 curr_offset = offset;
136                                 while (fd->cap_len > curr_offset) {
137                                         newline = strchr(line_pos, '\n');
138                                         if (!newline) {
139                                                 add_item_to_tree(lpd_tree, curr_offset,
140                                                         fd->cap_len - offset, "Text: %s", line_pos);
141                                                 break;
142                                         }
143                                         *newline = 0;
144                                         substr_len = strlen(line_pos);
145                                         add_item_to_tree(lpd_tree, curr_offset, substr_len + 1,
146                                                 "Text: %s", line_pos);
147                                         curr_offset += substr_len + 1;
148                                         line_pos = newline + 1;
149                                 }
150                         }
151                 }
152         }
153 }
154