]> The Tcpdump Group git mirrors - tcpdump/blob - print-wb.c
put __attribute__((packed)) to packet headers. s/u_short/u_int16_t/ and so
[tcpdump] / print-wb.c
1 /*
2 * Copyright (c) 1993, 1994, 1995, 1996
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22 #ifndef lint
23 static const char rcsid[] =
24 "@(#) $Header: /tcpdump/master/tcpdump/print-wb.c,v 1.29 2002-11-09 17:19:31 itojun Exp $ (LBL)";
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <tcpdump-stdinc.h>
32
33 #include <stdio.h>
34
35 #include "interface.h"
36 #include "addrtoname.h"
37
38 /* XXX need to add byte-swapping macros! */
39
40 /*
41 * Largest packet size. Everything should fit within this space.
42 * For instance, multiline objects are sent piecewise.
43 */
44 #define MAXFRAMESIZE 1024
45
46 /*
47 * Multiple drawing ops can be sent in one packet. Each one starts on a
48 * an even multiple of DOP_ALIGN bytes, which must be a power of two.
49 */
50 #define DOP_ALIGN 4
51 #define DOP_ROUNDUP(x) ((((int)(x)) + (DOP_ALIGN - 1)) & ~(DOP_ALIGN - 1))
52 #define DOP_NEXT(d)\
53 ((struct dophdr *)((u_char *)(d) + \
54 DOP_ROUNDUP(ntohs((d)->dh_len) + sizeof(*(d)))))
55
56 /*
57 * Format of the whiteboard packet header.
58 * The transport level header.
59 */
60 struct pkt_hdr {
61 u_int32_t ph_src; /* site id of source */
62 u_int32_t ph_ts; /* time stamp (for skew computation) */
63 u_int16_t ph_version; /* version number */
64 u_char ph_type; /* message type */
65 u_char ph_flags; /* message flags */
66 } __attribute__((packed));
67
68 /* Packet types */
69 #define PT_DRAWOP 0 /* drawing operation */
70 #define PT_ID 1 /* announcement packet */
71 #define PT_RREQ 2 /* repair request */
72 #define PT_RREP 3 /* repair reply */
73 #define PT_KILL 4 /* terminate participation */
74 #define PT_PREQ 5 /* page vector request */
75 #define PT_PREP 7 /* page vector reply */
76
77 #ifdef PF_USER
78 #undef PF_USER /* {Digital,Tru64} UNIX define this, alas */
79 #endif
80
81 /* flags */
82 #define PF_USER 0x01 /* hint that packet has interactive data */
83 #define PF_VIS 0x02 /* only visible ops wanted */
84
85 struct PageID {
86 u_int32_t p_sid; /* session id of initiator */
87 u_int32_t p_uid; /* page number */
88 } __attribute__((packed));
89
90 struct dophdr {
91 u_int32_t dh_ts; /* sender's timestamp */
92 u_int16_t dh_len; /* body length */
93 u_char dh_flags;
94 u_char dh_type; /* body type */
95 /* body follows */
96 } __attribute__((packed));
97 /*
98 * Drawing op sub-types.
99 */
100 #define DT_RECT 2
101 #define DT_LINE 3
102 #define DT_ML 4
103 #define DT_DEL 5
104 #define DT_XFORM 6
105 #define DT_ELL 7
106 #define DT_CHAR 8
107 #define DT_STR 9
108 #define DT_NOP 10
109 #define DT_PSCODE 11
110 #define DT_PSCOMP 12
111 #define DT_REF 13
112 #define DT_SKIP 14
113 #define DT_HOLE 15
114 #define DT_MAXTYPE 15
115
116 /*
117 * A drawing operation.
118 */
119 struct pkt_dop {
120 struct PageID pd_page; /* page that operations apply to */
121 u_int32_t pd_sseq; /* start sequence number */
122 u_int32_t pd_eseq; /* end sequence number */
123 /* drawing ops follow */
124 } __attribute__((packed));
125
126 /*
127 * A repair request.
128 */
129 struct pkt_rreq {
130 u_int32_t pr_id; /* source id of drawops to be repaired */
131 struct PageID pr_page; /* page of drawops */
132 u_int32_t pr_sseq; /* start seqno */
133 u_int32_t pr_eseq; /* end seqno */
134 } __attribute__((packed));
135
136 /*
137 * A repair reply.
138 */
139 struct pkt_rrep {
140 u_int32_t pr_id; /* original site id of ops */
141 struct pkt_dop pr_dop;
142 /* drawing ops follow */
143 } __attribute__((packed));
144
145 struct id_off {
146 u_int32_t id;
147 u_int32_t off;
148 } __attribute__((packed));
149
150 struct pgstate {
151 u_int32_t slot;
152 struct PageID page;
153 u_int16_t nid;
154 u_int16_t rsvd;
155 /* seqptr's */
156 } __attribute__((packed));
157
158 /*
159 * An announcement packet.
160 */
161 struct pkt_id {
162 u_int32_t pi_mslot;
163 struct PageID pi_mpage; /* current page */
164 struct pgstate pi_ps;
165 /* seqptr's */
166 /* null-terminated site name */
167 } __attribute__((packed));
168
169 struct pkt_preq {
170 struct PageID pp_page;
171 u_int32_t pp_low;
172 u_int32_t pp_high;
173 } __attribute__((packed));
174
175 struct pkt_prep {
176 u_int32_t pp_n; /* size of pageid array */
177 /* pgstate's follow */
178 } __attribute__((packed));
179
180 static int
181 wb_id(const struct pkt_id *id, u_int len)
182 {
183 int i;
184 const char *cp;
185 const struct id_off *io;
186 char c;
187 int nid;
188
189 printf(" wb-id:");
190 if (len < sizeof(*id) || (u_char *)(id + 1) > snapend)
191 return (-1);
192 len -= sizeof(*id);
193
194 printf(" %u/%s:%u (max %u/%s:%u) ",
195 (u_int32_t)ntohl(id->pi_ps.slot),
196 ipaddr_string(&id->pi_ps.page.p_sid),
197 (u_int32_t)ntohl(id->pi_ps.page.p_uid),
198 (u_int32_t)ntohl(id->pi_mslot),
199 ipaddr_string(&id->pi_mpage.p_sid),
200 (u_int32_t)ntohl(id->pi_mpage.p_uid));
201
202 nid = ntohs(id->pi_ps.nid);
203 len -= sizeof(*io) * nid;
204 io = (struct id_off *)(id + 1);
205 cp = (char *)(io + nid);
206 if ((u_char *)cp + len <= snapend) {
207 putchar('"');
208 (void)fn_print((u_char *)cp, (u_char *)cp + len);
209 putchar('"');
210 }
211
212 c = '<';
213 for (i = 0; i < nid && (u_char *)io < snapend; ++io, ++i) {
214 printf("%c%s:%u",
215 c, ipaddr_string(&io->id), (u_int32_t)ntohl(io->off));
216 c = ',';
217 }
218 if (i >= nid) {
219 printf(">");
220 return (0);
221 }
222 return (-1);
223 }
224
225 static int
226 wb_rreq(const struct pkt_rreq *rreq, u_int len)
227 {
228 printf(" wb-rreq:");
229 if (len < sizeof(*rreq) || (u_char *)(rreq + 1) > snapend)
230 return (-1);
231
232 printf(" please repair %s %s:%u<%u:%u>",
233 ipaddr_string(&rreq->pr_id),
234 ipaddr_string(&rreq->pr_page.p_sid),
235 (u_int32_t)ntohl(rreq->pr_page.p_uid),
236 (u_int32_t)ntohl(rreq->pr_sseq),
237 (u_int32_t)ntohl(rreq->pr_eseq));
238 return (0);
239 }
240
241 static int
242 wb_preq(const struct pkt_preq *preq, u_int len)
243 {
244 printf(" wb-preq:");
245 if (len < sizeof(*preq) || (u_char *)(preq + 1) > snapend)
246 return (-1);
247
248 printf(" need %u/%s:%u",
249 (u_int32_t)ntohl(preq->pp_low),
250 ipaddr_string(&preq->pp_page.p_sid),
251 (u_int32_t)ntohl(preq->pp_page.p_uid));
252 return (0);
253 }
254
255 static int
256 wb_prep(const struct pkt_prep *prep, u_int len)
257 {
258 int n;
259 const struct pgstate *ps;
260 const u_char *ep = snapend;
261
262 printf(" wb-prep:");
263 if (len < sizeof(*prep)) {
264 return (-1);
265 }
266 n = ntohl(prep->pp_n);
267 ps = (const struct pgstate *)(prep + 1);
268 while (--n >= 0 && (u_char *)ps < ep) {
269 const struct id_off *io, *ie;
270 char c = '<';
271
272 printf(" %u/%s:%u",
273 (u_int32_t)ntohl(ps->slot),
274 ipaddr_string(&ps->page.p_sid),
275 (u_int32_t)ntohl(ps->page.p_uid));
276 io = (struct id_off *)(ps + 1);
277 for (ie = io + ps->nid; io < ie && (u_char *)io < ep; ++io) {
278 printf("%c%s:%u", c, ipaddr_string(&io->id),
279 (u_int32_t)ntohl(io->off));
280 c = ',';
281 }
282 printf(">");
283 ps = (struct pgstate *)io;
284 }
285 return ((u_char *)ps <= ep? 0 : -1);
286 }
287
288
289 const char *dopstr[] = {
290 "dop-0!",
291 "dop-1!",
292 "RECT",
293 "LINE",
294 "ML",
295 "DEL",
296 "XFORM",
297 "ELL",
298 "CHAR",
299 "STR",
300 "NOP",
301 "PSCODE",
302 "PSCOMP",
303 "REF",
304 "SKIP",
305 "HOLE",
306 };
307
308 static int
309 wb_dops(const struct dophdr *dh, u_int32_t ss, u_int32_t es)
310 {
311 printf(" <");
312 for ( ; ss <= es; ++ss) {
313 register int t = dh->dh_type;
314
315 if (t > DT_MAXTYPE)
316 printf(" dop-%d!", t);
317 else {
318 printf(" %s", dopstr[t]);
319 if (t == DT_SKIP || t == DT_HOLE) {
320 u_int32_t ts = ntohl(dh->dh_ts);
321 printf("%d", ts - ss + 1);
322 if (ss > ts || ts > es) {
323 printf("[|]");
324 if (ts < ss)
325 return (0);
326 }
327 ss = ts;
328 }
329 }
330 dh = DOP_NEXT(dh);
331 if ((u_char *)dh > snapend) {
332 printf("[|wb]");
333 break;
334 }
335 }
336 printf(" >");
337 return (0);
338 }
339
340 static int
341 wb_rrep(const struct pkt_rrep *rrep, u_int len)
342 {
343 const struct pkt_dop *dop = &rrep->pr_dop;
344
345 printf(" wb-rrep:");
346 if (len < sizeof(*rrep) || (u_char *)(rrep + 1) > snapend)
347 return (-1);
348 len -= sizeof(*rrep);
349
350 printf(" for %s %s:%u<%u:%u>",
351 ipaddr_string(&rrep->pr_id),
352 ipaddr_string(&dop->pd_page.p_sid),
353 (u_int32_t)ntohl(dop->pd_page.p_uid),
354 (u_int32_t)ntohl(dop->pd_sseq),
355 (u_int32_t)ntohl(dop->pd_eseq));
356
357 if (vflag)
358 return (wb_dops((const struct dophdr *)(dop + 1),
359 ntohl(dop->pd_sseq), ntohl(dop->pd_eseq)));
360 return (0);
361 }
362
363 static int
364 wb_drawop(const struct pkt_dop *dop, u_int len)
365 {
366 printf(" wb-dop:");
367 if (len < sizeof(*dop) || (u_char *)(dop + 1) > snapend)
368 return (-1);
369 len -= sizeof(*dop);
370
371 printf(" %s:%u<%u:%u>",
372 ipaddr_string(&dop->pd_page.p_sid),
373 (u_int32_t)ntohl(dop->pd_page.p_uid),
374 (u_int32_t)ntohl(dop->pd_sseq),
375 (u_int32_t)ntohl(dop->pd_eseq));
376
377 if (vflag)
378 return (wb_dops((const struct dophdr *)(dop + 1),
379 ntohl(dop->pd_sseq), ntohl(dop->pd_eseq)));
380 return (0);
381 }
382
383 /*
384 * Print whiteboard multicast packets.
385 */
386 void
387 wb_print(register const void *hdr, register u_int len)
388 {
389 register const struct pkt_hdr *ph;
390
391 ph = (const struct pkt_hdr *)hdr;
392 if (len < sizeof(*ph) || (u_char *)(ph + 1) > snapend) {
393 printf("[|wb]");
394 return;
395 }
396 len -= sizeof(*ph);
397
398 if (ph->ph_flags)
399 printf("*");
400 switch (ph->ph_type) {
401
402 case PT_KILL:
403 printf(" wb-kill");
404 return;
405
406 case PT_ID:
407 if (wb_id((struct pkt_id *)(ph + 1), len) >= 0)
408 return;
409 break;
410
411 case PT_RREQ:
412 if (wb_rreq((struct pkt_rreq *)(ph + 1), len) >= 0)
413 return;
414 break;
415
416 case PT_RREP:
417 if (wb_rrep((struct pkt_rrep *)(ph + 1), len) >= 0)
418 return;
419 break;
420
421 case PT_DRAWOP:
422 if (wb_drawop((struct pkt_dop *)(ph + 1), len) >= 0)
423 return;
424 break;
425
426 case PT_PREQ:
427 if (wb_preq((struct pkt_preq *)(ph + 1), len) >= 0)
428 return;
429 break;
430
431 case PT_PREP:
432 if (wb_prep((struct pkt_prep *)(ph + 1), len) >= 0)
433 return;
434 break;
435
436 default:
437 printf(" wb-%d!", ph->ph_type);
438 return;
439 }
440 }