1 |
|
|
/* $OpenBSD: print-wb.c,v 1.10 2017/08/30 09:23:00 otto 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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
|
|
} |