/*****************************************************************************
* 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. PHP获取域名、IP地址的方法

    本文介绍下,在php中,获取域名以及域名对应的IP地址的方法,有需要的朋友参考下. 在php中可以使用内置函数gethostbyname获取域名对应的IP地址,比如: 1 <?php 2 ech ...

  2. windows8.1电话激活密钥

    请断网安装Windows 8.1核心版:334NH-RXG76-64THK-C7CKG-D3VPT Windows 8.1专业版:XHQ8N-C3MCJ-RQXB6-WCHYG-C9WKB

  3. Google Cloud Platfrom中运行基础的Apache Web服务

    Links: https://cloud.google.com/compute/docs/tutorials/basic-webserver-apache 步骤: 1.安装Apache 2.重写Apa ...

  4. 解释*args和**kwargs的含义

    当我们不知道向函数传递多少参数时,比如我们向传递一个列表或元组,我们就使用*args def func(*args): for i in args: print(i) func(3,2,1,4,7) ...

  5. iOS9 Search API 之 Spotlight

    iOS9以后 有三种api提供搜搜方式 加强引导用户关注 我们的app及相关内容的方式 NSUserActivity Web Markup  Core Spotlight 用法 前两种 实战操作性不够 ...

  6. UI控件之UIPickerView的协议方法

    UIPickerView:选择视图,父类是UIView UIPickerView *pickerView=[[UIPickerView alloc]initWithFrame:CGRectMake(1 ...

  7. jQuery开发入门

    jQuery是JavaScript库中的优秀一员. 下载完jQuery框架文件jquery-1.9.0.js 后,不需要任何安装,仅需使用<script>文件导入标记,将该框架文件导入页面 ...

  8. Qt浅谈之二十六图片滑动效果

    一.简介 博客中发现有作者写的仿360的代码,觉得其中图片滑动的效果很有意思,特提取其中的代码.并加上类似mac的画面移动的动画效果. 二.详解 1.代码一:界面滑动(QWidget) (1)slid ...

  9. Android 电容屏驱动

    Android 电容屏(一):电容屏基本原理篇 Android 电容屏(二):驱动调试之基本概念篇 Android 电容屏(三):驱动调试之驱动程序分析篇

  10. [POI2007]立方体大作战tet

    题目 BZOJ 洛谷 做法 很巧妙的题,注意每种颜色只有两个 消除一种颜色,其实就是看中间有多少个没有被消除的块,这种动态距离问题显然能用树状数组解决 洛谷输出方案,暴力往下爬就行 My comple ...