/*****************************************************************************
* CANopenSocket CANopenCommand.c hacking
* 说明:
* 分析一下CANopenSocket中的CANopenCommand部分是怎么工作的。
*
* 2017-3-23 深圳 南山平山村 曾剑锋
****************************************************************************/
/*
* Client socket command interface for CANopenSocket.
*
* @file CANopenCommand.c
* @author Janez Paternoster
* @copyright 2015 Janez Paternoster
*
* This file is part of CANopenNode, an opensource CANopen Stack.
* Project home page is <https://github.com/CANopenNode/CANopenNode>.
* For more information on CANopen see <http://www.can-cia.org/>.
*
* CANopenNode is free and open source 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, see <http://www.gnu.org/licenses/>.
*/ #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/un.h>
#include <sys/socket.h> #ifndef BUF_SIZE
#define BUF_SIZE 100000
#endif /**
* 错误退出函数
*/
/* Helper functions */
void errExit(char* msg) {
perror(msg);
exit(EXIT_FAILURE);
} /**
* 是否打印错误描述相关信息标志
*/
static int printErrorDescription = ; /**
* 发送命令函数,fd是socket描述符
*/
static void sendCommand(int fd, char* command, size_t commandLength); /**
* 参数使用方法说明
*/
static void printUsage(char *progName) {
fprintf(stderr,
"Usage: %s [options] <command string>\n", progName);
fprintf(stderr,
"\n"
"Program reads arguments or standard input or file. It sends commands to\n"
"canopend via socket, line after line. Result is printed to standard output.\n"
"For more information see http://www.can-cia.org/, CiA 309 standard.\n"
"\n"
"Options:\n"
" -f <input file path> Path to the input file.\n"
" -s <socket path> Path to the socket (default '/tmp/CO_command_socket').\n"
" -h Display description of error codes in case of error.\n"
" (Default, if command is passed by program arguments.)\n"
" --help Display this help.\n"
" --helpall Display this help, internal and SDO error codes.\n"
"\n"
"Command strings must start with \"[\"<sequence>\"]\" (except if from arguments):\n"
" - SDO upload: [[<net>] <node>] r[ead] <index> <subindex> [<datatype>]\n"
" - SDO download: [[<net>] <node>] w[rite] <index> <subindex> <datatype> <value>\n"
" - Configure SDO time-out: [<net>] set sdo_timeout <value>\n"
" - Enable SDO block transfer: [<net>] set sdo_block <value>\n"
" - Set default node: [<net>] set node <value>\n"
"\n"
" - Start node: [[<net>] <node>] start\n"
" - Stop node: [[<net>] <node>] stop\n"
" - Set node to pre-operational: [[<net>] <node>] preop[erational]\n"
" - Reset node: [[<net>] <node>] reset node\n"
" - Reset communication: [[<net>] <node>] reset comm[unication]\n"
"\n"
"Comments started with '#' are ignored. They may be on the beginning of the line\n"
"or after the command string. 'sdo_timeout' is in milliseconds, 500 by default.\n"
"If <node> is not specified within commands, then value defined by 'set node'\n"
"command is used.\n"
"\n"
"\n"
"Datatypes:\n"
" - b - Boolean.\n"
" - u8, u16, u32, u64 - Unsigned integers.\n"
" - i8, i16, i32, i64 - Signed integers.\n"
" - r32, r64 - Real numbers.\n"
" - t, td - Time of day, time difference.\n"
" - vs - Visible string (between double quotes).\n"
" - os, us, d - Octet string, unicode string, domain\n"
" (mime-base64 (RFC2045) should be used).\n"
"\n"
"\n"
"Response: \"[\"<sequence>\"]\" \\\n"
" OK | <value> | ERROR: <SDO-abort-code> | ERROR: <internal-error-code>\n"
"\n"
"\n"
"LICENSE\n"
" This program is part of CANopenSocket and can be downloaded from:\n"
" https://github.com/CANopenNode/CANopenSocket\n"
" Permission is granted to copy, distribute and/or modify this document\n"
" under the terms of the GNU General Public License, Version 2.\n"
"\n"
);
} /**
* 错误描述对应的结构体
*/
/* Extract error description */
typedef struct {
int code;
char* desc;
} errorDescs_t; /**
* 这里列出所有的canopend返回的错误编号对应的显示的英文
*/
static const errorDescs_t errorDescs[] = {
{, "Request not supported."},
{, "Syntax error."},
{, "Request not processed due to internal state."},
{, "Time-out (where applicable)."},
{, "No default net set."},
{, "No default node set."},
{, "Unsupported net."},
{, "Unsupported node."},
{, "Lost guarding message."},
{, "Lost connection."},
{, "Heartbeat started."},
{, "Heartbeat lost."},
{, "Wrong NMT state."},
{, "Boot-up."},
{, "Error passive."},
{, "Bus off."},
{, "CAN buffer overflow."},
{, "CAN init."},
{, "CAN active (at init or start-up)."},
{, "PDO already used."},
{, "PDO length exceeded."},
{, "LSS implementation- / manufacturer-specific error."},
{, "LSS node-ID not supported."},
{, "LSS bit-rate not supported."},
{, "LSS parameter storing failed."},
{, "LSS command failed because of media error."},
{, "Running out of memory."},
{0x00000000, "No abort."},
{0x05030000, "Toggle bit not altered."},
{0x05040000, "SDO protocol timed out."},
{0x05040001, "Command specifier not valid or unknown."},
{0x05040002, "Invalid block size in block mode."},
{0x05040003, "Invalid sequence number in block mode."},
{0x05040004, "CRC error (block mode only)."},
{0x05040005, "Out of memory."},
{0x06010000, "Unsupported access to an object."},
{0x06010001, "Attempt to read a write only object."},
{0x06010002, "Attempt to write a read only object."},
{0x06020000, "Object does not exist."},
{0x06040041, "Object cannot be mapped to the PDO."},
{0x06040042, "Number and length of object to be mapped exceeds PDO length."},
{0x06040043, "General parameter incompatibility reasons."},
{0x06040047, "General internal incompatibility in device."},
{0x06060000, "Access failed due to hardware error."},
{0x06070010, "Data type does not match, length of service parameter does not match."},
{0x06070012, "Data type does not match, length of service parameter too high."},
{0x06070013, "Data type does not match, length of service parameter too short."},
{0x06090011, "Sub index does not exist."},
{0x06090030, "Invalid value for parameter (download only)."},
{0x06090031, "Value range of parameter written too high."},
{0x06090032, "Value range of parameter written too low."},
{0x06090036, "Maximum value is less than minimum value."},
{0x060A0023, "Resource not available: SDO connection."},
{0x08000000, "General error."},
{0x08000020, "Data cannot be transferred or stored to application."},
{0x08000021, "Data cannot be transferred or stored to application because of local control."},
{0x08000022, "Data cannot be transferred or stored to application because of present device state."},
{0x08000023, "Object dictionary not present or dynamic generation fails."},
{0x08000024, "No data available."}
}; /**
* 打印所有的错误描述文档内容,有一部分是十进制的,有一部分是十六进制的,注意for循环中的if判断和上面结构体数组中的数值就能体现出来了
*/
static void printErrorDescs(void) {
int i, len; len = sizeof(errorDescs) / sizeof(errorDescs_t); fprintf(stderr, "Internal error codes:\n"); for(i=; i<len; i++) {
const errorDescs_t *ed = &errorDescs[i]; if(ed->code == ) break;
fprintf(stderr, " - %d - %s\n", ed->code, ed->desc);
} fprintf(stderr, "\n");
fprintf(stderr, "SDO abort codes:\n"); for(; i<len; i++) {
const errorDescs_t *ed = &errorDescs[i]; fprintf(stderr, " - 0x%08X - %s\n", ed->code, ed->desc);
} fprintf(stderr, "\n");
} /******************************************************************************/
int main (int argc, char *argv[]) {
char *socketPath = "/tmp/CO_command_socket"; /* Name of the local domain socket, configurable by arguments. */
char *inputFilePath = NULL; char buf[BUF_SIZE];
int fd;
struct sockaddr_un addr;
int opt;
int i; /**
* 输出基本帮助信息
*/
if(argc >= && strcmp(argv[], "--help") == ) {
printUsage(argv[]);
exit(EXIT_SUCCESS);
}
/**
* 输出基本帮助信息和返回的错误码信息
*/
if(argc >= && strcmp(argv[], "--helpall") == ) {
printUsage(argv[]);
printErrorDescs();
exit(EXIT_SUCCESS);
} /* Get program options */
/**
* 获取程序运行时命令行传递过来的参数,并解析
*/
while((opt = getopt(argc, argv, "s:f:h")) != -) {
switch (opt) {
case 'f': // 将命令放置于文件中,通过读取文件并发送给canopend处理
inputFilePath = optarg;
break;
case 's': // 指定canopend的socket的path在哪里
socketPath = optarg;
break;
case 'h': // 输出错误描述
printErrorDescription = ;
break;
default:
printUsage(argv[]);
exit(EXIT_FAILURE);
}
} /* Create and connect client socket */
/**
* 创建本地客户端socket
*/
fd = socket(AF_UNIX, SOCK_STREAM, );
if(fd == -) {
errExit("Socket creation failed");
} /**
* 设置本地socket
*/
memset(&addr, , sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socketPath, sizeof(addr.sun_path) - ); /**
* 链接本地socket
*/
if(connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) == -) {
errExit("Socket connection failed");
} /* get commands from input file, line after line */
/**
* 从文件中获取命令,这里不进行任何处理,直接全部传送,仅仅是将文件中的内容完整转给canopend处理
*/
if(inputFilePath != NULL) {
FILE *fp = fopen(inputFilePath, "r");
if(fp == NULL) {
errExit("Can't open input file");
} while(fgets(buf, BUF_SIZE, fp) != NULL) {
sendCommand(fd, buf, strlen(buf));
} fclose(fp);
} /* get command from arguments */
/**
* 从命令行的参数中获取命令
*/
else if(optind < argc) {
buf[] = ;
size_t buflen = ; /* Add sequence number if not present on command line arguments */
/**
* 如果CAN设备的序号没有提供,那么就是用默认的1号设备(can1)设备
*/
if(argv[optind][] != '[') {
strcat(buf, "[1] ");
} /**
* 将命令行参数合成命令
*/
for(i=optind; i<argc; i++) {
strncat(buf, argv[i], (BUF_SIZE - ) - buflen);
strcat(buf, " ");
buflen = strlen(buf);
if(buflen >= (BUF_SIZE - )) {
fprintf(stderr, "String too long!\n");
exit(EXIT_FAILURE);
}
}
/**
* 每一条命令都是使用'\n'结束,表示一行
*/
buf[buflen - ] = '\n'; /* replace last space with newline */ /**
* 将合成的命令发送给canopend
*/
printErrorDescription = ;
sendCommand(fd, buf, buflen);
} /* get commands from stdin, line after line */
/**
* 从终端的标准输入中一行一行的获取命令
*/
else {
while(fgets(buf, BUF_SIZE, stdin) != NULL) {
sendCommand(fd, buf, strlen(buf));
}
} close(fd); exit(EXIT_SUCCESS);
} static void sendCommand(int fd, char* command, size_t commandLength) {
size_t n;
char buf[BUF_SIZE]; /**
* 发送命令
*/
if (write(fd, command, commandLength) != commandLength) {
errExit("Socket write failed");
} /**
* 接收命令返回信息
*/
n = read(fd, buf, sizeof(buf)); if(n == -) {
errExit("Socket read failed");
} /**
* 是否处理返回的信息
*/
if(printErrorDescription == ) {
char *errLoc = strstr(buf, "ERROR:");
char *endLoc = strstr(buf, "\r\n"); if(errLoc != NULL && endLoc != NULL) {
int num;
char *sRet = NULL; errLoc += ; num = strtol(errLoc, &sRet, );
if(strlen(errLoc) != && sRet == strchr(errLoc, '\r')) {
int i, len; len = sizeof(errorDescs) / sizeof(errorDescs_t); /**
* 查找并输出信息
*/
for(i=; i<len; i++) {
const errorDescs_t *ed = &errorDescs[i];
if(ed->code == num) {
sprintf(endLoc, " - %s\r\n", ed->desc);
break;
}
}
}
}
} /**
* 输出返回原始信息
*/
printf("%s", buf);
}

CANopenSocket CANopenCommand.c hacking的更多相关文章

  1. CANopenSocket CANopenCGI.c hacking

    /**************************************************************************************** * CANopenS ...

  2. ★Kali信息收集~ 1.Google Hacking + Github Hacking

    一.google hacking site site:cnblogs.com 毒逆天 intitle intitle:login allintitle allintitle:index of alli ...

  3. 狗汪汪玩转无线电 -- GPS Hacking

    狗汪汪玩转无线电 -- GPS Hacking Kevin2600 · 2015/12/09 10:12 0x00 序 GPS Hacking 在过去几年的安全会议上一直都是很受关注的议题. 但往往因 ...

  4. GnuRadio Hacking②:使用SDR嗅探北欧芯片无线键盘鼠标数据包

    0×00 前言 上半年的时候安全公司Bastille Networks(巴士底狱)安全研究员发现大多数无线鼠标和接收器之间的通信信号是不加密的,黑客可对一两百米范围内存在漏洞的无线键鼠进行嗅探甚至劫持 ...

  5. GnuRadio Hacking①:使用GnuRadio+SDR破解固定码无线遥控

    0×01 信号捕获 在这篇文章中,我们将使用GnuRadio+SDR硬件对某品牌型号的无线跳蛋进行无线重放攻击的演示. 市面上常见的无线遥控工作的频段,通常工作在315Mhz.433Mhz,也有少数的 ...

  6. GSM Hacking Part② :使用SDR捕获GSM网络数据并解密

    0×00 在文章第一部分 GSM Hacking Part① :使用SDR扫描嗅探GSM网络 搭建了嗅探GSM流量的环境,在第二部中,我们来讨论如何捕获发短信以及通话过程中的流量,从捕获到的数据中解密 ...

  7. 移动安全初探:窃取微信聊天记录、Hacking Android with Metasploit

    在这篇文章中我们将讨论如何获取安卓.苹果设备中的微信聊天记录,并演示如何利用后门通过Metasploit对安卓设备进行控制.文章比较基础.可动手性强,有设备的童鞋不妨边阅读文章边操作,希望能激发大家对 ...

  8. Redis代码阅读之Hacking Strings

    Hacking Strings The implementation of Redis strings is contained in sds.c ( sds stands for Simple Dy ...

  9. RFID Hacking④:使用ProxMark3 破解门禁

    文中提及的部分技术可能带有一定攻击性,仅供安全学习和教学用途,禁止非法使用! 0×00 前言 国际黑客大会Defcon传统之一:开锁!因为黑客认为锁也是一种安全挑战.我们在黑客题材电影.电视剧中也常常 ...

随机推荐

  1. Vim 指令一览表

    vim 程序编辑器 移动光标的方法 h 或 向左箭头键(←) 光标向左移动一个字符 j 或 向下箭头键(↓) 光标向下移动一个字符 k 或 向上箭头键(↑) 光标向上移动一个字符 l 或 向右箭头键( ...

  2. Python之面向对象进阶------反射(Day26)

    一 classmethod class Classmethod_Demo(): role = 'dog' @classmethod def func(cls): print(cls.role) Cla ...

  3. Django源码剖析

    一.Django底层剖析之一次请求到响应的整个流程 As we all know,所有的Web应用,其本质上其实就是一个socket服务端,而用户的浏览器就是一个socket客户端 #!/usr/bi ...

  4. 友盟分享适配iOS9

    在新发布的iOS9系统上围绕用户数据的安全性和体验新增了一些安全特性,同时也影响了应用的实现以及集成方式,为了保证良好的稳定性和体验,需要做如下处理: 1.  HTTP传输安全 以iOS9 SDK编译 ...

  5. NorFlash、NandFlash、eMMC比较区别【转】

    本文转载自:http://www.veryarm.com/1200.html 快闪存储器(英语:Flash Memory),是一种电子式可清除程序化只读存储器的形式,允许在操作中被多次擦或写的存储器. ...

  6. 多校HDU5723 最小生成树+dfs回溯

    Abandoned country Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

  7. 最短路径Dijkstra模板

    算法思想:把所有的边分成两个集合A,B.集合A表示已经求出最短路径的点,不断扩展集合A,减少集合B.每一扩展就从结合B中找出到源点距离最短的点,加入到A. dis[i]数组代表从出发点到j的距离: m ...

  8. Luogu-3878 [TJOI2010]分金币

    这题和在我长郡考试时的一道题思路差不多...考虑折半搜索,预处理左半边选的方案所产生的数量差值\(x\)以及价值差值\(y\),把\(y\)扔到下标为\(x\)的set里面,然后在搜索右半边,每搜出一 ...

  9. Solr新建collection时报错 Caused by: Direct buffer memory

    错误如下 [root@192.168.1.235 conf]# curl "http://192.168.1.235:8983/solr/admin/collections ?action= ...

  10. SolrCloud 5.5.5 + Zookeeper + HDFS使用

    安装sol r 三个节点192.168.1.231,192.168.1.234,192.168.1.235 下载安装包solr.tar.gz 解压 tar -zxvf solr.tar.gz 配置ZK ...