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