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