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");