xref: /openbsd-src/usr.sbin/ldomd/ds.c (revision a70f65817d71450c31c39c0e9a46b5739484da9e)
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