/* * application/spidapp/src/spidapp.c * * (C) Copyright 2009 SPiDCOM Technologies * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "libspid.h" #include "libmme.h" #include "spidapp.h" struct cmd_entry cmd_table[] = { {NAME_CONFIG, required_argument, USAGE_CONFIG, cmd_config}, {NAME_SNIFFER, required_argument, USAGE_SNIFFER, cmd_sniffer}, {NAME_HELP, no_argument, USAGE_HELP, cmd_help}, {NULL, 0, NULL, NULL}, }; /******************************************************************************* * config command: configure a SPiDCOM system * (don't forget to save the modified configuration file in flash memory). ******************************************************************************/ int cmd_config (struct cmd_entry *cmd_entry, int argc, char **argv) { libspid_boolean_t save_and_warn = LIBSPID_FALSE; int c = 0, i = 0, opt_index = 0; char npw[LIBSPID_HPAV_CONF_NPW_MAX_LEN] = {0}, nmk_bin[LIBSPID_HPAV_CONF_NMK_BIN_LEN] = {0}, nmk_str[LIBSPID_HPAV_CONF_NMK_STR_LEN] = {0}; struct option long_opts[] = { {"cco-preferred", required_argument, NULL, 'c'}, {"was-cco", required_argument, NULL, 'w'}, {"npw", required_argument, NULL, 'p'}, {"nid", required_argument, NULL, 'n'}, {"sl", required_argument, NULL, 's'}, {"user-hfid", required_argument, NULL, 'u'}, {"avln-hfid", required_argument, NULL, 'a'}, {"help", no_argument, NULL, 'h'}, }; strcpy (npw, LIBSPID_HPAV_CONF_NPW_DEFAULT); while (-1 != (c = getopt_long_only (argc, argv, "c:w:p:n:s:u:a:h:", long_opts, &opt_index))) { switch (c) { case 'c': if (!strcmp (LIBSPID_VALUE_BOOLEAN_FALSE, optarg) || !strcmp (LIBSPID_VALUE_BOOLEAN_TRUE, optarg)) { if (LIBSPID_SUCCESS != libspid_config_write_item \ (LIBSPID_HPAV_CONF_PATH, LIBSPID_HPAV_CONF_LABEL_CCO_PREFERRED, optarg)) { printf ("%s: libspid config write item error\n", LIBSPID_HPAV_CONF_LABEL_CCO_PREFERRED); return -1; } printf ("%s: updated\n", LIBSPID_HPAV_CONF_LABEL_CCO_PREFERRED); } else { printf ("%s: argument error\n", LIBSPID_HPAV_CONF_LABEL_CCO_PREFERRED); return -1; } save_and_warn = LIBSPID_TRUE; break; case 'w': if (!strcmp (LIBSPID_VALUE_BOOLEAN_FALSE, optarg) || !strcmp (LIBSPID_VALUE_BOOLEAN_TRUE, optarg)) { if (LIBSPID_SUCCESS != libspid_config_write_item \ (LIBSPID_HPAV_CONF_PATH, LIBSPID_HPAV_CONF_LABEL_WAS_CCO, optarg)) { printf ("%s: libspid config write item error\n", LIBSPID_HPAV_CONF_LABEL_WAS_CCO); return -1; } printf ("%s: updated\n", LIBSPID_HPAV_CONF_LABEL_WAS_CCO); } else { printf ("%s: argument error\n", LIBSPID_HPAV_CONF_LABEL_WAS_CCO); return -1; } save_and_warn = LIBSPID_TRUE; break; case 'p': if ((LIBSPID_HPAV_CONF_NPW_MIN_LEN <= strlen (optarg)) && (LIBSPID_HPAV_CONF_NPW_MAX_LEN >= strlen(optarg))) { if (LIBSPID_HPAV_CONF_NPW_ADVISED_MIN_LEN >= strlen(optarg)) { printf ("NPW: may not be secure\n"); } for (i = 0; i < strlen (optarg); i++) { if ((32 > optarg[i]) || (127 < optarg[i])) { printf ("NPW: must use characters from ASCII[32] to ASCII[127]\n"); return -1; } } strcpy (npw, optarg); } else { printf ("NPW: cannot be created using less than 8 or more than 64 characters\n"); return -1; } if ((LIBSPID_SUCCESS != libspid_secu_pbkdf1 (npw, strlen (npw), LIBSPID_SECU_SALT_TYPE_NMK, LIBSPID_SECU_PBKDF1_ITERATION, nmk_bin, LIBSPID_SECU_OUTPUT_KEY_SIZE)) || (LIBSPID_SUCCESS != libspid_binary_to_hexstring (nmk_bin, LIBSPID_HPAV_CONF_NMK_BIN_LEN, nmk_str)) || (LIBSPID_SUCCESS != libspid_config_write_item \ (LIBSPID_HPAV_CONF_PATH, LIBSPID_HPAV_CONF_LABEL_NMK, nmk_str))) { printf ("%s: libspid error\n", LIBSPID_HPAV_CONF_LABEL_NMK); return -1; } printf ("%s: updated (%s)\n", LIBSPID_HPAV_CONF_LABEL_NMK, nmk_str); save_and_warn = LIBSPID_TRUE; break; case 'n': if (strcmp (LIBSPID_VALUE_NONE, optarg)) { if (LIBSPID_HPAV_CONF_NID_STR_LEN >= strlen (optarg)) { for (i = 0; i < strlen (optarg); i++) { if (!isxdigit (optarg[i])) { printf ("%s: argument error\n", LIBSPID_HPAV_CONF_LABEL_NID); return -1; } } } else { printf ("%s: argument error\n", LIBSPID_HPAV_CONF_LABEL_NID); return -1; } } if (LIBSPID_SUCCESS != libspid_config_write_item \ (LIBSPID_HPAV_CONF_PATH, LIBSPID_HPAV_CONF_LABEL_NID, optarg)) { printf ("%s: libspid config write item error\n", LIBSPID_HPAV_CONF_LABEL_NID); return -1; } printf ("%s: updated\n", LIBSPID_HPAV_CONF_LABEL_NID); save_and_warn = LIBSPID_TRUE; break; case 's': if (!strcmp (LIBSPID_HPAV_CONF_VALUE_SL_SC, optarg) || !strcmp (LIBSPID_HPAV_CONF_VALUE_SL_HS, optarg)) { if (LIBSPID_SUCCESS != libspid_config_write_item \ (LIBSPID_HPAV_CONF_PATH, LIBSPID_HPAV_CONF_LABEL_SL, optarg)) { printf ("%s: libspid config write item error\n", LIBSPID_HPAV_CONF_LABEL_SL); return -1; } } else { printf ("%s: argument error\n", LIBSPID_HPAV_CONF_LABEL_SL); return -1; } printf ("%s: updated\n", LIBSPID_HPAV_CONF_LABEL_SL); save_and_warn = LIBSPID_TRUE; break; case 'u': if (LIBSPID_HPAV_CONF_HFID_MAX_LEN >= strlen (optarg)) { if (LIBSPID_SUCCESS != libspid_config_write_item \ (LIBSPID_HPAV_CONF_PATH, LIBSPID_HPAV_CONF_LABEL_USER_HFID, optarg)) { printf ("%s: libspid config write item error\n", LIBSPID_HPAV_CONF_LABEL_USER_HFID); return -1; } } else { printf ("%s: argument error\n", LIBSPID_HPAV_CONF_LABEL_USER_HFID); return -1; } printf ("%s: updated\n", LIBSPID_HPAV_CONF_LABEL_USER_HFID); save_and_warn = LIBSPID_TRUE; break; case 'a': if (LIBSPID_HPAV_CONF_HFID_MAX_LEN >= strlen (optarg)) { if (LIBSPID_SUCCESS != libspid_config_write_item \ (LIBSPID_HPAV_CONF_PATH, LIBSPID_HPAV_CONF_LABEL_AVLN_HFID, optarg)) { printf ("%s: libspid config write item error\n", LIBSPID_HPAV_CONF_LABEL_AVLN_HFID); return -1; } } else { printf ("%s: argument error\n", LIBSPID_HPAV_CONF_LABEL_AVLN_HFID); return -1; } printf ("%s: updated\n", LIBSPID_HPAV_CONF_LABEL_AVLN_HFID); save_and_warn = LIBSPID_TRUE; break; case 'h': default: printf ("%s", cmd_entry->usage); return -1; } } if (LIBSPID_TRUE == save_and_warn) { /* save hpav.conf and inform plc daemon */ if ((LIBSPID_SUCCESS != libspid_system_save_file (LIBSPID_HPAV_CONF_PATH)) || (LIBSPID_SUCCESS != libspid_system_file_update_warn (getpid(), LIBSPID_HPAV_CONF_PATH))) { printf ("%s: libspid system error\n", LIBSPID_HPAV_CONF_PATH); return -1; } } return 0; } /******************************************************************************* * sniffer command: set the HPAV sniffer in sniff mode. * The final host target mac-address of sniff packet must be provided * else packets will be transmitted in broadcast mode ******************************************************************************/ int cmd_sniffer (struct cmd_entry *cmd_entry, int argc, char **argv) { int sock; struct sockaddr_ll sll; struct ifreq ifr; int c = 0; int opt_index = 0; unsigned char mode = 0; unsigned char mac_src[ETH_ALEN]; char pkt_buffer[1024]; MME_t *mme_hdr; int pkt_len, len; struct option long_opts[] = { {"mac", required_argument, NULL, 'a'}, {"mode", required_argument, NULL, 'm'}, {"help", no_argument, NULL, 'h'}, }; /* set default src mac to broadcast */ memset (mac_src, '\xff', ETH_ALEN); while (-1 != (c = getopt_long_only (argc, argv, "a:m:h:", long_opts, &opt_index))) { switch(c) { case 'a': if(libspid_mac_str_to_bin (optarg, mac_src) != LIBSPID_SUCCESS) { printf ("%s", cmd_entry->usage); return (-1); } break; case 'm': mode = atoi (optarg); if(mode & ~0xaf) { printf ("%s", cmd_entry->usage); return (-1); } break; case 'h': default: printf ("%s", cmd_entry->usage); return (-1); } } /* dirty, but we need to do it by hand because libmme does not * allow to change the src mac address of MME packet */ if (( sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) { perror ("Error creating raw socket"); return 0; } memset(&sll, 0x0, sizeof(sll)); memset(&ifr, 0x0, sizeof(ifr)); /* First Get the Interface Index */ strcpy(ifr.ifr_name, MME_IFACE_LOOPBACK); if ((ioctl(sock, SIOCGIFINDEX, &ifr)) < 0) { perror("Error getting plc0 interface index"); close(sock); return 0; } /* Bind our raw socket to this interface */ sll.sll_family = AF_PACKET; sll.sll_ifindex = ifr.ifr_ifindex; sll.sll_protocol = htons(ETH_P_ALL); if((bind(sock, (struct sockaddr *)&sll, sizeof(sll))) < 0) { perror("Error binding raw socket to plc0 interface"); close(sock); return 0; } /* get plc0 mac-address */ ioctl(sock, SIOCGIFHWADDR, &ifr); /* fill MME VS_SNIFFER.REQ packet */ mme_hdr = (MME_t *)pkt_buffer; memcpy (mme_hdr->mme_dest, (unsigned char *)ifr.ifr_hwaddr.sa_data, ETH_ALEN); //mme_hdr->mme_dest[4] = 0x02; // no need for this hack memcpy (mme_hdr->mme_src, mac_src, ETH_ALEN); mme_hdr->mtype = htons (MME_TYPE); mme_hdr->mmv = 1; mme_hdr->mmtype = VS_SNIFFER_REQ; mme_hdr->fmi = 0; memcpy ((unsigned char *)mme_hdr + sizeof(MME_t), OUI_SPIDCOM, sizeof(OUI_SPIDCOM) - 1); memcpy ((unsigned char *)mme_hdr + sizeof(MME_t) + sizeof(OUI_SPIDCOM) - 1, &mode, sizeof(mode)); pkt_len = sizeof(MME_t) + sizeof(OUI_SPIDCOM) - 1 + sizeof(mode); /* send MME */ if((len = write (sock, pkt_buffer, pkt_len)) != pkt_len) { perror ("Failed to transmit MME: "); } close (sock); return 0; } /******************************************************************************* * help command: print usage. ******************************************************************************/ int cmd_help (struct cmd_entry *cmd_entry, int argc, char **argv) { int i = 0; printf ("Utility tool for spc300\n"); printf ("Usage: spidapp [options]\n"); printf ("Command list:\n"); while (NULL != cmd_table[i].name) { printf ("%s", cmd_table[i].usage); i++; } } int main (int argc, char **argv) { int cmd_index = 0, argv_index = 0; struct cmd_entry *cmd_entry; if (argc < 2) { cmd_help (NULL, 0, NULL); exit (1); } argc--; argv_index++; while (NULL != cmd_table[cmd_index].name) { if (!strcmp (cmd_table[cmd_index].name, argv[argv_index])) break; cmd_index++; } if (NULL == cmd_table[cmd_index].name) { cmd_help (NULL, 0, NULL); exit (1); } if (0 > (cmd_table[cmd_index].cmd) (cmd_table + cmd_index, argc, argv + argv_index)) { exit (1); } exit (0); }