4 * This module implements a simple remote control protocol
6 * $DragonFly: src/bin/cpdup/hclink.c,v 1.4 2007/01/17 02:34:10 pavalos Exp $
23 static struct HCHead *hcc_read_command(struct HostConf *hc);
26 hcc_connect(struct HostConf *hc)
31 if (hc == NULL || hc->host == NULL)
36 if (pipe(fdout) < 0) {
41 if ((hc->pid = fork()) == 0) {
51 execl("/usr/bin/ssh", "ssh", "-T", hc->host, "cpdup", "-S", (char *) NULL);
53 } else if (hc->pid < 0) {
57 * Parent process. Do the initial handshake to make sure we are
58 * actually talking to a cpdup slave.
69 rc_badop(struct HostConf *hc __unused, struct HCHead *head)
71 head->error = EOPNOTSUPP;
76 hcc_slave(int fdin, int fdout, struct HCDesc *descs, int count)
78 struct HostConf hcslave;
81 int (*dispatch[256])(struct HostConf *, struct HCHead *);
86 bzero(&hcslave, sizeof(hcslave));
87 for (i = 0; i < count; ++i) {
88 struct HCDesc *desc = &descs[i];
89 assert(desc->cmd >= 0 && desc->cmd < 256);
90 dispatch[desc->cmd] = desc->func;
92 for (i = 0; i < 256; ++i) {
93 if (dispatch[i] == NULL)
94 dispatch[i] = rc_badop;
97 hcslave.fdout = fdout;
100 * Process commands on fdin and write out results on fdout
106 head = hcc_read_command(&hcslave);
111 * Start the reply and dispatch, then process the return code.
114 hcc_start_command(&hcslave, head->cmd | HCF_REPLY);
115 r = dispatch[head->cmd & 255](&hcslave, head);
118 head->error = EINVAL;
131 * Write out the reply
133 whead = (void *)hcslave.wbuf;
134 whead->bytes = hcslave.windex;
135 whead->error = head->error;
136 aligned_bytes = HCC_ALIGN(hcslave.windex);
138 hcc_debug_dump(whead);
140 if (write(hcslave.fdout, whead, aligned_bytes) != aligned_bytes)
147 * This reads a command from fdin, fixes up the byte ordering, and returns
148 * a pointer to HCHead.
152 hcc_read_command(struct HostConf *hc)
160 while (n < (int)sizeof(struct HCHead)) {
161 r = read(hc->fdin, hc->rbuf + n, sizeof(struct HCHead) - n);
166 head = (void *)hc->rbuf;
167 assert(head->bytes >= (int)sizeof(*head) && head->bytes < 65536);
168 assert(head->magic == HCMAGIC);
169 aligned_bytes = HCC_ALIGN(head->bytes);
170 while (n < aligned_bytes) {
171 r = read(hc->fdin, hc->rbuf + n, aligned_bytes - n);
177 hcc_debug_dump(head);
183 * Initialize for a new command
186 hcc_start_command(struct HostConf *hc, int16_t cmd)
188 struct HCHead *whead = (void *)hc->wbuf;
190 whead->magic = HCMAGIC;
195 hc->windex = sizeof(*whead);
199 * Finish constructing a command, transmit it, and await the reply.
200 * Return the HCHead of the reply.
203 hcc_finish_command(struct HostConf *hc)
205 struct HCHead *whead;
206 struct HCHead *rhead;
209 whead = (void *)hc->wbuf;
210 whead->bytes = hc->windex;
211 aligned_bytes = HCC_ALIGN(hc->windex);
212 if (write(hc->fdout, whead, aligned_bytes) != aligned_bytes) {
218 if (whead->cmd < 0x0010)
220 fprintf(stderr, "cpdup lost connection to %s\n", hc->host);
223 if ((rhead = hcc_read_command(hc)) == NULL) {
229 if (whead->cmd < 0x0010)
231 fprintf(stderr, "cpdup lost connection to %s\n", hc->host);
236 *__error = rhead->error;
238 errno = rhead->error;
245 hcc_leaf_string(struct HostConf *hc, int16_t leafid, const char *str)
248 int bytes = strlen(str) + 1;
250 item = (void *)(hc->wbuf + hc->windex);
251 assert(hc->windex + sizeof(*item) + bytes < 65536);
252 item->leafid = leafid;
254 item->bytes = sizeof(*item) + bytes;
255 bcopy(str, item + 1, bytes);
256 hc->windex = HCC_ALIGN(hc->windex + item->bytes);
260 hcc_leaf_data(struct HostConf *hc, int16_t leafid, const void *ptr, int bytes)
264 item = (void *)(hc->wbuf + hc->windex);
265 assert(hc->windex + sizeof(*item) + bytes < 65536);
266 item->leafid = leafid;
268 item->bytes = sizeof(*item) + bytes;
269 bcopy(ptr, item + 1, bytes);
270 hc->windex = HCC_ALIGN(hc->windex + item->bytes);
274 hcc_leaf_int32(struct HostConf *hc, int16_t leafid, int32_t value)
278 item = (void *)(hc->wbuf + hc->windex);
279 assert(hc->windex + sizeof(*item) + sizeof(value) < 65536);
280 item->leafid = leafid;
282 item->bytes = sizeof(*item) + sizeof(value);
283 *(int32_t *)(item + 1) = value;
284 hc->windex = HCC_ALIGN(hc->windex + item->bytes);
288 hcc_leaf_int64(struct HostConf *hc, int16_t leafid, int64_t value)
292 item = (void *)(hc->wbuf + hc->windex);
293 assert(hc->windex + sizeof(*item) + sizeof(value) < 65536);
294 item->leafid = leafid;
296 item->bytes = sizeof(*item) + sizeof(value);
297 *(int64_t *)(item + 1) = value;
298 hc->windex = HCC_ALIGN(hc->windex + item->bytes);
302 hcc_alloc_descriptor(struct HostConf *hc, void *ptr, int type)
304 struct HCHostDesc *hd;
305 struct HCHostDesc *hnew;
307 hnew = malloc(sizeof(struct HCHostDesc));
311 if ((hd = hc->hostdescs) != NULL) {
312 hnew->desc = hd->desc + 1;
317 hc->hostdescs = hnew;
322 hcc_get_descriptor(struct HostConf *hc, int desc, int type)
324 struct HCHostDesc *hd;
326 for (hd = hc->hostdescs; hd; hd = hd->next) {
327 if (hd->desc == desc && hd->type == type)
334 hcc_set_descriptor(struct HostConf *hc, int desc, void *ptr, int type)
336 struct HCHostDesc *hd;
337 struct HCHostDesc **hdp;
339 for (hdp = &hc->hostdescs; (hd = *hdp) != NULL; hdp = &hd->next) {
340 if (hd->desc == desc) {
352 hd = malloc(sizeof(*hd));
356 hd->next = hc->hostdescs;
362 hcc_firstitem(struct HCHead *head)
367 offset = sizeof(*head);
368 if (offset == head->bytes)
370 assert(head->bytes >= offset + (int)sizeof(*item));
371 item = (void *)(head + 1);
372 assert(head->bytes >= offset + item->bytes);
373 assert(item->bytes >= (int)sizeof(*item) && item->bytes < 65536 - offset);
378 hcc_nextitem(struct HCHead *head, struct HCLeaf *item)
382 item = (void *)((char *)item + HCC_ALIGN(item->bytes));
383 offset = (char *)item - (char *)head;
384 if (offset == head->bytes)
386 assert(head->bytes >= offset + (int)sizeof(*item));
387 assert(head->bytes >= offset + item->bytes);
388 assert(item->bytes >= (int)sizeof(*item) && item->bytes < 65536 - offset);
395 hcc_debug_dump(struct HCHead *head)
398 int aligned_bytes = HCC_ALIGN(head->bytes);
400 fprintf(stderr, "DUMP %04x (%d)", (u_int16_t)head->cmd, aligned_bytes);
401 if (head->cmd & HCF_REPLY)
402 fprintf(stderr, " error %d", head->error);
403 fprintf(stderr, "\n");
404 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
405 fprintf(stderr, " ITEM %04x DATA ", item->leafid);
406 switch(item->leafid & LCF_TYPEMASK) {
408 fprintf(stderr, "int32 %d\n", *(int32_t *)(item + 1));
411 fprintf(stderr, "int64 %lld\n", *(int64_t *)(item + 1));
414 fprintf(stderr, "\"%s\"\n", (char *)(item + 1));
417 fprintf(stderr, "(binary)\n");