/* SPC300 bundle {{{ * * Copyright (C) 2010 Spidcom * * <<>> * * }}} */ /** * \file devkit/plcd/src/plcd_stack.c * \brief communication with AV / EoC stack * \ingroup plcd * * Initialization of the AV / EoC stack, * and all communication functions with the AV / EoC stack. * */ #include "plcd_stack.h" #include "plcd_process.h" #include "plcd_main.h" #include "plcd_ctx.h" #include "libmme.h" #include "libspid.h" #include #include #include #include #include #include #include /* for htons() */ #include /* "utest_override" include must be the last include. */ #include "utest_override.h" /******************************************************************************/ /* DEBUG FUNCTION */ /******************************************************************************/ /** * Log packet contents. * * \param packet packet to log * \param len length of packet to log */ static void plcd_log_packet (const char *packet, int len) { int i = 0; char trace_buffer[256] = {0}; PLCD_ASSERT (NULL != packet); if (0 >= len) { return; } trace_buffer[0] = '\0'; for (i = 0; i < len; i++) { if ((0x20 < packet[i]) || (0x7f > packet[i])) { sprintf (trace_buffer + strlen (trace_buffer), "%c", packet[i]); } else { sprintf (trace_buffer + strlen (trace_buffer), "\\x%02x", packet[i]); } if (0 == i % 60) { syslog (LOG_INFO, trace_buffer); trace_buffer[0] = '\0'; } } syslog (LOG_INFO, trace_buffer); } int plcd_stack_event_dispatch (plcd_ctx_t *ctx) { struct msghdr msg; struct nlmsghdr *nlh = NULL; struct sockaddr_nl kernel_addr; struct iovec iov; MME_t *mme_hdr = NULL; fd_set readfds; struct timeval timeout; int result = 0, msg_len = 0; unsigned int result_len = 0; mme_ctx_t mme_ctx; unsigned char mme_buffer[ETH_DATA_LEN] = {0}; PLCD_ASSERT (NULL != ctx); FD_ZERO (&readfds); FD_SET (ctx->plc_sock, &readfds); timeout.tv_sec = PLCD_EVENT_REFRESH_TIMEOUT_MS / 1000; timeout.tv_usec = (PLCD_EVENT_REFRESH_TIMEOUT_MS % 1000) * 1000; /* select() on the netlink socket to poll received MME-s from PLC driver */ result = select (ctx->plc_sock + 1, &readfds, NULL, NULL, &timeout); if (0 > result) { /* look for interrupt */ if (EINTR == errno) { /* reset errno */ errno = 0; /* process interrupt */ } else { syslog (LOG_WARNING, "select failed (errno = %d)", errno); return -1; } } else if (0 < result) { if (FD_ISSET (ctx->plc_sock, &readfds)) { /* create message from PLC driver netlink */ nlh = (struct nlmsghdr *) malloc (NLMSG_LENGTH (ETH_DATA_LEN)); memset (nlh, 0, NLMSG_LENGTH(ETH_DATA_LEN)); memset (&kernel_addr, 0, sizeof (kernel_addr)); iov.iov_base = (void *) nlh; iov.iov_len = NLMSG_LENGTH (ETH_DATA_LEN); msg.msg_name = (void *) &kernel_addr; msg.msg_namelen = sizeof (kernel_addr); msg.msg_iov = &iov; msg.msg_iovlen = 1; if (0 > (msg_len = recvmsg (ctx->plc_sock, &msg, 0))) { syslog (LOG_WARNING, "recvmsg failed (errno = %d)", errno); free (nlh); return -1; } else if (msg_len > 0) { /* check MMTYPE */ mme_hdr = (MME_t *) NLMSG_DATA (nlh); if ((MME_SUCCESS != mme_init (&mme_ctx, mme_hdr->mmtype, mme_buffer, ETH_DATA_LEN)) || (MME_SUCCESS != mme_put (&mme_ctx, (unsigned char *) NLMSG_DATA (nlh) + sizeof (MME_t), ETH_DATA_LEN - sizeof (MME_t), &result_len))) { syslog (LOG_WARNING, "mme init / put failed"); free (nlh); return -1; } /* then, depending on MMTYPE of the received MME, * it calls different processing routines */ switch (mme_hdr->mmtype) { case (DRV_STA_STATUS | MME_IND): /* check DRV_STA_STATUS.IND contents and process new values */ if (0 > plcd_stack_event_status (ctx, &mme_ctx)) { syslog (LOG_WARNING, "stack event status failed"); free (nlh); return -1; } break; case (DRV_STA_SET_U_STA_HFID | MME_IND): case (DRV_STA_SET_AVLN_HFID | MME_IND): /* check DRV_STA_SET_*_HFID.IND contents and process new values */ if (0 > plcd_stack_event_hfid (ctx, &mme_ctx)) { syslog (LOG_WARNING, "stack event hfid failed"); free (nlh); return -1; } break; case (DRV_STA_SET_KEY | MME_IND): /* DRV_STA_SET_KEY.IND => process set key update */ if (0 > plcd_stack_event_key (ctx, &mme_ctx)) { syslog (LOG_WARNING, "stack event key failed"); free (nlh); return -1; } break; default: /* other received MME types generate an error */ syslog (LOG_WARNING, "stack event dispatch: unexpected mmtype (%04x)", mme_hdr->mmtype); free (nlh); return -1; } } free (nlh); } } else { /* timeout */ } if (is_process_signal_needed) { is_process_signal_needed = 0; /* now handle all config / info files changes (from spidapp / managerd) */ plcd_process_signal (ctx); } /* After processing, check if some other actions have to be performed. * These actions can be: * - save modified configuration files into flash; * - inform other processes about files modifications. */ /* check if hpav.conf save is needed */ if (ctx->is_save_conf_needed) { if (LIBSPID_SUCCESS != libspid_system_save_file (ctx->hpav_conf_path)) { syslog (LOG_WARNING, "libspid system save file failed"); return -1; } ctx->is_save_conf_needed = LIBSPID_FALSE; /* moreover, inform other processes about hpav.conf modification */ if (LIBSPID_SUCCESS != libspid_system_file_update_warn (getpid(), ctx->hpav_conf_path)) { syslog (LOG_WARNING, "libspid system file update warn failed"); return -1; } } /* check if manager daemon needs to be informed */ if (ctx->is_warn_needed) { if (LIBSPID_SUCCESS != libspid_system_file_update_warn (getpid(), ctx->hpav_info_path)) { syslog (LOG_WARNING, "libspid system file update warn failed"); return -1; } ctx->is_warn_needed = LIBSPID_FALSE; } return 0; } int plcd_send_recv_drv_mme (const plcd_ctx_t *ctx, const mme_ctx_t *request_ctx, mme_ctx_t *confirm_ctx, mme_ctx_t *indication_ctx) { struct sockaddr_nl kernel_addr; struct nlmsghdr *nlh = NULL; int msg_payload_len = 0; struct iovec iov; struct msghdr msg; MME_t *mme_hdr = NULL; fd_set readfds; struct timeval timeout; int result = 0; unsigned int cnf_len = 0, ind_len = 0; int recv_mme = 0; PLCD_ASSERT (NULL != ctx); PLCD_ASSERT (NULL != request_ctx); PLCD_ASSERT (MME_STATUS_INIT != request_ctx->status); PLCD_ASSERT (MME_REQ == (request_ctx->mmtype & MME_TYPE_MASK)); /* if confirm ctx is not NULL, it means that we expect to receive a .CNF, * after having sent the .REQ */ if (NULL != confirm_ctx) { PLCD_ASSERT (MME_STATUS_INIT != confirm_ctx->status); mme_get_free_space (confirm_ctx, &cnf_len); PLCD_ASSERT (ETH_DATA_LEN <= cnf_len); recv_mme++; } /* if indication ctx is not NULL, it means that we expect to receive a .IND, * after having sent the .REQ */ if (NULL != indication_ctx) { PLCD_ASSERT (MME_STATUS_INIT != indication_ctx->status); mme_get_free_space (indication_ctx, &ind_len); PLCD_ASSERT (ETH_DATA_LEN <= ind_len); recv_mme++; } msg_payload_len = request_ctx->tail - request_ctx->head + sizeof (MME_t); PLCD_ASSERT (ETH_FRAME_LEN >= msg_payload_len); /* fill the netlink address to send msg */ memset (&kernel_addr, 0, sizeof (kernel_addr)); kernel_addr.nl_family = AF_NETLINK; kernel_addr.nl_pid = 0; /* For Linux Kernel */ kernel_addr.nl_groups = 0; /* unicast */ /* create the message */ nlh = (struct nlmsghdr *) malloc (NLMSG_LENGTH(ETH_FRAME_LEN)); memset (nlh, 0, NLMSG_LENGTH (ETH_FRAME_LEN)); /* fill the netlink message header */ nlh->nlmsg_len = NLMSG_LENGTH (ETH_FRAME_LEN); nlh->nlmsg_pid = getpid(); /* self pid */ nlh->nlmsg_flags = 0; /* fill the MME header */ mme_hdr = (MME_t *) NLMSG_DATA (nlh); memcpy (mme_hdr->mme_dest, ctx->nvram->plc_address, ETH_ALEN); memcpy (mme_hdr->mme_src, ctx->nvram->plc_address, ETH_ALEN); mme_hdr->mtype = htons (MME_TYPE); mme_hdr->mmv = MME_VERSION; mme_hdr->mmtype = request_ctx->mmtype; /* fill MME payload */ memcpy ((unsigned char *) mme_hdr + sizeof (MME_t), request_ctx->buffer + request_ctx->head, request_ctx->tail - request_ctx->head); /* fill message info */ memset (&msg, 0, sizeof (msg)); msg.msg_name = (void *) &kernel_addr; msg.msg_namelen = sizeof (kernel_addr); msg.msg_iov = &iov; msg.msg_iovlen = 1; iov.iov_base = (void *) nlh; iov.iov_len = NLMSG_LENGTH (msg_payload_len); if (0 > sendmsg (ctx->plc_sock, &msg, 0)) { syslog (LOG_WARNING, "sendmsg failed (errno = %d): mmtype = %04x", errno, mme_hdr->mmtype); free (nlh); return -1; } /* prepare the recv message */ memset (nlh, 0, NLMSG_LENGTH (ETH_FRAME_LEN)); iov.iov_len = NLMSG_LENGTH (ETH_FRAME_LEN); /* wait for confirm/indication message(s) */ timeout.tv_sec = MME_TOUT; timeout.tv_usec = 0; FD_ZERO (&readfds); FD_SET (ctx->plc_sock, &readfds); while (recv_mme) { result = select (ctx->plc_sock + 1, &readfds, NULL, NULL, &timeout); if (0 > result) { /* look for interrupt */ if (EINTR == errno) { /* reset errno */ errno = 0; /* process interrupt */ } else { /* recv error */ syslog (LOG_WARNING, "select failed (errno = %d)", errno); free (nlh); return -1; } } else if (0 < result) { /* read received */ if (0 >= recvmsg (ctx->plc_sock, &msg, 0)) { syslog (LOG_WARNING, "recvmsg failed (errno = %d)", errno); free (nlh); return -1; } /* check MMTYPE */ mme_hdr = (MME_t *) NLMSG_DATA (nlh); if ((NULL != confirm_ctx) && ((request_ctx->mmtype & ~MME_TYPE_MASK) | MME_CNF) == mme_hdr->mmtype) { /* transfert to confirm ctx */ mme_put (confirm_ctx, (unsigned char *) NLMSG_DATA (nlh) + sizeof (MME_t), ETH_DATA_LEN - sizeof (MME_t), &cnf_len); recv_mme--; } else if ((NULL != indication_ctx) && ((request_ctx->mmtype & ~MME_TYPE_MASK) | MME_IND) == mme_hdr->mmtype) { /* transfert to indication ctx */ mme_put (indication_ctx, (unsigned char *) NLMSG_DATA (nlh) + sizeof (MME_t), ETH_DATA_LEN - sizeof (MME_t), &ind_len); recv_mme--; } else { syslog (LOG_WARNING, "send recv drv mme: unexpected mmtype (%04x)", mme_hdr->mmtype); free (nlh); return -1; } } else { /* timeout */ syslog (LOG_WARNING, "send recv drv mme: select timeout"); free (nlh); return -1; } } free (nlh); return 0; } int plcd_send_recv_single_value (const plcd_ctx_t *ctx, unsigned int mmtype, const void *value, unsigned int length) { unsigned char buffer[ETH_DATA_LEN] = {0}; mme_ctx_t request_ctx, confirm_ctx; unsigned char result = 0; unsigned int result_len = 0; PLCD_ASSERT (NULL != ctx); /* init mme */ mme_init (&request_ctx, mmtype | MME_REQ, buffer, ETH_DATA_LEN); mme_init (&confirm_ctx, mmtype | MME_CNF, buffer, ETH_DATA_LEN); if (NULL != value) { /* put value */ mme_put (&request_ctx, value, length, &result_len); } if ((0 > plcd_send_recv_drv_mme (ctx, &request_ctx, &confirm_ctx, NULL)) || (MME_SUCCESS != mme_pull (&confirm_ctx, &result, sizeof (result), &result_len)) || (MME_RESULT_SUCCESS != result)) { syslog (LOG_WARNING, "send recv drv mme / mme pull failed"); return -1; } return 0; } int plcd_stack_set_mac_address (const plcd_ctx_t *ctx, const unsigned char *mac_addr) { PLCD_ASSERT (NULL != ctx); PLCD_ASSERT (NULL != mac_addr); return plcd_send_recv_single_value (ctx, DRV_STA_SET_MAC_ADDR_REQ, mac_addr, ETH_ALEN); } int plcd_stack_set_cco_preferred (const plcd_ctx_t *ctx, libspid_boolean_t is_cco_preferred) { unsigned char value = (unsigned char) is_cco_preferred; PLCD_ASSERT (NULL != ctx); return plcd_send_recv_single_value (ctx, DRV_STA_SET_CCO_PREF_REQ, &value, sizeof (value)); } int plcd_stack_set_was_cco (const plcd_ctx_t *ctx, libspid_boolean_t was_cco) { unsigned char value = (unsigned char) was_cco; PLCD_ASSERT (NULL != ctx); return plcd_send_recv_single_value (ctx, DRV_STA_SET_WAS_CCO_REQ, &value, sizeof (value)); } int plcd_stack_set_key (const plcd_ctx_t *ctx, const char *nmk_str, const char *nid_str, const char *sl_str) { unsigned char buffer_req_cnf[ETH_DATA_LEN] = {0}; mme_ctx_t request_ctx, confirm_ctx; unsigned char result = 0; unsigned int result_len = 0; unsigned char tx_type = 0, tx_nid[LIBSPID_HPAV_CONF_NID_BIN_LEN] = {0}, \ tx_sl = 0, tx_nmk[LIBSPID_HPAV_CONF_NMK_BIN_LEN] = {0}; PLCD_ASSERT (NULL != ctx); PLCD_ASSERT (NULL != nmk_str); PLCD_ASSERT (NULL != nid_str); PLCD_ASSERT (NULL != sl_str); /* init mme */ mme_init (&request_ctx, DRV_STA_SET_KEY | MME_REQ, buffer_req_cnf, ETH_DATA_LEN); mme_init (&confirm_ctx, DRV_STA_SET_KEY | MME_CNF, buffer_req_cnf, ETH_DATA_LEN); /* check NMK */ if (!strcmp (nmk_str, LIBSPID_VALUE_NONE)) { syslog (LOG_WARNING, "stack set key: no nmk found \ => use spidapp to generate it from npw"); return -1; } /* convert NMK to binary */ if (LIBSPID_SUCCESS != libspid_hexstring_to_binary (nmk_str, tx_nmk, LIBSPID_HPAV_CONF_NMK_BIN_LEN)) { syslog (LOG_WARNING, "libspid string to binary failed"); return -1; } /* put NMK */ mme_put (&request_ctx, tx_nmk, LIBSPID_HPAV_CONF_NMK_BIN_LEN, &result_len); /* check NID */ if (!strcmp (nid_str, LIBSPID_VALUE_NONE)) { /* NID is none => send NMK and SL */ /* set Type to send: SL */ tx_type = MME_DRV_KEY_TYPE_SL; syslog (LOG_DEBUG, "stack set key: tx type is sl"); /* set SL to send */ if (!strcmp (sl_str, LIBSPID_HPAV_CONF_VALUE_SL_SC)) { tx_sl = MME_DRV_KEY_SL_SC; } else if (!strcmp (sl_str, LIBSPID_HPAV_CONF_VALUE_SL_HS)) { tx_sl = MME_DRV_KEY_SL_HS; } else { syslog (LOG_WARNING, "stack set key: unexpected sl"); return -1; } } else /* NID is not none => send NMK and NID */ { /* convert NID to binary */ if (LIBSPID_SUCCESS != libspid_hexstring_to_binary (nid_str, tx_nid, LIBSPID_HPAV_CONF_NID_BIN_LEN)) { syslog (LOG_WARNING, "libspid string to binary failed"); return -1; } /* set Type to send: NID */ tx_type = MME_DRV_KEY_TYPE_NID; syslog (LOG_DEBUG, "stack set key: tx type is nid"); } /* put Type */ mme_put (&request_ctx, &tx_type, sizeof (tx_type), &result_len); /* put NID */ mme_put (&request_ctx, tx_nid, LIBSPID_HPAV_CONF_NID_BIN_LEN, &result_len); /* put SL */ mme_put (&request_ctx, &tx_sl, sizeof (tx_sl), &result_len); if ((0 > plcd_send_recv_drv_mme (ctx, &request_ctx, &confirm_ctx, NULL)) || (MME_SUCCESS != mme_pull (&confirm_ctx, &result, sizeof (result), &result_len)) || (MME_RESULT_SUCCESS != result)) { syslog (LOG_WARNING, "send recv drv mme / mme pull failed"); return -1; } return 0; } int plcd_stack_set_dak (const plcd_ctx_t *ctx, const char *dpw) { unsigned char dak[LIBSPID_SECU_OUTPUT_KEY_SIZE]; PLCD_ASSERT (NULL != ctx); PLCD_ASSERT (NULL != dpw); /* firstly compute DAK from DPW */ if (LIBSPID_SUCCESS != libspid_secu_pbkdf1 (dpw, strlen (dpw), LIBSPID_SECU_SALT_TYPE_DAK, LIBSPID_SECU_PBKDF1_ITERATION, dak, LIBSPID_SECU_OUTPUT_KEY_SIZE)) { syslog (LOG_WARNING, "libspid secu pbkdf1 failed"); return -1; } return plcd_send_recv_single_value (ctx, DRV_STA_SET_DAK, dak, LIBSPID_SECU_OUTPUT_KEY_SIZE); } int plcd_stack_set_manu_hfid (const plcd_ctx_t *ctx, const char *manu_hfid) { PLCD_ASSERT (NULL != ctx); PLCD_ASSERT (NULL != manu_hfid); return plcd_send_recv_single_value (ctx, DRV_STA_SET_M_STA_HFID_REQ, manu_hfid, LIBSPID_HPAV_CONF_HFID_MAX_LEN); } int plcd_stack_set_user_hfid (const plcd_ctx_t *ctx, const char *user_hfid) { PLCD_ASSERT (NULL != ctx); PLCD_ASSERT (NULL != user_hfid); return plcd_send_recv_single_value (ctx, DRV_STA_SET_U_STA_HFID, user_hfid, LIBSPID_HPAV_CONF_HFID_MAX_LEN); } int plcd_stack_set_avln_hfid (const plcd_ctx_t *ctx, const char *avln_hfid) { PLCD_ASSERT (NULL != ctx); PLCD_ASSERT (NULL != avln_hfid); return plcd_send_recv_single_value (ctx, DRV_STA_SET_AVLN_HFID, avln_hfid, LIBSPID_HPAV_CONF_HFID_MAX_LEN); } int plcd_stack_set_tonemask (const plcd_ctx_t *ctx, const unsigned char *tonemask) { PLCD_ASSERT (NULL != ctx); PLCD_ASSERT (NULL != tonemask); return plcd_send_recv_single_value (ctx, DRV_STA_SET_TONEMASK, tonemask, 192); } /** * Send DRV_STA_SET_CONFIG.REQ with contents of given file, and receive * DRV_STA_SET_CONFIG.CNF. * * \param ctx plcd context * \param file name of file to be parsed * \param limit NULL terminated array of keywords to accept or NULL to * accept anything * \return -1 on error, 0 otherwise */ static int plcd_stack_set_config (const plcd_ctx_t *ctx, const char *file, const char * const *limit) { char key[LIBSPID_CONFIG_KEY_MAX_LEN + 1] = {0}, \ key_previous[LIBSPID_CONFIG_KEY_MAX_LEN + 1] = {0}; char *value[1] = {0}, line_buffer[LIBSPID_CONFIG_LINE_MAX_LEN] = {0}; char mme_buffer[MME_MAX_SIZE] = {0}; int elt_number = 0, result = 0; PLCD_ASSERT (NULL != ctx); /* firstly reads contents of file */ mme_buffer[0] = '\0'; *key = '\0'; elt_number = 1; /* get 1st key value */ if (LIBSPID_SUCCESS != (result = libspid_config_read_line \ (file, "= \t", key, &elt_number, value, line_buffer, LIBSPID_CONFIG_LINE_MAX_LEN))) { if (LIBSPID_ERROR_SYSTEM != result) { /* internal libspid error */ syslog (LOG_WARNING, "%s: libspid config read line failed" " (wrong format)", file); } return 0; } /* get all items */ while (0 < strlen (key)) { /* save current key */ strcpy (key_previous, key); elt_number = 1; /* get key value and next key */ if (LIBSPID_SUCCESS != (result = libspid_config_read_line \ (file, "= \t", key, &elt_number, value, line_buffer, LIBSPID_CONFIG_LINE_MAX_LEN))) { syslog (LOG_WARNING, "%s: libspid config read line failed:" " key = %s", file, key); return 0; } if (1 != elt_number) { continue; } if (limit) { const char * const *limitp; for (limitp = limit; *limitp && strcmp (*limitp, key_previous) != 0; limitp++) ; if (!*limitp) { syslog (LOG_WARNING, "%s: unknown parameter: key = %s", file, key_previous); continue; } } /* check free space */ if (strlen (mme_buffer) + strlen (key_previous) + 1 + strlen (value[0]) >= \ sizeof (mme_buffer)) { /* not enough free space: send current MME */ mme_buffer[strlen (mme_buffer) - 1] = '\0'; if (0 > (result = plcd_send_recv_single_value (ctx, DRV_STA_SET_CONFIG, mme_buffer, strlen (mme_buffer) + 1))) { return result; } /* reset buffer content */ mme_buffer[0] = '\0'; } /* push label into buffer */ strcat (mme_buffer, key_previous); strcat (mme_buffer, ":"); /* push value into buffer */ strcat (mme_buffer, value[0]); strcat (mme_buffer, " "); } /* replace last space by a NULL char */ mme_buffer[strlen (mme_buffer) - 1] = '\0'; /* send MME */ return plcd_send_recv_single_value (ctx, DRV_STA_SET_CONFIG, mme_buffer, strlen (mme_buffer) + 1); } int plcd_stack_set_phy (const plcd_ctx_t *ctx) { const char *limit[] = { "AMPMAP_FIRST_CARRIER", "AMPMAP_LAST_CARRIER", NULL }; return plcd_stack_set_config (ctx, ctx->phy_conf_path, limit); } int plcd_stack_set_internal (const plcd_ctx_t *ctx) { return plcd_stack_set_config (ctx, ctx->internal_conf_path, NULL); } int plcd_stack_start (const plcd_ctx_t *ctx) { PLCD_ASSERT (NULL != ctx); return plcd_send_recv_single_value (ctx, DRV_STA_MAC_START, NULL, 0); } int plcd_stack_init (const plcd_ctx_t *ctx) { PLCD_ASSERT (NULL != ctx); PLCD_ASSERT (NULL != ctx->nvram); /* send MAC address to AV / EoC stack */ if(0 > plcd_stack_set_mac_address (ctx, ctx->nvram->plc_address)) { syslog (LOG_WARNING, "stack set mac address failed"); return -1; } /* send CCO_PREFERRED to AV / EoC stack */ if (0 > plcd_stack_set_cco_preferred (ctx, ctx->hpav_conf.is_cco_preferred)) { syslog (LOG_WARNING, "stack set cco preferred failed"); return -1; } /* send WAS_CCO to AV / EoC stack */ if (0 > plcd_stack_set_was_cco (ctx, ctx->hpav_conf.was_cco)) { syslog (LOG_WARNING, "stack set was cco failed"); return -1; } /* send NMK and (NID or SL) */ if (0 > plcd_stack_set_key (ctx, ctx->hpav_conf.nmk_str, ctx->hpav_conf.nid_str, ctx->hpav_conf.sl_str)) { syslog (LOG_WARNING, "stack set key failed"); return -1; } /* send DAK */ if (0 > plcd_stack_set_dak (ctx, ctx->nvram->device_password)) { syslog (LOG_WARNING, "stack set dak failed"); return -1; } /* send manufacturer HFID */ if (0 > plcd_stack_set_manu_hfid (ctx, ctx->nvram->product_name)) { syslog (LOG_WARNING, "stack set manu hfid failed"); return -1; } /* send user HFID */ if (0 > plcd_stack_set_user_hfid (ctx, ctx->hpav_conf.user_hfid)) { syslog (LOG_WARNING, "stack set user hfid failed"); return -1; } /* send AVLN HFID */ if (0 > plcd_stack_set_avln_hfid (ctx, ctx->hpav_conf.avln_hfid)) { syslog (LOG_WARNING, "stack set avln hfid failed"); return -1; } /* send tonemask */ if (0 > plcd_stack_set_tonemask (ctx, ctx->nvram->tonemask)) { syslog (LOG_WARNING, "stack set tonemask failed"); return -1; } /* send phy config parameters */ if (0 > plcd_stack_set_phy (ctx)) { syslog (LOG_WARNING, "stack set phy failed"); return -1; } /* send internal config parameters */ if (0 > plcd_stack_set_internal (ctx)) { syslog (LOG_WARNING, "stack set internal failed"); return -1; } /* start AV / EoC stack */ if (0 > plcd_stack_start (ctx)) { syslog (LOG_WARNING, "stack start failed"); return -1; } return 0; }