+ * Send an error context to a client,
+ *
+ * \param cc Client info.
+ * \param errctx The error context string.
+ *
+ * \return The return value of the underlying call to send_sb_va().
+ *
+ * This function frees the error context string after it was sent.
+ */
+int send_errctx(struct command_context *cc, char *errctx)
+{
+ int ret;
+
+ if (!errctx)
+ return 0;
+ ret = send_sb_va(&cc->scc, SBD_ERROR_LOG, "%s\n", errctx);
+ free(errctx);
+ return ret;
+}
+
+static int check_sender_args(struct command_context *cc,
+ struct lls_parse_result *lpr, struct sender_command_data *scd)
+{
+ int i, ret;
+ const char * const subcmds[] = {SENDER_SUBCOMMANDS};
+ const char *arg;
+ char *errctx;
+ unsigned num_inputs = lls_num_inputs(lpr);
+
+ scd->sender_num = -1;
+ ret = lls(lls_check_arg_count(lpr, 2, INT_MAX, &errctx));
+ if (ret < 0) {
+ send_errctx(cc, errctx);
+ return ret;
+ }
+ arg = lls_input(0, lpr);
+ FOR_EACH_SENDER(i)
+ if (strcmp(senders[i]->name, arg) == 0)
+ break;
+ if (!senders[i])
+ return -E_COMMAND_SYNTAX;
+ scd->sender_num = i;
+ arg = lls_input(1, lpr);
+ for (i = 0; i < NUM_SENDER_CMDS; i++)
+ if (!strcmp(subcmds[i], arg))
+ break;
+ if (i == NUM_SENDER_CMDS)
+ return -E_COMMAND_SYNTAX;
+ scd->cmd_num = i;
+ if (!senders[scd->sender_num]->client_cmds[scd->cmd_num])
+ return -E_SENDER_CMD;
+ switch (scd->cmd_num) {
+ case SENDER_on:
+ case SENDER_off:
+ if (num_inputs != 2)
+ return -E_COMMAND_SYNTAX;
+ break;
+ case SENDER_deny:
+ case SENDER_allow:
+ if (num_inputs != 3 || parse_cidr(lls_input(2, lpr), scd->host,
+ sizeof(scd->host), &scd->netmask) == NULL)
+ return -E_COMMAND_SYNTAX;
+ break;
+ case SENDER_add:
+ case SENDER_delete:
+ if (num_inputs != 3)
+ return -E_COMMAND_SYNTAX;
+ return parse_fec_url(lls_input(2, lpr), scd);
+ default:
+ return -E_COMMAND_SYNTAX;
+ }
+ return 1;
+}
+
+/**
+ * Receive a sideband packet from a blocking file descriptor.