1*a70f6581Skn /* $OpenBSD: ds.c,v 1.12 2022/07/27 19:42:22 kn Exp $ */
2be8be80fSkettenis
3be8be80fSkettenis /*
4be8be80fSkettenis * Copyright (c) 2012 Mark Kettenis
5be8be80fSkettenis *
6be8be80fSkettenis * Permission to use, copy, modify, and distribute this software for any
7be8be80fSkettenis * purpose with or without fee is hereby granted, provided that the above
8be8be80fSkettenis * copyright notice and this permission notice appear in all copies.
9be8be80fSkettenis *
10be8be80fSkettenis * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11be8be80fSkettenis * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12be8be80fSkettenis * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13be8be80fSkettenis * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14be8be80fSkettenis * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15be8be80fSkettenis * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16be8be80fSkettenis * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17be8be80fSkettenis */
18be8be80fSkettenis
19be8be80fSkettenis #include <sys/types.h>
20be8be80fSkettenis #include <sys/poll.h>
21be8be80fSkettenis #include <sys/queue.h>
22be8be80fSkettenis #include <err.h>
23be8be80fSkettenis #include <fcntl.h>
24be8be80fSkettenis #include <stdio.h>
25be8be80fSkettenis #include <stdlib.h>
26be8be80fSkettenis #include <string.h>
27be8be80fSkettenis #include <unistd.h>
28be8be80fSkettenis
29be8be80fSkettenis #include "ds.h"
30d73a4c4fSkn #include "ldom_util.h"
31be8be80fSkettenis
32be8be80fSkettenis void ldc_rx_ctrl_vers(struct ldc_conn *, struct ldc_pkt *);
33be8be80fSkettenis void ldc_rx_ctrl_rtr(struct ldc_conn *, struct ldc_pkt *);
34be8be80fSkettenis void ldc_rx_ctrl_rts(struct ldc_conn *, struct ldc_pkt *);
35be8be80fSkettenis void ldc_rx_ctrl_rdx(struct ldc_conn *, struct ldc_pkt *);
36be8be80fSkettenis
37be8be80fSkettenis void ldc_send_ack(struct ldc_conn *);
3866e96321Skettenis void ldc_send_nack(struct ldc_conn *);
39be8be80fSkettenis void ldc_send_rtr(struct ldc_conn *);
40be8be80fSkettenis void ldc_send_rts(struct ldc_conn *);
41be8be80fSkettenis void ldc_send_rdx(struct ldc_conn *);
42be8be80fSkettenis
43be8be80fSkettenis void
ldc_rx_ctrl(struct ldc_conn * lc,struct ldc_pkt * lp)44be8be80fSkettenis ldc_rx_ctrl(struct ldc_conn *lc, struct ldc_pkt *lp)
45be8be80fSkettenis {
46be8be80fSkettenis switch (lp->ctrl) {
47be8be80fSkettenis case LDC_VERS:
48be8be80fSkettenis ldc_rx_ctrl_vers(lc, lp);
49be8be80fSkettenis break;
50be8be80fSkettenis
51be8be80fSkettenis case LDC_RTS:
52be8be80fSkettenis ldc_rx_ctrl_rts(lc, lp);
53be8be80fSkettenis break;
54be8be80fSkettenis
55be8be80fSkettenis case LDC_RTR:
56be8be80fSkettenis ldc_rx_ctrl_rtr(lc, lp);
57be8be80fSkettenis break;
58be8be80fSkettenis
59be8be80fSkettenis case LDC_RDX:
60be8be80fSkettenis ldc_rx_ctrl_rdx(lc, lp);
61be8be80fSkettenis break;
62be8be80fSkettenis
63be8be80fSkettenis default:
64be8be80fSkettenis DPRINTF(("CTRL/0x%02x/0x%02x\n", lp->stype, lp->ctrl));
65be8be80fSkettenis ldc_reset(lc);
66be8be80fSkettenis break;
67be8be80fSkettenis }
68be8be80fSkettenis }
69be8be80fSkettenis
70be8be80fSkettenis void
ldc_rx_ctrl_vers(struct ldc_conn * lc,struct ldc_pkt * lp)71be8be80fSkettenis ldc_rx_ctrl_vers(struct ldc_conn *lc, struct ldc_pkt *lp)
72be8be80fSkettenis {
73be8be80fSkettenis struct ldc_pkt *lvp = (struct ldc_pkt *)lp;
74be8be80fSkettenis
75be8be80fSkettenis switch (lp->stype) {
76be8be80fSkettenis case LDC_INFO:
77be8be80fSkettenis if (lc->lc_state == LDC_RCV_VERS) {
78be8be80fSkettenis DPRINTF(("Spurious CTRL/INFO/VERS: state %d\n",
79be8be80fSkettenis lc->lc_state));
80be8be80fSkettenis return;
81be8be80fSkettenis }
824ed9aa84Skettenis DPRINTF(("CTRL/INFO/VERS %d.%d\n", lvp->major, lvp->minor));
83be8be80fSkettenis if (lvp->major == LDC_VERSION_MAJOR &&
84be8be80fSkettenis lvp->minor == LDC_VERSION_MINOR)
85be8be80fSkettenis ldc_send_ack(lc);
86be8be80fSkettenis else
8766e96321Skettenis ldc_send_nack(lc);
88be8be80fSkettenis break;
89be8be80fSkettenis
90be8be80fSkettenis case LDC_ACK:
91be8be80fSkettenis if (lc->lc_state != LDC_SND_VERS) {
92be8be80fSkettenis DPRINTF(("Spurious CTRL/ACK/VERS: state %d\n",
93be8be80fSkettenis lc->lc_state));
94be8be80fSkettenis ldc_reset(lc);
95be8be80fSkettenis return;
96be8be80fSkettenis }
97be8be80fSkettenis DPRINTF(("CTRL/ACK/VERS\n"));
98be8be80fSkettenis ldc_send_rts(lc);
99be8be80fSkettenis break;
100be8be80fSkettenis
101be8be80fSkettenis case LDC_NACK:
102be8be80fSkettenis DPRINTF(("CTRL/NACK/VERS\n"));
103be8be80fSkettenis ldc_reset(lc);
104be8be80fSkettenis break;
105be8be80fSkettenis
106be8be80fSkettenis default:
107be8be80fSkettenis DPRINTF(("CTRL/0x%02x/VERS\n", lp->stype));
108be8be80fSkettenis ldc_reset(lc);
109be8be80fSkettenis break;
110be8be80fSkettenis }
111be8be80fSkettenis }
112be8be80fSkettenis
113be8be80fSkettenis void
ldc_rx_ctrl_rts(struct ldc_conn * lc,struct ldc_pkt * lp)114be8be80fSkettenis ldc_rx_ctrl_rts(struct ldc_conn *lc, struct ldc_pkt *lp)
115be8be80fSkettenis {
116be8be80fSkettenis switch (lp->stype) {
117be8be80fSkettenis case LDC_INFO:
118be8be80fSkettenis if (lc->lc_state != LDC_RCV_VERS) {
119be8be80fSkettenis DPRINTF(("Spurious CTRL/INFO/RTS: state %d\n",
120be8be80fSkettenis lc->lc_state));
121be8be80fSkettenis ldc_reset(lc);
122be8be80fSkettenis return;
123be8be80fSkettenis }
124be8be80fSkettenis DPRINTF(("CTRL/INFO/RTS\n"));
125be8be80fSkettenis if (lp->env != LDC_MODE_RELIABLE) {
126be8be80fSkettenis ldc_reset(lc);
127be8be80fSkettenis return;
128be8be80fSkettenis }
129be8be80fSkettenis ldc_send_rtr(lc);
130be8be80fSkettenis break;
131be8be80fSkettenis
132be8be80fSkettenis case LDC_ACK:
133be8be80fSkettenis DPRINTF(("CTRL/ACK/RTS\n"));
134be8be80fSkettenis ldc_reset(lc);
135be8be80fSkettenis break;
136be8be80fSkettenis
137be8be80fSkettenis case LDC_NACK:
138be8be80fSkettenis DPRINTF(("CTRL/NACK/RTS\n"));
139be8be80fSkettenis ldc_reset(lc);
140be8be80fSkettenis break;
141be8be80fSkettenis
142be8be80fSkettenis default:
143be8be80fSkettenis DPRINTF(("CTRL/0x%02x/RTS\n", lp->stype));
144be8be80fSkettenis ldc_reset(lc);
145be8be80fSkettenis break;
146be8be80fSkettenis }
147be8be80fSkettenis }
148be8be80fSkettenis
149be8be80fSkettenis void
ldc_rx_ctrl_rtr(struct ldc_conn * lc,struct ldc_pkt * lp)150be8be80fSkettenis ldc_rx_ctrl_rtr(struct ldc_conn *lc, struct ldc_pkt *lp)
151be8be80fSkettenis {
152be8be80fSkettenis switch (lp->stype) {
153be8be80fSkettenis case LDC_INFO:
154be8be80fSkettenis if (lc->lc_state != LDC_SND_RTS) {
155be8be80fSkettenis DPRINTF(("Spurious CTRL/INFO/RTR: state %d\n",
156be8be80fSkettenis lc->lc_state));
157be8be80fSkettenis ldc_reset(lc);
158be8be80fSkettenis return;
159be8be80fSkettenis }
160be8be80fSkettenis DPRINTF(("CTRL/INFO/RTR\n"));
161be8be80fSkettenis if (lp->env != LDC_MODE_RELIABLE) {
162be8be80fSkettenis ldc_reset(lc);
163be8be80fSkettenis return;
164be8be80fSkettenis }
165be8be80fSkettenis ldc_send_rdx(lc);
166be8be80fSkettenis #if 0
167be8be80fSkettenis lc->lc_start(lc);
168be8be80fSkettenis #endif
169be8be80fSkettenis break;
170be8be80fSkettenis
171be8be80fSkettenis case LDC_ACK:
172be8be80fSkettenis DPRINTF(("CTRL/ACK/RTR\n"));
173be8be80fSkettenis ldc_reset(lc);
174be8be80fSkettenis break;
175be8be80fSkettenis
176be8be80fSkettenis case LDC_NACK:
177be8be80fSkettenis DPRINTF(("CTRL/NACK/RTR\n"));
178be8be80fSkettenis ldc_reset(lc);
179be8be80fSkettenis break;
180be8be80fSkettenis
181be8be80fSkettenis default:
182be8be80fSkettenis DPRINTF(("CTRL/0x%02x/RTR\n", lp->stype));
183be8be80fSkettenis ldc_reset(lc);
184be8be80fSkettenis break;
185be8be80fSkettenis }
186be8be80fSkettenis }
187be8be80fSkettenis
188be8be80fSkettenis void
ldc_rx_ctrl_rdx(struct ldc_conn * lc,struct ldc_pkt * lp)189be8be80fSkettenis ldc_rx_ctrl_rdx(struct ldc_conn *lc, struct ldc_pkt *lp)
190be8be80fSkettenis {
191be8be80fSkettenis switch (lp->stype) {
192be8be80fSkettenis case LDC_INFO:
193be8be80fSkettenis if (lc->lc_state != LDC_SND_RTR) {
194be8be80fSkettenis DPRINTF(("Spurious CTRL/INFO/RTR: state %d\n",
195be8be80fSkettenis lc->lc_state));
196be8be80fSkettenis ldc_reset(lc);
197be8be80fSkettenis return;
198be8be80fSkettenis }
199be8be80fSkettenis DPRINTF(("CTRL/INFO/RDX\n"));
200be8be80fSkettenis #if 0
201be8be80fSkettenis lc->lc_start(lc);
202be8be80fSkettenis #endif
203be8be80fSkettenis break;
204be8be80fSkettenis
205be8be80fSkettenis case LDC_ACK:
206be8be80fSkettenis DPRINTF(("CTRL/ACK/RDX\n"));
207be8be80fSkettenis ldc_reset(lc);
208be8be80fSkettenis break;
209be8be80fSkettenis
210be8be80fSkettenis case LDC_NACK:
211be8be80fSkettenis DPRINTF(("CTRL/NACK/RDX\n"));
212be8be80fSkettenis ldc_reset(lc);
213be8be80fSkettenis break;
214be8be80fSkettenis
215be8be80fSkettenis default:
216be8be80fSkettenis DPRINTF(("CTRL/0x%02x/RDX\n", lp->stype));
217be8be80fSkettenis ldc_reset(lc);
218be8be80fSkettenis break;
219be8be80fSkettenis }
220be8be80fSkettenis }
221be8be80fSkettenis
222be8be80fSkettenis void
ldc_rx_data(struct ldc_conn * lc,struct ldc_pkt * lp)223be8be80fSkettenis ldc_rx_data(struct ldc_conn *lc, struct ldc_pkt *lp)
224be8be80fSkettenis {
225be8be80fSkettenis size_t len;
226be8be80fSkettenis
227be8be80fSkettenis if (lp->stype != LDC_INFO && lp->stype != LDC_ACK) {
228be8be80fSkettenis DPRINTF(("DATA/0x%02x\n", lp->stype));
229be8be80fSkettenis ldc_reset(lc);
230be8be80fSkettenis return;
231be8be80fSkettenis }
232be8be80fSkettenis
233be8be80fSkettenis if (lc->lc_state != LDC_SND_RTR &&
234be8be80fSkettenis lc->lc_state != LDC_SND_RDX) {
235be8be80fSkettenis DPRINTF(("Spurious DATA/INFO: state %d\n", lc->lc_state));
236be8be80fSkettenis ldc_reset(lc);
237be8be80fSkettenis return;
238be8be80fSkettenis }
239be8be80fSkettenis
240be8be80fSkettenis #if 0
241be8be80fSkettenis if (lp->ackid) {
242be8be80fSkettenis int i;
243be8be80fSkettenis
244be8be80fSkettenis for (i = 0; ds_service[i].ds_svc_id; i++) {
245be8be80fSkettenis if (ds_service[i].ds_ackid &&
246be8be80fSkettenis lp->ackid >= ds_service[i].ds_ackid) {
247be8be80fSkettenis ds_service[i].ds_ackid = 0;
248be8be80fSkettenis ds_service[i].ds_start(lc, ds_service[i].ds_svc_handle);
249be8be80fSkettenis }
250be8be80fSkettenis }
251be8be80fSkettenis }
252be8be80fSkettenis #endif
253be8be80fSkettenis if (lp->stype == LDC_ACK)
254be8be80fSkettenis return;
255be8be80fSkettenis
256be8be80fSkettenis if (lp->env & LDC_FRAG_START) {
257be8be80fSkettenis lc->lc_len = (lp->env & LDC_LEN_MASK);
258be8be80fSkettenis memcpy((uint8_t *)lc->lc_msg, &lp->data, lc->lc_len);
259be8be80fSkettenis } else {
260be8be80fSkettenis len = (lp->env & LDC_LEN_MASK);
261be8be80fSkettenis if (lc->lc_len + len > sizeof(lc->lc_msg)) {
262be8be80fSkettenis DPRINTF(("Buffer overrun\n"));
263be8be80fSkettenis ldc_reset(lc);
264be8be80fSkettenis return;
265be8be80fSkettenis }
266be8be80fSkettenis memcpy((uint8_t *)lc->lc_msg + lc->lc_len, &lp->data, len);
267be8be80fSkettenis lc->lc_len += len;
268be8be80fSkettenis }
269be8be80fSkettenis
270be8be80fSkettenis if (lp->env & LDC_FRAG_STOP) {
271be8be80fSkettenis ldc_ack(lc, lp->seqid);
272be8be80fSkettenis lc->lc_rx_data(lc, lc->lc_msg, lc->lc_len);
273be8be80fSkettenis }
274be8be80fSkettenis }
275be8be80fSkettenis
276be8be80fSkettenis void
ldc_send_vers(struct ldc_conn * lc)277be8be80fSkettenis ldc_send_vers(struct ldc_conn *lc)
278be8be80fSkettenis {
279be8be80fSkettenis struct ldc_pkt lp;
280be8be80fSkettenis ssize_t nbytes;
281be8be80fSkettenis
282be8be80fSkettenis bzero(&lp, sizeof(lp));
283be8be80fSkettenis lp.type = LDC_CTRL;
284be8be80fSkettenis lp.stype = LDC_INFO;
285be8be80fSkettenis lp.ctrl = LDC_VERS;
286be8be80fSkettenis lp.major = 1;
287be8be80fSkettenis lp.minor = 0;
288be8be80fSkettenis
289be8be80fSkettenis nbytes = write(lc->lc_fd, &lp, sizeof(lp));
290be8be80fSkettenis if (nbytes != sizeof(lp))
291be8be80fSkettenis err(1, "write");
292be8be80fSkettenis
293be8be80fSkettenis lc->lc_state = LDC_SND_VERS;
294be8be80fSkettenis }
295be8be80fSkettenis
296be8be80fSkettenis void
ldc_send_ack(struct ldc_conn * lc)297be8be80fSkettenis ldc_send_ack(struct ldc_conn *lc)
298be8be80fSkettenis {
299be8be80fSkettenis struct ldc_pkt lp;
300be8be80fSkettenis ssize_t nbytes;
301be8be80fSkettenis
302be8be80fSkettenis bzero(&lp, sizeof(lp));
303be8be80fSkettenis lp.type = LDC_CTRL;
304be8be80fSkettenis lp.stype = LDC_ACK;
305be8be80fSkettenis lp.ctrl = LDC_VERS;
306be8be80fSkettenis lp.major = 1;
307be8be80fSkettenis lp.minor = 0;
308be8be80fSkettenis
309be8be80fSkettenis nbytes = write(lc->lc_fd, &lp, sizeof(lp));
310be8be80fSkettenis if (nbytes != sizeof(lp))
311be8be80fSkettenis err(1, "write");
312be8be80fSkettenis
313be8be80fSkettenis lc->lc_state = LDC_RCV_VERS;
314be8be80fSkettenis }
315be8be80fSkettenis
316be8be80fSkettenis void
ldc_send_nack(struct ldc_conn * lc)31766e96321Skettenis ldc_send_nack(struct ldc_conn *lc)
31866e96321Skettenis {
31966e96321Skettenis struct ldc_pkt lp;
32066e96321Skettenis ssize_t nbytes;
32166e96321Skettenis
32266e96321Skettenis bzero(&lp, sizeof(lp));
32366e96321Skettenis lp.type = LDC_CTRL;
32466e96321Skettenis lp.stype = LDC_NACK;
32566e96321Skettenis lp.ctrl = LDC_VERS;
32666e96321Skettenis lp.major = 1;
32766e96321Skettenis lp.minor = 0;
32866e96321Skettenis
32966e96321Skettenis nbytes = write(lc->lc_fd, &lp, sizeof(lp));
33066e96321Skettenis if (nbytes != sizeof(lp))
33166e96321Skettenis err(1, "write");
33266e96321Skettenis
33366e96321Skettenis lc->lc_state = 0;
33466e96321Skettenis }
33566e96321Skettenis
33666e96321Skettenis void
ldc_send_rts(struct ldc_conn * lc)337be8be80fSkettenis ldc_send_rts(struct ldc_conn *lc)
338be8be80fSkettenis {
339be8be80fSkettenis struct ldc_pkt lp;
340be8be80fSkettenis ssize_t nbytes;
341be8be80fSkettenis
342be8be80fSkettenis bzero(&lp, sizeof(lp));
343be8be80fSkettenis lp.type = LDC_CTRL;
344be8be80fSkettenis lp.stype = LDC_INFO;
345be8be80fSkettenis lp.ctrl = LDC_RTS;
346be8be80fSkettenis lp.env = LDC_MODE_RELIABLE;
347be8be80fSkettenis lp.seqid = lc->lc_tx_seqid++;
348be8be80fSkettenis
349be8be80fSkettenis nbytes = write(lc->lc_fd, &lp, sizeof(lp));
350be8be80fSkettenis if (nbytes != sizeof(lp))
351be8be80fSkettenis err(1, "write");
352be8be80fSkettenis
353be8be80fSkettenis lc->lc_state = LDC_SND_RTS;
354be8be80fSkettenis }
355be8be80fSkettenis
356be8be80fSkettenis void
ldc_send_rtr(struct ldc_conn * lc)357be8be80fSkettenis ldc_send_rtr(struct ldc_conn *lc)
358be8be80fSkettenis {
359be8be80fSkettenis struct ldc_pkt lp;
360be8be80fSkettenis ssize_t nbytes;
361be8be80fSkettenis
362be8be80fSkettenis bzero(&lp, sizeof(lp));
363be8be80fSkettenis lp.type = LDC_CTRL;
364be8be80fSkettenis lp.stype = LDC_INFO;
365be8be80fSkettenis lp.ctrl = LDC_RTR;
366be8be80fSkettenis lp.env = LDC_MODE_RELIABLE;
367be8be80fSkettenis lp.seqid = lc->lc_tx_seqid++;
368be8be80fSkettenis
369be8be80fSkettenis nbytes = write(lc->lc_fd, &lp, sizeof(lp));
370be8be80fSkettenis if (nbytes != sizeof(lp))
371be8be80fSkettenis err(1, "write");
372be8be80fSkettenis
373be8be80fSkettenis lc->lc_state = LDC_SND_RTR;
374be8be80fSkettenis }
375be8be80fSkettenis
376be8be80fSkettenis void
ldc_send_rdx(struct ldc_conn * lc)377be8be80fSkettenis ldc_send_rdx(struct ldc_conn *lc)
378be8be80fSkettenis {
379be8be80fSkettenis struct ldc_pkt lp;
380be8be80fSkettenis ssize_t nbytes;
381be8be80fSkettenis
382be8be80fSkettenis bzero(&lp, sizeof(lp));
383be8be80fSkettenis lp.type = LDC_CTRL;
384be8be80fSkettenis lp.stype = LDC_INFO;
385be8be80fSkettenis lp.ctrl = LDC_RDX;
386be8be80fSkettenis lp.env = LDC_MODE_RELIABLE;
387be8be80fSkettenis lp.seqid = lc->lc_tx_seqid++;
388be8be80fSkettenis
389be8be80fSkettenis nbytes = write(lc->lc_fd, &lp, sizeof(lp));
390be8be80fSkettenis if (nbytes != sizeof(lp))
391be8be80fSkettenis err(1, "write");
392be8be80fSkettenis
393be8be80fSkettenis lc->lc_state = LDC_SND_RDX;
394be8be80fSkettenis }
395be8be80fSkettenis
396be8be80fSkettenis void
ldc_reset(struct ldc_conn * lc)397be8be80fSkettenis ldc_reset(struct ldc_conn *lc)
398be8be80fSkettenis {
399be8be80fSkettenis lc->lc_tx_seqid = 0;
400be8be80fSkettenis lc->lc_state = 0;
401be8be80fSkettenis #if 0
402be8be80fSkettenis lc->lc_reset(lc);
403be8be80fSkettenis #endif
404be8be80fSkettenis }
405be8be80fSkettenis
406be8be80fSkettenis void
ldc_ack(struct ldc_conn * lc,uint32_t ackid)407be8be80fSkettenis ldc_ack(struct ldc_conn *lc, uint32_t ackid)
408be8be80fSkettenis {
409be8be80fSkettenis struct ldc_pkt lp;
410be8be80fSkettenis ssize_t nbytes;
411be8be80fSkettenis
412be8be80fSkettenis bzero(&lp, sizeof(lp));
413be8be80fSkettenis lp.type = LDC_DATA;
414be8be80fSkettenis lp.stype = LDC_ACK;
415be8be80fSkettenis lp.seqid = lc->lc_tx_seqid++;
416be8be80fSkettenis lp.ackid = ackid;
417be8be80fSkettenis nbytes = write(lc->lc_fd, &lp, sizeof(lp));
418be8be80fSkettenis if (nbytes != sizeof(lp))
419be8be80fSkettenis err(1, "write");
420be8be80fSkettenis }
421be8be80fSkettenis
422be8be80fSkettenis void
ds_rx_msg(struct ldc_conn * lc,void * data,size_t len)423be8be80fSkettenis ds_rx_msg(struct ldc_conn *lc, void *data, size_t len)
424be8be80fSkettenis {
425be8be80fSkettenis struct ds_conn *dc = lc->lc_cookie;
426be8be80fSkettenis struct ds_msg *dm = data;
427be8be80fSkettenis
428be8be80fSkettenis switch(dm->msg_type) {
429be8be80fSkettenis case DS_INIT_REQ:
430be8be80fSkettenis {
431be8be80fSkettenis struct ds_init_req *dr = data;
432be8be80fSkettenis
433be8be80fSkettenis DPRINTF(("DS_INIT_REQ %d.%d\n", dr->major_vers,
434be8be80fSkettenis dr->minor_vers));
435be8be80fSkettenis if (dr->major_vers != 1 || dr->minor_vers != 0){
436be8be80fSkettenis ldc_reset(lc);
437be8be80fSkettenis return;
438be8be80fSkettenis }
439be8be80fSkettenis ds_init_ack(lc);
440be8be80fSkettenis break;
441be8be80fSkettenis }
442be8be80fSkettenis
443be8be80fSkettenis case DS_REG_REQ:
444be8be80fSkettenis {
445be8be80fSkettenis struct ds_reg_req *dr = data;
446be8be80fSkettenis struct ds_conn_svc *dcs;
4475a44f896Skettenis uint16_t major = 0;
448be8be80fSkettenis
449be8be80fSkettenis DPRINTF(("DS_REG_REQ %s %d.%d 0x%016llx\n", dr->svc_id,
450be8be80fSkettenis dr->major_vers, dr->minor_vers, dr->svc_handle));
451be8be80fSkettenis TAILQ_FOREACH(dcs, &dc->services, link) {
45225f16b1bSkettenis if (strcmp(dr->svc_id, dcs->service->ds_svc_id) == 0 &&
45325f16b1bSkettenis dr->major_vers == dcs->service->ds_major_vers) {
454be8be80fSkettenis dcs->svc_handle = dr->svc_handle;
455be8be80fSkettenis dcs->ackid = lc->lc_tx_seqid;
45625f16b1bSkettenis ds_reg_ack(lc, dcs->svc_handle,
45725f16b1bSkettenis dcs->service->ds_minor_vers);
458274866cdSkettenis dcs->service->ds_start(lc, dcs->svc_handle);
459be8be80fSkettenis return;
460be8be80fSkettenis }
461be8be80fSkettenis }
462be8be80fSkettenis
4635a44f896Skettenis TAILQ_FOREACH(dcs, &dc->services, link) {
4645a44f896Skettenis if (strcmp(dr->svc_id, dcs->service->ds_svc_id) == 0 &&
4655a44f896Skettenis dcs->service->ds_major_vers > major)
4665a44f896Skettenis major = dcs->service->ds_major_vers;
4675a44f896Skettenis }
4685a44f896Skettenis
4695a44f896Skettenis ds_reg_nack(lc, dr->svc_handle, major);
470be8be80fSkettenis break;
471be8be80fSkettenis }
472be8be80fSkettenis
473be8be80fSkettenis case DS_UNREG:
474be8be80fSkettenis {
475be8be80fSkettenis struct ds_unreg *du = data;
476be8be80fSkettenis
477be8be80fSkettenis DPRINTF(("DS_UNREG 0x%016llx\n", du->svc_handle));
478be8be80fSkettenis ds_unreg_ack(lc, du->svc_handle);
479be8be80fSkettenis break;
480be8be80fSkettenis }
481be8be80fSkettenis
482be8be80fSkettenis case DS_DATA:
483be8be80fSkettenis {
484be8be80fSkettenis struct ds_data *dd = data;
485be8be80fSkettenis struct ds_conn_svc *dcs;
486be8be80fSkettenis
487be8be80fSkettenis DPRINTF(("DS_DATA 0x%016llx\n", dd->svc_handle));
488be8be80fSkettenis TAILQ_FOREACH(dcs, &dc->services, link) {
489be8be80fSkettenis if (dcs->svc_handle == dd->svc_handle)
490be8be80fSkettenis dcs->service->ds_rx_data(lc, dd->svc_handle,
491be8be80fSkettenis data, len);
492be8be80fSkettenis }
493be8be80fSkettenis break;
494be8be80fSkettenis }
495be8be80fSkettenis
496be8be80fSkettenis default:
497be8be80fSkettenis DPRINTF(("Unknown DS message type 0x%x\n", dm->msg_type));
498be8be80fSkettenis ldc_reset(lc);
499be8be80fSkettenis break;
500be8be80fSkettenis }
501be8be80fSkettenis }
502be8be80fSkettenis
503be8be80fSkettenis void
ds_init_ack(struct ldc_conn * lc)504be8be80fSkettenis ds_init_ack(struct ldc_conn *lc)
505be8be80fSkettenis {
506be8be80fSkettenis struct ds_init_ack da;
507be8be80fSkettenis
508be8be80fSkettenis DPRINTF((" DS_INIT_ACK\n"));
509be8be80fSkettenis bzero(&da, sizeof(da));
510be8be80fSkettenis da.msg_type = DS_INIT_ACK;
511be8be80fSkettenis da.payload_len = sizeof(da) - 8;
512be8be80fSkettenis da.minor_vers = 0;
513be8be80fSkettenis ds_send_msg(lc, &da, sizeof(da));
514be8be80fSkettenis }
515be8be80fSkettenis
516be8be80fSkettenis void
ds_reg_ack(struct ldc_conn * lc,uint64_t svc_handle,uint16_t minor)51725f16b1bSkettenis ds_reg_ack(struct ldc_conn *lc, uint64_t svc_handle, uint16_t minor)
518be8be80fSkettenis {
519be8be80fSkettenis struct ds_reg_ack da;
520be8be80fSkettenis
521be8be80fSkettenis DPRINTF((" DS_REG_ACK 0x%016llx\n", svc_handle));
522be8be80fSkettenis bzero(&da, sizeof(da));
523be8be80fSkettenis da.msg_type = DS_REG_ACK;
524be8be80fSkettenis da.payload_len = sizeof(da) - 8;
525be8be80fSkettenis da.svc_handle = svc_handle;
52625f16b1bSkettenis da.minor_vers = minor;
527be8be80fSkettenis ds_send_msg(lc, &da, sizeof(da));
528be8be80fSkettenis }
529be8be80fSkettenis
530be8be80fSkettenis void
ds_reg_nack(struct ldc_conn * lc,uint64_t svc_handle,uint16_t major)5315a44f896Skettenis ds_reg_nack(struct ldc_conn *lc, uint64_t svc_handle, uint16_t major)
532be8be80fSkettenis {
533be8be80fSkettenis struct ds_reg_nack dn;
534be8be80fSkettenis
535be8be80fSkettenis DPRINTF((" DS_REG_NACK 0x%016llx\n", svc_handle));
536be8be80fSkettenis bzero(&dn, sizeof(dn));
537be8be80fSkettenis dn.msg_type = DS_REG_NACK;
538be8be80fSkettenis dn.payload_len = sizeof(dn) - 8;
539be8be80fSkettenis dn.svc_handle = svc_handle;
540be8be80fSkettenis dn.result = DS_REG_VER_NACK;
5415a44f896Skettenis dn.major_vers = major;
542be8be80fSkettenis ds_send_msg(lc, &dn, sizeof(dn));
543be8be80fSkettenis }
544be8be80fSkettenis
545be8be80fSkettenis void
ds_unreg_ack(struct ldc_conn * lc,uint64_t svc_handle)546be8be80fSkettenis ds_unreg_ack(struct ldc_conn *lc, uint64_t svc_handle)
547be8be80fSkettenis {
548be8be80fSkettenis struct ds_unreg du;
549be8be80fSkettenis
550be8be80fSkettenis DPRINTF((" DS_UNREG_ACK 0x%016llx\n", svc_handle));
551be8be80fSkettenis bzero(&du, sizeof(du));
552be8be80fSkettenis du.msg_type = DS_UNREG_ACK;
553be8be80fSkettenis du.payload_len = sizeof(du) - 8;
554be8be80fSkettenis du.svc_handle = svc_handle;
555be8be80fSkettenis ds_send_msg(lc, &du, sizeof(du));
556be8be80fSkettenis }
557be8be80fSkettenis
558be8be80fSkettenis void
ds_unreg_nack(struct ldc_conn * lc,uint64_t svc_handle)559be8be80fSkettenis ds_unreg_nack(struct ldc_conn *lc, uint64_t svc_handle)
560be8be80fSkettenis {
561be8be80fSkettenis struct ds_unreg du;
562be8be80fSkettenis
563be8be80fSkettenis DPRINTF((" DS_UNREG_NACK 0x%016llx\n", svc_handle));
564be8be80fSkettenis bzero(&du, sizeof(du));
565be8be80fSkettenis du.msg_type = DS_UNREG_NACK;
566be8be80fSkettenis du.payload_len = sizeof(du) - 8;
567be8be80fSkettenis du.svc_handle = svc_handle;
568be8be80fSkettenis ds_send_msg(lc, &du, sizeof(du));
569be8be80fSkettenis }
570be8be80fSkettenis
571be8be80fSkettenis void
ds_receive_msg(struct ldc_conn * lc,void * buf,size_t len)572be8be80fSkettenis ds_receive_msg(struct ldc_conn *lc, void *buf, size_t len)
573be8be80fSkettenis {
574be8be80fSkettenis int env = LDC_FRAG_START;
575be8be80fSkettenis struct ldc_pkt lp;
576be8be80fSkettenis uint8_t *p = buf;
577be8be80fSkettenis ssize_t nbytes;
578be8be80fSkettenis
579be8be80fSkettenis while (len > 0) {
580be8be80fSkettenis nbytes = read(lc->lc_fd, &lp, sizeof(lp));
581be8be80fSkettenis if (nbytes != sizeof(lp))
582be8be80fSkettenis err(1, "read");
583be8be80fSkettenis
584be8be80fSkettenis if (lp.type != LDC_DATA &&
585be8be80fSkettenis lp.stype != LDC_INFO) {
586be8be80fSkettenis ldc_reset(lc);
587be8be80fSkettenis return;
588be8be80fSkettenis }
589be8be80fSkettenis
590be8be80fSkettenis if ((lp.env & LDC_FRAG_START) != env) {
591be8be80fSkettenis ldc_reset(lc);
592be8be80fSkettenis return;
593be8be80fSkettenis }
594be8be80fSkettenis
595be8be80fSkettenis bcopy(&lp.data, p, (lp.env & LDC_LEN_MASK));
596be8be80fSkettenis p += (lp.env & LDC_LEN_MASK);
597be8be80fSkettenis len -= (lp.env & LDC_LEN_MASK);
598be8be80fSkettenis
599be8be80fSkettenis if (lp.env & LDC_FRAG_STOP)
600be8be80fSkettenis ldc_ack(lc, lp.seqid);
601be8be80fSkettenis
602be8be80fSkettenis env = (lp.env & LDC_FRAG_STOP) ? LDC_FRAG_START : 0;
603be8be80fSkettenis }
604be8be80fSkettenis }
605be8be80fSkettenis
606be8be80fSkettenis void
ldc_send_msg(struct ldc_conn * lc,void * buf,size_t len)607be8be80fSkettenis ldc_send_msg(struct ldc_conn *lc, void *buf, size_t len)
608be8be80fSkettenis {
609be8be80fSkettenis struct ldc_pkt lp;
610be8be80fSkettenis uint8_t *p = buf;
611be8be80fSkettenis ssize_t nbytes;
612be8be80fSkettenis
613be8be80fSkettenis while (len > 0) {
614be8be80fSkettenis bzero(&lp, sizeof(lp));
615be8be80fSkettenis lp.type = LDC_DATA;
616be8be80fSkettenis lp.stype = LDC_INFO;
617be8be80fSkettenis lp.env = min(len, LDC_PKT_PAYLOAD);
618be8be80fSkettenis if (p == buf)
619be8be80fSkettenis lp.env |= LDC_FRAG_START;
620be8be80fSkettenis if (len <= LDC_PKT_PAYLOAD)
621be8be80fSkettenis lp.env |= LDC_FRAG_STOP;
622be8be80fSkettenis lp.seqid = lc->lc_tx_seqid++;
623be8be80fSkettenis bcopy(p, &lp.data, min(len, LDC_PKT_PAYLOAD));
624be8be80fSkettenis
625be8be80fSkettenis nbytes = write(lc->lc_fd, &lp, sizeof(lp));
626be8be80fSkettenis if (nbytes != sizeof(lp))
627be8be80fSkettenis err(1, "write");
628be8be80fSkettenis p += min(len, LDC_PKT_PAYLOAD);
629be8be80fSkettenis len -= min(len, LDC_PKT_PAYLOAD);
630be8be80fSkettenis }
631be8be80fSkettenis }
632be8be80fSkettenis
633be8be80fSkettenis void
ds_send_msg(struct ldc_conn * lc,void * buf,size_t len)634be8be80fSkettenis ds_send_msg(struct ldc_conn *lc, void *buf, size_t len)
635be8be80fSkettenis {
636be8be80fSkettenis uint8_t *p = buf;
637be8be80fSkettenis struct ldc_pkt lp;
638be8be80fSkettenis ssize_t nbytes;
639be8be80fSkettenis
640be8be80fSkettenis while (len > 0) {
641be8be80fSkettenis ldc_send_msg(lc, p, min(len, LDC_MSG_MAX));
642be8be80fSkettenis p += min(len, LDC_MSG_MAX);
643be8be80fSkettenis len -= min(len, LDC_MSG_MAX);
644be8be80fSkettenis
645133ced1dSkettenis if (len > 0) {
646be8be80fSkettenis /* Consume ACK. */
647be8be80fSkettenis nbytes = read(lc->lc_fd, &lp, sizeof(lp));
648be8be80fSkettenis if (nbytes != sizeof(lp))
649be8be80fSkettenis err(1, "read");
650133ced1dSkettenis #if 0
651be8be80fSkettenis {
652be8be80fSkettenis uint64_t *msg = (uint64_t *)&lp;
653be8be80fSkettenis int i;
654be8be80fSkettenis
655be8be80fSkettenis for (i = 0; i < 8; i++)
656be8be80fSkettenis printf("%02x: %016llx\n", i, msg[i]);
657be8be80fSkettenis }
658be8be80fSkettenis #endif
659be8be80fSkettenis }
660be8be80fSkettenis }
661133ced1dSkettenis }
662be8be80fSkettenis
663be8be80fSkettenis TAILQ_HEAD(ds_conn_head, ds_conn) ds_conns =
664be8be80fSkettenis TAILQ_HEAD_INITIALIZER(ds_conns);
665be8be80fSkettenis int num_ds_conns;
666be8be80fSkettenis
667be8be80fSkettenis struct ds_conn *
ds_conn_open(const char * path,void * cookie)668be8be80fSkettenis ds_conn_open(const char *path, void *cookie)
669be8be80fSkettenis {
670be8be80fSkettenis struct ds_conn *dc;
671be8be80fSkettenis
672be8be80fSkettenis dc = xmalloc(sizeof(*dc));
673be8be80fSkettenis dc->path = xstrdup(path);
674be8be80fSkettenis dc->cookie = cookie;
675be8be80fSkettenis
676b7041c07Sderaadt dc->fd = open(path, O_RDWR);
677be8be80fSkettenis if (dc->fd == -1)
678c1729f59Sstsp err(1, "cannot open %s", path);
679be8be80fSkettenis
680be8be80fSkettenis memset(&dc->lc, 0, sizeof(dc->lc));
681be8be80fSkettenis dc->lc.lc_fd = dc->fd;
682be8be80fSkettenis dc->lc.lc_cookie = dc;
683be8be80fSkettenis dc->lc.lc_rx_data = ds_rx_msg;
684be8be80fSkettenis
685be8be80fSkettenis TAILQ_INIT(&dc->services);
686be8be80fSkettenis TAILQ_INSERT_TAIL(&ds_conns, dc, link);
687be8be80fSkettenis dc->id = num_ds_conns++;
688be8be80fSkettenis return dc;
689be8be80fSkettenis }
690be8be80fSkettenis
691be8be80fSkettenis void
ds_conn_register_service(struct ds_conn * dc,struct ds_service * ds)692be8be80fSkettenis ds_conn_register_service(struct ds_conn *dc, struct ds_service *ds)
693be8be80fSkettenis {
694be8be80fSkettenis struct ds_conn_svc *dcs;
695be8be80fSkettenis
696be8be80fSkettenis dcs = xzalloc(sizeof(*dcs));
697be8be80fSkettenis dcs->service = ds;
698be8be80fSkettenis
699be8be80fSkettenis TAILQ_INSERT_TAIL(&dc->services, dcs, link);
700be8be80fSkettenis }
701be8be80fSkettenis
702be8be80fSkettenis void
ds_conn_handle(struct ds_conn * dc)703be8be80fSkettenis ds_conn_handle(struct ds_conn *dc)
704be8be80fSkettenis {
705be8be80fSkettenis struct ldc_pkt lp;
706be8be80fSkettenis ssize_t nbytes;
707be8be80fSkettenis
708be8be80fSkettenis nbytes = read(dc->fd, &lp, sizeof(lp));
709be8be80fSkettenis if (nbytes != sizeof(lp)) {
710be8be80fSkettenis ldc_reset(&dc->lc);
711be8be80fSkettenis return;
712be8be80fSkettenis }
713be8be80fSkettenis
714be8be80fSkettenis switch (lp.type) {
715be8be80fSkettenis case LDC_CTRL:
716be8be80fSkettenis ldc_rx_ctrl(&dc->lc, &lp);
717be8be80fSkettenis break;
718be8be80fSkettenis case LDC_DATA:
719be8be80fSkettenis ldc_rx_data(&dc->lc, &lp);
720be8be80fSkettenis break;
721be8be80fSkettenis default:
722be8be80fSkettenis DPRINTF(("0x%02x/0x%02x/0x%02x\n", lp.type, lp.stype,
723be8be80fSkettenis lp.ctrl));
724be8be80fSkettenis ldc_reset(&dc->lc);
725be8be80fSkettenis break;
726be8be80fSkettenis }
727be8be80fSkettenis }
728be8be80fSkettenis
729be8be80fSkettenis void
ds_conn_serve(void)730be8be80fSkettenis ds_conn_serve(void)
731be8be80fSkettenis {
732be8be80fSkettenis struct ds_conn *dc;
733be8be80fSkettenis struct pollfd *pfd;
734133ced1dSkettenis int nfds;
735be8be80fSkettenis
736362c7d0fSderaadt pfd = xreallocarray(NULL, num_ds_conns, sizeof(*pfd));
737be8be80fSkettenis TAILQ_FOREACH(dc, &ds_conns, link) {
738be8be80fSkettenis pfd[dc->id].fd = dc->fd;
739be8be80fSkettenis pfd[dc->id].events = POLLIN;
740be8be80fSkettenis }
741be8be80fSkettenis
742be8be80fSkettenis while (1) {
743be8be80fSkettenis nfds = poll(pfd, num_ds_conns, -1);
744*a70f6581Skn if (nfds == -1)
745*a70f6581Skn err(1, "poll");
746*a70f6581Skn if (nfds == 0)
747*a70f6581Skn errx(1, "poll timeout");
748be8be80fSkettenis
749be8be80fSkettenis TAILQ_FOREACH(dc, &ds_conns, link) {
750be8be80fSkettenis if (pfd[dc->id].revents)
751be8be80fSkettenis ds_conn_handle(dc);
752be8be80fSkettenis }
753be8be80fSkettenis }
754be8be80fSkettenis }
755